diff --git a/.classpath b/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..c2aedce950ac12ddb11163c806a6d2a7d9b1fdac --- /dev/null +++ b/.classpath @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.factorypath b/.factorypath new file mode 100644 index 0000000000000000000000000000000000000000..28a1dbf2f05f70724b16347eddaf6c3f923a3fa2 --- /dev/null +++ b/.factorypath @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000000000000000000000000000000000000..6e5affb8428dc2234f58b3c134cf0a7247de44fb --- /dev/null +++ b/.project @@ -0,0 +1,28 @@ + + + dap-patternsearch-analysis-service-standalone + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.boot.validation.springbootbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000000000000000000000000000000000..29abf999564110a0d6aca109f55f439c72b7031c --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..dfa4f3adb289a4f7d73e0694f9045f99325604d7 --- /dev/null +++ b/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=true +org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations +org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..90f7a5b4252676e8f4a2fc496e91f323aa99c1f5 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..f897a7f1cb2389f85fe6381425d29f0a9866fb65 --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.springframework.ide.eclipse.prefs b/.settings/org.springframework.ide.eclipse.prefs new file mode 100644 index 0000000000000000000000000000000000000000..a12794d68f2d05b47d56cfe2497dbde7752dc695 --- /dev/null +++ b/.settings/org.springframework.ide.eclipse.prefs @@ -0,0 +1,2 @@ +boot.validation.initialized=true +eclipse.preferences.version=1 diff --git a/SEAL-3.5.1.tar.gz b/SEAL-3.5.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..34b1cca8970b7055a58a01594b2d130bebf3dde2 Binary files /dev/null and b/SEAL-3.5.1.tar.gz differ diff --git a/bigpiseal3.5.1/.clang-format b/bigpiseal3.5.1/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..59c40e85a9025b2c4a9b760aa2c2cf4e6e930cdb --- /dev/null +++ b/bigpiseal3.5.1/.clang-format @@ -0,0 +1,127 @@ +--- +Language: Cpp +# BasedOnStyle: Microsoft +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom # Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Merge +IncludeCategories: + - Regex: '<.*>' + Priority: 1 + - Regex: '"seal/util/.*"' + Priority: -2 + - Regex: '"seal/.*"' + Priority: -3 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +... + diff --git a/bigpiseal3.5.1/.gitignore b/bigpiseal3.5.1/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..36d9e779c430f758b077095c99ad6d24a0baf610 --- /dev/null +++ b/bigpiseal3.5.1/.gitignore @@ -0,0 +1,342 @@ +# Other stuff +cmake/SEALConfig.cmake +cmake/SEALConfigVersion.cmake +cmake/SEALTargets.cmake +native/src/seal/util/config.h +native/src/gsl +**/CMakeCache.txt +**/CMakeFiles +**/Makefile +**/.config +**/autom4te.cache/* +**/cmake_install.cmake +**/install_manifest.txt +.ycm_extra_conf.py +.vimrc +.lvimrc +.local_vimrc +**/*.code-workspace +**/.vscode +**/build +**/*.build +**/compile_commands.json +**/.DS_Store +**/GSL +**/*.args.json +thirdparty/zlib/* +!thirdparty/zlib/CMakeLists.txt +thirdparty/msgsl/* +!thirdparty/msgsl/CMakeLists.txt +thirdparty/googletest/* +!thirdparty/googletest/CMakeLists.txt +dotnet/nuget/nuget.exe +dotnet/nuget/SEALNet.nuspec +dotnet/nuget/SEALNet-multi.nuspec +dotnet/nuget/SEALNet.targets + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ib/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ diff --git a/bigpiseal3.5.1/CHANGES.md b/bigpiseal3.5.1/CHANGES.md new file mode 100644 index 0000000000000000000000000000000000000000..25358043ee9ef045e6508bfa1671c33008e28445 --- /dev/null +++ b/bigpiseal3.5.1/CHANGES.md @@ -0,0 +1,384 @@ +# List of Changes + +## Version 3.5.1 + +Changed version to 3.5.1. The two hotfixes below are included. + +## Version 3.5.0 + +### Hotfix - 4/30/2020 + +- Fixed a critical bug [(Issue 166)](https://github.com/microsoft/SEAL/issues/166) in `Evaluator::multiply_plain_inplace`. Thanks s0l0ist! + +### Hotfix - 4/29/2020 + +- Switched to using Microsoft GSL v3.0.1 and fixed minor GSL related issues in `CMakeLists.txt`. +- Fixed some typos in [README.md](README.md). +- Fixes bugs in ADO pipelines files. + +### New Features + +- Microsoft SEAL officially supports Android (Xamarin.Android) on ARM64. +- Microsoft SEAL is a CMake project (UNIX-like systems only): + - There is now a top-level `CMakeLists.txt` that builds all native components. + - The following CMake targets are created: `SEAL::seal` (static library), `SEAL::seal_shared` (shared library; optional), `SEAL::sealc` (C export library; optional). + - Examples and unit tests are built if enabled through CMake (see [README.md](README.md)). + - ZLIB is downloaded and compiled by CMake and automatically included in the library. + - Microsoft GSL is downloaded by CMake. Its header files are copied to `native/src/gsl` and installed with Microsoft SEAL. + - Google Test is downloaded and compiled by CMake. +- Improved serialization: + - `Serialization::SEALHeader` layout has been changed. SEAL 3.4 objects can still be loaded by SEAL 3.5, and the headers are automatically converted to SEAL 3.5 format. + - `Serialization::SEALHeader` captures version number information. + - Added examples for serialization. + - The seeded versions of `Encryptor`'s symmetric-key encryption and `KeyGenerator`'s `RelinKeys` and `GaloisKeys` generation now output `Serializable` objects. See more details in *API Changes* below. + +#### For Library Developers and Contributors + +We have created a set of C++ iterators that easily allows looping over polynomials in a ciphertext, over RNS components in a polynomial, and over coefficients in an RNS component. +There are also a few other iterators that can come in handy. +Currently `Evaluator` fully utilizes these, and in the future the rest of the library will as well. +The iterators are primarily intended to be used with `std::for_each_n` to simplify existing code and help with code correctness. +Please see [native/src/seal/util/iterator.h](native/src/seal/util/iterator.h) for guidance on how to use these. + +We have also completely rewritten the RNS tools that were previously in the `util::BaseConverter` class. +This functionality is now split between two classes: `util::BaseConverter` whose sole purpose is to perform the `FastBConv` computation of [[BEHZ16]](https://eprint.iacr.org/2016/510) and `util::RNSTool` that handles almost everything else. +RNS bases are now represented by the new `util::RNSBase` class. + +### API Changes + +The following changes are explained in C++ syntax and are introduced to .NET wrappers similarly: + +- New generic class `Serializable` wraps `Ciphertext`, `RelinKeys`, and `GaloisKeys` objects to provide a more flexible approach to the functionality provided in release 3.4 by `KeyGenerator::[relin|galois]_keys_save` and `Encryptor::encrypt_[zero_]symmetric_save` functions. +Specifically, these functions have been removed and replaced with overloads of `KeyGenerator::[relin|galois]_keys` and `Encryptor::encrypt_[zero_]symmetric` that return `Serializable` objects. +The `KeyGenerator::[relin|galois]_keys` methods in release 3.4 are renamed to `KeyGenerator::[relin|galois]_keys_local`. +The `Serializable` objects cannot be used directly by the API, and are only intended to be serialized, which activates the compression functionalities introduced earlier in release 3.4. +- `SmallModulus` class is renamed to `Modulus`, and is relocated to [native/src/seal/modulus.h](native/src/seal/modulus.h). +- `*coeff_mod_count*` methods are renamed to `*coeff_modulus_size*`, which applies to many classes. +- `parameter_error_name` and `parameter_error_message` methods are added to `EncryptionParameterQualifiers` and `SEALContext` classes to explain why an `EncryptionParameters` object is invalid. +- The data members and layout of `Serialization::SEALHeader` have changed. + +The following changes are specific to C++: + +- New bounds in [native/src/seal/util/defines.h](native/src/seal/util/defines.h): + - `SEAL_POLY_MOD_DEGREE_MAX` is increased to 131072; values bigger than 32768 require the security check to be disabled by passing `sec_level_type::none` to `SEALContext::Create`. + - `SEAL_COEFF_MOD_COUNT_MAX` is increased to 64. + - `SEAL_MOD_BIT_COUNT_MAX` and `SEAL_MOD_BIT_COUNT_MIN` are added and set to 61 and 2, respectively. + - `SEAL_INTERNAL_MOD_BIT_COUNT` is added and set to 61. +- `EncryptionParameterQualifiers` now has an error code `parameter_error` that interprets the reason why an `EncryptionParameter` object is invalid. +- `bool parameters_set()` is added to replace the previous `bool parameters_set` member. + +The following changes are specific to .NET: + +- Version numbers are retrievable in .NET through `SEALVersion` class. + +### Other Changes + +- Releases are now listed on [releases page](https://github.com/microsoft/SEAL/releases). +- The native library can serialize (save and load) objects larger than 4 GB. +Please be aware that compressed serialization requires an additional temporary buffer roughly the size of the object to be allocated, and the streambuffer for the output stream may consume some non-trivial amount of memory as well. +In the .NET library, objects are limited to 2 GB, and loading an object larger than 2 GB will throw an exception. +[(Issue 142)](https://github.com/microsoft/SEAL/issues/142) +- Larger-than-suggested parameters are supported for expert users. +To enable that, please adjust `SEAL_POLY_MOD_DEGREE_MAX` and `SEAL_COEFF_MOD_COUNT_MAX` in [native/src/seal/util/defines.h](native/src/seal/util/defines.h). +([Issue 150](https://github.com/microsoft/SEAL/issues/150), +[Issue 84](https://github.com/microsoft/SEAL/issues/84)) +- Serialization now clearly indicates an insufficient buffer size error. +[(Issue 117)](https://github.com/microsoft/SEAL/issues/117) +- Unsupported compression mode now throws `std::invalid_argument` (native) or `ArgumentException` (.NET). +- There is now a `.clang-format` for automated formatting of C++ (`.cpp` and `.h`) files. +Execute `tools/scripts/clang-format-all.sh` for easy formatting (UNIX-like systems only). +This is compatible with clang-format-9 and above. +Formatting for C# is not yet supported. +[(Issue 93)](https://github.com/microsoft/SEAL/issues/93) +- The C export library previously in `dotnet/native/` is moved to [native/src/seal/c/](native/src/seal/c/) and renamed to SEAL_C to support building of wrapper libraries in languages like .NET, Java, Python, etc. +- The .NET wrapper library targets .NET Standard 2.0, but the .NET example and test projects use C# 8.0 and require .NET Core 3.x. Therefore, Visual Studio 2017 is no longer supported for building the .NET example and test projects. +- Fixed issue when compiling in FreeBSD. +([PR 113](https://github.com/microsoft/SEAL/pull/113)) +- A [bug](https://eprint.iacr.org/2019/1266) in the [[BEHZ16]](https://eprint.iacr.org/2016/510)-style RNS operations is fixed; proper unit tests are added. +- Performance of methods in `Evaluator` are in general improved. +([PR 148](https://github.com/microsoft/SEAL/pull/148)) +This is compiler-dependent, however, and currently Clang seems to produce the fastest running code for Microsoft SEAL. + +### File Changes + +Renamed files and directories: + +- [dotnet/examples/7_Performance.cs](dotnet/examples/7_Performance.cs) was previously `dotnet/examples/6_Performance.cs` +- [native/examples/7_performance.cpp](native/examples/7_performance.cpp) was previously `native/examples/6_performance.cpp` +- [native/src/seal/c/](native/src/seal/c/) was previously `dotnet/native/sealnet`. +- [native/src/seal/util/ntt.h](native/src/seal/util/ntt.h) was previously `native/src/seal/util/smallntt.h`. +- [native/src/seal/util/ntt.cpp](native/src/seal/util/ntt.cpp) was previously `native/src/seal/util/smallntt.cpp`. +- [native/tests/seal/util/ntt.cpp](native/tests/seal/util/ntt.cpp) was previously `native/tests/seal/util/smallntt.cpp`. + +New files: + +- [android/](android/) +- [dotnet/examples/6_Serialization.cs](dotnet/examples/6_Serialization.cs) +- [dotnet/src/Serializable.cs](dotnet/src/Serializable.cs) +- [dotnet/src/Version.cs](dotnet/src/Version.cs) +- [dotnet/tests/SerializationTests.cs](dotnet/tests/SerializationTests.cs) +- [native/examples/6_serialization.cpp](native/examples/6_serialization.cpp) +- [native/src/seal/c/version.h](native/src/seal/c/version.h) +- [native/src/seal/c/version.cpp](native/src/seal/c/version.cpp) +- [native/src/seal/util/galois.h](native/src/seal/util/galois.h) +- [native/src/seal/util/galois.cpp](native/src/seal/util/galois.cpp) +- [native/src/seal/util/hash.cpp](native/src/seal/util/hash.cpp) +- [native/src/seal/util/iterator.h](native/src/seal/util/iterator.h) +- [native/src/seal/util/rns.h](native/src/seal/util/rns.h) +- [native/src/seal/util/rns.cpp](native/src/seal/util/rns.cpp) +- [native/src/seal/util/streambuf.h](native/src/seal/util/streambuf.h) +- [native/src/seal/util/streambuf.cpp](native/src/seal/util/streambuf.cpp) +- [native/src/seal/serializable.h](native/src/seal/serializable.h) +- [native/tests/seal/util/iterator.cpp](native/tests/seal/util/iterator.cpp) +- [native/tests/seal/util/galois.cpp](native/tests/seal/util/galois.cpp) +- [native/tests/seal/util/rns.cpp](native/tests/seal/util/rns.cpp) + +Removed files: + +- `dotnet/src/SmallModulus.cs` is merged to [dotnet/src/ModulusTests.cs](dotnet/src/Modulus.cs). +- `dotnet/tests/SmallModulusTests.cs` is merged to [dotnet/tests/ModulusTests.cs](dotnet/tests/ModulusTests.cs). +- `native/src/seal/util/baseconverter.h` +- `native/src/seal/util/baseconverter.cpp` +- `native/src/seal/smallmodulus.h` is merged to [native/src/seal/modulus.h](native/src/seal/modulus.h). +- `native/src/seal/smallmodulus.cpp` is merged to [native/src/seal/modulus.cpp](native/src/seal/modulus.cpp). +- `native/src/seal/c/smallmodulus.h` is merged to [native/src/seal/c/modulus.h](native/src/seal/c/modulus.h). +- `native/src/seal/c/smallmodulus.cpp` is merged to [native/src/seal/c/modulus.cpp](native/src/seal/c/modulus.cpp). +- `native/tests/seal/smallmodulus.cpp` is merged to [native/tests/seal/modulus.cpp](native/tests/seal/modulus.cpp). +- `native/tests/seal/util/baseconverter.cpp` + +## Version 3.4.5 + +- Fixed a concurrency issue in SEALNet: the `unordered_map` storing `SEALContext` pointers was not locked appropriately on construction and destruction of new `SEALContext` objects. +- Fixed a few typos in examples ([PR 71](https://github.com/microsoft/SEAL/pull/71)). +- Added include guard to config.h.in. + +## Version 3.4.4 + +- Fixed issues with `SEALNet.targets` file and `SEALNet.nuspec.in`. +- Updated `README.md` with information about existing multi-platform [NuGet package](https://www.nuget.org/packages/Microsoft.Research.SEALNet). + +## Version 3.4.3 + +- Fixed bug in .NET serialization code where an incorrect number of bytes was written when using ZLIB compression. +- Fixed an issue with .NET functions `Encryptor.EncryptSymmetric...`, where asymmetric encryption was done instead of symmetric encryption. +- Prevented `KeyGenerator::galois_keys` and `KeyGenerator::relin_keys` from being called when the encryption parameters do not support keyswitching. +- Fixed a bug in `Decryptor::invariant_noise_budget` where the computed noise budget was `log(plain_modulus)` bits smaller than it was supposed to be. +- Removed support for Microsoft GSL `gsl::multi_span`, as it was recently deprecated in GSL. + +## Version 3.4.2 + +- Fixed bug reported in [Issue 66](https://github.com/microsoft/SEAL/issues/66) on GitHub. +- CMake does version matching now (correctly) only on major and minor version, not patch version, so writing `find_package(SEAL 3.4)` works correctly and selects the newest version `3.4.x` it can find. + +## Version 3.4.1 + +This patch fixes a few issues with ZLIB support on Windows. +Specifically, + +- Fixed a mistake in `native/src/CMakeConfig.cmd` where the CMake library search path +suffix was incorrect. +- Switched to using a static version of ZLIB on Windows. +- Corrected instructions in [README.md](README.md) for enabling ZLIB support on Windows. + +## Version 3.4.0 + +### New Features + +- Microsoft SEAL can use [ZLIB](https://github.com/madler/zlib), a data compression library, to automatically compress data that is serialized. This applies to every serializable object in Microsoft SEAL. +This feature must be enabled by the user. See more explanation of the compression mechanism in [README.md](README.md#zlib). +Microsoft SEAL does not redistribute ZLIB. +- AES-128 is replaced with the BLAKE2 family of hash functions in the pseudorandom number generator, as BLAKE2 provides better cross-platform support. +Microsoft SEAL redistributes the [reference implementation of BLAKE2](https://github.com/BLAKE2/BLAKE2) with light modifications to silence some misleading warnings in Visual Studio. +The reference implementation of BLAKE2 is licensed under [CC0 1.0 Universal](https://github.com/BLAKE2/BLAKE2/blob/master/COPYING); see license boilerplates in files [native/src/seal/util/blake*](native/src/seal/util/). +- The serialization functionality has been completely rewritten to make it more safe and robust. +Every serialized Microsoft SEAL object starts with a 16-byte `Serialization::SEALHeader` struct, and then includes the data for the object member variables. +Every serializable object can now also be directly serialized into a memory buffer instead of a C++ stream. +This improves serialization for .NET and makes it much easier to wrap the serialization functionality in other languages, e.g., Java. +Unfortunately, old serialized Microsoft SEAL objects are incompatible with the new format. +- A ciphertext encrypted with a secret key, for example, a keyswitching key, has one component generated by the PRNG. +By using a seeded PRNG, this component can be replaced with the random seed used by the PRNG to reduce data size. +After transmitted to another party with Microsoft SEAL, the component can be restored (regenerated) with the same seed. +The security of using seeded PRNG is enhanced by switching to BLAKE2 hash function with a 512-bit seed. +- `Encryptor` now can be constructed with a secret key. +This enables symmetric key encryption which has methods that serialize ciphertexts (compressed with a seed) to a C++ stream or a memory buffer. +- The CMake system has been improved. +For example, multiple versions of Microsoft SEAL can now be installed on the same system easily, as the default installation directory and library filename now depend on the version of Microsoft SEAL. +Examples and unit tests can now be built without installing the library. +[README.md](README.md) has been updated to reflect these changes. +- `Encryptor::encrypt` operations in the BFV scheme are modified. +Each coefficient of a plaintext message is first multiplied with the ciphertext modulus, then divided by the plaintext modulus, and rounded to the nearest integer. +In comparison with the previous method, where each coefficient of a plaintext message is multiplied with the flooring of the coefficient modulus divided by the plaintext modulus, the new method reduces the noise introduced in encryption, increases a noise budget of a fresh encryption, slightly slows down encryption, and has no impact on the security at all. +- Merged [PR 62](https://github.com/microsoft/SEAL/pull/62) that uses a non-adjacent form (NAF) decomposition of random rotations to perform them in a minimal way from power-of-two rotations in both directions. +- This improves performance of random rotations. + +### API Changes + +#### C++ Native + +In all classes with `save` and `load` methods: + +- Replaced the old `save` with two new methods that saves to either a C++ stream or a memory buffer. +Optionally, a compression mode can be chosen when saving an object. +- Replaced the old `load` with two new methods that loads from either a C++ stream or a memory buffer. +- Added a method `save_size` to get an upper bound on the size of the object as if it was written to an output stream. +To save to a buffer, the user must ensure that the buffer has at least size equal to what the `save_size` member function returns. +- New `save` and `load` methods rely on the `Serialization` class declared in `serialization.h`. +This class unifies the serialization functionality for all serializable Microsoft SEAL classes. + +In class `Ciphertext`: + +- Added a method `int_array` for read-only access to the underlying `IntArray` object. +- Removed methods `uint64_count_capacity` and `uint64_count` that can now be accessed in a more descriptive manner through the `int_array` return value. + +In class `CKKSEncoder`: added support for `gsl::span` type of input. + +In class `SEALContext::ContextData`: added method `coeff_mod_plain_modulus` for read-only access to the non-RNS version of `upper_half_increment`. + +In class `EncryptionParameters`: an `EncryptionParameters` object can be constructed without `scheme_type` which by default is set to `scheme_type::none`. + +In class `Encryptor`: + +- An `Encryptor` object can now be constructed with a secret key to enable symmetric key encryption. +- Added methods `encrypt_symmetric` and `encrypt_zero_symmetric` that generate a `Ciphertext` using the secret key. +- Added methods `encrypt_symmetric_save` and `encrypt_zero_symmetric_save` that directly serialize the resulting `Ciphertext` to a C++ stream or a memory buffer. +The resulting `Ciphertext` no long exists after serilization. +In these methods, the second polynomial of a ciphertext is generated by the PRNG and is replaced with the random seed used. + +In class `KeyGenerator`: + +- Added methods `relin_keys_save` and `galois_keys_save` that generate and directly serialize keys to a C++ stream or a memory buffer. +The resulting keys no long exist after serilization. +In these methods, half of the polynomials in keys are generated by the PRNG and is replaced with the random seed used. +- Methods `galois_keys` and `galois_keys_save` throw an exception if `EncryptionParameters` do not support batching in the BFV scheme. + +In class `Plaintext`: added a method `int_array` for read-only access to the underlying `IntArray` object. + +In class `UniformRandomGenerator` and `UniformRandomGeneratorFactory`: redesigned for users to implement their own random number generators more easily. + +In file `valcheck.h`: validity checks are partitioned into finer methods; the `is_valid_for(...)` functions will validate all aspects fo the Microsoft SEAL ojects. + +New classes `BlakePRNG` and `BlakePRNGFactory`: uses Blake2 family of hash functions for PRNG. + +New class `Serialization`: + +- Gives a uniform serialization in Microsoft SEAL to save objects to a C++ stream or a memory buffer. +- Can be configured to use ZLIB compression. + +New files: + +- [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h) +- [native/src/seal/util/blake2.h](native/src/seal/util/blake2.h) +- [native/src/seal/util/blake2-impl.h](native/src/seal/util/blake2-impl.h) +- [native/src/seal/util/blake2b.c](native/src/seal/util/blake2b.c) +- [native/src/seal/util/blake2xb.c](native/src/seal/util/blake2xb.c) +- [native/src/seal/util/croots.cpp](native/src/seal/util/croots.cpp) +- [native/src/seal/util/croots.h](native/src/seal/util/croots.h) +- [native/src/seal/util/scalingvariant.cpp](native/src/seal/util/scalingvariant.cpp) +- [native/src/seal/util/scalingvariant.h](native/src/seal/util/scalingvariant.h) +- [native/src/seal/util/ztools.cpp](native/src/seal/util/ztools.cpp) +- [native/src/seal/util/ztools.h](native/src/seal/util/ztools.h) +- [native/src/seal/serialization.cpp](native/src/seal/serialization.cpp) +- [native/src/seal/serialization.h](native/src/seal/serialization.h) +- [native/tests/seal/serialization.cpp](native/tests/seal/serialization.cpp) +- [dotnet/native/sealnet/serialization_wrapper.cpp](dotnet/native/sealnet/serialization_wrapper.cpp) +- [dotnet/native/sealnet/serialization_wrapper.h](dotnet/native/sealnet/serialization_wrapper.h) + +Removed files: + +- [native/src/seal/util/hash.cpp](native/src/seal/util/hash.cpp) + +#### .NET + +API changes are mostly identical in terms of functionality to those in C++ native, except only the `IsValidFor` variant of the validity check functions is available in .NET, the more granular checks are not exposed. + +New files: + +- [dotnet/src/Serialization.cs](dotnet/src/Serialization.cs) + +### Minor Bug and Typo Fixes + +- Function `encrypt_zero_asymmetric` in [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h) handles the condition `is_ntt_form == false` correctly. +- Invariant noise calculation in BFV is now correct when the plaintext modulus is large and ciphertexts are fresh (reported in [issue 59](https://github.com/microsoft/SEAL/issues/59)). +- Fixed comments in [native/src/seal/util/smallntt.cpp](native/src/seal/util/smallntt.cpp) as reported in [issue 56](https://github.com/microsoft/SEAL/issues/56). +- Fixed an error in examples as reported in [issue 61](https://github.com/microsoft/SEAL/issues/61). +- `GaloisKeys` can no longer be created with encryption parameters that do not support batching. +- Security issues in deserialization were resolved. + +## Version 3.3.2 (patch) + +### Minor Bug and Typo Fixes + +- Switched to using RNS rounding instead of RNS flooring to fix the CKKS +accuracy issue reported in [issue 52](https://github.com/microsoft/SEAL/issues/52). +- Added support for QUIET option in CMake (`find_package(seal QUIET)`). +- Using `[[nodiscard]]` attribute when compiling as C++17. +- Fixed a bug in `Evaluator::multiply_many` where the input vector was changed. + +## Version 3.3.1 (patch) + +### Minor Bug and Typo Fixes + +- A bug was fixed that introduced significant extra inaccuracy in CKKS when compiled on Linux, at least with some versions of glibc; Windows and macOS were not affected. +- A bug was fixed where, on 32-bit platforms, some versions of GCC resolved the util::reverse_bits function to the incorrect overload. + +## Version 3.3.0 + +### New Features + +In this version, we have significantly improved the usability of the CKKS scheme in Microsoft SEAL and many of these improvements apply to the BFV scheme as well. +Homomorphic operations that are based on key switching, i.e., relinearization and rotation, do not consume any noise budget (BFV) or impact accuracy (CKKS). +The implementations of these operations are significantly simplified and unified, and no longer use bit decomposition, so decomposition bit count is gone. +Moreover, fresh ciphertexts now have lower noise. +These changes have an effect on the API and it will be especially worthwhile for users of older versions of the library to study the examples and comments in [native/examples/3_levels.cpp](native/examples/3_levels.cpp) (C++) or [dotnet/examples/3_Levels.cs](dotnet/examples/3_Levels.cs) (C#). + +The setup of `EncryptionParameters` has been made both easier and safer (see [API Changes](#api-changes) below). + +The examples in [native/examples/](native/examples/) and [dotnet/examples/](dotnet/examples/) have been redesigned to better teach the multiple technical concepts required to use Microsoft SEAL correctly and efficiently, and more compactly demonstrate the API. + +### API Changes + +Deleted header files: + +- `native/defaultparameters.h` + +New header files: + +- [native/src/seal/kswitchkeys.h](native/src/seal/kswitchkeys.h): new base class for `RelinKeys` and `GaloisKeys`) +- [native/src/seal/modulus.h](native/src/seal/modulus.h): static helper functions for parameter selection +- [native/src/seal/valcheck.h](native/src/seal/valcheck.h): object validity check functionality +- [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h) + +In class `SEALContext`: + +- Replaced `context_data(parms_id_type)` with `get_context_data(parms_id_type)`. +- Removed `context_data()`. +- Added `key_context_data()`, `key_parms_id()`, `first_context_data()`, and `last_context_data()`. +- Added `using_keyswitching()` that indicates whether key switching is supported in this `SEALContext`. +- `Create(...)` in C++, and constructor in C#, now accepts an optional security level based on [HomomorphicEncryption.org](https://HomomorphicEncryption.org) security standard, causing it to enforce the specified security level. +By default a 128-bit security level is used. +- Added `prev_context_data()` method to class `ContextData` (doubly linked modulus switching chain). +- In C# `SEALContext` now has a public constructor. + +Parameter selection: + +- Removed the `DefaultParams` class. +- Default `coeff_modulus` for the BFV scheme are now accessed through the function `CoeffModulus::BFVDefault(...)`. +These moduli are not recommended for the CKKS scheme. +- Customized `coeff_modulus` for the CKKS scheme can be created using `CoeffModulus::Create(...)` which takes the `poly_modulus_degree` and a vector of bit-lengths of the prime factors as arguments. +It samples suitable primes close to 2^bit_length and returns a vector of `SmallModulus` elements. +- `PlainModulus::Batching(...)` can be used to sample a prime for `plain_modulus` that supports `BatchEncoder` for the BFV scheme. + +Other important changes: + +- Removed `size_capacity` function and data members from `Ciphertext` class. +- Moved all validation methods such as `is_valid_for` and `is_metadata_valid_for` to `valcheck.h`. +- Removed argument `decomposition_bit_count` from methods `relin_keys(...)` and `galois_keys(...)` in class `KeyGenerator`. +- It is no longer possible to create more than one relinearization key. +This is to simplify the API and reduce confusion. We have never seen a real use-case where more relinearization keys would be a good idea. +- Added methods to generate an encryption of zero to `Encryptor`. +- Added comparison methods and primality check for `SmallModulus`. +- Classes `RelinKeys` and `GaloisKeys` are now derived from a common base class `KSwitchKeys`. +- GoogleTest framework is now included as a Git submodule. +- Numerous bugs have been fixed, particularly in the .NET wrappers. + +## Version 3.2 diff --git a/bigpiseal3.5.1/CMakeLists.txt b/bigpiseal3.5.1/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5696d3cb76fe1b3a0640f4b59b2da95ee1a4bb0e --- /dev/null +++ b/bigpiseal3.5.1/CMakeLists.txt @@ -0,0 +1,809 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.12) + +################################################### +# Project SEAL includes the following components: # +# 1. SEAL C++ library # +# 2. SEAL C export library # +# 3. SEAL C++ examples # +# 4. SEAL C++ tests # +################################################### + +project(SEAL VERSION 3.5.1 LANGUAGES CXX C) + +# Check operating system: for Windows, use Visual Studio solution/project files. +if(MSVC) + if(ALLOW_COMMAND_LINE_BUILD) + message(STATUS "Configuring for Visual Studio") + else() + message(FATAL_ERROR "Please build Microsoft SEAL using the attached Visual Studio solution/project files") + endif() +endif() + +######################## +# Global configuration # +######################## + +# [Option] CMAKE_BUILD_TYPE +# Build in Release mode by default; otherwise use selected option +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY + STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo") +endif() +message(STATUS "Build type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}") + +# [Flag] SEAL_DEBUG +# In Debug mode, enable SEAL_DEBUG +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(SEAL_DEBUG ON) +else() + set(SEAL_DEBUG OFF) +endif() +message(STATUS "Microsoft SEAL debug mode: ${SEAL_DEBUG}") + +# [Option] SEAL_USE_CXX17 +# Should we use C++14 or C++17? +set(SEAL_USE_CXX17_OPTION_STR "Use C++17") +option(SEAL_USE_CXX17 ${SEAL_USE_CXX17_OPTION_STR} ON) + +# Conditionally enable features from C++17 +set(SEAL_USE_STD_BYTE OFF) +set(SEAL_USE_SHARED_MUTEX OFF) +set(SEAL_USE_IF_CONSTEXPR OFF) +set(SEAL_USE_MAYBE_UNUSED OFF) +set(SEAL_USE_NODISCARD OFF) +set(SEAL_USE_STD_FOR_EACH_N OFF) +set(SEAL_LANG_FLAG "-std=c++14") +if(SEAL_USE_CXX17) + set(SEAL_USE_STD_BYTE ON) + set(SEAL_USE_SHARED_MUTEX ON) + set(SEAL_USE_IF_CONSTEXPR ON) + set(SEAL_USE_MAYBE_UNUSED ON) + set(SEAL_USE_NODISCARD ON) + set(SEAL_USE_STD_FOR_EACH_N ON) + set(SEAL_LANG_FLAG "-std=c++17") +endif() + +# [Option] CXX compiler flags +# For easier adding of CXX compiler flags +include(CheckCXXCompilerFlag) +function(enable_cxx_compiler_flag_if_supported flag) + string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set) + if(flag_already_set EQUAL -1) + message(STATUS "Adding CXX compiler flag: ${flag} ...") + check_cxx_compiler_flag("${flag}" flag_supported) + if(flag_supported) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) + endif() + unset(flag_supported CACHE) + endif() +endfunction() + +# Always build position-independent-code +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Don't make the install target depend on the all target. +set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY ON) + +# In Debug mode, enable extra compiler flags. +if(NOT MSVC AND SEAL_DEBUG) + enable_cxx_compiler_flag_if_supported("-Wall") + enable_cxx_compiler_flag_if_supported("-Wextra") + enable_cxx_compiler_flag_if_supported("-Wconversion") + enable_cxx_compiler_flag_if_supported("-Wshadow") + enable_cxx_compiler_flag_if_supported("-pedantic") +endif() + +# Path for outupt +if(ANDROID_ABI) + # Android compiles several targets at the same time. Need to specify + # separate directories for separate ABIs. + set(OUTLIB_PATH "lib/${ANDROID_ABI}") +else() + set(OUTLIB_PATH "lib") +endif() + +# Required files and directories +include(GNUInstallDirs) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/${OUTLIB_PATH}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/${OUTLIB_PATH}) +set(CMAKE_LIBRARY_RUNTIME_DIRECTORY ${SEAL_SOURCE_DIR}/bin) +set(SEAL_TARGETS_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALTargets.cmake) +set(SEAL_CONFIG_IN_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfig.cmake.in) +set(SEAL_CONFIG_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfig.cmake) +set(SEAL_CONFIG_VERSION_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfigVersion.cmake) +set(SEAL_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/SEAL-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR}) +set(SEAL_INCLUDES_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/SEAL-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR}) +set(SEAL_INCLUDES_BUILD_DIR ${SEAL_SOURCE_DIR}/native/src) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/bin) + +# For extra modules we might have +list(APPEND CMAKE_MODULE_PATH ${SEAL_SOURCE_DIR}/cmake) + +include(CMakePushCheckState) +include(CMakeDependentOption) +include(CheckIncludeFiles) +include(CheckCXXSourceCompiles) +include(CheckCXXSourceRuns) +include(CheckTypeSize) + +# We clean up native/src/gsl directory which is no longer used in version >= 3.5.0 +if(NOT MSVC AND EXISTS ${SEAL_INCLUDES_BUILD_DIR}/gsl) + message(STATUS "Removing ${SEAL_INCLUDES_BUILD_DIR}/gsl; this is no longer used by Microsoft SEAL >= 3.5.0") + file(REMOVE_RECURSE ${SEAL_INCLUDES_BUILD_DIR}/gsl) +endif() + +################################## +# Macros for configuring targets # +################################## + +# Set the C++ language version +macro(set_language target) + if(SEAL_USE_CXX17) + target_compile_features(${target} PUBLIC cxx_std_17) + else() + target_compile_features(${target} PUBLIC cxx_std_14) + endif() +endmacro() + +# Set the VERSION property +macro(set_version target) + set_target_properties(${target} PROPERTIES VERSION ${SEAL_VERSION}) +endmacro() + +# Set the library filename to reflect version +macro(set_version_filename target) + set_target_properties(${target} PROPERTIES + OUTPUT_NAME ${target}-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR}) +endmacro() + +# Set the SOVERSION property +macro(set_soversion target) + set_target_properties(${target} PROPERTIES + SOVERSION ${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR}) +endmacro() + +# Set include directories for build and install interfaces +macro(set_include_directories target) + target_include_directories(${target} PUBLIC + $ + $) +endmacro() + +# Link a thread library +macro(link_threads target) + # Require thread library + if(NOT TARGET Threads::Threads) + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + endif() + + # Link Threads + target_link_libraries(${target} PUBLIC Threads::Threads) +endmacro() + +# Include target to given export +macro(install_target target export) + install(TARGETS ${target} EXPORT ${export} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endmacro() + +######################### +# External dependencies # +######################### + +function(create_cache_entries dir_name) + set(cce_file_name ${dir_name}/cache_init.txt) + file(WRITE "${cce_file_name}" "set(CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\" CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\" CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_TOOLCHAIN_FILE \"${CMAKE_TOOLCHAIN_FILE}\" CACHE FILEPATH \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(ANDROID_ABI ${ANDROID_ABI} CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(ANDROID_NDK \"${ANDROID_NDK}\" CACHE FILEPATH \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(ANDROID_PLATFORM ${ANDROID_PLATFORM} CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_ANDROID_ARCH_ABI ${CMAKE_ANDROID_ARCH_ABI} CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_ANDROID_NDK \"${CMAKE_ANDROID_NDK}\" CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\" CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME} CACHE STRING \"\" FORCE)\n") + file(APPEND "${cce_file_name}" "set(CMAKE_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION} CACHE STRING \"\" FORCE)\n") +endfunction() + +set(THIRDPARTY_DIR ${SEAL_SOURCE_DIR}/thirdparty) + +# [option] SEAL_USE_MSGSL +set(SEAL_USE_MSGSL_OPTION_STR "Use Microsoft GSL") +option(SEAL_USE_MSGSL ${SEAL_USE_MSGSL_OPTION_STR} ON) + +# Download and configure +if(SEAL_USE_MSGSL AND NOT MSVC) + message(STATUS "Setting up MSGSL ...") + if(NOT CMAKE_TOOLCHAIN_FILE) + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl) + else() + create_cache_entries(${THIRDPARTY_DIR}/msgsl) + if(EXISTS ${THIRDPARTY_DIR}/msgsl/CMakeCache.txt) + # Force regenerating make files. When cross compiling we might be + # compiling more than one platform at a time. + file(REMOVE ${THIRDPARTY_DIR}/msgsl/CMakeCache.txt) + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -Ccache_init.txt + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl) + endif() + if(result) + message(WARNING "Failed to download MSGSL (${result}); disabling `SEAL_USE_MSGSL`") + endif() +endif() + +# Build +if(SEAL_USE_MSGSL AND NOT MSVC) + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl) + if(result) + message(WARNING "Failed to build MSGSL (${result}); disabling `SEAL_USE_MSGSL`") + endif() + set(GSL_CXX_STANDARD "14" CACHE STRING "" FORCE) + mark_as_advanced(GSL_CXX_STANDARD ) + set(GSL_TEST OFF CACHE BOOL "" FORCE) + mark_as_advanced(GSL_TEST) +endif() + +# Set up the targets +if(SEAL_USE_MSGSL AND NOT MSVC) + add_subdirectory( + ${THIRDPARTY_DIR}/msgsl/src + EXCLUDE_FROM_ALL) + set(MSGSL_INCLUDE_DIR ${THIRDPARTY_DIR}/msgsl/src/include) +endif() + +# [option] SEAL_USE_ZLIB +set(SEAL_USE_ZLIB_OPTION_STR "Use ZLIB for compressed serialization") +option(SEAL_USE_ZLIB ${SEAL_USE_ZLIB_OPTION_STR} ON) + +# ZLIB has no VERSION given to project(), needs to suppress CMP0048 warning +if(SEAL_USE_ZLIB AND NOT MSVC) + set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS TRUE CACHE INTERNAL "Suppress CMP0048 warning" FORCE) +endif() + +# Download and configure +if(SEAL_USE_ZLIB AND NOT MSVC) + message(STATUS "Setting up ZLIB ...") + + if(NOT CMAKE_TOOLCHAIN_FILE) + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib) + else() + create_cache_entries(${THIRDPARTY_DIR}/zlib) + if(EXISTS ${THIRDPARTY_DIR}/zlib/CMakeCache.txt) + # Force regenerating make files. When cross compiling we might be + # compiling more than one platform at a time. + file(REMOVE ${THIRDPARTY_DIR}/zlib/CMakeCache.txt) + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -Ccache_init.txt + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib) + endif() + if(result) + message(WARNING "Failed to download ZLIB (${result}); disabling `SEAL_USE_ZLIB`") + endif() + mark_as_advanced(AMD64) + mark_as_advanced(ASM686) + mark_as_advanced(EXECUTABLE_OUTPUT_PATH) + mark_as_advanced(CMAKE_INSTALL_PREFIX) + mark_as_advanced(INSTALL_BIN_DIR) + mark_as_advanced(INSTALL_INC_DIR) + mark_as_advanced(INSTALL_LIB_DIR) + mark_as_advanced(INSTALL_MAN_DIR) + mark_as_advanced(INSTALL_PKGCONFIG_DIR) + mark_as_advanced(LIBRARY_OUTPUT_PATH) + mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY) +endif() + +# Build +if(SEAL_USE_ZLIB AND NOT MSVC) + execute_process(COMMAND ${CMAKE_COMMAND} --build . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib) + if(result) + message(WARNING "Failed to build ZLIB (${result}); disabling `SEAL_USE_ZLIB`") + endif() +endif() + +# Set up the targets +if(SEAL_USE_ZLIB AND NOT MSVC) + add_subdirectory( + ${THIRDPARTY_DIR}/zlib/src + EXCLUDE_FROM_ALL) + list(APPEND SEAL_ZLIB_INCLUDE_DIRS ${THIRDPARTY_DIR}/zlib/src) + list(APPEND SEAL_ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/zlib/src) + set_target_properties(zlibstatic PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${SEAL_ZLIB_INCLUDE_DIRS}") + set(zlibstatic_LIBRARY_PATH ${THIRDPARTY_DIR}/zlib/src/libz.a) +endif() + +# Google Test +# This follows the example in +# https://github.com/google/googletest/blob/release-1.10.0/googletest/README.md. + +# Download and configure +if(SEAL_BUILD_TESTS AND NOT MSVC) + message(STATUS "Setting up Google Test ...") + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/googletest) + if(result) + message(WARNING "Failed to download Google Test (${result}); disabling `SEAL_BUILD_TESTS`") + endif() + set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) + mark_as_advanced(BUILD_GMOCK) + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + mark_as_advanced(INSTALL_GTEST) +endif() + +# Build +if(SEAL_BUILD_TESTS AND NOT MSVC) + execute_process(COMMAND ${CMAKE_COMMAND} --build . + OUTPUT_QUIET + RESULT_VARIABLE result + WORKING_DIRECTORY ${THIRDPARTY_DIR}/googletest) + if(result) + message(WARNING "Failed to build Google Test (${result}); disabling `SEAL_BUILD_TESTS`") + endif() +endif() + +# Set up the targets +if(SEAL_BUILD_TESTS AND NOT MSVC) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + add_subdirectory( + ${THIRDPARTY_DIR}/googletest/src + ${THIRDPARTY_DIR}/googletest/build + EXCLUDE_FROM_ALL) +endif() + +#################### +# SEAL C++ library # +#################### + +# Should we build also the shared library? +set(BUILD_SHARED_LIBS_STR "Build shared library") +option(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_STR} OFF) +if(MSVC AND BUILD_SHARED_LIBS) + message(WARNING "This build system only supports a static build; disabling `BUILD_SHARED_LIBS`") + set(BUILD_SHARED_LIBS OFF CACHE BOOL ${BUILD_SHARED_LIBS_STR} FORCE) +endif() + +# Throw on multiply_plain by a zero plaintext +set(SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT_STR "Throw an exception when a member of Evaluator outputs a transparent ciphertext") +option(SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT ${SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT_STR} ON) +mark_as_advanced(FORCE SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT) + +# In some non-MSVC compilers std::for_each_n is not available even when compiling as C++17 +if(SEAL_USE_STD_FOR_EACH_N) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_QUIET TRUE) + + if(NOT MSVC) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -O0 ${SEAL_LANG_FLAG}") + check_cxx_source_compiles(" + #include + int main() { + int a[1]{ 0 }; + volatile auto fun = std::for_each_n(a, 1, [](auto b) {}); + return 0; + }" + USE_STD_FOR_EACH_N + ) + if(NOT USE_STD_FOR_EACH_N EQUAL 1) + set(SEAL_USE_STD_FOR_EACH_N OFF) + endif() + unset(USE_STD_FOR_EACH_N CACHE) + endif() + + cmake_pop_check_state() +endif() + +# Use intrinsics if available +set(SEAL_USE_INTRIN_OPTION_STR "Use intrinsics") +option(SEAL_USE_INTRIN ${SEAL_USE_INTRIN_OPTION_STR} ON) + +# Check for intrin.h or x64intrin.h +if(SEAL_USE_INTRIN) + if(MSVC) + set(SEAL_INTRIN_HEADER "intrin.h") + else() + set(SEAL_INTRIN_HEADER "x86intrin.h") + endif() + + check_include_file_cxx(${SEAL_INTRIN_HEADER} HAVE_INTRIN_HEADER) + if(NOT HAVE_INTRIN_HEADER) + set(SEAL_USE_INTRIN OFF CACHE BOOL ${SEAL_USE_INTRIN_OPTION_STR} FORCE) + endif() + unset(HAVE_INTRIN_HEADER CACHE) +endif() + +# Specific intrinsics depending on SEAL_USE_INTRIN +if(MSVC) + set(SEAL_USE__UMUL128_OPTION_STR "Use _umul128") + cmake_dependent_option(SEAL_USE__UMUL128 ${SEAL_USE__UMUL128_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) + + set(SEAL_USE__BITSCANREVERSE64_OPTION_STR "Use _BitScanReverse64") + cmake_dependent_option(SEAL_USE__BITSCANREVERSE64 ${SEAL_USE__BITSCANREVERSE64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) +else() + set(SEAL_USE___INT128_OPTION_STR "Use __int128") + cmake_dependent_option(SEAL_USE___INT128 ${SEAL_USE___INT128_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) + + set(SEAL_USE___BUILTIN_CLZLL_OPTION_STR "Use __builtin_clzll") + cmake_dependent_option(SEAL_USE___BUILTIN_CLZLL ${SEAL_USE___BUILTIN_CLZLL_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) +endif() + +set(SEAL_USE__ADDCARRY_U64_OPTION_STR "Use _addcarry_u64") +cmake_dependent_option(SEAL_USE__ADDCARRY_U64 ${SEAL_USE__ADDCARRY_U64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) + +set(SEAL_USE__SUBBORROW_U64_OPTION_STR "Use _subborrow_u64") +cmake_dependent_option(SEAL_USE__SUBBORROW_U64 ${SEAL_USE__SUBBORROW_U64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF) + +if(SEAL_USE_INTRIN) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_QUIET TRUE) + if(NOT MSVC) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -O0 ${SEAL_LANG_FLAG}") + endif() + + if(MSVC) + # Check for presence of _umul128 + if(SEAL_USE__UMUL128) + check_cxx_source_runs(" + #include <${SEAL_INTRIN_HEADER}> + int main() { + unsigned long long a = 0, b = 0; + unsigned long long c; + volatile unsigned long long d; + d = _umul128(a, b, &c); + return 0; + }" + USE_UMUL128 + ) + if(NOT USE_UMUL128 EQUAL 1) + set(SEAL_USE__UMUL128 OFF CACHE BOOL ${SEAL_USE__UMUL128_OPTION_STR} FORCE) + endif() + unset(USE_UMUL128 CACHE) + endif() + + # Check for _BitScanReverse64 + if(SEAL_USE__BITSCANREVERSE64) + check_cxx_source_runs(" + #include <${SEAL_INTRIN_HEADER}> + int main() { + unsigned long a = 0, b = 0; + volatile unsigned char res = _BitScanReverse64(&a, b); + return 0; + }" + USE_BITSCANREVERSE64 + ) + if(NOT USE_BITSCANREVERSE64 EQUAL 1) + set(SEAL_USE__BITSCANREVERSE64 OFF CACHE BOOL ${SEAL_USE__BITSCANREVERSE64_OPTION_STR} FORCE) + endif() + unset(USE_BITSCANREVERSE64 CACHE) + endif() + else() + # Check for presence of __int128 + if(SEAL_USE___INT128) + set(CMAKE_EXTRA_INCLUDE_FILES ${SEAL_INTRIN_HEADER}) + check_type_size("__int128" INT128 LANGUAGE CXX) + if(NOT INT128 EQUAL 16) + set(SEAL_USE___INT128 OFF CACHE BOOL ${SEAL_USE___INT128_OPTION_STR} FORCE) + endif() + unset(HAVE_INT128 CACHE) + unset(INT128 CACHE) + endif() + + # Check for __builtin_clzll + if(SEAL_USE___BUILTIN_CLZLL) + check_cxx_source_runs(" + int main() { + volatile auto res = __builtin_clzll(0); + return 0; + }" + USE_BUILTIN_CLZLL + ) + if(NOT USE_BUILTIN_CLZLL EQUAL 1) + set(SEAL_USE___BUILTIN_CLZLL OFF CACHE BOOL ${SEAL_USE___BUILTIN_CLZLL_OPTION_STR} FORCE) + endif() + unset(USE_BUILTIN_CLZLL CACHE) + endif() + endif() + + # Check for _addcarry_u64 + if(SEAL_USE__ADDCARRY_U64) + check_cxx_source_runs(" + #include <${SEAL_INTRIN_HEADER}> + int main() { + unsigned long long a; + volatile auto res = _addcarry_u64(0,0,0,&a); + return 0; + }" + USE_ADDCARRY_U64 + ) + if(NOT USE_ADDCARRY_U64 EQUAL 1) + set(SEAL_USE__ADDCARRY_U64 OFF CACHE BOOL ${SEAL_USE__ADDCARRY_U64_OPTION_STR} FORCE) + endif() + unset(USE_ADDCARRY_U64 CACHE) + endif() + + # Check for _subborrow_u64 + if(SEAL_USE__SUBBORROW_U64) + check_cxx_source_runs(" + #include <${SEAL_INTRIN_HEADER}> + int main() { + unsigned long long a; + volatile auto res = _subborrow_u64(0,0,0,&a); + return 0; + }" + USE_SUBBORROW_U64 + ) + if(NOT USE_SUBBORROW_U64 EQUAL 1) + set(SEAL_USE__SUBBORROW_U64 OFF CACHE BOOL ${SEAL_USE__SUBBORROW_U64_OPTION_STR} FORCE) + endif() + unset(USE_SUBBORROW_U64 CACHE) + endif() + + cmake_pop_check_state() +endif() + +# Create an object library to compile sources only once +add_library(seal_obj OBJECT) + +# Add source files to library and header files to install +add_subdirectory(native/src/seal) + +# Set C++ language version and include directories for the object library +set_language(seal_obj) +set_include_directories(seal_obj) + +if(SEAL_USE_MSGSL AND NOT MSVC) + target_link_libraries(seal_obj PRIVATE GSL) +endif() + +if(SEAL_USE_ZLIB AND NOT MSVC) + target_link_libraries(seal_obj PRIVATE zlibstatic) +endif() + +# Always build the static library +add_library(seal STATIC $) +set_version(seal) +set_version_filename(seal) +set_language(seal) +set_include_directories(seal) +link_threads(seal) +install_target(seal SEALTargets) + +# Conditionally add MSGSL include directory to build interface +if(SEAL_USE_MSGSL AND NOT MSVC) + target_include_directories(seal PUBLIC $) +endif() + +# Conditionally build the shared library +if(BUILD_SHARED_LIBS) + add_library(seal_shared SHARED $) + set_target_properties(seal_shared PROPERTIES OUTPUT_NAME seal) + set_version(seal_shared) + set_soversion(seal_shared) + set_language(seal_shared) + set_include_directories(seal_shared) + link_threads(seal_shared) + + # Conditionally add MSGSL include directory to build interface + if(SEAL_USE_MSGSL AND NOT MSVC) + target_include_directories(seal_shared PUBLIC $) + endif() + + if(SEAL_USE_ZLIB AND NOT MSVC) + # In the shared build we link zlibstatic into the shared library + target_link_libraries(seal_shared PRIVATE zlibstatic) + endif() + + install_target(seal_shared SEALTargets) +endif() + +# In UNIX-like platforms combine manually seal and zlibstatic into a single archive; not pretty, but works +if(SEAL_USE_ZLIB AND NOT MSVC) + if(CMAKE_HOST_WIN32) + get_filename_component(CXX_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY) + set(AR_CMD_PATH "${CXX_DIR}/llvm-ar.exe") + file(TO_NATIVE_PATH "${AR_CMD_PATH}" AR_CMD_PATH) + set(DEL_CMD "del") + set(DEL_CMD_OPTS "") + else() + set(AR_CMD_PATH "ar") + set(DEL_CMD "rm") + set(DEL_CMD_OPTS "-rf") + endif() + file(COPY "${zlibstatic_LIBRARY_PATH}" DESTINATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") + add_custom_command(TARGET seal POST_BUILD + COMMAND "${AR_CMD_PATH}" x $ + COMMAND "${AR_CMD_PATH}" x $/libz.a + COMMAND "${AR_CMD_PATH}" rcs $ *.o + COMMAND ${DEL_CMD} ${DEL_CMD_OPTS} *.o + WORKING_DIRECTORY $) +endif() + +######################### +# SEAL C export library # +######################### + +# Check that size_t is 8 bytes +include(CheckTypeSize) +check_type_size("size_t" SIZET LANGUAGE C) + +set(SEAL_BUILD_SEAL_C_OPTION_STR "Build C export library for Microsoft SEAL") +cmake_dependent_option(SEAL_BUILD_SEAL_C ${SEAL_BUILD_SEAL_C_OPTION_STR} OFF "${SIZET} EQUAL 8" OFF) + +unset(SIZET CACHE) +unset(HAVE_SIZET CACHE) + +# Create shared SEAL_C library but add no source files yet +if(SEAL_BUILD_SEAL_C) + add_library(sealc SHARED) + + # Add source files to library and header files to install + add_subdirectory(native/src/seal/c) + set_version(sealc) + set_soversion(sealc) + set_language(sealc) + set_include_directories(sealc) + + target_link_libraries(sealc PUBLIC seal) + + install_target(sealc SEALTargets) +endif() + +################################# +# Installation and CMake config # +################################# + +# Create the CMake config file +include(CMakePackageConfigHelpers) +configure_package_config_file( + ${SEAL_CONFIG_IN_FILENAME} ${SEAL_CONFIG_FILENAME} + INSTALL_DESTINATION ${SEAL_CONFIG_INSTALL_DIR}) + +# Install the export +install( + EXPORT SEALTargets + NAMESPACE SEAL:: + DESTINATION ${SEAL_CONFIG_INSTALL_DIR}) + +# Version file; we require exact version match for downstream +write_basic_package_version_file( + ${SEAL_CONFIG_VERSION_FILENAME} + VERSION ${SEAL_VERSION} + COMPATIBILITY SameMinorVersion) + +# Install config and module files +install( + FILES + ${SEAL_CONFIG_FILENAME} + ${SEAL_CONFIG_VERSION_FILENAME} + DESTINATION ${SEAL_CONFIG_INSTALL_DIR}) + +# We export SEALTargets from the build tree so it can be used by other projects +# without requiring an install. +export( + EXPORT SEALTargets + NAMESPACE SEAL:: + FILE ${SEAL_TARGETS_FILENAME}) + +# In UNIX-like platforms install MSGSL header files +if(SEAL_USE_MSGSL AND NOT MSVC) + install( + DIRECTORY + ${MSGSL_INCLUDE_DIR}/gsl + DESTINATION + ${SEAL_INCLUDES_INSTALL_DIR} + ) +endif() + +##################### +# SEAL C++ examples # +##################### + +# [option] SEAL_BUILD_EXAMPLES +set(SEAL_BUILD_EXAMPLES_OPTION_STR "Build C++ examples for Microsoft SEAL") +option(SEAL_BUILD_EXAMPLES ${SEAL_BUILD_EXAMPLES_OPTION_STR} OFF) + +if(SEAL_BUILD_EXAMPLES) + add_executable(sealexamples) + add_subdirectory(native/examples) + add_subdirectory(native/examples/hello) + add_subdirectory(native/examples/generic) + #add_subdirectory(native/examples/patternSearch) + add_subdirectory(native/examples/patternSearch/v1) + add_subdirectory(native/examples/patternSearch/v2) + add_subdirectory(native/examples/similarityMatch/v1) + add_subdirectory(native/examples/ANN/v1) + target_link_libraries(sealexamples PRIVATE seal) +endif() + +################## +# SEAL C++ tests # +################## + +# [option] SEAL_BUILD_TESTS +set(SEAL_BUILD_TESTS_OPTION_STR "Build C++ tests for Microsoft SEAL") +option(SEAL_BUILD_TESTS ${SEAL_BUILD_TESTS_OPTION_STR} OFF) + +if(SEAL_BUILD_TESTS) + add_executable(sealtest) + add_subdirectory(native/tests/seal) + target_link_libraries(sealtest PRIVATE seal gtest) +endif() + +####################################### +# Configure SEALNet and NuGet package # +####################################### + +# Set the sealc dynamic library file names to be included in creating +# the NuGet package. When building a multi-platform NuGet package, the +# dynamic library paths need to be specified explicitly in the NuGet +# command. See dotnet/nuget/SEALNet.nuspec.in. + +# First create the multi-platform NuSpec file so disable all platform-specific +# library paths +unset(SEAL_WINDOWS_SEAL_C_PATH) +unset(SEAL_LINUX_SEAL_C_PATH) +unset(SEAL_MACOS_SEAL_C_PATH) + +# Create SEALNet-multi.nuspec for a multi-platform NuGet package +configure_file( + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet-multi.nuspec.in + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet-multi.nuspec + @ONLY) + +set(SEAL_WINDOWS_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/x64/$Configuration$/sealc.dll) +set(SEAL_LINUX_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/libsealc.so) +set(SEAL_MACOS_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/libsealc.dylib) + +# Supporting local building of NuGet package +if(MSVC) + set(NUGET_SEAL_C_PATH ${SEAL_WINDOWS_SEAL_C_PATH}) +elseif(UNIX) + set(NUGET_SEAL_C_PATH ${SEAL_LINUX_SEAL_C_PATH}) +elseif(APPLE) + set(NUGET_SEAL_C_PATH ${SEAL_MACOS_SEAL_C_PATH}) +endif() + +if(NUGET_SEAL_C_PATH) + # Create SEALNet.nuspec for a local NuGet pack from SEALNet.nuspec.in + configure_file( + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.nuspec.in + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.nuspec + @ONLY) +endif() + +# Create SEALNet.targets from SEALNet.targets.in +configure_file( + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.targets.in + ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.targets + @ONLY) diff --git a/bigpiseal3.5.1/CODE_OF_CONDUCT.md b/bigpiseal3.5.1/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000000000000000000000000000000..f9ba8cf65f3e3104dd061c178066ec8247811f33 --- /dev/null +++ b/bigpiseal3.5.1/CODE_OF_CONDUCT.md @@ -0,0 +1,9 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns diff --git a/bigpiseal3.5.1/CONTRIBUTING.md b/bigpiseal3.5.1/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..ca8c450ec03469445d22a828101b0eca8b35114e --- /dev/null +++ b/bigpiseal3.5.1/CONTRIBUTING.md @@ -0,0 +1,25 @@ +# Contributing + +This project welcomes contributions and suggestions. +Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. +For details, visit https://cla.opensource.microsoft.com. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/). +Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) for any additional questions or comments. + +### Pull Requests + +Submit pull requrests to **branch *contrib***. +Pull requests to any other branch will not be accepted. + +When you submit a pull request, a CLA bot will automatically determine whether you need to **provide a CLA** and decorate the PR appropriately (e.g., status check, comment). +Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +### Formatting + +Microsoft SEAL uses a customized `.clang-format` configuration for C++ code styling. +A script `tools/scripts/clang-format-all.sh` is provided to easily format all C++ sources and headers in the `native` directory. + +Documentation are mostly written in GitHub-flavored Markdown. +A line break is required after each full sentence. \ No newline at end of file diff --git a/bigpiseal3.5.1/ISSUES.md b/bigpiseal3.5.1/ISSUES.md new file mode 100644 index 0000000000000000000000000000000000000000..b5cc00412913fc3a7f528434632dc8695acff881 --- /dev/null +++ b/bigpiseal3.5.1/ISSUES.md @@ -0,0 +1,29 @@ +# Issues + +## Technical questions + +The best way to get help with technical questions is on +[StackOverflow](https://stackoverflow.com/questions/tagged/seal) using the `[seal]` +tag. To contact the Microsoft SEAL team directly, please email +[sealcrypto@microsoft.com](mailto:sealcrypto@microsoft.com). + +## Bug reports + +We appreciate community efforts to find and fix bugs and issues in Microsoft SEAL. +If you believe you have found a bug or want to report some other issue, please +do so on [GitHub](https://github.com/Microsoft/SEAL/issues). To help others +determine what the problem may be, we provide a helpful script that collects +relevant system information that you can submit with the bug report (see below). + +### System information + +To collect system information for an improved bug report, please run +``` +make -C tools system_info +``` +This will result in a file `system_info.tar.gz` to be generated, which you can +optionally attach with your bug report. + +## Critical security issues + +For reporting critical security issues, see [SECURITY.md](SECURITY.md). diff --git a/bigpiseal3.5.1/LICENSE b/bigpiseal3.5.1/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..21071075c24599ee98254f702bcfc504cdc275a6 --- /dev/null +++ b/bigpiseal3.5.1/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/bigpiseal3.5.1/NOTICE b/bigpiseal3.5.1/NOTICE new file mode 100644 index 0000000000000000000000000000000000000000..6ace895c31d9b58d7ced493431d29da7a064089a --- /dev/null +++ b/bigpiseal3.5.1/NOTICE @@ -0,0 +1,2 @@ +This software uses the BLAKE2 library (https://github.com/BLAKE2/BLAKE2) +The BLAKE2 library is licensed under CC0 Universal, version 1.0. You can find a copy of this license at https://creativecommons.org/publicdomain/zero/1.0/legalcode diff --git a/bigpiseal3.5.1/SEAL.sln b/bigpiseal3.5.1/SEAL.sln new file mode 100644 index 0000000000000000000000000000000000000000..66759e7fd520dba9f55252f24324d427c28e7b94 --- /dev/null +++ b/bigpiseal3.5.1/SEAL.sln @@ -0,0 +1,189 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEAL", "native\src\SEAL.vcxproj", "{7EA96C25-FC0D-485A-BB71-32B6DA55652A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEALTest", "native\tests\SEALTest.vcxproj", "{0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}" + ProjectSection(ProjectDependencies) = postProject + {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEALExamples", "native\examples\SEALExamples.vcxproj", "{2B57D847-26DC-45FF-B9AF-EE33910B5093}" + ProjectSection(ProjectDependencies) = postProject + {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEAL_C", "native\src\SEAL_C.vcxproj", "{70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}" + ProjectSection(ProjectDependencies) = postProject + {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNet", "dotnet\src\SEALNet.csproj", "{D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}" + ProjectSection(ProjectDependencies) = postProject + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D} = {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNetTest", "dotnet\tests\SEALNetTest.csproj", "{D0FCCA29-F0F8-49A3-9615-24FF899F1909}" + ProjectSection(ProjectDependencies) = postProject + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E} = {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNetExamples", "dotnet\examples\SEALNetExamples.csproj", "{18DA9F90-3131-461A-A3E8-40AC0B1D7632}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "native", "native", "{A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{0786F255-C3A7-4912-A669-12273E7AE013}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{33C15AAC-6E56-477E-A118-3451FD21AC49}" + ProjectSection(SolutionItems) = preProject + dotnet\nuget\NUGET.md = dotnet\nuget\NUGET.md + dotnet\nuget\SEALNet.nuspec.in = dotnet\nuget\SEALNet.nuspec.in + dotnet\nuget\SEALNet.targets.in = dotnet\nuget\SEALNet.targets.in + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C73A600E-7F50-467C-9228-58AC2C1A7DDA}" + ProjectSection(SolutionItems) = preProject + .clang-format = .clang-format + .gitignore = .gitignore + CHANGES.md = CHANGES.md + CMakeLists.txt = CMakeLists.txt + CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md + CONTRIBUTING.md = CONTRIBUTING.md + ISSUES.md = ISSUES.md + LICENSE = LICENSE + NOTICE = NOTICE + README.md = README.md + SECURITY.md = SECURITY.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "thirdparty", "thirdparty", "{6B00D0DE-8A17-44B8-BF47-F372E9189434}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zlib", "zlib", "{5E524D23-AD60-45AF-B279-0322941E9F31}" + ProjectSection(SolutionItems) = preProject + thirdparty\zlib\CMakeLists.txt = thirdparty\zlib\CMakeLists.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "msgsl", "msgsl", "{B4EF7358-C76B-4142-9746-B082114B1DDD}" + ProjectSection(SolutionItems) = preProject + thirdparty\msgsl\CMakeLists.txt = thirdparty\msgsl\CMakeLists.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "googletest", "googletest", "{0DD76E94-59E1-49D4-9ED7-8C696B89F26E}" + ProjectSection(SolutionItems) = preProject + thirdparty\googletest\CMakeLists.txt = thirdparty\googletest\CMakeLists.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmake", "cmake", "{256C7291-7A4D-466A-BF88-535B541D2CAC}" + ProjectSection(SolutionItems) = preProject + cmake\SEALConfig.cmake.in = cmake\SEALConfig.cmake.in + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{03B08661-29E2-4806-9F10-F1B7013D717D}" + ProjectSection(SolutionItems) = preProject + pipelines\jobs.yml = pipelines\jobs.yml + pipelines\nix.yml = pipelines\nix.yml + pipelines\nuget.yml = pipelines\nuget.yml + pipelines\pipeline-CI-Debug-Linux.yml = pipelines\pipeline-CI-Debug-Linux.yml + pipelines\pipeline-CI-Debug-macOS.yml = pipelines\pipeline-CI-Debug-macOS.yml + pipelines\pipeline-CI-Debug-Windows.yml = pipelines\pipeline-CI-Debug-Windows.yml + pipelines\pipeline-CI-Release-All.yml = pipelines\pipeline-CI-Release-All.yml + pipelines\pipeline-NuGet.yml = pipelines\pipeline-NuGet.yml + pipelines\pipeline-PR-Debug-All.yml = pipelines\pipeline-PR-Debug-All.yml + pipelines\windows.yml = pipelines\windows.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|Win32.Build.0 = Debug|Win32 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|x64.ActiveCfg = Debug|x64 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|x64.Build.0 = Debug|x64 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|Win32.ActiveCfg = Release|Win32 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|Win32.Build.0 = Release|Win32 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|x64.ActiveCfg = Release|x64 + {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|x64.Build.0 = Release|x64 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|Win32.ActiveCfg = Debug|Win32 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|Win32.Build.0 = Debug|Win32 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|x64.ActiveCfg = Debug|x64 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|x64.Build.0 = Debug|x64 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|Win32.ActiveCfg = Release|Win32 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|Win32.Build.0 = Release|Win32 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|x64.ActiveCfg = Release|x64 + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|x64.Build.0 = Release|x64 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|Win32.Build.0 = Debug|Win32 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|x64.ActiveCfg = Debug|x64 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|x64.Build.0 = Debug|x64 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|Win32.ActiveCfg = Release|Win32 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|Win32.Build.0 = Release|Win32 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|x64.ActiveCfg = Release|x64 + {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|x64.Build.0 = Release|x64 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|Win32.ActiveCfg = Debug|Win32 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|Win32.Build.0 = Debug|Win32 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|x64.ActiveCfg = Debug|x64 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|x64.Build.0 = Debug|x64 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|Win32.ActiveCfg = Release|Win32 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|Win32.Build.0 = Release|Win32 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|x64.ActiveCfg = Release|x64 + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|x64.Build.0 = Release|x64 + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|Win32.ActiveCfg = Debug|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|Win32.Build.0 = Debug|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|x64.ActiveCfg = Debug|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|x64.Build.0 = Debug|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|Win32.ActiveCfg = Release|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|Win32.Build.0 = Release|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|x64.ActiveCfg = Release|Any CPU + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|x64.Build.0 = Release|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|Win32.ActiveCfg = Debug|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|Win32.Build.0 = Debug|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|x64.ActiveCfg = Debug|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|x64.Build.0 = Debug|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|Win32.ActiveCfg = Release|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|Win32.Build.0 = Release|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|x64.ActiveCfg = Release|Any CPU + {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|x64.Build.0 = Release|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|Win32.ActiveCfg = Debug|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|Win32.Build.0 = Debug|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|x64.ActiveCfg = Debug|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|x64.Build.0 = Debug|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|Win32.ActiveCfg = Release|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|Win32.Build.0 = Release|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|x64.ActiveCfg = Release|Any CPU + {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|x64.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D} + {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D} + {2B57D847-26DC-45FF-B9AF-EE33910B5093} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D} + {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D} + {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E} = {0786F255-C3A7-4912-A669-12273E7AE013} + {D0FCCA29-F0F8-49A3-9615-24FF899F1909} = {0786F255-C3A7-4912-A669-12273E7AE013} + {18DA9F90-3131-461A-A3E8-40AC0B1D7632} = {0786F255-C3A7-4912-A669-12273E7AE013} + {33C15AAC-6E56-477E-A118-3451FD21AC49} = {0786F255-C3A7-4912-A669-12273E7AE013} + {6B00D0DE-8A17-44B8-BF47-F372E9189434} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA} + {5E524D23-AD60-45AF-B279-0322941E9F31} = {6B00D0DE-8A17-44B8-BF47-F372E9189434} + {B4EF7358-C76B-4142-9746-B082114B1DDD} = {6B00D0DE-8A17-44B8-BF47-F372E9189434} + {0DD76E94-59E1-49D4-9ED7-8C696B89F26E} = {6B00D0DE-8A17-44B8-BF47-F372E9189434} + {256C7291-7A4D-466A-BF88-535B541D2CAC} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA} + {03B08661-29E2-4806-9F10-F1B7013D717D} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {15A17F22-F747-4B82-BF5F-E0224AF4B3ED} + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection +EndGlobal diff --git a/bigpiseal3.5.1/SECURITY.md b/bigpiseal3.5.1/SECURITY.md new file mode 100644 index 0000000000000000000000000000000000000000..e0dfff56a9569fee0ec4628bb42319f81731b250 --- /dev/null +++ b/bigpiseal3.5.1/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/bigpiseal3.5.1/android/.gitignore b/bigpiseal3.5.1/android/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..603b14077394cd2294ac6922fe619669630ef3ab --- /dev/null +++ b/bigpiseal3.5.1/android/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/bigpiseal3.5.1/android/app/.gitignore b/bigpiseal3.5.1/android/app/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/bigpiseal3.5.1/android/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/bigpiseal3.5.1/android/app/build.gradle b/bigpiseal3.5.1/android/app/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..ce44320a98507c0f9d859a652bd7d1218d925d58 --- /dev/null +++ b/bigpiseal3.5.1/android/app/build.gradle @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + defaultConfig { + applicationId "com.microsoft.seal" + minSdkVersion 24 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags "" + arguments "-DSEAL_BUILD_SEAL_C=1", + "-DSEAL_USE_INTRIN=0" + } + } + ndk { + abiFilters 'x86_64' + abiFilters 'arm64-v8a' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + path "../../CMakeLists.txt" + version "3.12.0+" + } + } + ndkVersion "21.0.6113669" +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.0.2' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/bigpiseal3.5.1/android/app/proguard-rules.pro b/bigpiseal3.5.1/android/app/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..cb446e5802c1891b291de2390644515620e3f9aa --- /dev/null +++ b/bigpiseal3.5.1/android/app/proguard-rules.pro @@ -0,0 +1,24 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml b/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..03f4660430236c555b66f94f92233c4a58532f10 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..1f6bb290603d7caa16c5fb6f61bbfdc750622f5c --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml b/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d025f9bf6b67c63044a36a9ff44fbc69e5c5822 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..898f3ed59ac9f3248734a00e5902736c9367d455 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..dffca3601eba7bf5f409bdd520820e2eb5122c75 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..64ba76f75e9ce021aa3d95c213491f73bcacb597 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..dae5e082342fcdeee5db8a6e0b27028e2d2808f5 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e5ed46597ea8447d91ab1786a34e30f1c26b18bd Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..14ed0af35023e4f1901cf03487b6c524257b8483 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b0907cac3bfd8fbfdc46e1108247f0a1055387ec Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ae03154975f397f8ed1b84f2d4bf9783ecfa26 Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2c18de9e66108411737e910f5c1972476f03ddbf Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..beed3cdd2c32af5114a7dc70b9ef5b698eb8797e Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml b/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000000000000000000000000000000000..4af7e66858725b1387c4d84047793e1e3f9fd2bb --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + + + + #008577 + #00574B + #D81B60 + diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml b/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..695102d90d71516ad4ccc8927e97f4160f82c635 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + SEAL + diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml b/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..8873a554aa97974f85e80b3d3ca36811c9194481 --- /dev/null +++ b/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/bigpiseal3.5.1/android/build.gradle b/bigpiseal3.5.1/android/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..53c02c8db8574603f89a4267167893897dfe6a04 --- /dev/null +++ b/bigpiseal3.5.1/android/build.gradle @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + google() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/bigpiseal3.5.1/android/gradle.properties b/bigpiseal3.5.1/android/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..e4bbb28b9558f1606a4630bbf372ae25eaec6b13 --- /dev/null +++ b/bigpiseal3.5.1/android/gradle.properties @@ -0,0 +1,23 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + diff --git a/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..f6b961fd5a86aa5fbfe90f707c3138408be7c718 Binary files /dev/null and b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..8a68daf59cb8845e8bceac29d74cc1204ac6c832 --- /dev/null +++ b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,9 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +#Mon Apr 06 10:08:19 PDT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/bigpiseal3.5.1/android/gradlew b/bigpiseal3.5.1/android/gradlew new file mode 100644 index 0000000000000000000000000000000000000000..cccdd3d517fc5249beaefa600691cf150f2fa3e6 --- /dev/null +++ b/bigpiseal3.5.1/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/bigpiseal3.5.1/android/gradlew.bat b/bigpiseal3.5.1/android/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..f9553162f122c71b34635112e717c3e733b5b212 --- /dev/null +++ b/bigpiseal3.5.1/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/bigpiseal3.5.1/android/settings.gradle b/bigpiseal3.5.1/android/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..983cef286040c01a6ab5565d8085a49fe27ad664 --- /dev/null +++ b/bigpiseal3.5.1/android/settings.gradle @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +include ':app' +rootProject.name='SEAL' diff --git a/bigpiseal3.5.1/cmake/SEALConfig.cmake.in b/bigpiseal3.5.1/cmake/SEALConfig.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..b13a1d1d712838cca6b26aff82ba44909a3951d4 --- /dev/null +++ b/bigpiseal3.5.1/cmake/SEALConfig.cmake.in @@ -0,0 +1,101 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Exports target SEAL::seal +# +# Creates variables: +# SEAL_FOUND : If a static Microsoft SEAL library was found +# SEAL_SHARED_FOUND : If a shared Microsoft SEAL library was found +# SEAL_C_FOUND : If a Microsoft SEAL C export library was found +# SEAL_VERSION : The full version number +# SEAL_VERSION_MAJOR : The major version number +# SEAL_VERSION_MINOR : The minor version number +# SEAL_VERSION_PATCH : The patch version number +# SEAL_DEBUG : Set to non-zero value if library is compiled with extra debugging code (very slow!) +# SEAL_USE_CXX17 : Set to non-zero value if library is compiled as C++17 instead of C++14 +# SEAL_ENFORCE_HE_STD_SECURITY : Set to non-zero value if library is compiled to enforce at least +# a 128-bit security level based on HomomorphicEncryption.org security estimates +# SEAL_USE_MSGSL : Set to non-zero value if library is compiled with Microsoft GSL support +# SEAL_USE_ZLIB : Set to non-zero value if library is compiled with zlib support + +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +macro(warning_when_not_quiet msg) + if(NOT SEAL_FIND_QUIETLY) + message(WARNING ${msg}) + endif() +endmacro() + +macro(status_when_not_quiet msg) + if(NOT SEAL_FIND_QUIETLY) + message(STATUS ${msg}) + endif() +endmacro() + +macro(find_seal_dependency dep) + find_dependency(${dep}) + if(NOT ${dep}_FOUND) + warning_when_not_quiet("Could not find dependency `${dep}` required by this configuration") + set(SEAL_FOUND FALSE) + return() + endif() +endmacro() + +set(SEAL_FOUND FALSE) +set(SEAL_SHARED_FOUND FALSE) +set(SEAL_C_FOUND FALSE) + +set(SEAL_VERSION @SEAL_VERSION@) +set(SEAL_VERSION_MAJOR @SEAL_VERSION_MAJOR@) +set(SEAL_VERSION_MINOR @SEAL_VERSION_MINOR@) +set(SEAL_VERSION_PATCH @SEAL_VERSION_PATCH@) + +set(SEAL_BUILD_TYPE @CMAKE_BUILD_TYPE@) +set(SEAL_DEBUG @SEAL_DEBUG@) +set(SEAL_USE_CXX17 @SEAL_USE_CXX17@) +set(SEAL_ENFORCE_HE_STD_SECURITY @SEAL_ENFORCE_HE_STD_SECURITY@) + +set(SEAL_USE_MSGSL @SEAL_USE_MSGSL@) +set(SEAL_USE_ZLIB @SEAL_USE_ZLIB@) + +# Add the current directory to the module search path +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_seal_dependency(Threads) + +include(${CMAKE_CURRENT_LIST_DIR}/SEALTargets.cmake) + +if(TARGET SEAL::seal) + set(SEAL_FOUND TRUE) +endif() + +if(TARGET SEAL::seal_shared) + set(SEAL_SHARED_FOUND TRUE) +endif() + +if(TARGET SEAL::sealc) + set(SEAL_C_FOUND TRUE) +endif() + +if(SEAL_FOUND) + status_when_not_quiet("Microsoft SEAL -> Version ${SEAL_VERSION} detected") + if(SEAL_DEBUG) + status_when_not_quiet("Performance warning: Microsoft SEAL compiled in debug mode") + endif() + + set(SEAL_TARGETS_AVAILABLE "Microsoft SEAL -> Targets available: SEAL::seal") + if(SEAL_SHARED_FOUND) + string(APPEND SEAL_TARGETS_AVAILABLE ", SEAL::seal_shared") + endif() + if(SEAL_C_FOUND) + string(APPEND SEAL_TARGETS_AVAILABLE ", SEAL::sealc") + endif() + + status_when_not_quiet(${SEAL_TARGETS_AVAILABLE}) +else() + warning_when_not_quiet("Microsoft SEAL -> NOT FOUND") +endif() diff --git a/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs b/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs new file mode 100644 index 0000000000000000000000000000000000000000..8a1834210bec4f58dddc45302e838191df4ef67c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs @@ -0,0 +1,447 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.Research.SEAL; + +namespace SEALNetExamples +{ + partial class Examples + { + private static void ExampleBFVBasics() + { + Utilities.PrintExampleBanner("Example: BFV Basics"); + + /* + In this example, we demonstrate performing simple computations (a polynomial + evaluation) on encrypted integers using the BFV encryption scheme. + + The first task is to set up an instance of the EncryptionParameters class. + It is critical to understand how the different parameters behave, how they + affect the encryption scheme, performance, and the security level. There are + three encryption parameters that are necessary to set: + + - PolyModulusDegree (degree of polynomial modulus); + - CoeffModulus ([ciphertext] coefficient modulus); + - PlainModulus (plaintext modulus; only for the BFV scheme). + + The BFV scheme cannot perform arbitrary computations on encrypted data. + Instead, each ciphertext has a specific quantity called the `invariant noise + budget' -- or `noise budget' for short -- measured in bits. The noise budget + in a freshly encrypted ciphertext (initial noise budget) is determined by + the encryption parameters. Homomorphic operations consume the noise budget + at a rate also determined by the encryption parameters. In BFV the two basic + operations allowed on encrypted data are additions and multiplications, of + which additions can generally be thought of as being nearly free in terms of + noise budget consumption compared to multiplications. Since noise budget + consumption compounds in sequential multiplications, the most significant + factor in choosing appropriate encryption parameters is the multiplicative + depth of the arithmetic circuit that the user wants to evaluate on encrypted + data. Once the noise budget of a ciphertext reaches zero it becomes too + corrupted to be decrypted. Thus, it is essential to choose the parameters to + be large enough to support the desired computation; otherwise the result is + impossible to make sense of even with the secret key. + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + + /* + The first parameter we set is the degree of the `polynomial modulus'. This + must be a positive power of 2, representing the degree of a power-of-two + cyclotomic polynomial; it is not necessary to understand what this means. + + Larger PolyModulusDegree makes ciphertext sizes larger and all operations + slower, but enables more complicated encrypted computations. Recommended + values are 1024, 2048, 4096, 8192, 16384, 32768, but it is also possible + to go beyond this range. + + In this example we use a relatively small polynomial modulus. Anything + smaller than this will enable only very restricted encrypted computations. + */ + ulong polyModulusDegree = 4096; + parms.PolyModulusDegree = polyModulusDegree; + + /* + Next we set the [ciphertext] `coefficient modulus' (CoeffModulus). This + parameter is a large integer, which is a product of distinct prime numbers, + numbers, each represented by an instance of the Modulus class. The + bit-length of CoeffModulus means the sum of the bit-lengths of its prime + factors. + + A larger CoeffModulus implies a larger noise budget, hence more encrypted + computation capabilities. However, an upper bound for the total bit-length + of the CoeffModulus is determined by the PolyModulusDegree, as follows: + + +----------------------------------------------------+ + | PolyModulusDegree | max CoeffModulus bit-length | + +---------------------+------------------------------+ + | 1024 | 27 | + | 2048 | 54 | + | 4096 | 109 | + | 8192 | 218 | + | 16384 | 438 | + | 32768 | 881 | + +---------------------+------------------------------+ + + These numbers can also be found in native/src/seal/util/hestdparms.h encoded + in the function SEAL_HE_STD_PARMS_128_TC, and can also be obtained from the + function + + CoeffModulus.MaxBitCount(polyModulusDegree). + + For example, if PolyModulusDegree is 4096, the coeff_modulus could consist + of three 36-bit primes (108 bits). + + Microsoft SEAL comes with helper functions for selecting the CoeffModulus. + For new users the easiest way is to simply use + + CoeffModulus.BFVDefault(polyModulusDegree), + + which returns IEnumerable consisting of a generally good choice + for the given PolyModulusDegree. + */ + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + + /* + The plaintext modulus can be any positive integer, even though here we take + it to be a power of two. In fact, in many cases one might instead want it + to be a prime number; we will see this in later examples. The plaintext + modulus determines the size of the plaintext data type and the consumption + of noise budget in multiplications. Thus, it is essential to try to keep the + plaintext data type as small as possible for best performance. The noise + budget in a freshly encrypted ciphertext is + + ~ log2(CoeffModulus/PlainModulus) (bits) + + and the noise budget consumption in a homomorphic multiplication is of the + form log2(PlainModulus) + (other terms). + + The plaintext modulus is specific to the BFV scheme, and cannot be set when + using the CKKS scheme. + */ + parms.PlainModulus = new Modulus(1024); + + /* + Now that all parameters are set, we are ready to construct a SEALContext + object. This is a heavy class that checks the validity and properties of the + parameters we just set. + + C# 8.0 introduced the `using` declaration for local variables. This is a very + convenient addition to the language: it causes the Dispose method for the + object to be called at the end of the enclosing scope (in this case the end + of this function), hence automatically releasing the native resources held by + the object. This is helpful, because releasing the native resources returns + the allocated memory to the memory pool, speeding up further allocations. + Another way would be to call GC::Collect() at a convenient point in the code, + but this may be less optimal as it may still cause unnecessary allocations + of memory if native resources were not released early enough. In this program + we call GC::Collect() after every example (see Examples.cs) to make sure + everything is returned to the memory pool at latest before running the next + example. + */ + using SEALContext context = new SEALContext(parms); + + /* + Print the parameters that we have chosen. + */ + Utilities.PrintLine(); + Console.WriteLine("Set encryption parameters and print"); + Utilities.PrintParameters(context); + + /* + When parameters are used to create SEALContext, Microsoft SEAL will first + validate those parameters. The parameters chosen here are valid. + */ + Console.WriteLine("Parameter validation (success): {0}", context.ParameterErrorMessage()); + + Console.WriteLine(); + Console.WriteLine("~~~~~~ A naive way to calculate 4(x^2+1)(x+1)^2. ~~~~~~"); + + /* + The encryption schemes in Microsoft SEAL are public key encryption schemes. + For users unfamiliar with this terminology, a public key encryption scheme + has a separate public key for encrypting data, and a separate secret key for + decrypting data. This way multiple parties can encrypt data using the same + shared public key, but only the proper recipient of the data can decrypt it + with the secret key. + + We are now ready to generate the secret and public keys. For this purpose + we need an instance of the KeyGenerator class. Constructing a KeyGenerator + automatically generates the public and secret key, which can immediately be + read to local variables. + */ + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + + /* + To be able to encrypt we need to construct an instance of Encryptor. Note + that the Encryptor only requires the public key, as expected. + */ + using Encryptor encryptor = new Encryptor(context, publicKey); + + /* + Computations on the ciphertexts are performed with the Evaluator class. In + a real use-case the Evaluator would not be constructed by the same party + that holds the secret key. + */ + using Evaluator evaluator = new Evaluator(context); + + /* + We will of course want to decrypt our results to verify that everything worked, + so we need to also construct an instance of Decryptor. Note that the Decryptor + requires the secret key. + */ + using Decryptor decryptor = new Decryptor(context, secretKey); + + /* + As an example, we evaluate the degree 4 polynomial + + 4x^4 + 8x^3 + 8x^2 + 8x + 4 + + over an encrypted x = 6. The coefficients of the polynomial can be considered + as plaintext inputs, as we will see below. The computation is done modulo the + plain_modulus 1024. + + While this examples is simple and easy to understand, it does not have much + practical value. In later examples we will demonstrate how to compute more + efficiently on encrypted integers and real or complex numbers. + + Plaintexts in the BFV scheme are polynomials of degree less than the degree + of the polynomial modulus, and coefficients integers modulo the plaintext + modulus. For readers with background in ring theory, the plaintext space is + the polynomial quotient ring Z_T[X]/(X^N + 1), where N is PolyModulusDegree + and T is PlainModulus. + + To get started, we create a plaintext containing the constant 6. For the + plaintext element we use a constructor that takes the desired polynomial as + a string with coefficients represented as hexadecimal numbers. + */ + Utilities.PrintLine(); + int x = 6; + using Plaintext xPlain = new Plaintext(x.ToString()); + Console.WriteLine($"Express x = {x} as a plaintext polynomial 0x{xPlain}."); + + /* + We then encrypt the plaintext, producing a ciphertext. + */ + Utilities.PrintLine(); + using Ciphertext xEncrypted = new Ciphertext(); + Console.WriteLine("Encrypt xPlain to xEncrypted."); + encryptor.Encrypt(xPlain, xEncrypted); + + /* + In Microsoft SEAL, a valid ciphertext consists of two or more polynomials + whose coefficients are integers modulo the product of the primes in the + coeff_modulus. The number of polynomials in a ciphertext is called its `size' + and is given by Ciphertext.Size. A freshly encrypted ciphertext always has + size 2. + */ + Console.WriteLine($" + size of freshly encrypted x: {xEncrypted.Size}"); + + /* + There is plenty of noise budget left in this freshly encrypted ciphertext. + */ + Console.WriteLine(" + noise budget in freshly encrypted x: {0} bits", + decryptor.InvariantNoiseBudget(xEncrypted)); + + /* + We decrypt the ciphertext and print the resulting plaintext in order to + demonstrate correctness of the encryption. + */ + using Plaintext xDecrypted = new Plaintext(); + Console.Write(" + decryption of encrypted_x: "); + decryptor.Decrypt(xEncrypted, xDecrypted); + Console.WriteLine($"0x{xDecrypted} ...... Correct."); + + /* + When using Microsoft SEAL, it is typically advantageous to compute in a way + that minimizes the longest chain of sequential multiplications. In other + words, encrypted computations are best evaluated in a way that minimizes + the multiplicative depth of the computation, because the total noise budget + consumption is proportional to the multiplicative depth. For example, for + our example computation it is advantageous to factorize the polynomial as + + 4x^4 + 8x^3 + 8x^2 + 8x + 4 = 4(x + 1)^2 * (x^2 + 1) + + to obtain a simple depth 2 representation. Thus, we compute (x + 1)^2 and + (x^2 + 1) separately, before multiplying them, and multiplying by 4. + + First, we compute x^2 and add a plaintext "1". We can clearly see from the + print-out that multiplication has consumed a lot of noise budget. The user + can vary the plain_modulus parameter to see its effect on the rate of noise + budget consumption. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute xSqPlusOne (x^2+1)."); + using Ciphertext xSqPlusOne = new Ciphertext(); + evaluator.Square(xEncrypted, xSqPlusOne); + using Plaintext plainOne = new Plaintext("1"); + evaluator.AddPlainInplace(xSqPlusOne, plainOne); + + /* + Encrypted multiplication results in the output ciphertext growing in size. + More precisely, if the input ciphertexts have size M and N, then the output + ciphertext after homomorphic multiplication will have size M+N-1. In this + case we perform a squaring, and observe both size growth and noise budget + consumption. + */ + Console.WriteLine($" + size of xSqPlusOne: {xSqPlusOne.Size}"); + Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits", + decryptor.InvariantNoiseBudget(xSqPlusOne)); + + /* + Even though the size has grown, decryption works as usual as long as noise + budget has not reached 0. + */ + using Plaintext decryptedResult = new Plaintext(); + Console.Write(" + decryption of xSqPlusOne: "); + decryptor.Decrypt(xSqPlusOne, decryptedResult); + Console.WriteLine($"0x{decryptedResult} ...... Correct."); + + /* + Next, we compute (x + 1)^2. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute xPlusOneSq ((x+1)^2)."); + using Ciphertext xPlusOneSq = new Ciphertext(); + evaluator.AddPlain(xEncrypted, plainOne, xPlusOneSq); + evaluator.SquareInplace(xPlusOneSq); + Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}"); + Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits", + decryptor.InvariantNoiseBudget(xPlusOneSq)); + Console.Write(" + decryption of xPlusOneSq: "); + decryptor.Decrypt(xPlusOneSq, decryptedResult); + Console.WriteLine($"0x{decryptedResult} ...... Correct."); + + /* + Finally, we multiply (x^2 + 1) * (x + 1)^2 * 4. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute encryptedResult (4(x^2+1)(x+1)^2)."); + using Ciphertext encryptedResult = new Ciphertext(); + using Plaintext plainFour = new Plaintext("4"); + evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour); + evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult); + Console.WriteLine($" + size of encrypted_result: {encryptedResult.Size}"); + Console.WriteLine(" + noise budget in encrypted_result: {0} bits", + decryptor.InvariantNoiseBudget(encryptedResult)); + Console.WriteLine("NOTE: Decryption can be incorrect if noise budget is zero."); + + Console.WriteLine(); + Console.WriteLine("~~~~~~ A better way to calculate 4(x^2+1)(x+1)^2. ~~~~~~"); + + /* + Noise budget has reached 0, which means that decryption cannot be expected + to give the correct result. This is because both ciphertexts xSqPlusOne and + xPlusOneSq consist of 3 polynomials due to the previous squaring operations, + and homomorphic operations on large ciphertexts consume much more noise budget + than computations on small ciphertexts. Computing on smaller ciphertexts is + also computationally significantly cheaper. + + `Relinearization' is an operation that reduces the size of a ciphertext after + multiplication back to the initial size, 2. Thus, relinearizing one or both + input ciphertexts before the next multiplication can have a huge positive + impact on both noise growth and performance, even though relinearization has + a significant computational cost itself. It is only possible to relinearize + size 3 ciphertexts down to size 2, so often the user would want to relinearize + after each multiplication to keep the ciphertext sizes at 2. + + Relinearization requires special `relinearization keys', which can be thought + of as a kind of public key. Relinearization keys can easily be created with + the KeyGenerator. + + Relinearization is used similarly in both the BFV and the CKKS schemes, but + in this example we continue using BFV. We repeat our computation from before, + but this time relinearize after every multiplication. + + Here we use the function KeyGenerator.RelinKeysLocal(). In production code + it is much better to use KeyGenerator.RelinKeys() instead. We will explain + and discuss these differences in `6_Serialization.cs'. + */ + Utilities.PrintLine(); + Console.WriteLine("Generate locally usable relinearization keys."); + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + + /* + We now repeat the computation relinearizing after each multiplication. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute and relinearize xSquared (x^2),"); + Console.WriteLine(new string(' ', 13) + "then compute xSqPlusOne (x^2+1)"); + using Ciphertext xSquared = new Ciphertext(); + evaluator.Square(xEncrypted, xSquared); + Console.WriteLine($" + size of xSquared: {xSquared.Size}"); + evaluator.RelinearizeInplace(xSquared, relinKeys); + Console.WriteLine(" + size of xSquared (after relinearization): {0}", + xSquared.Size); + evaluator.AddPlain(xSquared, plainOne, xSqPlusOne); + Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits", + decryptor.InvariantNoiseBudget(xSqPlusOne)); + Console.Write(" + decryption of xSqPlusOne: "); + decryptor.Decrypt(xSqPlusOne, decryptedResult); + Console.WriteLine($"0x{decryptedResult} ...... Correct."); + + Utilities.PrintLine(); + using Ciphertext xPlusOne = new Ciphertext(); + Console.WriteLine("Compute xPlusOne (x+1),"); + Console.WriteLine(new string(' ', 13) + + "then compute and relinearize xPlusOneSq ((x+1)^2)."); + evaluator.AddPlain(xEncrypted, plainOne, xPlusOne); + evaluator.Square(xPlusOne, xPlusOneSq); + Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}"); + evaluator.RelinearizeInplace(xPlusOneSq, relinKeys); + Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits", + decryptor.InvariantNoiseBudget(xPlusOneSq)); + Console.Write(" + decryption of xPlusOneSq: "); + decryptor.Decrypt(xPlusOneSq, decryptedResult); + Console.WriteLine($"0x{decryptedResult} ...... Correct."); + + Utilities.PrintLine(); + Console.WriteLine("Compute and relinearize encryptedResult (4(x^2+1)(x+1)^2)."); + evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour); + evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult); + Console.WriteLine($" + size of encryptedResult: {encryptedResult.Size}"); + evaluator.RelinearizeInplace(encryptedResult, relinKeys); + Console.WriteLine(" + size of encryptedResult (after relinearization): {0}", + encryptedResult.Size); + Console.WriteLine(" + noise budget in encryptedResult: {0} bits", + decryptor.InvariantNoiseBudget(encryptedResult)); + + Console.WriteLine(); + Console.WriteLine("NOTE: Notice the increase in remaining noise budget."); + + /* + Relinearization clearly improved our noise consumption. We have still plenty + of noise budget left, so we can expect the correct answer when decrypting. + */ + Utilities.PrintLine(); + Console.WriteLine("Decrypt encrypted_result (4(x^2+1)(x+1)^2)."); + decryptor.Decrypt(encryptedResult, decryptedResult); + Console.WriteLine(" + decryption of 4(x^2+1)(x+1)^2 = 0x{0} ...... Correct.", + decryptedResult); + + /* + For x=6, 4(x^2+1)(x+1)^2 = 7252. Since the plaintext modulus is set to 1024, + this result is computed in integers modulo 1024. Therefore the expected output + should be 7252 % 1024 == 84, or 0x54 in hexadecimal. + */ + + /* + Sometimes we create customized encryption parameters which turn out to be invalid. + Microsoft SEAL can interpret the reason why parameters are considered invalid. + Here we simply reduce the polynomial modulus degree to make the parameters not + compliant with the HomomorphicEncryption.org security standard. + */ + Utilities.PrintLine(); + Console.WriteLine("An example of invalid parameters"); + parms.PolyModulusDegree = 2048; + using SEALContext new_context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine("Parameter validation (failed): {0}", new_context.ParameterErrorMessage()); + + /* + This information is helpful to fix invalid encryption parameters. + */ + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs b/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs new file mode 100644 index 0000000000000000000000000000000000000000..d74c0146959e0792ad2b8ed6232adac5281aeaa9 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs @@ -0,0 +1,487 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.Research.SEAL; + +namespace SEALNetExamples +{ + partial class Examples + { + /* + In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the + BFV scheme. The computation was performed modulo the PlainModulus parameter, and + utilized only one coefficient from a BFV plaintext polynomial. This approach has + two notable problems: + + (1) Practical applications typically use integer or real number arithmetic, + not modular arithmetic; + (2) We used only one coefficient of the plaintext polynomial. This is really + wasteful, as the plaintext polynomial is large and will in any case be + encrypted in its entirety. + + For (1), one may ask why not just increase the PlainModulus parameter until no + overflow occurs, and the computations behave as in integer arithmetic. The problem + is that increasing PlainModulus increases noise budget consumption, and decreases + the initial noise budget too. + + In these examples we will discuss other ways of laying out data into plaintext + elements (encoding) that allow more computations without data type overflow, and + can allow the full plaintext polynomial to be utilized. + */ + private static void ExampleIntegerEncoder() + { + Utilities.PrintExampleBanner("Example: Encoders / Integer Encoder"); + + /* + [IntegerEncoder] (For BFV scheme only) + + The IntegerEncoder encodes integers to BFV plaintext polynomials as follows. + First, a binary expansion of the integer is computed. Next, a polynomial is + created with the bits as coefficients. For example, the integer + + 26 = 2^4 + 2^3 + 2^1 + + is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext + polynomials are decoded by evaluating them at x=2. For negative numbers the + IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is + represented by the unsigned integer PlainModulus - 1 in memory. + + Since encrypted computations operate on the polynomials rather than on the + encoded integers themselves, the polynomial coefficients will grow in the + course of such computations. For example, computing the sum of the encrypted + encoded integer 26 with itself will result in an encrypted polynomial with + larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded + integer 26 results also in increased coefficients due to cross-terms, namely, + + (1x^4 + 1x^3 + 1x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2; + + further computations will quickly increase the coefficients much more. + Decoding will still work correctly in this case (evaluating the polynomial + at x=2), but since the coefficients of plaintext polynomials are really + integers modulo plain_modulus, implicit reduction modulo plain_modulus may + yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself + plain_modulus many times will result in the constant polynomial 0, which is + clearly not equal to 26 * plain_modulus. It can be difficult to predict when + such overflow will take place especially when computing several sequential + multiplications. + + The IntegerEncoder is easy to understand and use for simple computations, + and can be a good tool to experiment with for users new to Microsoft SEAL. + However, advanced users will probably prefer more efficient approaches, + such as the BatchEncoder or the CKKSEncoder. + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + ulong polyModulusDegree = 4096; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + + /* + There is no hidden logic behind our choice of the plain_modulus. The only + thing that matters is that the plaintext polynomial coefficients will not + exceed this value at any point during our computation; otherwise the result + will be incorrect. + */ + parms.PlainModulus = new Modulus(512); + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + /* + We create an IntegerEncoder. + */ + using IntegerEncoder encoder = new IntegerEncoder(context); + + /* + First, we encode two integers as plaintext polynomials. Note that encoding + is not encryption: at this point nothing is encrypted. + */ + int value1 = 5; + using Plaintext plain1 = encoder.Encode(value1); + Utilities.PrintLine(); + Console.WriteLine($"Encode {value1} as polynomial {plain1} (plain1),"); + + int value2 = -7; + using Plaintext plain2 = encoder.Encode(value2); + Console.WriteLine(new string(' ', 13) + + $"Encode {value2} as polynomial {plain2} (plain2),"); + + /* + Now we can encrypt the plaintext polynomials. + */ + using Ciphertext encrypted1 = new Ciphertext(); + using Ciphertext encrypted2 = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Encrypt plain1 to encrypted1 and plain2 to encrypted2."); + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + Console.WriteLine(" + Noise budget in encrypted1: {0} bits", + decryptor.InvariantNoiseBudget(encrypted1)); + Console.WriteLine(" + Noise budget in encrypted2: {0} bits", + decryptor.InvariantNoiseBudget(encrypted2)); + + /* + As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2. + */ + encryptor.Encrypt(plain2, encrypted2); + using Ciphertext encryptedResult = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2."); + evaluator.Negate(encrypted1, encryptedResult); + evaluator.AddInplace(encryptedResult, encrypted2); + evaluator.MultiplyInplace(encryptedResult, encrypted2); + Console.WriteLine(" + Noise budget in encryptedResult: {0} bits", + decryptor.InvariantNoiseBudget(encryptedResult)); + + using Plaintext plainResult = new Plaintext(); + Utilities.PrintLine(); + Console.WriteLine("Decrypt encrypted_result to plain_result."); + decryptor.Decrypt(encryptedResult, plainResult); + + /* + Print the result plaintext polynomial. The coefficients are not even close + to exceeding our plainModulus, 512. + */ + Console.WriteLine($" + Plaintext polynomial: {plainResult}"); + + /* + Decode to obtain an integer result. + */ + Utilities.PrintLine(); + Console.WriteLine("Decode plain_result."); + Console.WriteLine(" + Decoded integer: {0} ...... Correct.", + encoder.DecodeInt32(plainResult)); + } + + private static void ExampleBatchEncoder() + { + Utilities.PrintExampleBanner("Example: Encoders / Batch Encoder"); + + /* + [BatchEncoder] (For BFV scheme only) + + Let N denote the PolyModulusDegree and T denote the PlainModulus. Batching + allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with + each element an integer modulo T. In the matrix view, encrypted operations act + element-wise on encrypted matrices, allowing the user to obtain speeds-ups of + several orders of magnitude in fully vectorizable computations. Thus, in all + but the simplest computations, batching should be the preferred method to use + with BFV, and when used properly will result in implementations outperforming + anything done with the IntegerEncoder. + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + + /* + To enable batching, we need to set the plain_modulus to be a prime number + congruent to 1 modulo 2*PolyModulusDegree. Microsoft SEAL provides a helper + method for finding such a prime. In this example we create a 20-bit prime + that supports batching. + */ + parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); + + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + /* + We can verify that batching is indeed enabled by looking at the encryption + parameter qualifiers created by SEALContext. + */ + using var qualifiers = context.FirstContextData.Qualifiers; + Console.WriteLine($"Batching enabled: {qualifiers.UsingBatching}"); + + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + /* + Batching is done through an instance of the BatchEncoder class. + */ + using BatchEncoder batchEncoder = new BatchEncoder(context); + + /* + The total number of batching `slots' equals the PolyModulusDegree, N, and + these slots are organized into 2-by-(N/2) matrices that can be encrypted and + computed on. Each slot contains an integer modulo PlainModulus. + */ + ulong slotCount = batchEncoder.SlotCount; + ulong rowSize = slotCount / 2; + Console.WriteLine($"Plaintext matrix row size: {rowSize}"); + + /* + The matrix plaintext is simply given to BatchEncoder as a flattened vector + of numbers. The first `rowSize' many numbers form the first row, and the + rest form the second row. Here we create the following matrix: + + [ 0, 1, 2, 3, 0, 0, ..., 0 ] + [ 4, 5, 6, 7, 0, 0, ..., 0 ] + */ + ulong[] podMatrix = new ulong[slotCount]; + podMatrix[0] = 0; + podMatrix[1] = 1; + podMatrix[2] = 2; + podMatrix[3] = 3; + podMatrix[rowSize] = 4; + podMatrix[rowSize + 1] = 5; + podMatrix[rowSize + 2] = 6; + podMatrix[rowSize + 3] = 7; + + Console.WriteLine("Input plaintext matrix:"); + Utilities.PrintMatrix(podMatrix, (int)rowSize); + + /* + First we use BatchEncoder to encode the matrix into a plaintext polynomial. + */ + using Plaintext plainMatrix = new Plaintext(); + Utilities.PrintLine(); + Console.WriteLine("Encode plaintext matrix:"); + batchEncoder.Encode(podMatrix, plainMatrix); + + /* + We can instantly decode to verify correctness of the encoding. Note that no + encryption or decryption has yet taken place. + */ + List podResult = new List(); + Console.WriteLine(" + Decode plaintext matrix ...... Correct."); + batchEncoder.Decode(plainMatrix, podResult); + Utilities.PrintMatrix(podResult, (int)rowSize); + + /* + Next we encrypt the encoded plaintext. + */ + using Ciphertext encryptedMatrix = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Encrypt plainMatrix to encryptedMatrix."); + encryptor.Encrypt(plainMatrix, encryptedMatrix); + Console.WriteLine(" + Noise budget in encryptedMatrix: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + + /* + Operating on the ciphertext results in homomorphic operations being performed + simultaneously in all 8192 slots (matrix elements). To illustrate this, we + form another plaintext matrix + + [ 1, 2, 1, 2, 1, 2, ..., 2 ] + [ 1, 2, 1, 2, 1, 2, ..., 2 ] + + and encode it into a plaintext. + */ + ulong[] podMatrix2 = new ulong[slotCount]; + for (ulong i = 0; i < slotCount; i++) + { + podMatrix2[i] = (i % 2) + 1; + } + using Plaintext plainMatrix2 = new Plaintext(); + batchEncoder.Encode(podMatrix2, plainMatrix2); + Console.WriteLine(); + Console.WriteLine("Second input plaintext matrix:"); + Utilities.PrintMatrix(podMatrix2, (int)rowSize); + + /* + We now add the second (plaintext) matrix to the encrypted matrix, and square + the sum. + */ + Utilities.PrintLine(); + Console.WriteLine("Sum, square, and relinearize."); + evaluator.AddPlainInplace(encryptedMatrix, plainMatrix2); + evaluator.SquareInplace(encryptedMatrix); + evaluator.RelinearizeInplace(encryptedMatrix, relinKeys); + + /* + How much noise budget do we have left? + */ + Console.WriteLine(" + Noise budget in result: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + + /* + We decrypt and decompose the plaintext to recover the result as a matrix. + */ + using Plaintext plainResult = new Plaintext(); + Utilities.PrintLine(); + Console.WriteLine("Decrypt and decode result."); + decryptor.Decrypt(encryptedMatrix, plainResult); + batchEncoder.Decode(plainResult, podResult); + Console.WriteLine(" + Result plaintext matrix ...... Correct."); + Utilities.PrintMatrix(podResult, (int)rowSize); + + /* + Batching allows us to efficiently use the full plaintext polynomial when the + desired encrypted computation is highly parallelizable. However, it has not + solved the other problem mentioned in the beginning of this file: each slot + holds only an integer modulo plain_modulus, and unless plain_modulus is very + large, we can quickly encounter data type overflow and get unexpected results + when integer computations are desired. Note that overflow cannot be detected + in encrypted form. The CKKS scheme (and the CKKSEncoder) addresses the data + type overflow issue, but at the cost of yielding only approximate results. + */ + } + + static private void ExampleCKKSEncoder() + { + Utilities.PrintExampleBanner("Example: Encoders / CKKS Encoder"); + + /* + [CKKSEncoder] (For CKKS scheme only) + + In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for + computing on encrypted real or complex numbers. We start by creating + encryption parameters for the CKKS scheme. There are two important + differences compared to the BFV scheme: + + (1) CKKS does not use the PlainModulus encryption parameter; + (2) Selecting the CoeffModulus in a specific way can be very important + when using the CKKS scheme. We will explain this further in the file + `CKKS_Basics.cs'. In this example we use CoeffModulus.Create to + generate 5 40-bit prime numbers. + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.Create( + polyModulusDegree, new int[]{ 40, 40, 40, 40, 40 }); + + /* + We create the SEALContext as usual and print the parameters. + */ + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + /* + Keys are created the same way as for the BFV scheme. + */ + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + + /* + We also set up an Encryptor, Evaluator, and Decryptor as usual. + */ + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + /* + To create CKKS plaintexts we need a special encoder: there is no other way + to create them. The IntegerEncoder and BatchEncoder cannot be used with the + CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into + Plaintext objects, which can subsequently be encrypted. At a high level this + looks a lot like what BatchEncoder does for the BFV scheme, but the theory + behind it is completely different. + */ + using CKKSEncoder encoder = new CKKSEncoder(context); + + /* + In CKKS the number of slots is PolyModulusDegree / 2 and each slot encodes + one real or complex number. This should be contrasted with BatchEncoder in + the BFV scheme, where the number of slots is equal to PolyModulusDegree + and they are arranged into a matrix with two rows. + */ + ulong slotCount = encoder.SlotCount; + Console.WriteLine($"Number of slots: {slotCount}"); + + /* + We create a small vector to encode; the CKKSEncoder will implicitly pad it + with zeros to full size (PolyModulusDegree / 2) when encoding. + */ + double[] input = new double[]{ 0.0, 1.1, 2.2, 3.3 }; + Console.WriteLine("Input vector: "); + Utilities.PrintVector(input); + + /* + Now we encode it with CKKSEncoder. The floating-point coefficients of `input' + will be scaled up by the parameter `scale'. This is necessary since even in + the CKKS scheme the plaintext elements are fundamentally polynomials with + integer coefficients. It is instructive to think of the scale as determining + the bit-precision of the encoding; naturally it will affect the precision of + the result. + + In CKKS the message is stored modulo CoeffModulus (in BFV it is stored modulo + PlainModulus), so the scaled message must not get too close to the total size + of CoeffModulus. In this case our CoeffModulus is quite large (200 bits) so + we have little to worry about in this regard. For this simple example a 30-bit + scale is more than enough. + */ + using Plaintext plain = new Plaintext(); + double scale = Math.Pow(2.0, 30); + Utilities.PrintLine(); + Console.WriteLine("Encode input vector."); + encoder.Encode(input, scale, plain); + + /* + We can instantly decode to check the correctness of encoding. + */ + List output = new List(); + Console.WriteLine(" + Decode input vector ...... Correct."); + encoder.Decode(plain, output); + Utilities.PrintVector(output); + + /* + The vector is encrypted the same was as in BFV. + */ + using Ciphertext encrypted = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Encrypt input vector, square, and relinearize."); + encryptor.Encrypt(plain, encrypted); + + /* + Basic operations on the ciphertexts are still easy to do. Here we square + the ciphertext, decrypt, decode, and print the result. We note also that + decoding returns a vector of full size (PolyModulusDegree / 2); this is + because of the implicit zero-padding mentioned above. + */ + evaluator.SquareInplace(encrypted); + evaluator.RelinearizeInplace(encrypted, relinKeys); + + /* + We notice that the scale in the result has increased. In fact, it is now + the square of the original scale: 2^60. + */ + Console.WriteLine(" + Scale in squared input: {0} ({1} bits)", + encrypted.Scale, + (int)Math.Ceiling(Math.Log(encrypted.Scale, newBase: 2))); + Utilities.PrintLine(); + Console.WriteLine("Decrypt and decode."); + decryptor.Decrypt(encrypted, plain); + encoder.Decode(plain, output); + Console.WriteLine(" + Result vector ...... Correct."); + Utilities.PrintVector(output); + + /* + The CKKS scheme allows the scale to be reduced between encrypted computations. + This is a fundamental and critical feature that makes CKKS very powerful and + flexible. We will discuss it in great detail in `3_Levels.cs' and later in + `4_CKKS_Basics.cs'. + */ + } + + private static void ExampleEncoders() + { + Utilities.PrintExampleBanner("Example: Encoders"); + + /* + Run all encoder examples. + */ + ExampleIntegerEncoder(); + ExampleBatchEncoder(); + ExampleCKKSEncoder(); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/3_Levels.cs b/bigpiseal3.5.1/dotnet/examples/3_Levels.cs new file mode 100644 index 0000000000000000000000000000000000000000..bc0b27bfb5369b0515f633a16b8c87425b857736 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/3_Levels.cs @@ -0,0 +1,348 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.Research.SEAL; + +namespace SEALNetExamples +{ + partial class Examples + { + private static void ExampleLevels() + { + Utilities.PrintExampleBanner("Example: Levels"); + + /* + In this examples we describe the concept of `levels' in BFV and CKKS and the + related objects that represent them in Microsoft SEAL. + + In Microsoft SEAL a set of encryption parameters (excluding the random number + generator) is identified uniquely by a 256-bit hash of the parameters. This + hash is called the `ParmsId' and can be easily accessed and printed at any + time. The hash will change as soon as any of the parameters is changed. + + When a SEALContext is created from a given EncryptionParameters instance, + Microsoft SEAL automatically creates a so-called `modulus switching chain', + which is a chain of other encryption parameters derived from the original set. + The parameters in the modulus switching chain are the same as the original + parameters with the exception that size of the coefficient modulus is + decreasing going down the chain. More precisely, each parameter set in the + chain attempts to remove the last coefficient modulus prime from the + previous set; this continues until the parameter set is no longer valid + (e.g., PlainModulus is larger than the remaining CoeffModulus). It is easy + to walk through the chain and access all the parameter sets. Additionally, + each parameter set in the chain has a `chain index' that indicates its + position in the chain so that the last set has index 0. We say that a set + of encryption parameters, or an object carrying those encryption parameters, + is at a higher level in the chain than another set of parameters if its the + chain index is bigger, i.e., it is earlier in the chain. + + Each set of parameters in the chain involves unique pre-computations performed + when the SEALContext is created, and stored in a SEALContext.ContextData + object. The chain is basically a linked list of SEALContext.ContextData + objects, and can easily be accessed through the SEALContext at any time. Each + node can be identified by the ParmsId of its specific encryption parameters + (PolyModulusDegree remains the same but CoeffModulus varies). + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + + /* + In this example we use a custom CoeffModulus, consisting of 5 primes of + sizes 50, 30, 30, 50, and 50 bits. Note that this is still OK according to + the explanation in `1_BFV_Basics.cs'. Indeed, + + CoeffModulus.MaxBitCount(polyModulusDegree) + + returns 218 (greater than 50+30+30+50+50=210). + + Due to the modulus switching chain, the order of the 5 primes is significant. + The last prime has a special meaning and we call it the `special prime'. Thus, + the first parameter set in the modulus switching chain is the only one that + involves the special prime. All key objects, such as SecretKey, are created + at this highest level. All data objects, such as Ciphertext, can be only at + lower levels. The special modulus should be as large as the largest of the + other primes in the CoeffModulus, although this is not a strict requirement. + + special prime +---------+ + | + v + CoeffModulus: { 50, 30, 30, 50, 50 } +---+ Level 4 (all keys; `key level') + | + | + CoeffModulus: { 50, 30, 30, 50 } +---+ Level 3 (highest `data level') + | + | + CoeffModulus: { 50, 30, 30 } +---+ Level 2 + | + | + CoeffModulus: { 50, 30 } +---+ Level 1 + | + | + CoeffModulus: { 50 } +---+ Level 0 (lowest level) + */ + parms.CoeffModulus = CoeffModulus.Create( + polyModulusDegree, new int[] { 50, 30, 30, 50, 50 }); + + /* + In this example the PlainModulus does not play much of a role; we choose + some reasonable value. + */ + parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); + + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + + /* + There are convenience method for accessing the SEALContext.ContextData for + some of the most important levels: + + SEALContext.KeyContextData: access to key level ContextData + SEALContext.FirstContextData: access to highest data level ContextData + SEALContext.LastContextData: access to lowest level ContextData + + We iterate over the chain and print the ParmsId for each set of parameters. + */ + Console.WriteLine(); + Utilities.PrintLine(); + Console.WriteLine("Print the modulus switching chain."); + + /* + First print the key level parameter information. + */ + SEALContext.ContextData contextData = context.KeyContextData; + Console.WriteLine("----> Level (chain index): {0} ...... KeyContextData", + contextData.ChainIndex); + Console.WriteLine($" ParmsId: {contextData.ParmsId}"); + Console.Write(" CoeffModulus primes: "); + foreach (Modulus prime in contextData.Parms.CoeffModulus) + { + Console.Write($"{Utilities.ULongToString(prime.Value)} "); + } + Console.WriteLine(); + Console.WriteLine("\\"); + Console.Write(" \\--> "); + + /* + Next iterate over the remaining (data) levels. + */ + contextData = context.FirstContextData; + while (null != contextData) + { + Console.Write($"Level (chain index): {contextData.ChainIndex}"); + if (contextData.ParmsId.Equals(context.FirstParmsId)) + { + Console.WriteLine(" ...... FirstContextData"); + } + else if (contextData.ParmsId.Equals(context.LastParmsId)) + { + Console.WriteLine(" ...... LastContextData"); + } + else + { + Console.WriteLine(); + } + Console.WriteLine($" ParmsId: {contextData.ParmsId}"); + Console.Write(" CoeffModulus primes: "); + foreach (Modulus prime in contextData.Parms.CoeffModulus) + { + Console.Write($"{Utilities.ULongToString(prime.Value)} "); + } + Console.WriteLine(); + Console.WriteLine("\\"); + Console.Write(" \\--> "); + + /* + Step forward in the chain. + */ + contextData = contextData.NextContextData; + } + Console.WriteLine("End of chain reached"); + Console.WriteLine(); + + /* + We create some keys and check that indeed they appear at the highest level. + */ + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + + /* + In this example we create a local version of the GaloisKeys object using + KeyGenerator.GaloisKeysLocal(). In a production setting where the Galois + keys would need to be communicated to a server, it would be much better to + use KeyGenerator.GaloisKeys(), which outputs a Serializable + object for compressed serialization. + */ + using GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + Utilities.PrintLine(); + Console.WriteLine("Print the parameter IDs of generated elements."); + Console.WriteLine($" + publicKey: {publicKey.ParmsId}"); + Console.WriteLine($" + secretKey: {secretKey.ParmsId}"); + Console.WriteLine($" + relinKeys: {relinKeys.ParmsId}"); + Console.WriteLine($" + galoisKeys: {galoisKeys.ParmsId}"); + + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + /* + In the BFV scheme plaintexts do not carry a ParmsId, but ciphertexts do. Note + how the freshly encrypted ciphertext is at the highest data level. + */ + using Plaintext plain = new Plaintext("1x^3 + 2x^2 + 3x^1 + 4"); + using Ciphertext encrypted = new Ciphertext(); + encryptor.Encrypt(plain, encrypted); + Console.WriteLine($" + plain: {plain.ParmsId} (not set in BFV)"); + Console.WriteLine($" + encrypted: {encrypted.ParmsId}"); + Console.WriteLine(); + + /* + `Modulus switching' is a technique of changing the ciphertext parameters down + in the chain. The function Evaluator.ModSwitchToNext always switches to the + next level down the chain, whereas Evaluator.ModSwitchTo switches to a parameter + set down the chain corresponding to a given ParmsId. However, it is impossible + to switch up in the chain. + */ + Utilities.PrintLine(); + Console.WriteLine("Perform modulus switching on encrypted and print."); + contextData = context.FirstContextData; + Console.Write("----> "); + while (null != contextData.NextContextData) + { + Console.WriteLine($"Level (chain index): {contextData.ChainIndex}"); + Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}"); + Console.WriteLine(" Noise budget at this level: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + Console.WriteLine("\\"); + Console.Write(" \\--> "); + evaluator.ModSwitchToNextInplace(encrypted); + contextData = contextData.NextContextData; + } + Console.WriteLine($"Level (chain index): {contextData.ChainIndex}"); + Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}"); + Console.WriteLine(" Noise budget at this level: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + Console.WriteLine("\\"); + Console.Write(" \\--> "); + Console.WriteLine("End of chain reached"); + Console.WriteLine(); + + /* + At this point it is hard to see any benefit in doing this: we lost a huge + amount of noise budget (i.e., computational power) at each switch and seemed + to get nothing in return. Decryption still works. + */ + Utilities.PrintLine(); + Console.WriteLine("Decrypt still works after modulus switching."); + decryptor.Decrypt(encrypted, plain); + Console.WriteLine($" + Decryption of encrypted: {plain} ...... Correct."); + Console.WriteLine(); + + /* + However, there is a hidden benefit: the size of the ciphertext depends + linearly on the number of primes in the coefficient modulus. Thus, if there + is no need or intention to perform any further computations on a given + ciphertext, we might as well switch it down to the smallest (last) set of + parameters in the chain before sending it back to the secret key holder for + decryption. + + Also the lost noise budget is actually not an issue at all, if we do things + right, as we will see below. + + First we recreate the original ciphertext and perform some computations. + */ + Console.WriteLine("Computation is more efficient with modulus switching."); + Utilities.PrintLine(); + Console.WriteLine("Compute the eight power."); + encryptor.Encrypt(plain, encrypted); + Console.WriteLine(" + Noise budget fresh: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + evaluator.SquareInplace(encrypted); + evaluator.RelinearizeInplace(encrypted, relinKeys); + Console.WriteLine(" + Noise budget of the 2nd power: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + evaluator.SquareInplace(encrypted); + evaluator.RelinearizeInplace(encrypted, relinKeys); + Console.WriteLine(" + Noise budget of the 4th power: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + /* + Surprisingly, in this case modulus switching has no effect at all on the + noise budget. + */ + evaluator.ModSwitchToNextInplace(encrypted); + Console.WriteLine(" + Noise budget after modulus switching: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + + + /* + This means that there is no harm at all in dropping some of the coefficient + modulus after doing enough computations. In some cases one might want to + switch to a lower level slightly earlier, actually sacrificing some of the + noise budget in the process, to gain computational performance from having + smaller parameters. We see from the print-out that the next modulus switch + should be done ideally when the noise budget is down to around 25 bits. + */ + evaluator.SquareInplace(encrypted); + evaluator.RelinearizeInplace(encrypted, relinKeys); + Console.WriteLine(" + Noise budget of the 8th power: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + evaluator.ModSwitchToNextInplace(encrypted); + Console.WriteLine(" + Noise budget after modulus switching: {0} bits", + decryptor.InvariantNoiseBudget(encrypted)); + + /* + At this point the ciphertext still decrypts correctly, has very small size, + and the computation was as efficient as possible. Note that the decryptor + can be used to decrypt a ciphertext at any level in the modulus switching + chain. + */ + decryptor.Decrypt(encrypted, plain); + Console.WriteLine(" + Decryption of the 8th power (hexadecimal) ...... Correct."); + Console.WriteLine($" {plain}"); + Console.WriteLine(); + + /* + In BFV modulus switching is not necessary and in some cases the user might + not want to create the modulus switching chain, except for the highest two + levels. This can be done by passing a bool `false' to SEALContext constructor. + */ + using SEALContext context2 = new SEALContext(parms, expandModChain: false); + + /* + We can check that indeed the modulus switching chain has been created only + for the highest two levels (key level and highest data level). The following + loop should execute only once. + */ + Console.WriteLine("Optionally disable modulus switching chain expansion."); + Utilities.PrintLine(); + Console.WriteLine("Print the modulus switching chain."); + Console.Write("----> "); + for (contextData = context2.KeyContextData; null != contextData; + contextData = contextData.NextContextData) + { + Console.WriteLine($"Level (chain index): {contextData.ChainIndex}"); + Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}"); + Console.Write(" CoeffModulus primes: "); + foreach (Modulus prime in contextData.Parms.CoeffModulus) + { + Console.Write($"{Utilities.ULongToString(prime.Value)} "); + } + Console.WriteLine(); + Console.WriteLine("\\"); + Console.Write(" \\--> "); + } + Console.WriteLine("End of chain reached"); + Console.WriteLine(); + + /* + It is very important to understand how this example works since in the CKKS + scheme modulus switching has a much more fundamental purpose and the next + examples will be difficult to understand unless these basic properties are + totally clear. + */ + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs b/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs new file mode 100644 index 0000000000000000000000000000000000000000..9a4f1cd60a8133813debe85414c14abc5d043aaa --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs @@ -0,0 +1,321 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.Research.SEAL; + +namespace SEALNetExamples +{ + partial class Examples + { + private static void ExampleCKKSBasics() + { + Utilities.PrintExampleBanner("Example: CKKS Basics"); + + /* + In this example we demonstrate evaluating a polynomial function + + PI*x^3 + 0.4*x + 1 + + on encrypted floating-point input data x for a set of 4096 equidistant points + in the interval [0, 1]. This example demonstrates many of the main features + of the CKKS scheme, but also the challenges in using it. + + We start by setting up the CKKS scheme. + */ + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + + /* + We saw in `2_Encoders.cs' that multiplication in CKKS causes scales in + ciphertexts to grow. The scale of any ciphertext must not get too close to + the total size of CoeffModulus, or else the ciphertext simply runs out of + room to store the scaled-up plaintext. The CKKS scheme provides a `rescale' + functionality that can reduce the scale, and stabilize the scale expansion. + + Rescaling is a kind of modulus switch operation (recall `3_Levels.cs'). + As modulus switching, it removes the last of the primes from CoeffModulus, + but as a side-effect it scales down the ciphertext by the removed prime. + Usually we want to have perfect control over how the scales are changed, + which is why for the CKKS scheme it is more common to use carefully selected + primes for the CoeffModulus. + + More precisely, suppose that the scale in a CKKS ciphertext is S, and the + last prime in the current CoeffModulus (for the ciphertext) is P. Rescaling + to the next level changes the scale to S/P, and removes the prime P from the + CoeffModulus, as usual in modulus switching. The number of primes limits + how many rescalings can be done, and thus limits the multiplicative depth of + the computation. + + It is possible to choose the initial scale freely. One good strategy can be + to is to set the initial scale S and primes P_i in the CoeffModulus to be + very close to each other. If ciphertexts have scale S before multiplication, + they have scale S^2 after multiplication, and S^2/P_i after rescaling. If all + P_i are close to S, then S^2/P_i is close to S again. This way we stabilize the + scales to be close to S throughout the computation. Generally, for a circuit + of depth D, we need to rescale D times, i.e., we need to be able to remove D + primes from the coefficient modulus. Once we have only one prime left in the + coeff_modulus, the remaining prime must be larger than S by a few bits to + preserve the pre-decimal-point value of the plaintext. + + Therefore, a generally good strategy is to choose parameters for the CKKS + scheme as follows: + + (1) Choose a 60-bit prime as the first prime in CoeffModulus. This will + give the highest precision when decrypting; + (2) Choose another 60-bit prime as the last element of CoeffModulus, as + this will be used as the special prime and should be as large as the + largest of the other primes; + (3) Choose the intermediate primes to be close to each other. + + We use CoeffModulus.Create to generate primes of the appropriate size. Note + that our CoeffModulus is 200 bits total, which is below the bound for our + PolyModulusDegree: CoeffModulus.MaxBitCount(8192) returns 218. + */ + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.Create( + polyModulusDegree, new int[]{ 60, 40, 40, 60 }); + + /* + We choose the initial scale to be 2^40. At the last level, this leaves us + 60-40=20 bits of precision before the decimal point, and enough (roughly + 10-20 bits) of precision after the decimal point. Since our intermediate + primes are 40 bits (in fact, they are very close to 2^40), we can achieve + scale stabilization as described above. + */ + double scale = Math.Pow(2.0, 40); + + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + using CKKSEncoder encoder = new CKKSEncoder(context); + ulong slotCount = encoder.SlotCount; + Console.WriteLine($"Number of slots: {slotCount}"); + + List input = new List((int)slotCount); + double currPoint = 0, stepSize = 1.0 / (slotCount - 1); + for (ulong i = 0; i < slotCount; i++, currPoint += stepSize) + { + input.Add(currPoint); + } + Console.WriteLine("Input vector:"); + Utilities.PrintVector(input, 3, 7); + + Console.WriteLine("Evaluating polynomial PI*x^3 + 0.4x + 1 ..."); + + /* + We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder.Encode + that encodes the given floating-point value to every slot in the vector. + */ + using Plaintext plainCoeff3 = new Plaintext(), + plainCoeff1 = new Plaintext(), + plainCoeff0 = new Plaintext(); + encoder.Encode(3.14159265, scale, plainCoeff3); + encoder.Encode(0.4, scale, plainCoeff1); + encoder.Encode(1.0, scale, plainCoeff0); + + using Plaintext xPlain = new Plaintext(); + Utilities.PrintLine(); + Console.WriteLine("Encode input vectors."); + encoder.Encode(input, scale, xPlain); + using Ciphertext x1Encrypted = new Ciphertext(); + encryptor.Encrypt(xPlain, x1Encrypted); + + /* + To compute x^3 we first compute x^2 and relinearize. However, the scale has + now grown to 2^80. + */ + using Ciphertext x3Encrypted = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Compute x^2 and relinearize:"); + evaluator.Square(x1Encrypted, x3Encrypted); + evaluator.RelinearizeInplace(x3Encrypted, relinKeys); + Console.WriteLine(" + Scale of x^2 before rescale: {0} bits", + Math.Log(x3Encrypted.Scale, newBase: 2)); + + /* + Now rescale; in addition to a modulus switch, the scale is reduced down by + a factor equal to the prime that was switched away (40-bit prime). Hence, the + new scale should be close to 2^40. Note, however, that the scale is not equal + to 2^40: this is because the 40-bit prime is only close to 2^40. + */ + Utilities.PrintLine(); + Console.WriteLine("Rescale x^2."); + evaluator.RescaleToNextInplace(x3Encrypted); + Console.WriteLine(" + Scale of x^2 after rescale: {0} bits", + Math.Log(x3Encrypted.Scale, newBase: 2)); + + /* + Now x3Encrypted is at a different level than x1Encrypted, which prevents us + from multiplying them to compute x^3. We could simply switch x1Encrypted to + the next parameters in the modulus switching chain. However, since we still + need to multiply the x^3 term with PI (plainCoeff3), we instead compute PI*x + first and multiply that with x^2 to obtain PI*x^3. To this end, we compute + PI*x and rescale it back from scale 2^80 to something close to 2^40. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute and rescale PI*x."); + using Ciphertext x1EncryptedCoeff3 = new Ciphertext(); + evaluator.MultiplyPlain(x1Encrypted, plainCoeff3, x1EncryptedCoeff3); + Console.WriteLine(" + Scale of PI*x before rescale: {0} bits", + Math.Log(x1EncryptedCoeff3.Scale, newBase: 2)); + evaluator.RescaleToNextInplace(x1EncryptedCoeff3); + Console.WriteLine(" + Scale of PI*x after rescale: {0} bits", + Math.Log(x1EncryptedCoeff3.Scale, newBase: 2)); + + /* + Since x3Encrypted and x1EncryptedCoeff3 have the same exact scale and use + the same encryption parameters, we can multiply them together. We write the + result to x3Encrypted, relinearize, and rescale. Note that again the scale + is something close to 2^40, but not exactly 2^40 due to yet another scaling + by a prime. We are down to the last level in the modulus switching chain. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute, relinearize, and rescale (PI*x)*x^2."); + evaluator.MultiplyInplace(x3Encrypted, x1EncryptedCoeff3); + evaluator.RelinearizeInplace(x3Encrypted, relinKeys); + Console.WriteLine(" + Scale of PI*x^3 before rescale: {0} bits", + Math.Log(x3Encrypted.Scale, newBase: 2)); + evaluator.RescaleToNextInplace(x3Encrypted); + Console.WriteLine(" + Scale of PI*x^3 after rescale: {0} bits", + Math.Log(x3Encrypted.Scale, newBase: 2)); + + /* + Next we compute the degree one term. All this requires is one MultiplyPlain + with plainCoeff1. We overwrite x1Encrypted with the result. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute and rescale 0.4*x."); + evaluator.MultiplyPlainInplace(x1Encrypted, plainCoeff1); + Console.WriteLine(" + Scale of 0.4*x before rescale: {0} bits", + Math.Log(x1Encrypted.Scale, newBase: 2)); + evaluator.RescaleToNextInplace(x1Encrypted); + Console.WriteLine(" + Scale of 0.4*x after rescale: {0} bits", + Math.Log(x1Encrypted.Scale, newBase: 2)); + + /* + Now we would hope to compute the sum of all three terms. However, there is + a serious problem: the encryption parameters used by all three terms are + different due to modulus switching from rescaling. + + Encrypted addition and subtraction require that the scales of the inputs are + the same, and also that the encryption parameters (ParmsId) match. If there + is a mismatch, Evaluator will throw an exception. + */ + Console.WriteLine(); + Utilities.PrintLine(); + Console.WriteLine("Parameters used by all three terms are different:"); + Console.WriteLine(" + Modulus chain index for x3Encrypted: {0}", + context.GetContextData(x3Encrypted.ParmsId).ChainIndex); + Console.WriteLine(" + Modulus chain index for x1Encrypted: {0}", + context.GetContextData(x1Encrypted.ParmsId).ChainIndex); + Console.WriteLine(" + Modulus chain index for plainCoeff0: {0}", + context.GetContextData(plainCoeff0.ParmsId).ChainIndex); + Console.WriteLine(); + + /* + Let us carefully consider what the scales are at this point. We denote the + primes in coeff_modulus as P_0, P_1, P_2, P_3, in this order. P_3 is used as + the special modulus and is not involved in rescalings. After the computations + above the scales in ciphertexts are: + + - Product x^2 has scale 2^80 and is at level 2; + - Product PI*x has scale 2^80 and is at level 2; + - We rescaled both down to scale 2^80/P2 and level 1; + - Product PI*x^3 has scale (2^80/P_2)^2; + - We rescaled it down to scale (2^80/P_2)^2/P_1 and level 0; + - Product 0.4*x has scale 2^80; + - We rescaled it down to scale 2^80/P_2 and level 1; + - The contant term 1 has scale 2^40 and is at level 2. + + Although the scales of all three terms are approximately 2^40, their exact + values are different, hence they cannot be added together. + */ + Utilities.PrintLine(); + Console.WriteLine("The exact scales of all three terms are different:"); + Console.WriteLine(" + Exact scale in PI*x^3: {0:0.0000000000}", x3Encrypted.Scale); + Console.WriteLine(" + Exact scale in 0.4*x: {0:0.0000000000}", x1Encrypted.Scale); + Console.WriteLine(" + Exact scale in 1: {0:0.0000000000}", plainCoeff0.Scale); + Console.WriteLine(); + + /* + There are many ways to fix this problem. Since P_2 and P_1 are really close + to 2^40, we can simply "lie" to Microsoft SEAL and set the scales to be the + same. For example, changing the scale of PI*x^3 to 2^40 simply means that we + scale the value of PI*x^3 by 2^120/(P_2^2*P_1), which is very close to 1. + This should not result in any noticeable error. + + Another option would be to encode 1 with scale 2^80/P_2, do a MultiplyPlain + with 0.4*x, and finally rescale. In this case we would need to additionally + make sure to encode 1 with appropriate encryption parameters (ParmsId). + + In this example we will use the first (simplest) approach and simply change + the scale of PI*x^3 and 0.4*x to 2^40. + */ + Utilities.PrintLine(); + Console.WriteLine("Normalize scales to 2^40."); + x3Encrypted.Scale = Math.Pow(2.0, 40); + x1Encrypted.Scale = Math.Pow(2.0, 40); + + /* + We still have a problem with mismatching encryption parameters. This is easy + to fix by using traditional modulus switching (no rescaling). CKKS supports + modulus switching just like the BFV scheme, allowing us to switch away parts + of the coefficient modulus when it is simply not needed. + */ + Utilities.PrintLine(); + Console.WriteLine("Normalize encryption parameters to the lowest level."); + ParmsId lastParmsId = x3Encrypted.ParmsId; + evaluator.ModSwitchToInplace(x1Encrypted, lastParmsId); + evaluator.ModSwitchToInplace(plainCoeff0, lastParmsId); + + /* + All three ciphertexts are now compatible and can be added. + */ + Utilities.PrintLine(); + Console.WriteLine("Compute PI*x^3 + 0.4*x + 1."); + using Ciphertext encryptedResult = new Ciphertext(); + evaluator.Add(x3Encrypted, x1Encrypted, encryptedResult); + evaluator.AddPlainInplace(encryptedResult, plainCoeff0); + + /* + First print the true result. + */ + using Plaintext plainResult = new Plaintext(); + Utilities.PrintLine(); + Console.WriteLine("Decrypt and decode PI * x ^ 3 + 0.4x + 1."); + Console.WriteLine(" + Expected result:"); + List trueResult = new List(input.Count); + foreach (double x in input) + { + trueResult.Add((3.14159265 * x * x + 0.4) * x + 1); + } + Utilities.PrintVector(trueResult, 3, 7); + + /* + We decrypt, decode, and print the result. + */ + decryptor.Decrypt(encryptedResult, plainResult); + List result = new List(); + encoder.Decode(plainResult, result); + Console.WriteLine(" + Computed result ...... Correct."); + Utilities.PrintVector(result, 3, 7); + + /* + While we did not show any computations on complex numbers in these examples, + the CKKSEncoder would allow us to have done that just as easily. Additions + and multiplications of complex numbers behave just as one would expect. + */ + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs b/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs new file mode 100644 index 0000000000000000000000000000000000000000..a9c04124bf820d8010fa950a44a1f32d7e54b669 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.Research.SEAL; +using System.Collections.Generic; + +namespace SEALNetExamples +{ + partial class Examples + { + /* + Both the BFV scheme (with BatchEncoder) as well as the CKKS scheme support native + vectorized computations on encrypted numbers. In addition to computing slot-wise, + it is possible to rotate the encrypted vectors cyclically. + */ + private static void ExampleRotationBFV() + { + Utilities.PrintExampleBanner("Example: Rotation / Rotation in BFV"); + + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); + + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + using BatchEncoder batchEncoder = new BatchEncoder(context); + ulong slotCount = batchEncoder.SlotCount; + ulong rowSize = slotCount / 2; + Console.WriteLine($"Plaintext matrix row size: {rowSize}"); + + ulong[] podMatrix = new ulong[slotCount]; + podMatrix[0] = 0; + podMatrix[1] = 1; + podMatrix[2] = 2; + podMatrix[3] = 3; + podMatrix[rowSize] = 4; + podMatrix[rowSize + 1] = 5; + podMatrix[rowSize + 2] = 6; + podMatrix[rowSize + 3] = 7; + + Console.WriteLine("Input plaintext matrix:"); + Utilities.PrintMatrix(podMatrix, (int)rowSize); + Console.WriteLine(); + + /* + First we use BatchEncoder to encode the matrix into a plaintext. We encrypt + the plaintext as usual. + */ + Utilities.PrintLine(); + using Plaintext plainMatrix = new Plaintext(); + Console.WriteLine("Encode and encrypt."); + batchEncoder.Encode(podMatrix, plainMatrix); + using Ciphertext encryptedMatrix = new Ciphertext(); + encryptor.Encrypt(plainMatrix, encryptedMatrix); + Console.WriteLine(" + Noise budget in fresh encryption: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + Console.WriteLine(); + + /* + Rotations require yet another type of special key called `Galois keys'. These + are easily obtained from the KeyGenerator. + */ + using GaloisKeys galKeys = keygen.GaloisKeysLocal(); + + /* + Now rotate both matrix rows 3 steps to the left, decrypt, decode, and print. + */ + Utilities.PrintLine(); + Console.WriteLine("Rotate rows 3 steps left."); + evaluator.RotateRowsInplace(encryptedMatrix, 3, galKeys); + using Plaintext plainResult = new Plaintext(); + Console.WriteLine(" + Noise budget after rotation: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + Console.WriteLine(" + Decrypt and decode ...... Correct."); + decryptor.Decrypt(encryptedMatrix, plainResult); + List podResult = new List(); + batchEncoder.Decode(plainResult, podResult); + Utilities.PrintMatrix(podResult, (int)rowSize); + + /* + We can also rotate the columns, i.e., swap the rows. + */ + Utilities.PrintLine(); + Console.WriteLine("Rotate columns."); + evaluator.RotateColumnsInplace(encryptedMatrix, galKeys); + Console.WriteLine(" + Noise budget after rotation: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + Console.WriteLine(" + Decrypt and decode ...... Correct."); + decryptor.Decrypt(encryptedMatrix, plainResult); + batchEncoder.Decode(plainResult, podResult); + Utilities.PrintMatrix(podResult, (int)rowSize); + + /* + Finally, we rotate the rows 4 steps to the right, decrypt, decode, and print. + */ + Utilities.PrintLine(); + Console.WriteLine("Rotate rows 4 steps right."); + evaluator.RotateRowsInplace(encryptedMatrix, -4, galKeys); + Console.WriteLine(" + Noise budget after rotation: {0} bits", + decryptor.InvariantNoiseBudget(encryptedMatrix)); + Console.WriteLine(" + Decrypt and decode ...... Correct."); + decryptor.Decrypt(encryptedMatrix, plainResult); + batchEncoder.Decode(plainResult, podResult); + Utilities.PrintMatrix(podResult, (int)rowSize); + + /* + Note that rotations do not consume any noise budget. However, this is only + the case when the special prime is at least as large as the other primes. The + same holds for relinearization. Microsoft SEAL does not require that the + special prime is of any particular size, so ensuring this is the case is left + for the user to do. + */ + } + + private static void ExampleRotationCKKS() + { + Utilities.PrintExampleBanner("Example: Rotation / Rotation in CKKS"); + + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + + ulong polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.Create( + polyModulusDegree, new int[] { 40, 40, 40, 40, 40 }); + + using SEALContext context = new SEALContext(parms); + Utilities.PrintParameters(context); + Console.WriteLine(); + + using KeyGenerator keygen = new KeyGenerator(context); + using PublicKey publicKey = keygen.PublicKey; + using SecretKey secretKey = keygen.SecretKey; + using RelinKeys relinKeys = keygen.RelinKeysLocal(); + using GaloisKeys galKeys = keygen.GaloisKeysLocal(); + using Encryptor encryptor = new Encryptor(context, publicKey); + using Evaluator evaluator = new Evaluator(context); + using Decryptor decryptor = new Decryptor(context, secretKey); + + using CKKSEncoder ckksEncoder = new CKKSEncoder(context); + + ulong slotCount = ckksEncoder.SlotCount; + Console.WriteLine($"Number of slots: {slotCount}"); + + List input = new List((int)slotCount); + double currPoint = 0, stepSize = 1.0 / (slotCount - 1); + for (ulong i = 0; i < slotCount; i++, currPoint += stepSize) + { + input.Add(currPoint); + } + Console.WriteLine("Input vector:"); + Utilities.PrintVector(input, 3, 7); + + double scale = Math.Pow(2.0, 50); + + Utilities.PrintLine(); + Console.WriteLine("Encode and encrypt."); + using Plaintext plain = new Plaintext(); + ckksEncoder.Encode(input, scale, plain); + using Ciphertext encrypted = new Ciphertext(); + encryptor.Encrypt(plain, encrypted); + + using Ciphertext rotated = new Ciphertext(); + Utilities.PrintLine(); + Console.WriteLine("Rotate 2 steps left."); + evaluator.RotateVector(encrypted, 2, galKeys, rotated); + Console.WriteLine(" + Decrypt and decode ...... Correct."); + decryptor.Decrypt(encrypted, plain); + List result = new List(); + ckksEncoder.Decode(plain, result); + Utilities.PrintVector(result, 3, 7); + + /* + With the CKKS scheme it is also possible to evaluate a complex conjugation on + a vector of encrypted complex numbers, using Evaluator.ComplexConjugate. This + is in fact a kind of rotation, and requires also Galois keys. + */ + } + + private static void ExampleRotation() + { + Utilities.PrintExampleBanner("Example: Rotation"); + + /* + Run all rotation examples. + */ + ExampleRotationBFV(); + ExampleRotationCKKS(); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs b/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs new file mode 100644 index 0000000000000000000000000000000000000000..fe1ec9b7f77a86a99fa95f95f7511004899fd3e4 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs @@ -0,0 +1,423 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Collections.Generic; +using Microsoft.Research.SEAL; + +namespace SEALNetExamples +{ + partial class Examples + { + /* + In this example we show how serialization works in Microsoft SEAL. Specifically, + we present important concepts that enable the user to optimize the data size when + communicating ciphertexts and keys for outsourced computation. Unlike the previous + examples, we organize this one in a client-server style for maximal clarity. The + server selects encryption parameters, the client generates keys, the server does + the encrypted computation, and the client decrypts. + */ + private static void ExampleSerialization() + { + Utilities.PrintExampleBanner("Example: Serialization"); + + /* + We require ZLIB support for this example to be available. + */ + if (!Serialization.IsSupportedComprMode(ComprModeType.Deflate)) + { + Console.WriteLine("ZLIB support is not enabled; this example is not available."); + Console.WriteLine(); + return; + } + + /* + To simulate client-server interaction, we set up a shared C# stream. In real + use-cases this can be a network stream, a filestream, or any shared resource. + + It is critical to note that all data serialized by Microsoft SEAL is in binary + form, so it is not meaningful to print the data as ASCII characters. Encodings + such as Base64 would increase the data size, which is already a bottleneck in + homomorphic encryption. Hence, serialization into text is not supported or + recommended. + + In this example we use a couple of shared MemoryStreams. + */ + MemoryStream parmsStream = new MemoryStream(); + MemoryStream dataStream = new MemoryStream(); + MemoryStream skStream = new MemoryStream(); + + /* + The server first determines the computation and sets encryption parameters + accordingly. + */ + { + ulong polyModulusDegree = 8192; + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.Create( + polyModulusDegree, new int[]{ 50, 20, 50 }); + + /* + Serialization of the encryption parameters to our shared stream is very + simple with the EncryptionParameters.Save function. + */ + long size = parms.Save(parmsStream); + + /* + Seek the parmsStream head back to beginning of the stream. + */ + parmsStream.Seek(0, SeekOrigin.Begin); + + /* + The return value of this function is the actual byte count of data written + to the stream. + */ + Utilities.PrintLine(); + Console.WriteLine($"EncryptionParameters: wrote {size} bytes"); + + /* + Before moving on, we will take some time to discuss further options in + serialization. These will become particularly important when the user + needs to optimize communication and storage sizes. + */ + + /* + It is possible to enable or disable ZLIB ("deflate") compression for + serialization by providing EncryptionParameters.Save with the desired + compression mode as in the following examples: + + long size = parms.Save(sharedStream, ComprModeType.None); + long size = parms.Save(sharedStream, ComprModeType.Deflate); + + If Microsoft SEAL is compiled with ZLIB support, the default is to use + ComprModeType.Deflate, so to instead disable compression one would use + the first version of the two. + */ + + /* + In many cases, when working with fixed size memory, it is necessary + to know ahead of time an upper bound on the serialized data size to + allocate enough memory. This information is returned by the + EncryptionParameters.SaveSize function. This function accepts the + desired compression mode, with ComprModeType.Deflate being the default + when Microsoft SEAL is compiled with ZLIB support. + + In more detail, the output of EncryptionParameters.SaveSize is as follows: + + - Exact buffer size required for ComprModeType.None; + - Upper bound on the size required for ComprModeType.Deflate. + + As we can see from the print-out, the sizes returned by these functions + are significantly larger than the compressed size written into the shared + stream in the beginning. This is normal: compression yielded a significant + improvement in the data size, yet it is hard to estimate the size of the + compressed data. + */ + Utilities.PrintLine(); + Console.Write("EncryptionParameters: data size upper bound (ComprModeType.None): "); + Console.WriteLine(parms.SaveSize(ComprModeType.None)); + Console.Write(" "); + Console.Write("EncryptionParameters: data size upper bound (ComprModeType.Deflate): "); + Console.WriteLine(parms.SaveSize(ComprModeType.Deflate)); + + /* + As an example, we now serialize the encryption parameters to a fixed + size buffer. + */ + MemoryStream buffer = new MemoryStream(new byte[parms.SaveSize()]); + parms.Save(buffer); + + /* + To illustrate deserialization, we load back the encryption parameters + from our buffer into another instance of EncryptionParameters. First + we need to seek our stream back to the beginning. + */ + buffer.Seek(0, SeekOrigin.Begin); + using EncryptionParameters parms2 = new EncryptionParameters(); + parms2.Load(buffer); + + /* + We can check that the saved and loaded encryption parameters indeed match. + */ + Utilities.PrintLine(); + Console.WriteLine($"EncryptionParameters: parms == parms2: {parms.Equals(parms2)}"); + } + + /* + Client starts by loading the encryption parameters, sets up the SEALContext, + and creates the required keys. + */ + { + using EncryptionParameters parms = new EncryptionParameters(); + parms.Load(parmsStream); + + /* + Seek the parmsStream head back to beginning of the stream because we + will use the same stream to read the parameters repeatedly. + */ + parmsStream.Seek(0, SeekOrigin.Begin); + + using SEALContext context = new SEALContext(parms); + + using KeyGenerator keygen = new KeyGenerator(context); + using SecretKey sk = keygen.SecretKey; + using PublicKey pk = keygen.PublicKey; + + /* + We need to save the secret key so we can decrypt later. + */ + sk.Save(skStream); + skStream.Seek(0, SeekOrigin.Begin); + + /* + In this example we will also use relinearization keys. For realinearization + and Galois keys the KeyGenerator.RelinKeys and KeyGenerator.GaloisKeys + functions return special Serializable objects. These objects are meant + to be serialized and never used locally. On the other hand, for local use + of RelinKeys and GaloisKeys, the functions KeyGenerator.RelinKeysLocal + and KeyGenerator.GaloisKeysLocal can be used to create the RelinKeys + and GaloisKeys objects directly. The difference is that the Serializable + objects contain a partly seeded version of the RelinKeys (or GaloisKeys) + that will result in a significantly smaller size when serialized. Using + this method has no impact on security. Such seeded RelinKeys (GaloisKeys) + must be expanded before being used in computations; this is automatically + done by deserialization. + */ + using Serializable rlk = keygen.RelinKeys(); + + /* + Before continuing, we demonstrate the significant space saving from this + method. + */ + long sizeRlk = rlk.Save(dataStream); + + using RelinKeys rlkLocal = keygen.RelinKeysLocal(); + long sizeRlkLocal = rlkLocal.Save(dataStream); + + /* + Now compare the serialized sizes of rlk and rlkLocal. + */ + Utilities.PrintLine(); + Console.WriteLine($"Serializable: wrote {sizeRlk} bytes"); + Console.Write(" "); + Console.WriteLine($"RelinKeys (local): wrote {sizeRlkLocal} bytes"); + + /* + Seek back in dataStream to where rlk data ended, i.e., sizeRlkLocal + bytes backwards from current position. + */ + dataStream.Seek(-sizeRlkLocal, SeekOrigin.Current); + + /* + Next set up the CKKSEncoder and Encryptor, and encrypt some numbers. + */ + double scale = Math.Pow(2.0, 20); + CKKSEncoder encoder = new CKKSEncoder(context); + using Plaintext plain1 = new Plaintext(), + plain2 = new Plaintext(); + encoder.Encode(2.3, scale, plain1); + encoder.Encode(4.5, scale, plain2); + + using Encryptor encryptor = new Encryptor(context, pk); + using Ciphertext encrypted1 = new Ciphertext(), + encrypted2 = new Ciphertext(); + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + + /* + Now, we could serialize both encrypted1 and encrypted2 to dataStream + using Ciphertext.Save. However, for this example, we demonstrate another + size-saving trick that can come in handy. + + As you noticed, we set up the Encryptor using the public key. Clearly this + indicates that the CKKS scheme is a public-key encryption scheme. However, + both BFV and CKKS can operate also in a symmetric-key mode. This can be + beneficial when the public-key functionality is not exactly needed, like + in simple outsourced computation scenarios. The benefit is that in these + cases it is possible to produce ciphertexts that are partly seeded, hence + significantly smaller. Such ciphertexts must be expanded before being used + in computations; this is automatically done by deserialization. + + To use symmetric-key encryption, we need to set up the Encryptor with the + secret key instead. + */ + using Encryptor symEncryptor = new Encryptor(context, sk); + using Serializable symEncrypted1 = symEncryptor.EncryptSymmetric(plain1); + using Serializable symEncrypted2 = symEncryptor.EncryptSymmetric(plain2); + + /* + Before continuing, we demonstrate the significant space saving from this + method. + */ + long sizeSymEncrypted1 = symEncrypted1.Save(dataStream); + long sizeEncrypted1 = encrypted1.Save(dataStream); + + /* + Now compare the serialized sizes of encrypted1 and symEncrypted1. + */ + Utilities.PrintLine(); + Console.Write("Serializable (symmetric-key): "); + Console.WriteLine($"wrote {sizeSymEncrypted1} bytes"); + Console.Write(" "); + Console.WriteLine($"Ciphertext (public-key): wrote {sizeEncrypted1} bytes"); + + /* + Seek back in dataStream to where symEncrypted1 data ended, i.e., + sizeEncrypted1 bytes backwards from current position and write + symEncrypted2 right after symEncrypted1. + */ + dataStream.Seek(-sizeEncrypted1, SeekOrigin.Current); + symEncrypted2.Save(dataStream); + dataStream.Seek(0, SeekOrigin.Begin); + + /* + We have seen how using KeyGenerator.RelinKeys (KeyGenerator.GaloisKeys) + can result in huge space savings over the local variants when the objects + are not needed for local use. We have seen how symmetric-key encryption + can be used to achieve much smaller ciphertext sizes when the public-key + functionality is not needed. + + We would also like to draw attention to the fact there we could easily + serialize multiple Microsoft SEAL objects sequentially in a stream. Each + object writes its own size into the stream, so deserialization knows + exactly how many bytes to read. We will see this working next. + + Finally, we would like to point out that none of these methods provide any + space savings unless Microsoft SEAL is compiled with ZLIB support, or when + serialized with ComprModeType.None. + */ + } + + /* + The server can now compute on the encrypted data. We will recreate the + SEALContext and set up an Evaluator here. + */ + { + using EncryptionParameters parms = new EncryptionParameters(); + parms.Load(parmsStream); + parmsStream.Seek(0, SeekOrigin.Begin); + using SEALContext context = new SEALContext(parms); + + using Evaluator evaluator = new Evaluator(context); + + /* + Next we need to load relinearization keys and the ciphertexts from our + dataStream. + */ + using RelinKeys rlk = new RelinKeys(); + using Ciphertext encrypted1 = new Ciphertext(), + encrypted2 = new Ciphertext(); + + /* + Deserialization is as easy as serialization. + */ + rlk.Load(context, dataStream); + encrypted1.Load(context, dataStream); + encrypted2.Load(context, dataStream); + + /* + Compute the product, rescale, and relinearize. + */ + using Ciphertext encryptedProd = new Ciphertext(); + evaluator.Multiply(encrypted1, encrypted2, encryptedProd); + evaluator.RelinearizeInplace(encryptedProd, rlk); + evaluator.RescaleToNextInplace(encryptedProd); + + /* + We use dataStream to communicate encryptedProd back to the client. There + is no way to save the encryptedProd as Serializable even + though it is still a symmetric-key encryption: only freshly encrypted + ciphertexts can be seeded. Note how the size of the result ciphertext is + smaller than the size of a fresh ciphertext because it is at a lower level + due to the rescale operation. + */ + dataStream.Seek(0, SeekOrigin.Begin); + long sizeEncryptedProd = encryptedProd.Save(dataStream); + dataStream.Seek(0, SeekOrigin.Begin); + + Utilities.PrintLine(); + Console.Write($"Ciphertext (symmetric-key): "); + Console.WriteLine($"wrote {sizeEncryptedProd} bytes"); + } + + /* + In the final step the client decrypts the result. + */ + { + using EncryptionParameters parms = new EncryptionParameters(); + parms.Load(parmsStream); + parmsStream.Seek(0, SeekOrigin.Begin); + using SEALContext context = new SEALContext(parms); + + /* + Load back the secret key from skStream. + */ + using SecretKey sk = new SecretKey(); + sk.Load(context, skStream); + using Decryptor decryptor = new Decryptor(context, sk); + using CKKSEncoder encoder = new CKKSEncoder(context); + + using Ciphertext encryptedResult = new Ciphertext(); + encryptedResult.Load(context, dataStream); + + using Plaintext plainResult = new Plaintext(); + decryptor.Decrypt(encryptedResult, plainResult); + List result = new List(); + encoder.Decode(plainResult, result); + + Utilities.PrintLine(); + Console.WriteLine("Result: "); + Utilities.PrintVector(result, 3, 7); + } + + /* + Finally, we give a little bit more explanation of the structure of data + serialized by Microsoft SEAL. Serialized data always starts with a 16-byte + SEALHeader struct, as defined in dotnet/src/Serialization.cs, and is + followed by the possibly compressed data for the object. + + A SEALHeader contains the following data: + + [offset 0] 2-byte magic number 0xA15E (Serialization.SEALMagic) + [offset 2] 1-byte indicating the header size in bytes (always 16) + [offset 3] 1-byte indicating the Microsoft SEAL major version number + [offset 4] 1-byte indicating the Microsoft SEAL minor version number + [offset 5] 1-byte indicating the compression mode type + [offset 6] 2-byte reserved field (unused) + [offset 8] 8-byte size in bytes of the serialized data, including the header + + Currently Microsoft SEAL supports only little-endian systems. + + As an example, we demonstrate the SEALHeader created by saving a plaintext. + Note that the SEALHeader is never compressed, so there is no need to specify + the compression mode. + */ + using Plaintext pt = new Plaintext("1x^2 + 3"); + MemoryStream stream = new MemoryStream(); + long dataSize = pt.Save(stream); + + /* + Seek the stream head back to beginning of the stream. + */ + stream.Seek(0, SeekOrigin.Begin); + + /* + We can now load just the SEALHeader back from the stream as follows. + */ + Serialization.SEALHeader header = new Serialization.SEALHeader(); + Serialization.LoadHeader(stream, header); + + /* + Now confirm that the size of data written to stream matches with what is + indicated by the SEALHeader. + */ + Utilities.PrintLine(); + Console.WriteLine($"Size written to stream: {dataSize} bytes"); + Console.Write(" "); + Console.WriteLine($"Size indicated in SEALHeader: {header.Size} bytes"); + Console.WriteLine(); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/7_Performance.cs b/bigpiseal3.5.1/dotnet/examples/7_Performance.cs new file mode 100644 index 0000000000000000000000000000000000000000..7bc10d9a711a1cdd155825606a04ea3d56c2d01a --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/7_Performance.cs @@ -0,0 +1,785 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.Research.SEAL; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace SEALNetExamples +{ + partial class Examples + { + private static void BFVPerformanceTest(SEALContext context) + { + Stopwatch timer; + Utilities.PrintParameters(context); + Console.WriteLine(); + + using EncryptionParameters parms = context.FirstContextData.Parms; + using Modulus plainModulus = parms.PlainModulus; + ulong polyModulusDegree = parms.PolyModulusDegree; + + Console.Write("Generating secret/public keys: "); + using KeyGenerator keygen = new KeyGenerator(context); + Console.WriteLine("Done"); + + using SecretKey secretKey = keygen.SecretKey; + using PublicKey publicKey = keygen.PublicKey; + + Func GetRelinKeys = () => { + if (context.UsingKeyswitching) + { + /* + Generate relinearization keys. + */ + Console.Write("Generating relinearization keys: "); + timer = Stopwatch.StartNew(); + RelinKeys result = keygen.RelinKeysLocal(); + int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); + Console.WriteLine($"Done [{micros} microseconds]"); + return result; + } + else + { + return null; + } + }; + + Func GetGaloisKeys = () => { + if (context.UsingKeyswitching) + { + if (!context.KeyContextData.Qualifiers.UsingBatching) + { + Console.WriteLine("Given encryption parameters do not support batching."); + return null; + } + + /* + Generate Galois keys. In larger examples the Galois keys can use a lot of + memory, which can be a problem in constrained systems. The user should + try some of the larger runs of the test and observe their effect on the + memory pool allocation size. The key generation can also take a long time, + as can be observed from the print-out. + */ + Console.Write($"Generating Galois keys: "); + timer = Stopwatch.StartNew(); + GaloisKeys result = keygen.GaloisKeysLocal(); + int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); + Console.WriteLine($"Done [{micros} microseconds]"); + return result; + } + else + { + return null; + } + }; + + using RelinKeys relinKeys = GetRelinKeys(); + using GaloisKeys galKeys = GetGaloisKeys(); + + using Encryptor encryptor = new Encryptor(context, publicKey); + using Decryptor decryptor = new Decryptor(context, secretKey); + using Evaluator evaluator = new Evaluator(context); + using BatchEncoder batchEncoder = new BatchEncoder(context); + using IntegerEncoder encoder = new IntegerEncoder(context); + + /* + These will hold the total times used by each operation. + */ + Stopwatch timeBatchSum = new Stopwatch(); + Stopwatch timeUnbatchSum = new Stopwatch(); + Stopwatch timeEncryptSum = new Stopwatch(); + Stopwatch timeDecryptSum = new Stopwatch(); + Stopwatch timeAddSum = new Stopwatch(); + Stopwatch timeMultiplySum = new Stopwatch(); + Stopwatch timeMultiplyPlainSum = new Stopwatch(); + Stopwatch timeSquareSum = new Stopwatch(); + Stopwatch timeRelinearizeSum = new Stopwatch(); + Stopwatch timeRotateRowsOneStepSum = new Stopwatch(); + Stopwatch timeRotateRowsRandomSum = new Stopwatch(); + Stopwatch timeRotateColumnsSum = new Stopwatch(); + + /* + How many times to run the test? + */ + int count = 10; + + /* + Populate a vector of values to batch. + */ + ulong slotCount = batchEncoder.SlotCount; + ulong[] podValues = new ulong[slotCount]; + Random rnd = new Random(); + for (ulong i = 0; i < batchEncoder.SlotCount; i++) + { + podValues[i] = (ulong)rnd.Next() % plainModulus.Value; + } + + Console.Write("Running tests "); + for (int i = 0; i < count; i++) + { + /* + [Batching] + There is nothing unusual here. We batch our random plaintext matrix + into the polynomial. Note how the plaintext we create is of the exactly + right size so unnecessary reallocations are avoided. + */ + using Plaintext plain = new Plaintext(parms.PolyModulusDegree, 0); + timeBatchSum.Start(); + batchEncoder.Encode(podValues, plain); + timeBatchSum.Stop(); + + /* + [Unbatching] + We unbatch what we just batched. + */ + List podList = new List((int)slotCount); + timeUnbatchSum.Start(); + batchEncoder.Decode(plain, podList); + timeUnbatchSum.Stop(); + if (!podList.SequenceEqual(podValues)) + { + throw new InvalidOperationException("Batch/unbatch failed. Something is wrong."); + } + + /* + [Encryption] + We make sure our ciphertext is already allocated and large enough + to hold the encryption with these encryption parameters. We encrypt + our random batched matrix here. + */ + using Ciphertext encrypted = new Ciphertext(context); + timeEncryptSum.Start(); + encryptor.Encrypt(plain, encrypted); + timeEncryptSum.Stop(); + + /* + [Decryption] + We decrypt what we just encrypted. + */ + using Plaintext plain2 = new Plaintext(polyModulusDegree, 0); + timeDecryptSum.Start(); + decryptor.Decrypt(encrypted, plain2); + timeDecryptSum.Stop(); + if (!plain2.Equals(plain)) + { + throw new InvalidOperationException("Encrypt/decrypt failed. Something is wrong."); + } + + /* + [Add] + We create two ciphertexts and perform a few additions with them. + */ + using Ciphertext encrypted1 = new Ciphertext(context); + encryptor.Encrypt(encoder.Encode(i), encrypted1); + using Ciphertext encrypted2 = new Ciphertext(context); + encryptor.Encrypt(encoder.Encode(i + 1), encrypted2); + + timeAddSum.Start(); + evaluator.AddInplace(encrypted1, encrypted1); + evaluator.AddInplace(encrypted2, encrypted2); + evaluator.AddInplace(encrypted1, encrypted2); + timeAddSum.Stop(); + + /* + [Multiply] + We multiply two ciphertexts. Since the size of the result will be 3, + and will overwrite the first argument, we reserve first enough memory + to avoid reallocating during multiplication. + */ + encrypted1.Reserve(3); + timeMultiplySum.Start(); + evaluator.MultiplyInplace(encrypted1, encrypted2); + timeMultiplySum.Stop(); + + /* + [Multiply Plain] + We multiply a ciphertext with a random plaintext. Recall that + MultiplyPlain does not change the size of the ciphertext so we use + encrypted2 here. + */ + timeMultiplyPlainSum.Start(); + evaluator.MultiplyPlainInplace(encrypted2, plain); + timeMultiplyPlainSum.Stop(); + + /* + [Square] + We continue to use encrypted2. Now we square it; this should be + faster than generic homomorphic multiplication. + */ + timeSquareSum.Start(); + evaluator.SquareInplace(encrypted2); + timeSquareSum.Stop(); + + if (context.UsingKeyswitching) + { + /* + [Relinearize] + Time to get back to encrypted1. We now relinearize it back + to size 2. Since the allocation is currently big enough to + contain a ciphertext of size 3, no costly reallocations are + needed in the process. + */ + timeRelinearizeSum.Start(); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + timeRelinearizeSum.Stop(); + + /* + [Rotate Rows One Step] + We rotate matrix rows by one step left and measure the time. + */ + timeRotateRowsOneStepSum.Start(); + evaluator.RotateRowsInplace(encrypted, 1, galKeys); + evaluator.RotateRowsInplace(encrypted, -1, galKeys); + timeRotateRowsOneStepSum.Stop(); + + /* + [Rotate Rows Random] + We rotate matrix rows by a random number of steps. This is much more + expensive than rotating by just one step. + */ + int rowSize = (int)batchEncoder.SlotCount / 2; + int randomRotation = rnd.Next() % rowSize; + timeRotateRowsRandomSum.Start(); + evaluator.RotateRowsInplace(encrypted, randomRotation, galKeys); + timeRotateRowsRandomSum.Stop(); + + /* + [Rotate Columns] + Nothing surprising here. + */ + timeRotateColumnsSum.Start(); + evaluator.RotateColumnsInplace(encrypted, galKeys); + timeRotateColumnsSum.Stop(); + } + + + /* + Print a dot to indicate progress. + */ + Console.Write("."); + Console.Out.Flush(); + } + + Console.WriteLine(" Done"); + Console.WriteLine(); + Console.Out.Flush(); + + int avgBatch = (int)(timeBatchSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgUnbatch = (int)(timeUnbatchSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgEncrypt = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgDecrypt = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgAdd = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count)); + int avgMultiply = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count); + int avgMultiplyPlain = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgSquare = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRelinearize = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRotateRowsOneStep = (int)(timeRotateRowsOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count)); + int avgRotateRowsRandom = (int)(timeRotateRowsRandomSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRotateColumns = (int)(timeRotateColumnsSum.Elapsed.TotalMilliseconds * 1000 / count); + + Console.WriteLine($"Average batch: {avgBatch} microseconds"); + Console.WriteLine($"Average unbatch: {avgUnbatch} microseconds"); + Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds"); + Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds"); + Console.WriteLine($"Average add: {avgAdd} microseconds"); + Console.WriteLine($"Average multiply: {avgMultiply} microseconds"); + Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds"); + Console.WriteLine($"Average square: {avgSquare} microseconds"); + if (context.UsingKeyswitching) + { + Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds"); + Console.WriteLine($"Average rotate rows one step: {avgRotateRowsOneStep} microseconds"); + Console.WriteLine($"Average rotate rows random: {avgRotateRowsRandom} microseconds"); + Console.WriteLine($"Average rotate columns: {avgRotateColumns} microseconds"); + } + Console.Out.Flush(); + } + + private static void CKKSPerformanceTest(SEALContext context) + { + Stopwatch timer; + Utilities.PrintParameters(context); + Console.WriteLine(); + + using EncryptionParameters parms = context.FirstContextData.Parms; + ulong polyModulusDegree = parms.PolyModulusDegree; + + Console.Write("Generating secret/public keys: "); + using KeyGenerator keygen = new KeyGenerator(context); + Console.WriteLine("Done"); + + using SecretKey secretKey = keygen.SecretKey; + using PublicKey publicKey = keygen.PublicKey; + + Func GetRelinKeys = () => { + if (context.UsingKeyswitching) + { + /* + Generate relinearization keys. + */ + Console.Write("Generating relinearization keys: "); + timer = Stopwatch.StartNew(); + RelinKeys result = keygen.RelinKeysLocal(); + int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); + Console.WriteLine($"Done [{micros} microseconds]"); + return result; + } + else + { + return null; + } + }; + + Func GetGaloisKeys = () => { + if (context.UsingKeyswitching) + { + if (!context.KeyContextData.Qualifiers.UsingBatching) + { + Console.WriteLine("Given encryption parameters do not support batching."); + return null; + } + + /* + Generate Galois keys. In larger examples the Galois keys can use a lot of + memory, which can be a problem in constrained systems. The user should + try some of the larger runs of the test and observe their effect on the + memory pool allocation size. The key generation can also take a long time, + as can be observed from the print-out. + */ + Console.Write($"Generating Galois keys: "); + timer = Stopwatch.StartNew(); + GaloisKeys result = keygen.GaloisKeysLocal(); + int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); + Console.WriteLine($"Done [{micros} microseconds]"); + return result; + } + else + { + return null; + } + }; + + using RelinKeys relinKeys = GetRelinKeys(); + using GaloisKeys galKeys = GetGaloisKeys(); + + using Encryptor encryptor = new Encryptor(context, publicKey); + using Decryptor decryptor = new Decryptor(context, secretKey); + using Evaluator evaluator = new Evaluator(context); + using CKKSEncoder ckksEncoder = new CKKSEncoder(context); + + Stopwatch timeEncodeSum = new Stopwatch(); + Stopwatch timeDecodeSum = new Stopwatch(); + Stopwatch timeEncryptSum = new Stopwatch(); + Stopwatch timeDecryptSum = new Stopwatch(); + Stopwatch timeAddSum = new Stopwatch(); + Stopwatch timeMultiplySum = new Stopwatch(); + Stopwatch timeMultiplyPlainSum = new Stopwatch(); + Stopwatch timeSquareSum = new Stopwatch(); + Stopwatch timeRelinearizeSum = new Stopwatch(); + Stopwatch timeRescaleSum = new Stopwatch(); + Stopwatch timeRotateOneStepSum = new Stopwatch(); + Stopwatch timeRotateRandomSum = new Stopwatch(); + Stopwatch timeConjugateSum = new Stopwatch(); + + Random rnd = new Random(); + + /* + How many times to run the test? + */ + int count = 10; + + /* + Populate a vector of floating-point values to batch. + */ + ulong slotCount = ckksEncoder.SlotCount; + double[] podValues = new double[slotCount]; + for (ulong i = 0; i < slotCount; i++) + { + podValues[i] = 1.001 * i; + } + + Console.Write("Running tests "); + for (int i = 0; i < count; i++) + { + /* + [Encoding] + For scale we use the square root of the last CoeffModulus prime + from parms. + */ + double scale = Math.Sqrt(parms.CoeffModulus.Last().Value); + using Plaintext plain = new Plaintext(parms.PolyModulusDegree * + (ulong)parms.CoeffModulus.Count(), 0); + timeEncodeSum.Start(); + ckksEncoder.Encode(podValues, scale, plain); + timeEncodeSum.Stop(); + + /* + [Decoding] + */ + List podList = new List((int)slotCount); + timeDecodeSum.Start(); + ckksEncoder.Decode(plain, podList); + timeDecodeSum.Stop(); + + /* + [Encryption] + */ + using Ciphertext encrypted = new Ciphertext(context); + timeEncryptSum.Start(); + encryptor.Encrypt(plain, encrypted); + timeEncryptSum.Stop(); + + /* + [Decryption] + */ + using Plaintext plain2 = new Plaintext(polyModulusDegree, 0); + timeDecryptSum.Start(); + decryptor.Decrypt(encrypted, plain2); + timeDecryptSum.Stop(); + + /* + [Add] + */ + using Ciphertext encrypted1 = new Ciphertext(context); + ckksEncoder.Encode(i + 1, plain); + encryptor.Encrypt(plain, encrypted1); + using Ciphertext encrypted2 = new Ciphertext(context); + ckksEncoder.Encode(i + 1, plain2); + encryptor.Encrypt(plain2, encrypted2); + timeAddSum.Start(); + evaluator.AddInplace(encrypted1, encrypted2); + evaluator.AddInplace(encrypted2, encrypted2); + evaluator.AddInplace(encrypted1, encrypted2); + timeAddSum.Stop(); + + /* + [Multiply] + */ + encrypted1.Reserve(3); + timeMultiplySum.Start(); + evaluator.MultiplyInplace(encrypted1, encrypted2); + timeMultiplySum.Stop(); + + /* + [Multiply Plain] + */ + timeMultiplyPlainSum.Start(); + evaluator.MultiplyPlainInplace(encrypted2, plain); + timeMultiplyPlainSum.Stop(); + + /* + [Square] + */ + timeSquareSum.Start(); + evaluator.SquareInplace(encrypted2); + timeSquareSum.Stop(); + + if (context.UsingKeyswitching) + { + /* + [Relinearize] + */ + timeRelinearizeSum.Start(); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + timeRelinearizeSum.Stop(); + + /* + [Rescale] + */ + timeRescaleSum.Start(); + evaluator.RescaleToNextInplace(encrypted1); + timeRescaleSum.Stop(); + + /* + [Rotate Vector] + */ + timeRotateOneStepSum.Start(); + evaluator.RotateVectorInplace(encrypted, 1, galKeys); + evaluator.RotateVectorInplace(encrypted, -1, galKeys); + timeRotateOneStepSum.Stop(); + + /* + [Rotate Vector Random] + */ + int randomRotation = rnd.Next() % (int)ckksEncoder.SlotCount; + timeRotateRandomSum.Start(); + evaluator.RotateVectorInplace(encrypted, randomRotation, galKeys); + timeRotateRandomSum.Stop(); + + /* + [Complex Conjugate] + */ + timeConjugateSum.Start(); + evaluator.ComplexConjugateInplace(encrypted, galKeys); + timeConjugateSum.Stop(); + } + + /* + Print a dot to indicate progress. + */ + Console.Write("."); + Console.Out.Flush(); + } + + Console.WriteLine(" Done"); + Console.WriteLine(); + Console.Out.Flush(); + + int avgEncode = (int)(timeEncodeSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgDecode = (int)(timeDecodeSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgEncrypt = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgDecrypt = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgAdd = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count)); + int avgMultiply = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count); + int avgMultiplyPlain = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgSquare = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRelinearize = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRescale = (int)(timeRescaleSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgRotateOneStep = (int)(timeRotateOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count)); + int avgRotateRandom = (int)(timeRotateRandomSum.Elapsed.TotalMilliseconds * 1000 / count); + int avgConjugate = (int)(timeConjugateSum.Elapsed.TotalMilliseconds * 1000 / count); + + Console.WriteLine($"Average encode: {avgEncode} microseconds"); + Console.WriteLine($"Average decode: {avgDecode} microseconds"); + Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds"); + Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds"); + Console.WriteLine($"Average add: {avgAdd} microseconds"); + Console.WriteLine($"Average multiply: {avgMultiply} microseconds"); + Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds"); + Console.WriteLine($"Average square: {avgSquare} microseconds"); + if (context.UsingKeyswitching) + { + Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds"); + Console.WriteLine($"Average rescale: {avgRescale} microseconds"); + Console.WriteLine($"Average rotate vector one step: {avgRotateOneStep} microseconds"); + Console.WriteLine($"Average rotate vector random: {avgRotateRandom} microseconds"); + Console.WriteLine($"Average complex conjugate: {avgConjugate} microseconds"); + } + Console.Out.Flush(); + } + + private static void ExampleBFVPerformanceDefault() + { + Utilities.PrintExampleBanner("BFV Performance Test with Degrees: 4096, 8192, and 16384"); + + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + ulong polyModulusDegree = 4096; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + parms.PlainModulus = new Modulus(786433); + using (SEALContext context = new SEALContext(parms)) + { + BFVPerformanceTest(context); + } + + Console.WriteLine(); + polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + parms.PlainModulus = new Modulus(786433); + using (SEALContext context = new SEALContext(parms)) + { + BFVPerformanceTest(context); + } + + Console.WriteLine(); + polyModulusDegree = 16384; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + parms.PlainModulus = new Modulus(786433); + using (SEALContext context = new SEALContext(parms)) + { + BFVPerformanceTest(context); + } + + /* + Comment out the following to run the biggest example. + */ + //Console.WriteLine(); + //polyModulusDegree = 32768; + //parms.PolyModulusDegree = polyModulusDegree; + //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + //parms.PlainModulus = new Modulus(786433); + //using (SEALContext context = new SEALContext(parms)) + //{ + // BFVPerformanceTest(context); + //} + } + + private static void ExampleBFVPerformanceCustom() + { + Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): "); + string input = Console.ReadLine(); + if (!ulong.TryParse(input, out ulong polyModulusDegree)) + { + Console.WriteLine("Invalid option."); + return; + } + if (polyModulusDegree < 1024 || polyModulusDegree > 32768 || + (polyModulusDegree & (polyModulusDegree - 1)) != 0) + { + Console.WriteLine("Invalid option."); + return; + } + + string banner = $"BFV Performance Test with Degree: {polyModulusDegree}"; + Utilities.PrintExampleBanner(banner); + + using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = polyModulusDegree, + CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree) + }; + if (polyModulusDegree == 1024) + { + parms.PlainModulus = new Modulus(12289); + } + else + { + parms.PlainModulus = new Modulus(786433); + } + + using (SEALContext context = new SEALContext(parms)) + { + BFVPerformanceTest(context); + } + } + + private static void ExampleCKKSPerformanceDefault() + { + Utilities.PrintExampleBanner("CKKS Performance Test with Degrees: 4096, 8192, and 16384"); + + // It is not recommended to use BFVDefault primes in CKKS. However, for performance + // test, BFVDefault primes are good enough. + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + ulong polyModulusDegree = 4096; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + using (SEALContext context = new SEALContext(parms)) + { + CKKSPerformanceTest(context); + } + + Console.WriteLine(); + polyModulusDegree = 8192; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + using (SEALContext context = new SEALContext(parms)) + { + CKKSPerformanceTest(context); + } + + Console.WriteLine(); + polyModulusDegree = 16384; + parms.PolyModulusDegree = polyModulusDegree; + parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + using (SEALContext context = new SEALContext(parms)) + { + CKKSPerformanceTest(context); + } + + /* + Comment out the following to run the biggest example. + */ + //Console.WriteLine(); + //polyModulusDegree = 32768; + //parms.PolyModulusDegree = polyModulusDegree; + //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); + //using (SEALContext context = new SEALContext(parms)) + //{ + // CKKSPerformanceTest(context); + //} + } + + private static void ExampleCKKSPerformanceCustom() + { + Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): "); + string input = Console.ReadLine(); + if (!ulong.TryParse(input, out ulong polyModulusDegree)) + { + Console.WriteLine("Invalid option."); + return; + } + if (polyModulusDegree < 1024 || polyModulusDegree > 32768 || + (polyModulusDegree & (polyModulusDegree - 1)) != 0) + { + Console.WriteLine("Invalid option."); + return; + } + + string banner = $"CKKS Performance Test with Degree: {polyModulusDegree}"; + Utilities.PrintExampleBanner(banner); + + using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = polyModulusDegree, + CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree) + }; + + using (SEALContext context = new SEALContext(parms)) + { + CKKSPerformanceTest(context); + } + } + + private static void ExamplePerformanceTest() + { + Utilities.PrintExampleBanner("Example: Performance Test"); + + if (!Stopwatch.IsHighResolution) + { + Console.WriteLine("WARNING: High resolution stopwatch not available in this machine."); + Console.WriteLine(" Timings might not be accurate."); + } + + while (true) + { + Console.WriteLine(); + Console.WriteLine("Select a scheme (and optionally PolyModulusDegree):"); + Console.WriteLine(" 1. BFV with default degrees"); + Console.WriteLine(" 2. BFV with a custom degree"); + Console.WriteLine(" 3. CKKS with default degrees"); + Console.WriteLine(" 4. CKKS with a custom degree"); + Console.WriteLine(" 0. Back to main menu"); + Console.WriteLine(); + + ConsoleKeyInfo key; + do + { + Console.Write("> Run performance test (1 ~ 4) or go back (0): "); + key = Console.ReadKey(); + Console.WriteLine(); + } while (key.KeyChar < '0' || key.KeyChar > '4'); + switch (key.Key) + { + case ConsoleKey.D1: + ExampleBFVPerformanceDefault(); + break; + + case ConsoleKey.D2: + ExampleBFVPerformanceCustom(); + break; + + case ConsoleKey.D3: + ExampleCKKSPerformanceDefault(); + break; + + case ConsoleKey.D4: + ExampleCKKSPerformanceCustom(); + break; + + case ConsoleKey.D0: + Console.WriteLine(); + return; + + default: + Console.WriteLine(" [Beep~~] Invalid option: type 0 ~ 4"); + break; + } + } + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/Examples.cs b/bigpiseal3.5.1/dotnet/examples/Examples.cs new file mode 100644 index 0000000000000000000000000000000000000000..f3690c3bac9375c1c9b39557d0baae3b202ec405 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/Examples.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using System; + +namespace SEALNetExamples +{ + partial class Examples + { + static void Main(string[] args) + { + Console.WriteLine("Microsoft SEAL version: " + SEALVersion.Version); + while (true) + { + Console.WriteLine("+---------------------------------------------------------+"); + Console.WriteLine("| The following examples should be executed while reading |"); + Console.WriteLine("| comments in associated files in dotnet/examples/. |"); + Console.WriteLine("+---------------------------------------------------------+"); + Console.WriteLine("| Examples | Source Files |"); + Console.WriteLine("+----------------------------+----------------------------+"); + Console.WriteLine("| 1. BFV Basics | 1_BFV_Basics.cs |"); + Console.WriteLine("| 2. Encoders | 2_Encoders.cs |"); + Console.WriteLine("| 3. Levels | 3_Levels.cs |"); + Console.WriteLine("| 4. CKKS Basics | 4_CKKS_Basics.cs |"); + Console.WriteLine("| 5. Rotation | 5_Rotation.cs |"); + Console.WriteLine("| 6. Serialization | 6_Serialization.cs |"); + Console.WriteLine("| 7. Performance Test | 7_Performance.cs |"); + Console.WriteLine("+----------------------------+----------------------------+"); + + /* + Print how much memory we have allocated from the current memory pool. + By default the memory pool will be a static global pool and the + MemoryManager class can be used to change it. Most users should have + little or no reason to touch the memory allocation system. + */ + ulong megabytes = MemoryManager.GetPool().AllocByteCount >> 20; + Console.WriteLine("[{0,7} MB] Total allocation from the memory pool", megabytes); + + ConsoleKeyInfo key; + do + { + Console.WriteLine(); + Console.Write("> Run example (1 ~ 7) or exit (0): "); + key = Console.ReadKey(); + Console.WriteLine(); + } while (key.KeyChar < '0' || key.KeyChar > '7'); + switch (key.Key) + { + case ConsoleKey.D1: + ExampleBFVBasics(); + break; + + case ConsoleKey.D2: + ExampleEncoders(); + break; + + case ConsoleKey.D3: + ExampleLevels(); + break; + + case ConsoleKey.D4: + ExampleCKKSBasics(); + break; + + case ConsoleKey.D5: + ExampleRotation(); + break; + + case ConsoleKey.D6: + ExampleSerialization(); + break; + + case ConsoleKey.D7: + ExamplePerformanceTest(); + break; + + case ConsoleKey.D0: + return; + + default: + Console.WriteLine(" [Beep~~] Invalid option: type 0 ~ 7"); + break; + } + + /* + We may want to force a garbage collection after each example to accurately show memory pool use. + */ + GC.Collect(); + } + } + } +} diff --git a/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj b/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj new file mode 100644 index 0000000000000000000000000000000000000000..73063c88fba67f34677b79a4830edf998e0f6e96 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj @@ -0,0 +1,31 @@ + + + + Exe + netcoreapp3.1 + Microsoft Research + Microsoft Corporation + .NET wrapper examples for Microsoft SEAL + Microsoft Corporation 2020 + + + + x64 + $(ProjectDir)../../bin/dotnet/$(Configuration) + + + + + + + + + + + + + + + + + diff --git a/bigpiseal3.5.1/dotnet/examples/Utilities.cs b/bigpiseal3.5.1/dotnet/examples/Utilities.cs new file mode 100644 index 0000000000000000000000000000000000000000..63f8511b14dd6258d6c4d1517ac22d2c0ab0cc77 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/examples/Utilities.cs @@ -0,0 +1,189 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace SEALNetExamples +{ + public static class Utilities + { + /// + /// Helper function: Prints the name of the example in a fancy banner. + /// + public static void PrintExampleBanner(string title) + { + if (!string.IsNullOrEmpty(title)) + { + int titleLength = title.Length; + int bannerLength = titleLength + 2 * 10; + string bannerTop = "+" + new string('-', bannerLength - 2) + "+"; + string bannerMiddle = + "|" + new string(' ', 9) + title + new string(' ', 9) + "|"; + + Console.WriteLine(); + Console.WriteLine(bannerTop); + Console.WriteLine(bannerMiddle); + Console.WriteLine(bannerTop); + } + } + + /// + /// Helper function: Prints the parameters in a SEALContext. + /// + public static void PrintParameters(SEALContext context) + { + // Verify parameters + if (null == context) + { + throw new ArgumentNullException("context is not set"); + } + SEALContext.ContextData contextData = context.KeyContextData; + + /* + Which scheme are we using? + */ + string schemeName = null; + switch (contextData.Parms.Scheme) + { + case SchemeType.BFV: + schemeName = "BFV"; + break; + case SchemeType.CKKS: + schemeName = "CKKS"; + break; + default: + throw new ArgumentException("unsupported scheme"); + } + + Console.WriteLine("/"); + Console.WriteLine("| Encryption parameters:"); + Console.WriteLine($"| Scheme: {schemeName}"); + Console.WriteLine("| PolyModulusDegree: {0}", + contextData.Parms.PolyModulusDegree); + + /* + Print the size of the true (product) coefficient modulus. + */ + Console.Write("| CoeffModulus size: {0} (", + contextData.TotalCoeffModulusBitCount); + List coeffModulus = + (List)contextData.Parms.CoeffModulus; + for (int i = 0; i < coeffModulus.Count - 1; i++) + { + Console.Write($"{coeffModulus[i].BitCount} + "); + } + Console.WriteLine($"{coeffModulus.Last().BitCount}) bits"); + + /* + For the BFV scheme print the PlainModulus parameter. + */ + if (contextData.Parms.Scheme == SchemeType.BFV) + { + Console.WriteLine("| PlainModulus: {0}", + contextData.Parms.PlainModulus.Value); + } + + Console.WriteLine("\\"); + } + + /// + /// Helper function: Print the first and last printSize elements + /// of a 2 row matrix. + /// + public static void PrintMatrix(IEnumerable matrixPar, + int rowSize, int printSize = 5) + { + ulong[] matrix = matrixPar.ToArray(); + Console.WriteLine(); + + /* + We're not going to print every column of the matrix (may be big). Instead + print printSize slots from beginning and end of the matrix. + */ + Console.Write(" ["); + for (int i = 0; i < printSize; i++) + { + Console.Write("{0,3}, ", matrix[i]); + } + Console.Write(" ..."); + for (int i = rowSize - printSize; i < rowSize; i++) + { + Console.Write(", {0,3}", matrix[i]); + } + Console.WriteLine(" ]"); + Console.Write(" ["); + for (int i = rowSize; i < rowSize + printSize; i++) + { + Console.Write("{0,3}, ", matrix[i]); + } + Console.Write(" ..."); + for (int i = 2 * rowSize - printSize; i < 2 * rowSize; i++) + { + Console.Write(", {0,3}", matrix[i]); + } + Console.WriteLine(" ]"); + Console.WriteLine(); + } + + /// + /// Helper function: Convert a ulong to a hex string representation + /// + public static string ULongToString(ulong value) + { + byte[] bytes = BitConverter.GetBytes(value); + return BitConverter.ToString(bytes).Replace("-", ""); + } + + /// + /// Helper function: Prints a vector of floating-point values. + /// + public static void PrintVector( + IEnumerable vec, int printSize = 4, int prec = 3) + { + string numFormat = string.Format("{{0:N{0}}}", prec); + T[] veca = vec.ToArray(); + int slotCount = veca.Length; + Console.WriteLine(); + if (slotCount <= 2 * printSize) + { + Console.Write(" ["); + for (int i = 0; i < slotCount; i++) + { + Console.Write(" " + string.Format(numFormat, veca[i])); + if (i != (slotCount - 1)) + Console.Write(","); + else + Console.Write(" ]"); + } + Console.WriteLine(); + } + else + { + Console.Write(" ["); + for (int i = 0; i < printSize; i++) + { + Console.Write(" "+ string.Format(numFormat, veca[i]) + ", "); + } + if (veca.Length > 2 * printSize) + { + Console.Write(" ..."); + } + for (int i = slotCount - printSize; i < slotCount; i++) + { + Console.Write(", " + string.Format(numFormat, veca[i])); + } + Console.WriteLine(" ]"); + } + Console.WriteLine(); + } + + public static void PrintLine([CallerLineNumber] int lineNumber = 0) + { + Console.Write("Line {0,3} --> ", lineNumber); + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/nuget/NUGET.md b/bigpiseal3.5.1/dotnet/nuget/NUGET.md new file mode 100644 index 0000000000000000000000000000000000000000..8a7315be4dae3dd20f917f8492f47f16e7f8e72a --- /dev/null +++ b/bigpiseal3.5.1/dotnet/nuget/NUGET.md @@ -0,0 +1,36 @@ +# Creating a NuGet package + +After building `dotnet\src\SEALNet.csproj` you can create a NuGet package that you can +use to easily add Microsoft SEAL capabilities to all of your .NET projects. Currently +the NuGet package is only supported in Windows. + +You will need to: +1. Compile binaries + 1. `native\src\SEAL.vcxproj` + 2. `native\src\SEAL_C.vcxproj` + 3. `dotnet\src\SEALNet.csproj` +3. [Download the NuGet command line tool](https://dist.nuget.org/win-x86-commandline/latest/nuget.exe) +4. Run the command below to create NuGet package +5. Add NuGet package reference to your .NET projects + +The command to create the NuGet package after compiling binaries is the following: + +```` +cd dotnet\nuget +nuget.exe pack SEALNet.nuspec -properties Configuration=Release -Verbosity detailed -OutputDir Release +cd ..\.. +```` + +After the package is created, copy it from `dotnet\nuget\Release` to a known location (e.g., `C:\NuGetPackages`). + +To add a reference to the NuGet package, you will need to configure Visual Studio so it can find +packages in this known location. In Microsoft Visual Studio 2019, for example, you can: +1. Select the menu uption `Tools / Options...` +2. On the left pane of the Options dialog, navigate to `NuGet Package Manager / Package Sources` +3. On the right pane of the Options dialog, add a new package source that points to the directory + where you copied the NuGet package (e.g., `C:\NuGetPackages`) + +After this, you should be able to add a reference to this package in your own .NET project. After +creating or opening your project in Visual Studio, you can right click on the project in the +Solution Explorer window, and select `Manage NuGet packages...`. In the window that appears +you will be able to select the `Microsoft.Research.SEAL` NuGet package to add to your project. \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in new file mode 100644 index 0000000000000000000000000000000000000000..6f77d3624582d9e86df6dc74fb6fdf5cce7e491c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in @@ -0,0 +1,34 @@ + + + + + + + Microsoft.Research.SEALNet + @SEAL_VERSION@ + Microsoft SEAL + Microsoft + Microsoft + http://sealcrypto.org + LICENSE + false + Microsoft SEAL is an easy-to-use and powerful open source homomorphic encryption library, developed by researchers in the Cryptography and Privacy Research Group at Microsoft Research. Microsoft SEAL is licensed under the MIT license. + https://GitHub.com/Microsoft/SEAL + © Microsoft Corporation. All rights reserved. + c# crypto cryptography homomorphic encryption + + + + + + + + + + + + + + + diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in new file mode 100644 index 0000000000000000000000000000000000000000..5fd8c2154df3b3fc476faebb7cb8446d31b334f2 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in @@ -0,0 +1,32 @@ + + + + + + + Microsoft.Research.SEALNet + @SEAL_VERSION@ + Microsoft SEAL + Microsoft + Microsoft + http://sealcrypto.org + LICENSE + false + Microsoft SEAL is an easy-to-use and powerful open source homomorphic encryption library, developed by researchers in the Cryptography and Privacy Research Group at Microsoft Research. Microsoft SEAL is licensed under the MIT license. + https://GitHub.com/Microsoft/SEAL + © Microsoft Corporation. All rights reserved. + c# crypto cryptography homomorphic encryption + + + + + + + + + + + + + diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in new file mode 100644 index 0000000000000000000000000000000000000000..a0071eb8c3547738a0a63d5f530dae91531a1b5b --- /dev/null +++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in @@ -0,0 +1,30 @@ + + + + + + + + + + + + + sealc.dll + libsealc.so + libsealc.dylib + PreserveNewest + + + + + arm64-v8a + libs\arm64-v8a\libsealc.so + + + x86_64 + libs\x86_64\libsealc.so + + + diff --git a/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs b/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs new file mode 100644 index 0000000000000000000000000000000000000000..e623a7a12660ca086c16713dd5413fa459f8b811 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Research.SEAL +{ + /// + /// Provides functionality for CRT batching. If the polynomial modulus degree is N, and + /// the plaintext modulus is a prime number T such that T is congruent to 1 modulo 2N, + /// then BatchEncoder allows the plaintext elements to be viewed as 2-by-(N/2) + /// matrices of integers modulo T. Homomorphic operations performed on such encrypted + /// matrices are applied coefficient (slot) wise, enabling powerful SIMD functionality + /// for computations that are vectorizable. This functionality is often called "batching" + /// in the homomorphic encryption literature. + /// + /// + /// + /// Mathematical Background + /// Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, and + /// PlainModulus is a prime number T such that 2N divides T-1, then integers modulo T + /// contain a primitive 2N-th root of unity and the polynomial X^N+1 splits into n distinct + /// linear factors as X^N+1 = (X-a_1)*...*(X-a_N) mod T, where the constants a_1, ..., a_n + /// are all the distinct primitive 2N-th roots of unity in integers modulo T. The Chinese + /// Remainder Theorem (CRT) states that the plaintext space Z_T[X]/(X^N+1) in this case is + /// isomorphic (as an algebra) to the N-fold direct product of fields Z_T. The isomorphism + /// is easy to compute explicitly in both directions, which is what this class does. + /// Furthermore, the Galois group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose + /// action on the primitive roots of unity is easy to describe. Since the batching slots + /// correspond 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the + /// plaintext act by permuting the slots. By applying generators of the two cyclic + /// subgroups of the Galois group, we can effectively view the plaintext as a 2-by-(N/2) + /// matrix, and enable cyclic row rotations, and column rotations (row swaps). + /// + /// + /// Valid Parameters + /// Whether batching can be used depends on whether the plaintext modulus has been chosen + /// appropriately. Thus, to construct a BatchEncoder the user must provide an instance + /// of SEALContext such that its associated EncryptionParameterQualifiers object has the + /// flags ParametersSet and EnableBatching set to true. + /// + /// + /// see EncryptionParameters for more information about encryption parameters. + /// see EncryptionParameterQualifiers for more information about parameter qualifiers. + /// see Evaluator for rotating rows and columns of encrypted matrices. + public class BatchEncoder : NativeObject + { + /// + /// Creates a BatchEncoder. It is necessary that the encryption parameters + /// given through the SEALContext object support batching. + /// + /// The SEALContext + /// @param[in] context + /// if context is null. + /// if the context is not set or encryption + /// parameters are not valid for batching + /// if scheme is not SchemeType.BFV + public BatchEncoder(SEALContext context) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + + SEALContext.ContextData contextData = context.FirstContextData; + if (contextData.Parms.Scheme != SchemeType.BFV) + throw new ArgumentException("Unsupported scheme"); + if (!contextData.Qualifiers.UsingBatching) + throw new ArgumentException("Encryption parameters are not valid for batching"); + + NativeMethods.BatchEncoder_Create(context.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates a plaintext from a given matrix. This function "batches" a given matrix + /// of integers modulo the plaintext modulus into a plaintext element, and stores + /// the result in the destination parameter. The input vector must have size at most equal + /// to the degree of the polynomial modulus. The first half of the elements represent the + /// first row of the matrix, and the second half represent the second row. The numbers + /// in the matrix can be at most equal to the plaintext modulus for it to represent + /// a valid plaintext. + /// + /// If the destination plaintext overlaps the input values in memory, the behavior of + /// this function is undefined. + /// + /// The matrix of integers modulo plaintext modulus to batch + /// The plaintext polynomial to overwrite with the result + /// if either values or destination are null + /// if values is too large + public void Encode(IEnumerable values, Plaintext destination) + { + if (null == values) + throw new ArgumentNullException(nameof(values)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + ulong[] valarray = values.ToArray(); + NativeMethods.BatchEncoder_Encode(NativePtr, (ulong)valarray.LongLength, valarray, destination.NativePtr); + } + + /// + /// Creates a plaintext from a given matrix. This function "batches" a given matrix + /// of integers modulo the plaintext modulus into a plaintext element, and stores + /// the result in the destination parameter. The input vector must have size at most equal + /// to the degree of the polynomial modulus. The first half of the elements represent the + /// first row of the matrix, and the second half represent the second row. The numbers + /// in the matrix can be at most equal to the plaintext modulus for it to represent + /// a valid plaintext. + /// + /// If the destination plaintext overlaps the input values in memory, the behavior of + /// this function is undefined. + /// + /// The matrix of integers modulo plaintext modulus to batch + /// The plaintext polynomial to overwrite with the result + /// if either values or destionation are null + /// if values is too large + public void Encode(IEnumerable values, Plaintext destination) + { + if (null == values) + throw new ArgumentNullException(nameof(values)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + long[] valarray = values.ToArray(); + NativeMethods.BatchEncoder_Encode(NativePtr, (ulong)valarray.LongLength, valarray, destination.NativePtr); + } + + /// + /// Creates a plaintext from a given matrix. This function "batches" a given matrix + /// of integers modulo the plaintext modulus in-place into a plaintext ready to be + /// encrypted. The matrix is given as a plaintext element whose first N/2 coefficients + /// represent the first row of the matrix, and the second N/2 coefficients represent the + /// second row, where N denotes the degree of the polynomial modulus. The input plaintext + /// must have degress less than the polynomial modulus, and coefficients less than the + /// plaintext modulus, i.e. it must be a valid plaintext for the encryption parameters. + /// Dynamic memory allocations in the process are allocated from the memory pool pointed + /// to by the given MemoryPoolHandle. + /// + /// The matrix of integers modulo plaintext modulus to batch + /// + /// if plain is null. + /// if plain is not valid for the encryption parameters + /// if plain is in NTT form + /// if pool is uninitialized + public void Encode(Plaintext plain, MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.BatchEncoder_Encode(NativePtr, plain.NativePtr, poolPtr); + } + + /// + /// Inverse of encode. This function "unbatches" a given plaintext into a matrix + /// of integers modulo the plaintext modulus, and stores the result in the destination + /// parameter. The input plaintext must have degress less than the polynomial modulus, + /// and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + /// for the encryption parameters. Dynamic memory allocations in the process are + /// allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The plaintext polynomial to unbatch + /// The matrix to be overwritten with the values in the slots + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destionation are null + /// if plain is not valid for the encryption parameters + /// if plain is in NTT form + /// if pool is uninitialized + public void Decode(Plaintext plain, ICollection destination, MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + ulong destCount = 0; + + // Allocate a big enough array to hold the result + ulong[] destArray = new ulong[SlotCount]; + NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr); + + // Transfer result to actual destination + destination.Clear(); + for (ulong i = 0; i < destCount; i++) + { + destination.Add(destArray[i]); + } + } + + /// + /// Inverse of encode. This function "unbatches" a given plaintext into a matrix + /// of integers modulo the plaintext modulus, and stores the result in the destination + /// parameter. The input plaintext must have degress less than the polynomial modulus, + /// and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + /// for the encryption parameters. Dynamic memory allocations in the process are + /// allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The plaintext polynomial to unbatch + /// The matrix to be overwritten with the values in the slots + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destination are null + /// if plain is not valid for the encryption parameters + /// if plain is in NTT form + /// if pool is uninitialized + public void Decode(Plaintext plain, ICollection destination, MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + ulong destCount = 0; + + // Allocate a big enough array to hold the result + long[] destArray = new long[SlotCount]; + NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr); + + // Transfer result to actual destination + destination.Clear(); + for (ulong i = 0; i < destCount; i++) + { + destination.Add(destArray[i]); + } + } + + /// + /// Inverse of encode. This function "unbatches" a given plaintext in-place into + /// a matrix of integers modulo the plaintext modulus. The input plaintext must have + /// degress less than the polynomial modulus, and coefficients less than the plaintext + /// modulus, i.e. it must be a valid plaintext for the encryption parameters. Dynamic + /// memory allocations in the process are allocated from the memory pool pointed to by + /// the given MemoryPoolHandle. + /// + /// The plaintext polynomial to unbatch + /// The MemoryPoolHandle pointing to a valid memory pool + /// if plain is null + /// if plain is not valid for the encryption parameters + /// if plain is in NTT form + /// if pool is uninitialized + public void Decode(Plaintext plain, MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + + NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, poolPtr); + } + + /// + /// Returns the number of slots. + /// + public ulong SlotCount + { + get + { + NativeMethods.BatchEncoder_GetSlotCount(NativePtr, out ulong slotCount); + return slotCount; + } + } + + /// + /// Destroy native object + /// + protected override void DestroyNativeObject() + { + NativeMethods.BatchEncoder_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/BigUInt.cs b/bigpiseal3.5.1/dotnet/src/BigUInt.cs new file mode 100644 index 0000000000000000000000000000000000000000..67b8b1d8cb861ac28c2feac57ec557b30fe1306b --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/BigUInt.cs @@ -0,0 +1,1348 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Numerics; +using System.Text; +using Microsoft.Research.SEAL.Tools; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Represents an unsigned integer with a specified bit width. + /// + /// + /// + /// Represents an unsigned integer with a specified bit width. BigUInts are mutable + /// and able to be resized. The bit count for a BigUInt (which can be read with + /// ) is set initially by the constructor and can be resized + /// either explicitly with the function or implicitly + /// with an assignment operation (e.g., one of the Set() functions). A rich set + /// of unsigned integer operations are provided by the BigUInt class, including + /// comparison, traditional arithmetic (addition, subtraction, multiplication, + /// division), and modular arithmetic functions. + /// + /// + /// The backing array for a BigUInt stores its unsigned integer value as a contiguous + /// System.UInt64 array. Each System.UInt64 in the array sequentially represents + /// 64-bits of the integer value, with the least significant quad-word storing the + /// lower 64-bits and the order of the bits for each quad word dependent on the + /// architecture's System.UInt64 representation. The size of the array equals the bit + /// count of the BigUInt (which can be read with ) rounded up + /// to the next System.UInt64 boundary (i.e., rounded up to the next 64-bit boundary). + /// The property returns the number of System.UInt64 in the + /// backing array. The method returns an element of the + /// System.UInt64 array. Additionally, the index property allows accessing the + /// individual bytes of the integer value in a platform-independent way - for example, + /// reading the third byte will always return bits 16-24 of the BigUInt value + /// regardless of the platform being little-endian or big-endian. + /// + /// + /// Both the copy constructor and the Set function allocate more memory for the + /// backing array when needed, i.e. when the source BigUInt has a larger backing + /// array than the destination. Conversely, when the destination backing array is + /// already large enough, the data is only copied and the unnecessary higher order + /// bits are set to zero. When new memory has to be allocated, only the significant + /// bits of the source BigUInt are taken into account. This is is important, because + /// it avoids unnecessary zero bits to be included in the destination, which in some + /// cases could accumulate and result in very large unnecessary allocations. However, + /// sometimes it is necessary to preserve the original size, even if some of the + /// leading bits are zero. For this purpose BigUInt contains functions + /// and , which create an exact + /// copy of the source BigUInt. + /// + /// + /// An aliased BigUInt (which can be determined with ) is + /// a special type of BigUInt that does not manage its underlying System.UInt64 + /// pointer used to store the value. An aliased BigUInt supports most of the same + /// operations as a non-aliased BigUInt, including reading and writing the value, + /// however an aliased BigUInt does not internally allocate or deallocate its backing + /// array and, therefore, does not support resizing. Any attempt, either explicitly + /// or implicitly, to resize the BigUInt will result in an exception being thrown. + /// Aliased BigUInt's are only created internally. Aliasing is useful in cases where + /// it is desirable to not have each BigUInt manage its own memory allocation and/or + /// to prevent unnecessary copying. + /// + /// + /// In general, reading a BigUInt is thread-safe while mutating is not. Specifically, + /// the backing array may be freed whenever a resize occurs or the BigUInt is + /// destroyed. When it is known that a resize will not occur, concurrent reading and + /// mutating will not inherently fail but it is possible for a read to see a partially + /// updated value from a concurrent write. A non-aliased BigUInt allocates its backing + /// array from the global (thread-safe) memory pool. Consequently, creating or + /// resizing a large number of BigUInt can result in a performance loss due to thread + /// contention. + /// + /// + public class BigUInt : NativeObject, IEquatable, IComparable + { + /// Creates an empty BigUInt with zero bit width. + /// + /// Creates an empty BigUInt with zero bit width. No memory is allocated by + /// this constructor. + /// + public BigUInt() + { + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(out ptr); + NativePtr = ptr; + } + + /// Creates a zero-initialized BigUInt of the specified bit + /// width. + /// The bit width + /// if bitCount is negative + public BigUInt(int bitCount) + { + if (bitCount < 0) + throw new ArgumentException("bitCount cannot be negative"); + + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(bitCount, out ptr); + NativePtr = ptr; + } + + /// Creates a BigUInt of the specified bit width and initializes + /// it with the unsigned hexadecimal integer specified by the string. + /// + /// Creates a BigUInt of the specified bit width and initializes it with + /// the unsigned hexadecimal integer specified by the string. The string + /// must match the format returned by and must + /// consist of only the characters 0-9, A-F, or a-f, most-significant nibble + /// first. + /// + /// + /// The bit width + /// The hexadecimal integer string specifying the + /// initial value + /// if hexString is null + /// if bitCount is negative + /// if hexString does not adhere to the + /// expected format + public BigUInt(int bitCount, string hexString) + { + if (null == hexString) + throw new ArgumentNullException(nameof(hexString)); + if (bitCount < 0) + throw new ArgumentException("bitCount cannot be negative"); + + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(bitCount, hexString, out ptr); + NativePtr = ptr; + } + + /// Creates a BigUInt of the specified bit width and initializes it + /// to the specified unsigned integer value. + /// + /// The bit width + /// The initial value to set the BigUInt + /// if bitCount is negative + public BigUInt(int bitCount, ulong value) + { + if (bitCount < 0) + throw new ArgumentException("bitCount cannot be negative"); + + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(bitCount, value, out ptr); + NativePtr = ptr; + } + + /// Creates a BigUInt initialized and minimally sized to fit the + /// unsigned hexadecimal integer specified by the string. + /// + /// Creates a BigUInt initialized and minimally sized to fit the unsigned + /// hexadecimal integer specified by the string. The string matches the format + /// returned by and must consist of only the characters + /// 0-9, A-F, or a-f, most-significant nibble first. + /// + /// The hexadecimal integer string specifying the + /// initial value + /// if hexString is null + /// if hexString does not adhere to the + /// expected format + public BigUInt(string hexString) + { + if (null == hexString) + throw new ArgumentNullException(nameof(hexString)); + + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(hexString, out ptr); + NativePtr = ptr; + } + + /// Creates a deep copy of a BigUInt. + /// + /// Creates a deep copy of a BigUInt. The created BigUInt will have the same + /// bit count and value as the original. + /// + /// The BigUInt to copy from + /// if copy is null + public BigUInt(BigUInt copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(copy.NativePtr, out ptr); + NativePtr = ptr; + } + + /// + /// Creates a BigUInt initialized and minimally sized to fit the unsigned + /// hexadecimal integer specified by the . + /// + /// The initial value of the BigUInt + /// if bigInteger is null + public BigUInt(BigInteger bigInteger) + { + if (null == bigInteger) + throw new ArgumentNullException(nameof(bigInteger)); + + string hex = bigInteger.ToString("X"); + IntPtr ptr = IntPtr.Zero; + NativeMethods.BigUInt_Create(hex, out ptr); + NativePtr = ptr; + } + + /// + /// Creates a BigUInt from an IntPtr. + /// + /// Native pointer + /// Whether this BigUInt instance owns the native + /// pointer + internal BigUInt(IntPtr ptr, bool owned = true) + : base(ptr, owned) + { + } + + /// Returns whether or not the BigUInt is an alias. + public bool IsAlias + { + get + { + NativeMethods.BigUInt_IsAlias(NativePtr, out bool isAlias); + return isAlias; + } + } + + /// Returns the bit count for the BigUInt. + public int BitCount + { + get + { + NativeMethods.BigUInt_BitCount(NativePtr, out int bitCount); + return bitCount; + } + } + + /// Returns the number of bytes in the backing array used to store + /// the BigUInt value. + public ulong ByteCount + { + get + { + NativeMethods.BigUInt_ByteCount(NativePtr, out ulong byteCount); + return byteCount; + } + } + + /// Returns the number of System.UInt64 in the backing array used + /// to store the BigUInt value. + public ulong UInt64Count + { + get + { + NativeMethods.BigUInt_UInt64Count(NativePtr, out ulong uint64Count); + return uint64Count; + } + } + + /// Gets/sets the byte at the corresponding byte index of the BigUInt's + /// integer value. + /// + /// Gets/sets the byte at the corresponding byte index of the BigUInt's integer + /// value. The bytes of the BigUInt are indexed least-significant byte first. + /// + /// The index of the byte to get/set + /// if index is not within + /// [0, ) + public byte this[ulong index] + { + get + { + if (index >= ByteCount) + throw new ArgumentOutOfRangeException(nameof(index)); + + NativeMethods.BigUInt_Get(NativePtr, index, out byte result); + return result; + } + set + { + if (index >= ByteCount) + throw new ArgumentOutOfRangeException(nameof(index)); + + NativeMethods.BigUInt_Set(NativePtr, index, value); + } + } + + /// + /// Returns the ulong value at a given position in the backing array storing + /// the BigUInt value. + /// + /// + /// Returns the value that is at position + /// in the backing array storing the BigUInt value. + /// + /// + /// if index is not within + /// [0, ) + public ulong Data(ulong index) + { + if (index >= UInt64Count) + throw new ArgumentOutOfRangeException(nameof(index)); + + NativeMethods.BigUInt_GetU64(NativePtr, index, out ulong result); + return result; + } + + /// + /// Returns whether or not the BigUInt has the value zero. + /// + public bool IsZero + { + get + { + NativeMethods.BigUInt_IsZero(NativePtr, out bool isZero); + return isZero; + } + } + + /// + /// Returns the number of significant bits for the BigUInt. + /// + public int GetSignificantBitCount() + { + NativeMethods.BigUInt_GetSignificantBitCount(NativePtr, out int result); + return result; + } + + /// + /// Overwrites the BigUInt with the value of the specified BigUInt, enlarging + /// if needed to fit the assigned value. + /// + /// + /// Overwrites the BigUInt with the value of the specified BigUInt, enlarging + /// if needed to fit the assigned value. Only significant bits are used to size + /// the BigUInt. + /// + /// The BigUInt whose value should be assigned to the + /// current BigUInt + /// if assign is null + /// if BigUInt is an alias and + /// the assigned BigUInt is too large to fit the current bit width + public void Set(BigUInt assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + if (IsAlias) + throw new InvalidOperationException("Cannot assign to an alias"); + + NativeMethods.BigUInt_Set(NativePtr, assign.NativePtr); + } + + /// + /// Overwrites the BigUInt with the unsigned hexadecimal value specified by + /// the string, enlarging if needed to fit the assigned value. + /// + /// + /// Overwrites the BigUInt with the unsigned hexadecimal value specified by + /// the string, enlarging if needed to fit the assigned value. The string must + /// match the format returned by and must consist of + /// only the characters 0-9, A-F, or a-f, most-significant nibble first. + /// + /// The hexadecimal integer string specifying the value + /// to assign + /// if assign is null + /// if assign does not adhere to the + /// expected format + /// if BigUInt is an alias and + /// the assigned value is too large to fit the current bit width + public void Set(string assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + if (IsAlias) + throw new InvalidOperationException("Cannot assign to an alias"); + + NativeMethods.BigUInt_Set(NativePtr, assign); + } + + /// Overwrites the BigUInt with the specified integer value, enlarging + /// if needed to fit the value. + /// + /// The value to assign + /// if BigUInt is an alias and + /// the significant bit count of assign is too large to fit the current bit + /// width + public void Set(ulong assign) + { + NativeMethods.BigUInt_Set(NativePtr, assign); + } + + /// Sets the BigUInt value to zero. + /// + /// Sets the BigUInt value to zero. This does not resize the BigUInt. + /// + public void SetZero() + { + NativeMethods.BigUInt_SetZero(NativePtr); + } + + /// + /// Returns an upper bound on the size of the BigUInt, as if it was written + /// to an output stream. + /// + /// The compression mode + /// if the compression mode is not + /// supported + /// if the size does not fit in + /// the return type + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.BigUInt_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// Saves the BigUInt to an output stream. + /// + /// Saves the BigUInt to an output stream. The full state of the BigUInt is + /// serialized, including insignificant bits. The output is in binary format + /// and not human-readable. + /// + /// The stream to save the BigUInt to + /// The desired compression mode + /// if stream is null + /// if the stream is closed or does not + /// support writing, or if compression mode is not supported + /// if I/O operations failed + /// if the data to be saved + /// is invalid, or if compression failed + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.BigUInt_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// + /// Loads a BigUInt from an input stream overwriting the current BigUInt. + /// + /// The stream to load the BigUInt from + /// if stream is null + /// if the stream is closed or does not + /// support reading + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, if the + /// loaded compression mode is not supported, or if the loaded BigUInt is too + /// large for an aliased BigUInt + public long Load(Stream stream) + { + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.BigUInt_Load(NativePtr, outptr, size, out outBytes), + stream); + } + + /// + /// Resizes the BigUInt to the specified bit width, copying over the old + /// value as much as will fit. + /// + /// The bit width + /// if bitCount is negative + /// if the BigUInt is an + /// alias + public void Resize(int bitCount) + { + if (bitCount < 0) + throw new ArgumentException("bitCount cannot be negative"); + if (IsAlias) + throw new InvalidOperationException("Cannot resize an alias"); + + NativeMethods.BigUInt_Resize(NativePtr, bitCount); + } + + /// + /// Returns the BigUInt value as a . + /// + public BigInteger ToBigInteger() + { + ulong byteCount = ByteCount; + byte[] bytes = new byte[byteCount + 1]; + for (ulong i = 0; i < byteCount; i++) + { + bytes[i] = this[i]; + } + bytes[byteCount] = 0; + + BigInteger result = new BigInteger(bytes); + return result; + } + + /// + /// Returns the BigUInt value as a decimal string. + /// + public string ToDecimalString() + { + NativeMethods.BigUInt_ToDecimalString(NativePtr, null, length: out ulong length); + StringBuilder buffer = new StringBuilder(checked((int)length)); + NativeMethods.BigUInt_ToDecimalString(NativePtr, buffer, out length); + return buffer.ToString(); + } + + /// + /// Compares a BigUInt and an unsigned integer and returns -1, 0, or 1 if + /// the BigUInt is less-than, equal-to, or greater-than the second operand + /// respectively. The input operands are not modified. + /// + /// The value to compare against + public int CompareTo(ulong compare) + { + NativeMethods.BigUInt_CompareTo(NativePtr, compare, out int result); + return result; + } + + /// Divides two BigUInts and returns the quotient and sets the + /// remainder parameter to the remainder. + /// + /// Divides two BigUInts and returns the quotient and sets the remainder + /// parameter to the remainder. The bit count of the quotient is set to be + /// the significant bit count of the BigUInt. The remainder is resized if + /// and only if it is smaller than the bit count of the BigUInt. + /// + /// The second operand to divide + /// The BigUInt to store the remainder + /// if operand2 or remainder is + /// null + /// if operand2 is zero + /// if the remainder is an alias + /// and the operator attempts to enlarge the BigUInt to fit the result + public BigUInt DivideRemainder(BigUInt operand2, BigUInt remainder) + { + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + if (null == remainder) + throw new ArgumentNullException(nameof(remainder)); + if (operand2.IsZero) + throw new ArgumentException("operand2 is zero"); + if (remainder.IsAlias) + throw new InvalidOperationException("remainder is an alias"); + + NativeMethods.BigUInt_DivideRemainder(NativePtr, operand2.NativePtr, + remainder.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Divides a BigUInt and an unsigned integer and returns the quotient + /// and sets the remainder parameter to the remainder. + /// + /// + /// Divides a BigUInt and an unsigned integer and returns the quotient and + /// sets the remainder parameter to the remainder. The bit count of the quotient + /// is set to be the significant bit count of the BigUInt. The remainder is + /// resized if and only if it is smaller than the bit count of the BigUInt. + /// + /// The second operand to divide + /// The BigUInt to store the remainder + /// if remainder is null + /// if operand2 is zero + /// if the remainder is an alias + /// which the function attempts to enlarge to fit the result + public BigUInt DivideRemainder(ulong operand2, BigUInt remainder) + { + if (null == remainder) + throw new ArgumentNullException(nameof(remainder)); + if (operand2 == 0) + throw new ArgumentException("operand2 is zero"); + if (remainder.IsAlias) + throw new InvalidOperationException("remainder is an alias"); + + NativeMethods.BigUInt_DivideRemainder(NativePtr, operand2, + remainder.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Returns the inverse of a BigUInt with respect to the specified + /// modulus. + /// + /// Returns the inverse of a BigUInt with respect to the specified modulus. + /// The original BigUInt is not modified. The bit count of the inverse is + /// set to be the significant bit count of the modulus. + /// + /// The modulus to calculate the inverse with respect + /// to + /// if modulus is null + /// if modulus is zero + /// if modulus is not greater than the + /// BigUInt value + /// if the BigUInt value and modulus + /// are not co-prime + /// if the BigUInt value is + /// zero + public BigUInt ModuloInvert(BigUInt modulus) + { + if (null == modulus) + throw new ArgumentNullException(nameof(modulus)); + + BigUInt result = null; + NativeMethods.BigUInt_ModuloInvert(NativePtr, modulus.NativePtr, + out IntPtr resultptr); + result = new BigUInt(resultptr); + return result; + } + + /// Returns the inverse of a BigUInt with respect to the specified + /// modulus. + /// + /// Returns the inverse of a BigUInt with respect to the specified modulus. + /// The original BigUInt is not modified. The bit count of the inverse is set + /// to be the significant bit count of the modulus. + /// + /// The modulus to calculate the inverse with respect + /// to + /// if modulus is zero + /// if modulus is not greater than the + /// BigUInt value + /// if the BigUInt value and modulus + /// are not co-prime + public BigUInt ModuloInvert(ulong modulus) + { + NativeMethods.BigUInt_ModuloInvert(NativePtr, modulus, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Attempts to calculate the inverse of a BigUInt with respect to + /// the specified modulus, returning whether or not the inverse was successful + /// and setting the inverse parameter to the inverse. + /// + /// Attempts to calculate the inverse of a BigUInt with respect to the specified + /// modulus, returning whether or not the inverse was successful and setting + /// the inverse parameter to the inverse. The original BigUInt is not modified. + /// The inverse parameter is resized if and only if its bit count is smaller + /// than the significant bit count of the modulus. + /// + /// The modulus to calculate the inverse with respect + /// to + /// Stores the inverse if the inverse operation was + /// successful + /// if modulus or inverse is null + /// if modulus is zero + /// if modulus is not greater than the + /// BigUInt value + /// if the inverse is an alias + /// which the function attempts to enlarge to fit the result + public bool TryModuloInvert(BigUInt modulus, BigUInt inverse) + { + if (null == modulus) + throw new ArgumentNullException(nameof(modulus)); + if (null == inverse) + throw new ArgumentNullException(nameof(inverse)); + if (inverse.IsAlias) + throw new InvalidOperationException("inverse is an alias"); + + NativeMethods.BigUInt_TryModuloInvert(NativePtr, modulus.NativePtr, + inverse.NativePtr, out bool result); + return result; + } + + /// Attempts to calculate the inverse of a BigUInt with respect to + /// the specified modulus, returning whether or not the inverse was successful + /// and setting the inverse parameter to the inverse. + /// + /// Attempts to calculate the inverse of a BigUInt with respect to the + /// specified modulus, returning whether or not the inverse was successful + /// and setting the inverse parameter to the inverse. The original BigUInt + /// is not modified. The inverse parameter is resized if and only if its bit + /// count is smaller than the significant bit count of the modulus. + /// + /// The modulus to calculate the inverse with respect + /// to + /// Stores the inverse if the inverse operation was + /// successful + /// if inverse is null + /// if modulus is zero + /// if modulus is not greater than the + /// BigUInt value + /// if the inverse is an alias + /// which the function attempts to enlarge to fit the result + public bool TryModuloInvert(ulong modulus, BigUInt inverse) + { + if (null == inverse) + throw new ArgumentNullException(nameof(inverse)); + if (inverse.IsAlias) + throw new InvalidOperationException("inverse is an alias"); + + NativeMethods.BigUInt_TryModuloInvert(NativePtr, modulus, + inverse.NativePtr, out bool result); + return result; + } + + /// Duplicates the current BigUInt. + /// + /// Duplicates the current BigUInt. The bit count and the value of the given + /// BigUInt are set to be exactly the same as in the current one. + /// + /// The BigUInt to overwrite with the duplicate + /// if destination is null + /// if the destination BigUInt + /// is an alias + public void DuplicateTo(BigUInt destination) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (destination.IsAlias) + throw new InvalidOperationException("destination is an alias"); + + NativeMethods.BigUInt_DuplicateTo(NativePtr, destination.NativePtr); + } + + /// Duplicates a given BigUInt. + /// + /// Duplicates a given BigUInt. The bit count and the value of the current + /// BigUInt are set to be exactly the same as in the given one. + /// + /// The BigUInt to duplicate + /// if value is null + /// if the current BigUInt is + /// an alias + public void DuplicateFrom(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + NativeMethods.BigUInt_DuplicateFrom(NativePtr, value.NativePtr); + } + + #region Operators + + /// Returns a copy of the BigUInt value resized to the significant bit count. + /// + /// The operand to copy + /// if operand is null + public static BigUInt operator +(BigUInt operand) + { + if (null == operand) + throw new ArgumentNullException(nameof(operand)); + + return new BigUInt(operand); + } + + /// Returns a negated copy of the BigUInt value. + /// + /// + /// Returns a negated copy of the BigUInt value. The bit count does not change. + /// + /// The operand to negate + /// if operand is null + public static BigUInt operator -(BigUInt operand) + { + if (null == operand) + throw new ArgumentNullException(nameof(operand)); + + NativeMethods.BigUInt_OperatorNeg(operand.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Returns an inverted copy of the BigUInt value. + /// + /// + /// Returns an inverted copy of the BigUInt value. The bit count does not change. + /// + /// The operand to invert + /// if operand is null + public static BigUInt operator ~(BigUInt operand) + { + if (null == operand) + throw new ArgumentNullException(nameof(operand)); + + NativeMethods.BigUInt_OperatorTilde(operand.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Increments the BigUInt and returns the incremented value. + /// + /// + /// Increments the BigUInt and returns the incremented value. The BigUInt will increment the bit count if needed to fit the + /// carry. + /// + /// The operand to increment + /// if operand is null + /// if BigUInt is an alias and a carry occurs requiring the BigUInt to + /// be resized + public static BigUInt operator ++(BigUInt operand) + { + if (null == operand) + throw new ArgumentNullException(nameof(operand)); + + NativeMethods.BigUInt_OperatorPlus(operand.NativePtr, operand: 1ul, result: out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Decrements the BigUInt and returns the decremented value. + /// + /// + /// Decrements the BigUInt and returns the decremented value. The bit count does not change. + /// + /// The operand to decrement + /// if operand is null + public static BigUInt operator --(BigUInt operand) + { + if (null == operand) + throw new ArgumentNullException(nameof(operand)); + + NativeMethods.BigUInt_OperatorMinus(operand.NativePtr, operand: 1ul, result: out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Adds two BigUInts and returns the sum. + /// + /// + /// Adds two BigUInts and returns the sum. The input operands are not modified. The bit count of the sum is set to be one + /// greater than the significant bit count of the larger of the two input operands. + /// + /// The first operand to add + /// The second operand to add + /// if operand1 or operand2 is null + public static BigUInt operator +(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorPlus(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Adds a BigUInt and an unsigned integer and returns the sum. + /// + /// + /// Adds a BigUInt and an unsigned integer and returns the sum. The input operands are not modified. The bit count of the + /// sum is set to be one greater than the significant bit count of the larger of the two operands. + /// + /// The first operand to add + /// The second operand to add + /// if operand1 is null + public static BigUInt operator +(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorPlus(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Subtracts two BigUInts and returns the difference. + /// + /// + /// Subtracts two BigUInts and returns the difference. The input operands are not modified. The bit count of the difference + /// is set to be the significant bit count of the larger of the two input operands. + /// + /// The first operand to subtract + /// The second operand to subtract + /// if operand1 or operand2 is null + public static BigUInt operator -(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorMinus(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Subtracts a BigUInt and an unsigned integer and returns the difference. + /// + /// + /// Subtracts a BigUInt and an unsigned integer and returns the difference. The input operands are not modified. The bit + /// count of the difference is set to be the significant bit count of the larger of the two operands. + /// + /// The first operand to subtract + /// The second operand to subtract + /// if operand1 is null + public static BigUInt operator -(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorMinus(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Multiplies two BigUInts and returns the product. + /// + /// + /// Multiplies two BigUInts and returns the product. The input operands are not modified. The bit count of the product is + /// set to be the sum of the significant bit counts of the two input operands. + /// + /// The first operand to multiply + /// The second operand to multiply + /// if operand1 or operand2 is null + public static BigUInt operator *(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorMult(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Multiplies a BigUInt and an unsigned integer and returns the product. + /// + /// + /// Multiplies a BigUInt and an unsigned integer and returns the product. The input operands are not modified. The bit + /// count of the product is set to be the sum of the significant bit counts of the two input operands. + /// + /// The first operand to multiply + /// The second operand to multiply + /// if operand1 is null + public static BigUInt operator *(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorMult(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Divides two BigUInts and returns the quotient. + /// + /// + /// Divides two BigUInts and returns the quotient. The input operands are not modified. The bit count of the quotient is + /// set to be the significant bit count of the first input operand. + /// + /// The first operand to divide + /// The second operand to divide + /// if operand1 or operand2 is null + /// if operand2 is zero + public static BigUInt operator /(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + if (operand2.IsZero) + throw new ArgumentException("operand2 is zero"); + + NativeMethods.BigUInt_OperatorDiv(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Divides a BigUInt and an unsigned integer and returns the quotient. + /// + /// + /// Divides a BigUInt and an unsigned integer and returns the quotient. The input operands are not modified. The bit count + /// of the quotient is set to be the significant bit count of the first input operand. + /// + /// The first operand to divide + /// The second operand to divide + /// if operand1 is null + /// if operand2 is zero + public static BigUInt operator /(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (0 == operand2) + throw new ArgumentException("operand2 is zero"); + + NativeMethods.BigUInt_OperatorDiv(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise XOR operation between two BigUInts and returns the result. + /// + /// + /// Performs a bit-wise XOR operation between two BigUInts and returns the result. The input operands are not modified. The + /// bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to XOR + /// The second operand to XOR + /// if operand1 or operand2 is null + public static BigUInt operator ^(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorXor(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise XOR operation between a BigUInt and an unsigned integer and returns the result. + /// + /// + /// Performs a bit-wise XOR operation between a BigUInt and an unsigned integer and returns the result. The input operands + /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to XOR + /// The second operand to XOR + /// if operand1 is null + public static BigUInt operator ^(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorXor(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise AND operation between two BigUInts and returns the result. + /// + /// + /// Performs a bit-wise AND operation between two BigUInts and returns the result. The input operands are not modified. The + /// bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to AND + /// The second operand to AND + /// if operand1 or operand2 is null + public static BigUInt operator &(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorAnd(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise AND operation between a BigUInt and an unsigned integer and returns the result. + /// + /// + /// Performs a bit-wise AND operation between a BigUInt and an unsigned integer and returns the result. The input operands + /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to AND + /// The second operand to AND + /// if operand1 is null + public static BigUInt operator &(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorAnd(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise OR operation between two BigUInts and returns the result. + /// + /// + /// Performs a bit-wise OR operation between two BigUInts and returns the result. The input operands are not modified. The + /// bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to OR + /// The second operand to OR + /// if operand1 or operand2 is null + public static BigUInt operator |(BigUInt operand1, BigUInt operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (null == operand2) + throw new ArgumentNullException(nameof(operand2)); + + NativeMethods.BigUInt_OperatorOr(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Performs a bit-wise OR operation between a BigUInt and an unsigned integer and returns the result. + /// + /// + /// Performs a bit-wise OR operation between a BigUInt and an unsigned integer and returns the result. The input operands + /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts. + /// + /// The first operand to OR + /// The second operand to OR + /// if operand1 is null + public static BigUInt operator |(BigUInt operand1, ulong operand2) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + + NativeMethods.BigUInt_OperatorOr(operand1.NativePtr, operand2, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Returns a left-shifted copy of the BigUInt. + /// + /// + /// Returns a left-shifted copy of the BigUInt. The bit count of the returned value is the sum of the original significant + /// bit count and the shift amount. + /// + /// The operand to left-shift + /// The number of bits to shift by + /// if operand1 is null + /// if shift is negative + public static BigUInt operator <<(BigUInt operand1, int shift) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (shift < 0) + throw new ArgumentException("shift is negative"); + + NativeMethods.BigUInt_OperatorShiftLeft(operand1.NativePtr, shift, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Returns a right-shifted copy of the BigUInt. + /// + /// + /// Returns a right-shifted copy of the BigUInt. The bit count of the returned value is the original significant bit count + /// subtracted by the shift amount (clipped to zero if negative). + /// + /// The operand to right-shift + /// The number of bits to shift by + /// if operand1 is null + /// if shift is negative + public static BigUInt operator >>(BigUInt operand1, int shift) + { + if (null == operand1) + throw new ArgumentNullException(nameof(operand1)); + if (shift < 0) + throw new ArgumentException("shift is negative"); + + NativeMethods.BigUInt_OperatorShiftRight(operand1.NativePtr, shift, out IntPtr resultptr); + BigUInt result = new BigUInt(resultptr); + return result; + } + + /// Returns the BigUInt value as a double. + /// + /// Returns the BigUInt value as a double. Note that precision may be lost during the conversion. + /// + /// The value to convert + /// if value is null + public static explicit operator double(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + NativeMethods.BigUInt_ToDouble(value.NativePtr, out double result); + return result; + } + + /// Returns the BigUInt value as a float. + /// + /// Returns the BigUInt value as a float. Note that precision may be lost during the conversion. + /// + /// The value to convert + /// if value is null + public static explicit operator float(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + double dblvalue = (double)value; + return unchecked((float)dblvalue); + } + + /// Returns the lower 64-bits of a BigUInt value. + /// + /// Returns the lower 64-bits of a BigUInt value. Note that if the value is greater than 64-bits, + /// the higher bits are dropped. + /// + /// The value to convert + /// if value is null + public static explicit operator ulong(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + if (value.BitCount == 0) + return 0; + + return value.Data(0); + } + + /// Returns the lower 64-bits of a BigUInt value as a signed-integer. + /// + /// Returns the lower 64-bits of a BigUInt value as a signed-integer. Note that if the value is greater than + /// 64-bits, the result may be negative and the higher bits are dropped. + /// + /// The value to convert + /// if value is null + public static explicit operator long(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + ulong ulvalue = (ulong)value; + return unchecked((long)ulvalue); + } + + /// Returns the lower 32-bits of a BigUInt value. + /// + /// Returns the lower 32-bits of a BigUInt value. Note that if the value is greater than 32-bits, + /// the higher bits are dropped. + /// + /// The value to convert + /// if value is null + public static explicit operator uint(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + ulong ulvalue = (ulong)value; + return unchecked((uint)ulvalue); + } + + /// Returns the lower 32-bits of a BigUInt value as a signed-integer. + /// + /// Returns the lower 32-bits of a BigUInt value as a signed-integer. Note that if the value is greater than + /// 32-bits, the result may be negative and the higher bits are dropped. + /// + /// The value to convert + /// if value is null + public static explicit operator int(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + ulong ulvalue = (ulong)value; + return unchecked((int)ulvalue); + } + + #endregion // Operators + + #region IComparable methods + + /// Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is less-than, equal-to, or greater-than the + /// second operand respectively. + /// + /// + /// Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is less-than, equal-to, or greater-than the second + /// operand respectively. The input operands are not modified. + /// + /// The value to compare against + public int CompareTo(BigUInt compare) + { + if (null == compare) + return 1; + + NativeMethods.BigUInt_CompareTo(NativePtr, compare.NativePtr, out int result); + return result; + } + + #endregion + + #region IEquatable methods + + /// Returns whether or not a BigUInt is equal to a second BigUInt. + /// + /// Returns whether or not a BigUInt is equal to a second BigUInt. The input operands are not modified. + /// + /// + /// The value to compare against + public bool Equals(BigUInt compare) + { + if (null == compare) + return false; + + NativeMethods.BigUInt_Equals(NativePtr, compare.NativePtr, out bool result); + return result; + } + + #endregion + + #region Object overrides + + /// Returns whether or not a BigUInt is equal to a second BigUInt. + /// + /// Returns whether or not a BigUInt is equal to a second BigUInt. The input operands are not modified. + /// + /// + /// The value to compare against + public override bool Equals(object compare) + { + BigUInt other = compare as BigUInt; + return Equals(other); + } + + /// + /// Returns the BigUInt value as a hexadecimal string. + /// + public override string ToString() + { + NativeMethods.BigUInt_ToString(NativePtr, null, length: out ulong length); + StringBuilder buffer = new StringBuilder(checked((int)length)); + NativeMethods.BigUInt_ToString(NativePtr, buffer, out length); + return buffer.ToString(); + } + + /// + /// Returns a hash-code based on the value of the BigUInt. + /// + public override int GetHashCode() + { + ulong[] data = new ulong[UInt64Count]; + for (long i = 0; i < data.LongLength; i++) + { + data[i] = Data((ulong)i); + } + + return Utilities.ComputeArrayHashCode(data); + } + + #endregion + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.BigUInt_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs b/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs new file mode 100644 index 0000000000000000000000000000000000000000..99611ad612853b7d02400c4ab69a9e78a5d6f3bb --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs @@ -0,0 +1,449 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace Microsoft.Research.SEAL +{ + /// + /// Provides functionality for encoding vectors of complex or real numbers into plaintext + /// polynomials to be encrypted and computed on using the CKKS scheme. If the polynomial + /// modulus degree is N, then CKKSEncoder converts vectors of N/2 complex numbers into + /// plaintext elements. Homomorphic operations performed on such encrypted vectors are + /// applied coefficient (slot-)wise, enabling powerful SIMD functionality for computations + /// that are vectorizable. This functionality is often called "batching" in the homomorphic + /// encryption literature. + /// + /// + /// + /// Mathematical Background + /// Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, the + /// CKKSEncoder implements an approximation of the canonical embedding of the ring of + /// integers Z[X]/(X^N+1) into C^(N/2), where C denotes the complex numbers. The Galois + /// group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose action on the primitive roots + /// of unity modulo CoeffModulus is easy to describe. Since the batching slots correspond + /// 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the plaintext + /// acts by permuting the slots. By applying generators of the two cyclic subgroups of the + /// Galois group, we can effectively enable cyclic rotations and complex conjugations of + /// the encrypted complex vectors. + /// + /// + public class CKKSEncoder : NativeObject + { + /// + /// Creates a CKKSEncoder instance initialized with the specified SEALContext. + /// + /// The SEALContext + /// if context is null + /// if the context is not set or encryption parameters + /// are not valid + /// if scheme is not SchemeType.CKKS + public CKKSEncoder(SEALContext context) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + + SEALContext.ContextData contextData = context.FirstContextData; + if (contextData.Parms.Scheme != SchemeType.CKKS) + throw new ArgumentException("Unsupported scheme"); + + NativeMethods.CKKSEncoder_Create(context.NativePtr, out IntPtr ptr); + NativePtr = ptr; + + context_ = context; + } + + /// + /// Encodes a vector of double-precision floating-point real numbers into a plaintext + /// polynomial. + /// + /// + /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The enumeration of double-precision floating-point numbers + /// to encode + /// parmsId determining the encryption parameters to be used + /// by the result plaintext + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either values, parmsId or destionation are null. + /// if values has invalid size + /// if parmsId is not valid for the encryption + /// parameters + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(IEnumerable values, ParmsId parmsId, + double scale, Plaintext destination, MemoryPoolHandle pool = null) + { + if (null == values) + throw new ArgumentNullException(nameof(values)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + double[] valuearray = values.ToArray(); + NativeMethods.CKKSEncoder_EncodeDouble(NativePtr, (ulong)valuearray.LongLength, valuearray, + parmsId.Block, scale, destination.NativePtr, poolPtr); + } + + /// + /// Encodes a vector of double-precision floating-point complex numbers into a plaintext + /// polynomial. + /// + /// + /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The enumeration of double-precision complex numbers + /// to encode + /// parmsId determining the encryption parameters to be used + /// by the result plaintext + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either values, parmsId or destionation are null. + /// if values has invalid size + /// if parmsId is not valid for the encryption + /// parameters + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(IEnumerable values, ParmsId parmsId, + double scale, Plaintext destination, MemoryPoolHandle pool = null) + { + if (null == values) + throw new ArgumentNullException(nameof(values)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + double[] valuearray = new double[values.LongCount() * 2]; + ulong idx = 0; + foreach(Complex complex in values) + { + valuearray[idx++] = complex.Real; + valuearray[idx++] = complex.Imaginary; + } + + // Note that we should pass values.Count as the length instead of valuearray.Length, + // since we are using two doubles in the array per element. + NativeMethods.CKKSEncoder_EncodeComplex(NativePtr, (ulong)values.LongCount(), valuearray, + parmsId.Block, scale, destination.NativePtr, poolPtr); + } + + /// + /// Encodes a vector of double-precision floating-point real numbers into a plaintext + /// polynomial. + /// + /// + /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// The encryption parameters used are the top level parameters for the given context. + /// + /// The enumeration of double-precision floating-point numbers + /// to encode + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either values or destionation are null. + /// if values has invalid size + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(IEnumerable values, double scale, + Plaintext destination, MemoryPoolHandle pool = null) + { + Encode(values, context_.FirstParmsId, scale, destination, pool); + } + + /// + /// Encodes a vector of double-precision floating-point complex numbers into a plaintext + /// polynomial. + /// + /// + /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// The encryption parameters used are the top level parameters for the given context. + /// + /// The enumeration of double-precision floating-point numbers + /// to encode + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either values or destionation are null. + /// if values has invalid size + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(IEnumerable values, double scale, + Plaintext destination, MemoryPoolHandle pool = null) + { + Encode(values, context_.FirstParmsId, scale, destination, pool); + } + + /// + /// Encodes a double-precision floating-point real number into a plaintext polynomial. + /// + /// + /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The double-precision floating-point number to encode + /// parmsId determining the encryption parameters to be used + /// by the result plaintext + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either parmsId or destination are null + /// if parmsId is not valid for the encryption + /// parameters + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(double value, ParmsId parmsId, + double scale, Plaintext destination, + MemoryPoolHandle pool = null) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.CKKSEncoder_Encode(NativePtr, value, parmsId.Block, scale, destination.NativePtr, poolPtr); + } + + /// + /// Encodes a double-precision floating-point real number into a plaintext polynomial. + /// + /// + /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// The encryption parameters used are the top level parameters for the given context. + /// + /// The double-precision floating-point number to encode + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if destination is null + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(double value, double scale, Plaintext destination, + MemoryPoolHandle pool = null) + { + Encode(value, context_.FirstParmsId, scale, destination, pool); + } + + /// + /// Encodes a double-precision floating-point complex number into a plaintext polynomial. + /// + /// + /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The double-precision complex number to encode + /// parmsId determining the encryption parameters to be used + /// by the result plaintext + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either parmsId or destination are null + /// if parmsId is not valid for the encryption + /// parameters + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(Complex value, ParmsId parmsId, double scale, + Plaintext destination, MemoryPoolHandle pool = null) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.CKKSEncoder_Encode(NativePtr, value.Real, value.Imaginary, parmsId.Block, scale, destination.NativePtr, poolPtr); + } + + /// + /// Encodes a double-precision floating-point complex number into a plaintext polynomial. + /// + /// + /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// The encryption parameters used are the top level parameters for the given context. + /// + /// The double-precision complex number to encode + /// Scaling parameter defining encoding precision + /// The plaintext polynomial to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if destination is null + /// if scale is not strictly positive + /// if encoding is too large for the encryption + /// parameters + /// if pool is uninitialized + public void Encode(Complex value, double scale, Plaintext destination, + MemoryPoolHandle pool = null) + { + Encode(value, context_.FirstParmsId, scale, destination, pool); + } + + /// + /// Encodes an integer number into a plaintext polynomial without any scaling. + /// + /// + /// The number repeats for N/2 times to fill all slots. + /// + /// The integer number to encode + /// parmsId determining the encryption parameters to be used + /// by the result plaintext + /// The plaintext polynomial to overwrite with the result + /// if either parmsId or destionation are null + /// if parmsId is not valid for the encryption + /// parameters + public void Encode(long value, ParmsId parmsId, Plaintext destination) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.CKKSEncoder_Encode(NativePtr, value, parmsId.Block, destination.NativePtr); + } + + /// + /// Encodes an integer number into a plaintext polynomial without any scaling. + /// + /// + /// The number repeats for N/2 times to fill all slots. The encryption parameters used are + /// the top level parameters for the given context. + /// + /// The integer number to encode + /// The plaintext polynomial to overwrite with the result + /// if destination is null + public void Encode(long value, Plaintext destination) + { + Encode(value, context_.FirstParmsId, destination); + } + + /// + /// Decodes a plaintext polynomial into double-precision floating-point real numbers. + /// + /// + /// Dynamic memory allocations in the process are allocated from the memory pool pointed to + /// by the given MemoryPoolHandle. + /// + /// plain The plaintext to decode + /// The collection to be overwritten with the values in the slots + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destination are null + /// if plain is not in NTT form or is invalid for the + /// encryption parameters + /// if pool is uninitialized + public void Decode(Plaintext plain, ICollection destination, + MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + ulong destCount = 0; + + // Allocate a big enough array to hold the result + double[] destArray = new double[SlotCount]; + NativeMethods.CKKSEncoder_DecodeDouble(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr); + + // Transfer result to actual destination; only destArray many slots were filled + destination.Clear(); + for (ulong i = 0; i < destCount; i++) + { + destination.Add(destArray[i]); + } + } + + /// + /// Decodes a plaintext polynomial into double-precision floating-point complex numbers. + /// + /// + /// Dynamic memory allocations in the process are allocated from the memory pool pointed to + /// by the given MemoryPoolHandle. + /// + /// plain The plaintext to decode + /// The collection to be overwritten with the values in the slots + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destination are null + /// if plain is not in NTT form or is invalid for the + /// encryption parameters + /// if pool is uninitialized + public void Decode(Plaintext plain, ICollection destination, + MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + ulong destCount = 0; + + // Allocate a big enough array to hold the result + double[] destArray = new double[SlotCount * 2]; + NativeMethods.CKKSEncoder_DecodeComplex(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr); + + // Transfer result to actual destination + destination.Clear(); + for (ulong i = 0; i < destCount; i++) + { + destination.Add(new Complex(destArray[i * 2], destArray[i * 2 + 1])); + } + } + + /// + /// Returns the number of complex numbers encoded. + /// + public ulong SlotCount + { + get + { + NativeMethods.CKKSEncoder_SlotCount(NativePtr, out ulong slotCount); + return slotCount; + } + } + + /// + /// SEALContext for this encoder + /// + private readonly SEALContext context_ = null; + + /// + /// Destroy native object + /// + protected override void DestroyNativeObject() + { + NativeMethods.CKKSEncoder_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Ciphertext.cs b/bigpiseal3.5.1/dotnet/src/Ciphertext.cs new file mode 100644 index 0000000000000000000000000000000000000000..37cf1a4dc35e71fcf096734c2fafd1b8d14340b0 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Ciphertext.cs @@ -0,0 +1,680 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Class to store a ciphertext element. The data for a ciphertext consists + /// of two or more polynomials, which are in Microsoft SEAL stored in a CRT + /// form with respect to the factors of the coefficient modulus. This data + /// itself is not meant to be modified directly by the user, but is instead + /// operated on by functions in the Evaluator class. The size of the backing + /// array of a ciphertext depends on the encryption parameters and the size + /// of the ciphertext (at least 2). If the PolyModulusDegree encryption + /// parameter is N, and the number of primes in the CoeffModulus encryption + /// parameter is K, then the ciphertext backing array requires precisely + /// 8*N*K*size bytes of memory. A ciphertext also carries with it the + /// parmsId of its associated encryption parameters, which is used to check + /// the validity of the ciphertext for homomorphic operations and decryption. + /// + /// + /// + /// Memory Management + /// The size of a ciphertext refers to the number of polynomials it contains, + /// whereas its capacity refers to the number of polynomials that fit in the + /// current memory allocation. In high-performance applications unnecessary + /// re-allocations should be avoided by reserving enough memory for the + /// ciphertext to begin with either by providing the desired capacity to the + /// constructor as an extra argument, or by calling the reserve function at + /// any time. + /// + /// + /// Thread Safety + /// In general, reading from ciphertext is thread-safe as long as no other + /// thread is concurrently mutating it. This is due to the underlying data + /// structure storing the ciphertext not being thread-safe. + /// + /// + /// See Plaintext for the class that stores plaintexts. + public class Ciphertext : + NativeObject, + ISerializableObject, + ISettable + { + /// + /// Constructs an empty ciphertext allocating no memory. + /// + public Ciphertext() : this(pool: null) + { + } + + /// + /// Constructs an empty ciphertext allocating no memory. + /// + /// The MemoryPoolHandle pointing to a valid memory pool + /// if pool is uninitialized + public Ciphertext(MemoryPoolHandle pool) + { + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Ciphertext_Create1(poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Constructs an empty ciphertext with capacity 2. In addition to the + /// capacity, the allocation size is determined by the highest-level + /// parameters associated to the given SEALContext. + /// + /// The SEALContext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + /// if pool is uninitialized + public Ciphertext(SEALContext context, MemoryPoolHandle pool = null) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Ciphertext_Create3(context.NativePtr, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Constructs an empty ciphertext with capacity 2. In addition to the + /// capacity, the allocation size is determined by the encryption parameters + /// with given ParmsId. + /// + /// The SEALContext + /// The ParmsId corresponding to the encryption + /// parameters to be used + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either context or parmsId are null + /// if the context is not set or encryption + /// parameters are not valid + /// if parmsId is not valid for the encryption + /// parameters + /// if pool is uninitialized + public Ciphertext(SEALContext context, ParmsId parmsId, MemoryPoolHandle pool = null) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Ciphertext_Create4(context.NativePtr, parmsId.Block, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Constructs an empty ciphertext with given capacity. In addition to + /// the capacity, the allocation size is determined by the given + /// encryption parameters. + /// + /// The SEALContext + /// The ParmsId corresponding to the encryption + /// parameters to be used + /// The capacity + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either context or parmsId are null + /// if the context is not set or encryption + /// parameters are not valid + /// if parmsId is not valid for the encryption + /// parameters + /// if sizeCapacity is less than 2 or too large + /// if pool is uninitialized + public Ciphertext(SEALContext context, ParmsId parmsId, ulong sizeCapacity, + MemoryPoolHandle pool = null) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Ciphertext_Create5(context.NativePtr, parmsId.Block, sizeCapacity, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Constructs a new ciphertext by copying a given one. + /// + /// The ciphertext to copy from + /// if copy is null + public Ciphertext(Ciphertext copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.Ciphertext_Create2(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Constructs a new ciphertext by copying a given one. + /// + /// The ciphertext to copy from + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either copy or pool are null + /// if pool is uninitialized + public Ciphertext(Ciphertext copy, MemoryPoolHandle pool) : this(pool) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + Set(copy); + } + + /// + /// Constructs a new ciphertext by initializing it with a native + /// object pointer. + /// + /// The native Ciphertext pointer + /// Whether this object owns the native pointer + internal Ciphertext(IntPtr ciphertextPtr, bool owned = true) + : base(ciphertextPtr, owned) + { + } + + /// + /// Allocates enough memory to accommodate the backing array of a ciphertext + /// with given capacity. In addition to the capacity, the allocation size is + /// determined by the encryption parameters corresponing to the given + /// parmsId. + /// + /// The SEALContext + /// The ParmsId corresponding to the encryption + /// parameters to be used + /// The capacity + /// if either context or parmsId are null + /// if the context is not set or encryption + /// parameters are not valid + /// if parmsId is not valid for the encryption + /// parameters + /// if sizeCapacity is less than 2 or too large + public void Reserve(SEALContext context, ParmsId parmsId, ulong sizeCapacity) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + NativeMethods.Ciphertext_Reserve(NativePtr, context.NativePtr, parmsId.Block, sizeCapacity); + } + + /// + /// Allocates enough memory to accommodate the backing array of a ciphertext + /// with given capacity. In addition to the capacity, the allocation size is + /// determined by the highest-level parameters associated to the given + /// SEALContext. + /// + /// The SEALContext + /// The capacity + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + /// if sizeCapacity is less than 2 or too large + public void Reserve(SEALContext context, ulong sizeCapacity) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.Ciphertext_Reserve(NativePtr, context.NativePtr, sizeCapacity); + } + + /// + /// Allocates enough memory to accommodate the backing array of a ciphertext + /// with given capacity. In addition to the capacity, the allocation size is + /// determined by the current encryption parameters. + /// + /// The capacity + /// if sizeCapacity is less than 2 or too large + public void Reserve(ulong sizeCapacity) + { + NativeMethods.Ciphertext_Reserve(NativePtr, sizeCapacity); + } + + /// + /// Resizes the ciphertext to given size, reallocating if the capacity + /// of the ciphertext is too small. The ciphertext parameters are + /// determined by the given SEALContext and parmsId. + /// + /// This function is mainly intended for internal use and is called + /// automatically by functions such as Evaluator::multiply and + /// Evaluator::relinearize. A normal user should never have a reason + /// to manually resize a ciphertext. + /// + /// The SEALContext + /// The ParmsId corresponding to the encryption + /// parameters to be used + /// The new size + /// if either context or parmsId are null + /// if the context is not set or encryption + /// parameters are not valid + /// if parmsId is not valid for the encryption + /// parameters + /// if size is less than 2 or too large + public void Resize(SEALContext context, ParmsId parmsId, ulong size) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + NativeMethods.Ciphertext_Resize(NativePtr, context.NativePtr, parmsId.Block, size); + } + + /// + /// Resizes the ciphertext to given size, reallocating if the capacity + /// of the ciphertext is too small. The ciphertext parameters are + /// determined by the highest-level parameters associated to the given + /// SEALContext. + /// + /// This function is mainly intended for internal use and is called + /// automatically by functions such as Evaluator::multiply and + /// Evaluator::relinearize. A normal user should never have a reason + /// to manually resize a ciphertext. + /// + /// The SEALContext + /// The new size + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + /// if size is less than 2 or too large + public void Resize(SEALContext context, ulong size) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.Ciphertext_Resize(NativePtr, context.NativePtr, size); + } + + /// + /// Resizes the ciphertext to given size, reallocating if the capacity + /// of the ciphertext is too small. + /// + /// This function is mainly intended for internal use and is called + /// automatically by functions such as Evaluator::multiply and + /// Evaluator::relinearize. A normal user should never have a reason + /// to manually resize a ciphertext. + /// + /// The new size + /// if size is less than 2 or too large + public void Resize(ulong size) + { + NativeMethods.Ciphertext_Resize(NativePtr, size); + } + + /// + /// Resizes the ciphertext to the given size, poly modulus degree and + /// coefficient mod count. This is a helper for loading a ciphertext + /// from a stream. + /// + /// The new size + /// The new poly modulus degree + /// The new coefficient mod count + private void Resize(ulong size, ulong polyModulusDegree, ulong coeffModCount) + { + NativeMethods.Ciphertext_Resize(NativePtr, size, polyModulusDegree, coeffModCount); + } + + /// + /// Resets the ciphertext. This function releases any memory allocated + /// by the ciphertext, returning it to the memory pool. It also sets all + /// encryption parameter specific size information to zero. + /// + public void Release() + { + NativeMethods.Ciphertext_Release(NativePtr); + } + + /// + /// Copies a given ciphertext to the current one. + /// + /// The ciphertext to copy from + /// if assign is null + public void Set(Ciphertext assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.Ciphertext_Set(NativePtr, assign.NativePtr); + } + + /// + /// Returns the polynomial coefficient at a particular index in the ciphertext data. If the + /// polynomial modulus has degree N, and the number of primes in the coefficient modulus is K, then + /// the ciphertext contains size*N*K coefficients. Thus, the index has a range of [0, size*N*K). + /// + /// The index of the coefficient + /// if coeffIndex is out of range + public ulong this[ulong coeffIndex] + { + get + { + try + { + NativeMethods.Ciphertext_GetDataAt(NativePtr, coeffIndex, out ulong value); + return value; + } + catch (COMException ex) + { + if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex) + throw new IndexOutOfRangeException(nameof(coeffIndex), ex); + throw; + } + } + + set + { + try + { + NativeMethods.Ciphertext_SetDataAt(NativePtr, coeffIndex, value); + } + catch (COMException ex) + { + if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex) + throw new IndexOutOfRangeException(nameof(coeffIndex), ex); + throw; + } + } + } + + /// + /// Get the value of a coefficient at the given index from + /// a particular polynomial in the ciphertext + /// data. Note that Microsoft SEAL stores each polynomial in the ciphertext + /// modulo all of the K primes in the coefficient modulus. The data + /// returned by this function is to the beginning (constant coefficient) + /// of the first one of these K polynomials. + /// + /// The index of the polynomial in the ciphertext + /// The index of the polynomial data + /// if polyIndex is less than 0 or bigger + /// than the size of the ciphertext + /// if coeffIndex is less than 0 or bigger + /// than the size of the ciphertext + public ulong this[ulong polyIndex, ulong coeffIndex] + { + get + { + try + { + NativeMethods.Ciphertext_GetDataAt(NativePtr, polyIndex, coeffIndex, out ulong data); + return data; + } + catch(COMException ex) + { + if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex) + throw new IndexOutOfRangeException("polyIndex or coeffIndex out of range", ex); + throw; + } + } + } + + /// + /// Returns the number of primes in the coefficient modulus of the + /// associated encryption parameters. This directly affects the + /// allocation size of the ciphertext. + /// + public ulong CoeffModulusSize + { + get + { + NativeMethods.Ciphertext_CoeffModulusSize(NativePtr, out ulong coeffModCount); + return coeffModCount; + } + } + + + /// + /// Returns the degree of the polynomial modulus of the associated + /// encryption parameters.This directly affects the allocation size + /// of the ciphertext. + /// + public ulong PolyModulusDegree + { + get + { + NativeMethods.Ciphertext_PolyModulusDegree(NativePtr, out ulong polyModulusDegree); + return polyModulusDegree; + } + } + + /// + /// Returns the capacity of the allocation. This means the largest size + /// of the ciphertext that can be stored in the current allocation with + /// the current encryption parameters. + /// + public ulong SizeCapacity + { + get + { + NativeMethods.Ciphertext_SizeCapacity(NativePtr, out ulong sizeCapacity); + return sizeCapacity; + } + } + + /// + /// Returns the size of the ciphertext. + /// + public ulong Size + { + get + { + NativeMethods.Ciphertext_Size(NativePtr, out ulong size); + return size; + } + } + + /// + /// Check whether the current ciphertext is transparent, i.e. does not require + /// a secret key to decrypt. In typical security models such transparent + /// ciphertexts would not be considered to be valid. Starting from the second + /// polynomial in the current ciphertext, this function returns true if all + /// following coefficients are identically zero. Otherwise, returns false. + /// + public bool IsTransparent + { + get + { + NativeMethods.Ciphertext_IsTransparent(NativePtr, out bool result); + return result; + } + } + + /// + /// Returns an upper bound on the size of the ciphertext, as if it was written + /// to an output stream. + /// + /// The compression mode + /// if the compression mode is not + /// supported + /// if the size does not fit in + /// the return type + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.Ciphertext_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// Saves the ciphertext to an output stream. + /// + /// Saves the ciphertext to an output stream. The output is in binary format + /// and not human-readable. + /// + /// The stream to save the ciphertext to + /// The desired compression mode + /// if stream is null + /// if the stream is closed or does not + /// support writing, or if compression mode is not supported + /// if I/O operations failed + /// if the data to be saved + /// is invalid, or if compression failed + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.Ciphertext_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// Loads a ciphertext from an input stream overwriting the current + /// ciphertext. + /// + /// Loads a ciphertext from an input stream overwriting the current ciphertext. + /// No checking of the validity of the ciphertext data against encryption + /// parameters is performed. This function should not be used unless the + /// ciphertext comes from a fully trusted source. + /// + /// The SEALContext + /// The stream to load the ciphertext from + /// if context or stream is + /// null + /// if the stream is closed or does not + /// support reading + /// if context is not set or encryption + /// parameters are not valid + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long UnsafeLoad(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.Ciphertext_UnsafeLoad(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// Loads a ciphertext from an input stream overwriting the current + /// ciphertext. + /// + /// Loads a ciphertext from an input stream overwriting the current ciphertext. + /// The loaded ciphertext is verified to be valid for the given SEALContext. + /// + /// The SEALContext + /// The stream to load the ciphertext from + /// if context or stream is + /// null + /// if the stream is closed or does not + /// support reading + /// if context is not set or encryption + /// parameters are not valid + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long Load(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.Ciphertext_Load(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// + /// Returns whether the ciphertext is in NTT form. + /// + public bool IsNTTForm + { + get + { + NativeMethods.Ciphertext_IsNTTForm(NativePtr, out bool isNTTForm); + return isNTTForm; + } + + private set + { + NativeMethods.Ciphertext_SetIsNTTForm(NativePtr, value); + } + } + + /// + /// Returns a copy of ParmsId. + /// + public ParmsId ParmsId + { + get + { + ParmsId parmsId = new ParmsId(); + NativeMethods.Ciphertext_ParmsId(NativePtr, parmsId.Block); + return parmsId; + } + private set + { + NativeMethods.Ciphertext_SetParmsId(NativePtr, value.Block); + } + } + + /// + /// Returns a reference to the scale. This is only needed when using the + /// CKKS encryption scheme. The user should have little or no reason to ever + /// change the scale by hand. + /// + public double Scale + { + get + { + NativeMethods.Ciphertext_Scale(NativePtr, out double scale); + return scale; + } + set + { + NativeMethods.Ciphertext_SetScale(NativePtr, value); + } + } + + /// + /// Returns the currently used MemoryPoolHandle. + /// + public MemoryPoolHandle Pool + { + get + { + NativeMethods.Ciphertext_Pool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.Ciphertext_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Decryptor.cs b/bigpiseal3.5.1/dotnet/src/Decryptor.cs new file mode 100644 index 0000000000000000000000000000000000000000..ed8a7fa8a02d48837872515dd11f563ae552127b --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Decryptor.cs @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; + +namespace Microsoft.Research.SEAL +{ + /// + /// Decrypts Ciphertext objects into Plaintext objects. Constructing a Decryptor requires + /// a SEALContext with valid encryption parameters, and the secret key. The Decryptor is + /// also used to compute the invariant noise budget in a given ciphertext. + /// + /// + /// + /// Overloads + /// For the decrypt function we provide two overloads concerning the memory pool used in + /// allocations needed during the operation. In one overload the global memory pool is used + /// for this purpose, and in another overload the user can supply a MemoryPoolHandle + /// to to be used instead. This is to allow one single Decryptor to be used concurrently by + /// several threads without running into thread contention in allocations taking place during + /// operations. For example, one can share one single Decryptor across any number of threads, + /// but in each thread call the decrypt function by giving it a thread-local MemoryPoolHandle + /// to use. It is important for a developer to understand how this works to avoid unnecessary + /// performance bottlenecks. + /// + /// + /// NTT form + /// When using the BFV scheme (SchemeType.BFV), all plaintext and ciphertexts should + /// remain by default in the usual coefficient representation, i.e. not in NTT form. + /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts + /// should remain by default in NTT form. We call these scheme-specific NTT states the + /// "default NTT form". Decryption requires the input ciphertexts to be in the default + /// NTT form, and will throw an exception if this is not the case. + /// + /// + public class Decryptor : NativeObject + { + /// + /// Creates a Decryptor instance initialized with the specified SEALContext + /// and secret key. + /// + /// The SEALContext + /// The secret key + /// if either context or secretKey are null + /// if the context is not set or encryption + /// parameters are not valid + /// if secretKey is not valid + public Decryptor(SEALContext context, SecretKey secretKey) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == secretKey) + throw new ArgumentNullException(nameof(secretKey)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + if (!ValCheck.IsValidFor(secretKey, context)) + throw new ArgumentException("Secret key is not valid for encryption parameters"); + + NativeMethods.Decryptor_Create(context.NativePtr, secretKey.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Decrypts a Ciphertext and stores the result in the destination parameter. Dynamic + /// memory allocations in the process are allocated from the memory pool pointed to by + /// the given MemoryPoolHandle. + /// + /// The ciphertext to decrypt + /// The plaintext to overwrite with the decrypted ciphertext + /// if either encrypted or destination are null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if pool is uninitialized + public void Decrypt(Ciphertext encrypted, Plaintext destination) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Decryptor_Decrypt(NativePtr, encrypted.NativePtr, destination.NativePtr); + } + + /// + /// Computes the invariant noise budget (in bits) of a ciphertext. The invariant noise + /// budget measures the amount of room there is for the noise to grow while ensuring + /// correct decryptions. Dynamic memory allocations in the process are allocated from + /// the memory pool pointed to by the given MemoryPoolHandle. This function works only + /// with the BFV scheme. + /// + /// + /// + /// Invariant Noise Budget + /// The invariant noise polynomial of a ciphertext is a rational coefficient polynomial, + /// such that a ciphertext decrypts correctly as long as the coefficients of the invariant + /// noise polynomial are of absolute value less than 1/2. Thus, we call the infinity-norm + /// of the invariant noise polynomial the invariant noise, and for correct decryption require + /// it to be less than 1/2. If v denotes the invariant noise, we define the invariant noise + /// budget as -log2(2v). Thus, the invariant noise budget starts from some initial value, + /// which depends on the encryption parameters, and decreases when computations are performed. + /// When the budget reaches zero, the ciphertext becomes too noisy to decrypt correctly. + /// + /// + /// The ciphertext + /// if encrypted is null + /// if the scheme is not BFV + /// if encrypted is not valid for the encryption parameters + /// if encrypted is in NTT form + /// if pool is uninitialized + public int InvariantNoiseBudget(Ciphertext encrypted) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + + NativeMethods.Decryptor_InvariantNoiseBudget(NativePtr, encrypted.NativePtr, out int result); + return result; + } + + /// + /// Destroy native object + /// + protected override void DestroyNativeObject() + { + NativeMethods.Decryptor_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs b/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs new file mode 100644 index 0000000000000000000000000000000000000000..34a6a23dab3a69868f6e3f2435f736b82ff82aa4 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs @@ -0,0 +1,216 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Text; +using Microsoft.Research.SEAL.Tools; + +namespace Microsoft.Research.SEAL +{ + /// + /// Stores a set of attributes (qualifiers) of a set of encryption parameters. + /// + /// + /// + /// Stores a set of attributes (qualifiers) of a set of encryption parameters. + /// These parameters are mainly used internally in various parts of the library, + /// e.g., to determine which algorithmic optimizations the current support. + /// The qualifiers are automatically created by the + /// class, silently passed on to classes such as , + /// , and , and the only way + /// to change them is by changing the encryption parameters themselves. In + /// other words, a user will never have to create their own instance of this + /// class, and in most cases never have to worry about it at all. + /// + public class EncryptionParameterQualifiers : NativeObject + { + /// + /// Create a copy of an existing instance of EncryptionParameterQualifiers + /// + /// Original object to copy + public EncryptionParameterQualifiers(EncryptionParameterQualifiers copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.EPQ_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Create an instance of EncryptionParameterQualifiers through a pointer to + /// a native object. + /// + /// Pointer to native EncryptionParameterQualifiers. + /// Whether this instance owns the native pointer. + internal EncryptionParameterQualifiers(IntPtr ptr, bool owned = true) + : base(ptr, owned) + { + } + + /// + /// If the encryption parameters are set in a way that is considered valid by SEAL, + /// the variable ParametersSet is set to true. + /// + public bool ParametersSet + { + get + { + NativeMethods.EPQ_ParametersSet(NativePtr, out bool result); + return result; + } + } + + /// + /// If the encryption parameters are set in a way that is considered valid by SEAL, return "success". + /// If the encryption parameters are set but not validated yet, return "none". + /// Otherwise, return a brief reason. + /// + public string ParametersErrorName() + { + NativeMethods.EPQ_ParameterErrorName(NativePtr, null, out ulong length); + StringBuilder buffer = new StringBuilder(checked((int)length)); + NativeMethods.EPQ_ParameterErrorName(NativePtr, buffer, out length); + return buffer.ToString(); + } + + /// + /// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid". + /// Otherwise, return a comprehensive reason. + /// + public string ParametersErrorMessage() + { + NativeMethods.EPQ_ParameterErrorMessage(NativePtr, null, out ulong length); + StringBuilder buffer = new StringBuilder(checked((int)length)); + NativeMethods.EPQ_ParameterErrorMessage(NativePtr, buffer, out length); + return buffer.ToString(); + } + + /// + /// Tells whether FFT can be used for polynomial multiplication. + /// + /// + /// + /// Tells whether FFT can be used for polynomial multiplication. If the polynomial modulus + /// is of the form X^N+1, where N is a power of two, then FFT can be used for fast + /// multiplication of polynomials modulo the polynomial modulus. In this case the + /// variable UsingFFT will be set to true. However, currently Microsoft SEAL requires this + /// to be the case for the parameters to be valid. Therefore, ParametersSet can only + /// be true if UsingFFT is true. + /// + public bool UsingFFT + { + get + { + NativeMethods.EPQ_UsingFFT(NativePtr, out bool result); + return result; + } + } + + /// + /// Tells whether NTT can be used for polynomial multiplication. + /// + /// + /// + /// Tells whether NTT can be used for polynomial multiplication. If the primes in the + /// coefficient modulus are congruent to 1 modulo 2N, where X^N+1 is the polynomial + /// modulus and N is a power of two, then the number-theoretic transform (NTT) can be + /// used for fast multiplications of polynomials modulo the polynomial modulus and + /// coefficient modulus.In this case the variable UsingNTT will be set to true. However, + /// currently Microsoft SEAL requires this to be the case for the parameters to be valid. + /// Therefore, ParametersSet can only be true if UsingNTT is true. + /// + public bool UsingNTT + { + get + { + NativeMethods.EPQ_UsingNTT(NativePtr, out bool result); + return result; + } + } + + /// + /// Tells whether batching is supported by the encryption parameters. + /// + /// + /// + /// Tells whether batching is supported by the encryption parameters. If the plaintext + /// modulus is congruent to 1 modulo 2N, where X^N+1 is the polynomial modulus and N is + /// a power of two, then it is possible to use the BatchEncoder class to view plaintext + /// elements as 2-by-(N/2) matrices of integers modulo the plaintext modulus.This is + /// called batching, and allows the user to operate on the matrix elements(slots) in + /// a SIMD fashion, and rotate the matrix rows and columns.When the computation is + /// easily vectorizable, using batching can yield a huge performance boost.If the + /// encryption parameters support batching, the variable UsingBatching is set to true. + /// + public bool UsingBatching + { + get + { + NativeMethods.EPQ_UsingBatching(NativePtr, out bool result); + return result; + } + } + + /// + /// Tells whether fast plain lift is supported by the encryption parameters. + /// + /// + /// + /// Tells whether fast plain lift is supported by the encryption parameters. A certain + /// performance optimization in multiplication of a ciphertext by a plaintext + /// (Evaluator.MultiplyPlain) and in transforming a plaintext element to NTT domain + /// (Evaluator.TransformToNTT) can be used when the plaintext modulus is smaller than + /// each prime in the coefficient modulus. In this case the variable UsingFastPlainLift + /// is set to true. + /// + public bool UsingFastPlainLift + { + get + { + NativeMethods.EPQ_UsingFastPlainLift(NativePtr, out bool result); + return result; + } + } + + /// + /// Tells whether the coefficient modulus consists of a set of primes that are in + /// decreasing order. + /// + /// + /// + /// Tells whether the coefficient modulus consists of a set of primes that are in + /// decreasing order. If this is true, certain modular reductions in base conversion + /// can be omitted, improving performance. + /// + public bool UsingDescendingModulusChain + { + get + { + NativeMethods.EPQ_UsingDescendingModulusChain(NativePtr, out bool result); + return result; + } + } + + /// + /// Tells whether the encryption parameters are secure based on the standard + /// parameters from HomomorphicEncryption.org security standard. + /// + public SecLevelType SecLevel + { + get + { + NativeMethods.EPQ_SecLevel(NativePtr, out int result); + return (SecLevelType)result; + } + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.EPQ_Destroy(NativePtr); + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs b/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs new file mode 100644 index 0000000000000000000000000000000000000000..1e55bd9405981a5bd5f29d56b52a1d0fb41398b3 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs @@ -0,0 +1,414 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Describes the type of encryption scheme to be used. + /// + public enum SchemeType : byte + { + /// + /// No scheme set; cannot be used for encryption + /// + None = 0x0, + + /// + /// Brakerski/Fan-Vercauteren scheme + /// + BFV = 0x1, + + /// + /// Cheon-Kim-Kim-Song scheme + /// + CKKS = 0x2 + } + + /// + /// Represents the user-customizable encryption scheme settings. + /// + /// + /// + /// Represents user-customizable encryption scheme settings. The parameters (most + /// importantly PolyModulus, CoeffModulus, PlainModulus) significantly affect the + /// performance, capabilities, and security of the encryption scheme. Once an + /// instance of EncryptionParameters is populated with appropriate parameters, it + /// can be used to create an instance of the class, + /// which verifies the validity of the parameters, and performs necessary + /// pre-computations. + /// + /// + /// Picking appropriate encryption parameters is essential to enable a particular + /// application while balancing performance and security. Some encryption settings + /// will not allow some inputs (e.g. attempting to encrypt a polynomial with more + /// coefficients than PolyModulus or larger coefficients than PlainModulus) or + /// support the desired computations (with noise growing too fast due to too large + /// PlainModulus and too small CoeffModulus). + /// + /// + /// The EncryptionParameters class maintains at all times a 256-bit hash of the + /// currently set encryption parameters called the ParmsId. This hash acts as + /// a unique identifier of the encryption parameters and is used by all further + /// objects created for these encryption parameters. The ParmsId is not intended + /// to be directly modified by the user but is used internally for pre-computation + /// data lookup and input validity checks. In modulus switching the user can use + /// the ParmsId to keep track of the chain of encryption parameters. The ParmsId is + /// not exposed in the public API of EncryptionParameters, but can be accessed + /// through the class once the SEALContext + /// has been created. + /// + /// + /// In general, reading from EncryptionParameters is thread-safe, while mutating + /// is not. + /// + /// + /// Choosing inappropriate encryption parameters may lead to an encryption scheme + /// that is not secure, does not perform well, and/or does not support the input + /// and computation of the desired application. We highly recommend consulting an + /// expert in RLWE-based encryption when selecting parameters, as this is where + /// inexperienced users seem to most often make critical mistakes. + /// + /// + public class EncryptionParameters : NativeObject, IEquatable + { + /// + /// Creates an empty set of encryption parameters. + /// + /// + /// Scheme for the encryption parameters + public EncryptionParameters(SchemeType scheme = SchemeType.None) + { + NativeMethods.EncParams_Create((byte)scheme, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates an empty set of encryption parameters. + /// + /// Scheme for the encryption parameters + /// if scheme is not supported + public EncryptionParameters(byte scheme) + { + NativeMethods.EncParams_Create(scheme, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates a copy of a given instance of EncryptionParameters. + /// + /// The EncryptionParameters to copy from + /// if copy is null + public EncryptionParameters(EncryptionParameters copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.EncParams_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Create an instance of Encryption Parameters through a pointer to a + /// native object. + /// + /// Native encryption parameters + /// Whether this instance owns the native pointer + internal EncryptionParameters(IntPtr ptr, bool owned = true) + : base(ptr, owned) + { + } + + /// + /// Overwrites the EncryptionParameters instance with a copy of a given + /// instance. + /// + /// The EncryptionParameters to copy from + /// if assign is null + public void Set(EncryptionParameters assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.EncParams_Set(NativePtr, assign.NativePtr); + } + + /// + /// Returns or Sets the degree of the polynomial modulus parameter. + /// + /// + /// Sets the degree of the polynomial modulus parameter to the specified value. + /// The polynomial modulus directly affects the number of coefficients in plaintext + /// polynomials, the size of ciphertext elements, the computational performance of + /// the scheme (bigger is worse), and the security level(bigger is better). In SEAL + /// the degree of the polynomial modulus must be a power of 2 (e.g. 1024, 2048, 4096, + /// 8192, 16384, or 32768). + /// + public ulong PolyModulusDegree + { + get + { + NativeMethods.EncParams_GetPolyModulusDegree(NativePtr, out ulong result); + return result; + } + set + { + NativeMethods.EncParams_SetPolyModulusDegree(NativePtr, value); + } + } + + /// + /// Get a copy of the currently set coefficient modulus parameter, or + /// set the coefficient modulus parameter. + /// + /// + /// When setting: + /// Sets the coefficient modulus parameter. The coefficient modulus consists of a list + /// of distinct prime numbers, and is represented by a list of + /// objects. The coefficient modulus directly affects the size of ciphertext elements, + /// the amount of computation that the scheme can perform (bigger is better), and the + /// security level (bigger is worse). In Microsoft SEAL each of the prime numbers in + /// the coefficient modulus must be at most 60 bits, and must be congruent to 1 modulo + /// 2*PolyModulusDegree. + /// + /// if the value being set is null + /// if the value being set is invalid + public IEnumerable CoeffModulus + { + get + { + ulong length = 0; + NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, null); + + IntPtr[] coeffArray = new IntPtr[length]; + NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, coeffArray); + + List result = new List(checked((int)length)); + foreach(IntPtr sm in coeffArray) + { + result.Add(new Modulus(sm)); + } + + return result; + } + + set + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + IntPtr[] coeffArray = value.Select(sm => sm.NativePtr).ToArray(); + NativeMethods.EncParams_SetCoeffModulus(NativePtr, (ulong)coeffArray.LongLength, coeffArray); + } + } + + /// + /// Get a copy of the currently set plaintext modulus parameter, or + /// set the plaintext modulus parameter. + /// + /// + /// When setting: + /// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus + /// represented by the class. The plaintext modulus determines + /// the largest coefficient that plaintext polynomials can represent. It also affects the + /// amount of computation that the scheme can perform (bigger is worse). In Microsoft SEAL + /// the plaintext modulus can be at most 60 bits long, but can otherwise be any integer. + /// Note, however, that some features (e.g. batching) require the plaintext modulus to be + /// of a particular form. + /// + /// if the value being set is null + /// if scheme is not SchemeType.BFV + public Modulus PlainModulus + { + get + { + NativeMethods.EncParams_GetPlainModulus(NativePtr, out IntPtr ptr); + Modulus sm = new Modulus(ptr, owned: false); + return sm; + } + set + { + NativeMethods.EncParams_SetPlainModulus(NativePtr, value.NativePtr); + } + } + + /// + /// Sets the plaintext modulus parameter. + /// + /// + /// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus + /// represented by the class. This method instead takes + /// a ulong and automatically creates the Modulus object. The plaintext modulus + /// determines the largest coefficient that plaintext polynomials can represent. It also + /// affects the amount of computation that the scheme can perform (bigger is worse). In + /// Microsoft SEAL the plaintext modulus can be at most 60 bits long, but can otherwise + /// be any integer. Note, however, that some features (e.g. batching) require the + /// plaintext modulus to be of a particular form. + /// + /// The new plaintext modulus + /// if scheme is not CKKS + public void SetPlainModulus(ulong plainModulus) + { + NativeMethods.EncParams_SetPlainModulus(NativePtr, plainModulus); + } + + /// + /// Returns the encryption scheme type. + /// + public SchemeType Scheme + { + get + { + NativeMethods.EncParams_GetScheme(NativePtr, out byte scheme); + return (SchemeType)scheme; + } + } + + /// + /// Returns an upper bound on the size of the EncryptionParameters, as if + /// it was written to an output stream. + /// + /// The compression mode + /// if the compression mode is not + /// supported + /// if the size does not fit in + /// the return type + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.EncParams_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// Saves the EncryptionParameters to an output stream. + /// + /// Saves the EncryptionParameters to an output stream. The output is in + /// binary format and not human-readable. + /// + /// The stream to save the EncryptionParameters to + /// The desired compression mode + /// if stream is null + /// if the stream is closed or does not + /// support writing, or if compression mode is not supported + /// if I/O operations failed + /// if the data to be saved + /// is invalid, or if compression failed + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.EncParams_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// + /// Loads an EncryptionParameters from an input stream overwriting the + /// current EncryptionParameters. + /// + /// The stream to load the EncryptionParameters from + /// if stream is null + /// if the stream is closed or does not + /// support reading + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long Load(Stream stream) + { + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.EncParams_Load(NativePtr, outptr, size, + out outBytes), + stream); + } + + /// + /// Returns the ParmsId of the current parameters. This function is intended + /// for internal use. + /// + internal ParmsId ParmsId + { + get + { + ParmsId id = new ParmsId(); + NativeMethods.EncParams_GetParmsId(NativePtr, id.Block); + return id; + } + } + + /// + /// Compares a given set of encryption parameters to the current set of + /// encryption parameters. + /// + /// + /// Compares a given set of encryption parameters to the current set of encryption + /// parameters. The comparison is performed by comparing hash blocks of the parameter + /// sets rather than comparing the parameters individually. + /// + /// The EncryptionParameters to compare against + public override bool Equals(object obj) + { + EncryptionParameters encParams = obj as EncryptionParameters; + return Equals(encParams); + } + + /// + /// Returns a hash-code based on the EncryptionParameters. + /// + public override int GetHashCode() + { + return Utilities.ComputeArrayHashCode(ParmsId.Block); + } + + #region IEquatable methods + + /// + /// Compares a given set of encryption parameters to the current set of + /// encryption parameters. + /// + /// + /// + /// Compares a given set of encryption parameters to the current set of encryption + /// parameters. The comparison is performed by comparing hash blocks of the parameter + /// sets rather than comparing the parameters individually. + /// + /// The EncryptionParameters to compare against + public bool Equals(EncryptionParameters other) + { + if (null == other) + return false; + + NativeMethods.EncParams_Equals(NativePtr, other.NativePtr, out bool result); + return result; + } + + #endregion + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.EncParams_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Encryptor.cs b/bigpiseal3.5.1/dotnet/src/Encryptor.cs new file mode 100644 index 0000000000000000000000000000000000000000..fd4aba54af8f4c9c586dc01e89082ea2578fa409 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Encryptor.cs @@ -0,0 +1,484 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Encrypts Plaintext objects into Ciphertext objects. + /// + /// + /// + /// Encrypts Plaintext objects into Ciphertext objects. Constructing an Encryptor + /// requires a SEALContext with valid encryption parameters, the public key and/or + /// the secret key. If an Encrytor is given a secret key, it supports symmetric-key + /// encryption. If an Encryptor is given a public key, it supports asymmetric-key + /// encryption. + /// + /// + /// Overloads + /// For the encrypt function we provide two overloads concerning the memory pool used in + /// allocations needed during the operation. In one overload the global memory pool is used + /// for this purpose, and in another overload the user can supply a MemoryPoolHandle + /// to to be used instead. This is to allow one single Encryptor to be used concurrently by + /// several threads without running into thread contention in allocations taking place during + /// operations. For example, one can share one single Encryptor across any number of threads, + /// but in each thread call the encrypt function by giving it a thread-local MemoryPoolHandle + /// to use. It is important for a developer to understand how this works to avoid unnecessary + /// performance bottlenecks. + /// + /// + /// NTT form + /// When using the BFV scheme (SchemeType.BFV), all plaintext and ciphertexts should + /// remain by default in the usual coefficient representation, i.e. not in NTT form. + /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts + /// should remain by default in NTT form. We call these scheme-specific NTT states the + /// "default NTT form". Decryption requires the input ciphertexts to be in the default + /// NTT form, and will throw an exception if this is not the case. + /// + /// + public class Encryptor : NativeObject + { + /// + /// Creates an Encryptor instance initialized with the specified SEALContext, + /// public key, and/or secret key. + /// + /// The SEALContext + /// The public key + /// The secret key + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + /// if publicKey is not valid + /// if secretKey is not null and not valid + public Encryptor(SEALContext context, PublicKey publicKey, SecretKey secretKey = null) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + if (!ValCheck.IsValidFor(publicKey, context)) + throw new ArgumentException("Public key is not valid for encryption parameters"); + + if (null == secretKey) + { + NativeMethods.Encryptor_Create( + context.NativePtr, publicKey.NativePtr, IntPtr.Zero, out IntPtr ptr); + NativePtr = ptr; + } + else + { + if (!ValCheck.IsValidFor(secretKey, context)) + throw new ArgumentException("Secret key is not valid for encryption parameters"); + NativeMethods.Encryptor_Create( + context.NativePtr, publicKey.NativePtr, secretKey.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + } + + /// + /// Creates an Encryptor instance initialized with the specified SEALContext + /// and secret key. + /// + /// The SEALContext + /// The secret key + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + /// if secretKey is not valid + public Encryptor(SEALContext context, SecretKey secretKey) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + if (!ValCheck.IsValidFor(secretKey, context)) + throw new ArgumentException("Secret key is not valid for encryption parameters"); + + NativeMethods.Encryptor_Create(context.NativePtr, IntPtr.Zero, secretKey.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Give a new instance of public key. + /// + /// The public key + /// if publicKey is not valid + public void SetPublicKey(PublicKey publicKey) + { + NativeMethods.Encryptor_SetPublicKey(NativePtr, publicKey.NativePtr); + } + + /// + /// Give a new instance of secret key. + /// + /// The secret key + /// if secretKey is not valid + public void SetSecretKey(SecretKey secretKey) + { + NativeMethods.Encryptor_SetSecretKey(NativePtr, secretKey.NativePtr); + } + + /// + /// Encrypts a plaintext with the public key and stores the result in destination. + /// + /// + /// + /// Encrypts a plaintext with the public key and stores the result in destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to: + /// 1) in BFV, the highest (data) level in the modulus switching chain, + /// 2) in CKKS, the encryption parameters of the plaintext. + /// Dynamic memory allocations in the process are allocated from the memory + /// pool pointed to by the given MemoryPoolHandle. + /// + /// + /// The plaintext to encrypt + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destination + /// are null + /// if a public key is not + /// set + /// if plain is not valid for the + /// encryption parameters + /// if plain is not in default NTT + /// form + /// if pool is uninitialized + public void Encrypt( + Plaintext plain, Ciphertext destination, + MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_Encrypt( + NativePtr, plain.NativePtr, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a zero plaintext with the public key and stores the result in + /// destination. + /// + /// + /// + /// Encrypts a zero plaintext with the public key and stores the result in + /// destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to + /// the given ParmsId. Dynamic memory allocations in the process are allocated + /// from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// + /// The ParmsId for the resulting ciphertext + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either parmsId or destination are + /// null + /// if a public key is not set + /// if parmsId is not valid for the encryption + /// parameters + /// if pool is uninitialized + public void EncryptZero( + ParmsId parmsId, Ciphertext destination, + MemoryPoolHandle pool = null) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_EncryptZero1( + NativePtr, parmsId.Block, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a zero plaintext with the public key and stores the result in + /// destination. + /// + /// + /// + /// Encrypts a zero plaintext with the public key and stores the result in + /// destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to the + /// highest (data) level in the modulus switching chain. Dynamic memory allocations + /// in the process are allocated from the memory pool pointed to by the given + /// MemoryPoolHandle. + /// + /// + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if destination is null + /// if a public key is not set + /// if pool is uninitialized + public void EncryptZero(Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_EncryptZero2(NativePtr, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a plaintext with the secret key and stores the result in destination. + /// + /// + /// + /// Encrypts a plaintext with the secret key and stores the result in destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to: + /// 1) in BFV, the highest (data) level in the modulus switching chain, + /// 2) in CKKS, the encryption parameters of the plaintext. + /// Dynamic memory allocations in the process are allocated from the memory + /// pool pointed to by the given MemoryPoolHandle. + /// + /// + /// The plaintext to encrypt + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or destination are + /// null + /// if a secret key is not set + /// if plain is not valid for the encryption + /// parameters + /// if plain is not in default NTT form + /// if pool is uninitialized + public void EncryptSymmetric( + Plaintext plain, Ciphertext destination, + MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_EncryptSymmetric( + NativePtr, plain.NativePtr, false, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a zero plaintext with the secret key and stores the result in + /// destination. + /// + /// + /// + /// Encrypts a zero plaintext with the secret key and stores the result in + /// destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to the given + /// ParmsId. Dynamic memory allocations in the process are allocated from the + /// memory pool pointed to by the given MemoryPoolHandle. + /// + /// + /// The ParmsId for the resulting ciphertext + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either parmsId or destination are + /// null + /// if a secret key is not set + /// if parmsId is not valid for the encryption + /// parameters + /// if pool is uninitialized + public void EncryptZeroSymmetric( + ParmsId parmsId, Ciphertext destination, + MemoryPoolHandle pool = null) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_EncryptZeroSymmetric1( + NativePtr, parmsId.Block, false, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a zero plaintext with the secret key and stores the result in + /// destination. + /// + /// + /// + /// Encrypts a zero plaintext with the secret key and stores the result in + /// destination. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to the + /// highest (data) level in the modulus switching chain. Dynamic memory allocations + /// in the process are allocated from the memory pool pointed to by the given + /// MemoryPoolHandle. + /// + /// + /// The ciphertext to overwrite with the encrypted + /// plaintext + /// The MemoryPoolHandle pointing to a valid memory pool + /// if destination is null + /// if a secret key is not set + /// if pool is uninitialized + public void EncryptZeroSymmetric( + Ciphertext destination, + MemoryPoolHandle pool = null) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Encryptor_EncryptZeroSymmetric2( + NativePtr, false, destination.NativePtr, poolHandle); + } + + /// + /// Encrypts a plaintext with the secret key and returns the ciphertext as + /// a serializable object. + /// + /// + /// + /// Encrypts a plaintext with the secret key and returns the ciphertext as + /// a serializable object. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to: + /// 1) in BFV, the highest (data) level in the modulus switching chain, + /// 2) in CKKS, the encryption parameters of the plaintext. + /// Dynamic memory allocations in the process are allocated from the memory + /// pool pointed to by the given MemoryPoolHandle. + /// + /// + /// Half of the ciphertext data is pseudo-randomly generated from a seed to + /// reduce the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// The plaintext to encrypt + /// The MemoryPoolHandle pointing to a valid memory pool + /// if plain is null + /// if a secret key is not set + /// if plain is not valid for the encryption + /// parameters + /// if plain is not in default NTT + /// form + /// if pool is uninitialized + public Serializable EncryptSymmetric( + Plaintext plain, + MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + Ciphertext destination = new Ciphertext(); + NativeMethods.Encryptor_EncryptSymmetric( + NativePtr, plain.NativePtr, true, destination.NativePtr, poolHandle); + return new Serializable(destination); + } + + /// + /// Encrypts a zero plaintext with the secret key and returns the ciphertext + /// as a serializable object. + /// + /// + /// + /// Encrypts a zero plaintext with the secret key and returns the ciphertext + /// as a serializable object. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to + /// the given ParmsId. Dynamic memory allocations in the process are allocated + /// from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// + /// Half of the ciphertext data is pseudo-randomly generated from a seed to + /// reduce the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// The ParmsId for the resulting ciphertext + /// The MemoryPoolHandle pointing to a valid memory + /// pool + /// if parmsId is null + /// if a secret key is not + /// set + /// if parmsId is not valid for the + /// encryption parameters + /// if pool is uninitialized + public Serializable EncryptZeroSymmetric( + ParmsId parmsId, + MemoryPoolHandle pool = null) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + Ciphertext destination = new Ciphertext(); + NativeMethods.Encryptor_EncryptZeroSymmetric1( + NativePtr, parmsId.Block, true, destination.NativePtr, poolHandle); + return new Serializable(destination); + } + + /// + /// Encrypts a zero plaintext with the secret key and returns the ciphertext + /// as a serializable object. + /// + /// + /// + /// Encrypts a zero plaintext with the secret key and returns the ciphertext + /// as a serializable object. + /// + /// + /// The encryption parameters for the resulting ciphertext correspond to the + /// highest (data) level in the modulus switching chain. Dynamic memory + /// allocations in the process are allocated from the memory pool pointed to + /// by the given MemoryPoolHandle. + /// + /// + /// Half of the ciphertext data is pseudo-randomly generated from a seed to + /// reduce the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// The MemoryPoolHandle pointing to a valid memory + /// pool + /// if a secret key is not + /// set + /// if pool is uninitialized + public Serializable EncryptZeroSymmetric(MemoryPoolHandle pool = null) + { + IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero; + Ciphertext destination = new Ciphertext(); + NativeMethods.Encryptor_EncryptZeroSymmetric2( + NativePtr, true, destination.NativePtr, poolHandle); + return new Serializable(destination); + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.Encryptor_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Evaluator.cs b/bigpiseal3.5.1/dotnet/src/Evaluator.cs new file mode 100644 index 0000000000000000000000000000000000000000..84a53ce33c3f0c87f6dcd4a447933952a6c2c985 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Evaluator.cs @@ -0,0 +1,1628 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Provides operations on ciphertexts. + /// + /// + /// + /// + /// Provides operations on ciphertexts. Due to the properties of the encryption scheme, + /// the arithmetic operations pass through the encryption layer to the underlying plaintext, + /// changing it according to the type of the operation. Since the plaintext elements are + /// fundamentally polynomials in the polynomial quotient ring Z_T[x]/(X^N+1), where T is + /// the plaintext modulus and X^N+1 is the polynomial modulus, this is the ring where the + /// arithmetic operations will take place. BatchEncoder (batching) provider an alternative + /// possibly more convenient view of the plaintext elements as 2-by-(N2/2) matrices of + /// integers modulo the plaintext modulus. In the batching view the arithmetic operations + /// act on the matrices element-wise. Some of the operations only apply in the batching + /// view, such as matrix row and column rotations. Other operations such as relinearization + /// have no semantic meaning but are necessary for performance reasons. + /// + /// + /// Arithmetic Operations + /// The core operations are arithmetic operations, in particular multiplication and addition + /// of ciphertexts. In addition to these, we also provide negation, subtraction, squaring, + /// exponentiation, and multiplication and addition of several ciphertexts for convenience. + /// in many cases some of the inputs to a computation are plaintext elements rather than + /// ciphertexts. For this we provide fast "plain" operations: plain addition, plain subtraction, + /// and plain multiplication. + /// + /// + /// Relinearization + /// One of the most important non-arithmetic operations is relinearization, which takes + /// as input a ciphertext of size K+1 and relinearization keys (at least K-1 keys are needed), + /// and changes the size of the ciphertext down to 2 (minimum size). For most use-cases only + /// one relinearization key suffices, in which case relinearization should be performed after + /// every multiplication. Homomorphic multiplication of ciphertexts of size K+1 and L+1 + /// outputs a ciphertext of size K+L+1, and the computational cost of multiplication is + /// proportional to K*L. Plain multiplication and addition operations of any type do not + /// change the size. Relinearization requires relinearization keys to have been generated. + /// + /// + /// Rotations + /// When batching is enabled, we provide operations for rotating the plaintext matrix rows + /// cyclically left or right, and for rotating the columns (swapping the rows). Rotations + /// require Galois keys to have been generated. + /// + /// + /// Other Operations + /// We also provide operations for transforming ciphertexts to NTT form and back, and for + /// transforming plaintext polynomials to NTT form. These can be used in a very fast plain + /// multiplication variant, that assumes the inputs to be in NTT form. Since the NTT has to + /// be done in any case in plain multiplication, this function can be used when e.g. one + /// plaintext input is used in several plain multiplication, and transforming it several + /// times would not make sense. + /// + /// + /// NTT form + /// When using the BFV scheme (SchemeType.BFV), all plaintexts and ciphertexts should + /// remain by default in the usual coefficient representation, i.e., not in NTT form. + /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts + /// should remain by default in NTT form. We call these scheme-specific NTT states the + /// "default NTT form". Some functions, such as add, work even if the inputs are not in + /// the default state, but others, such as multiply, will throw an exception. The output + /// of all evaluation functions will be in the same state as the input(s), with the + /// exception of the TransformToNTT and TransformFromNTT functions, which change the + /// state. Ideally, unless these two functions are called, all other functions should + /// "just work". + /// + /// + /// for more details on encryption parameters. + /// for more details on batching + /// for more details on relinearization keys. + /// for more details on Galois keys. + public class Evaluator : NativeObject + { + /// + /// Creates an Evaluator instance initialized with the specified SEALContext. + /// + /// + /// The SEALContext + /// if context is null + /// if the context is not set or encryption + /// parameters are not valid + public Evaluator(SEALContext context) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + + NativeMethods.Evaluator_Create(context.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Negates a ciphertext. + /// + /// + /// The ciphertext to negate + /// if encrypted is null + /// if encrypted is not valid for the encryption parameters + /// if result ciphertext is transparent + public void NegateInplace(Ciphertext encrypted) + { + Negate(encrypted, destination: encrypted); + } + + /// + /// Negates a ciphertext and stores the result in the destination parameter. + /// + /// The ciphertext to negate + /// The ciphertext to overwrite with the negated result + /// if either encrypted or destionation are null + /// if encrypted is not valid for the encryption parameters + /// if result ciphertext is transparent + public void Negate(Ciphertext encrypted, Ciphertext destination) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_Negate(NativePtr, encrypted.NativePtr, destination.NativePtr); + } + + /// + /// Adds two ciphertexts. + /// + /// + /// This function adds together encrypted1 and encrypted2 and stores the result in encrypted1. + /// + /// The first ciphertext to add + /// The second ciphertext to add + /// if either encrypted1 or encrypted2 are null + /// if encrypted1 or encrypted2 is not valid for + /// the encryption parameters + /// if encrypted1 and encrypted2 are in different + /// NTT forms + /// if encrypted1 and encrypted2 have different scale + /// if result ciphertext is transparent + public void AddInplace(Ciphertext encrypted1, Ciphertext encrypted2) + { + Add(encrypted1, encrypted2, destination: encrypted1); + } + + /// + /// Adds two ciphertexts. + /// + /// + /// This function adds together encrypted1 and encrypted2 and stores the result in the destination + /// parameter. + /// + /// The first ciphertext to add + /// The second ciphertext to add + /// The ciphertext to overwrite with the addition result + /// if either encrypted1, encrypted2 or destination are null + /// if encrypted1 or encrypted2 is not valid for + /// the encryption parameters + /// if encrypted1 and encrypted2 are in different + /// NTT forms + /// if encrypted1 and encrypted2 have different scale + /// if result ciphertext is transparent + public void Add(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination) + { + if (null == encrypted1) + throw new ArgumentNullException(nameof(encrypted1)); + if (null == encrypted2) + throw new ArgumentNullException(nameof(encrypted2)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_Add(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr); + } + + /// + /// Adds together a vector of ciphertexts and stores the result in the destination + /// parameter. + /// + /// The ciphertexts to add + /// The ciphertext to overwrite with the addition result + /// if either encrypteds or destination are null + /// if encrypteds is empty + /// if the encrypteds are not valid for the encryption + /// parameters + /// if encrypteds are in different NTT forms + /// if encrypteds have different scale + /// if result ciphertext is transparent + public void AddMany(IEnumerable encrypteds, Ciphertext destination) + { + if (null == encrypteds) + throw new ArgumentNullException(nameof(encrypteds)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray(); + NativeMethods.Evaluator_AddMany(NativePtr, (ulong)encarray.Length, encarray, destination.NativePtr); + } + + /// + /// Subtracts two ciphertexts. + /// + /// + /// This function computes the difference of encrypted1 and encrypted2, and stores the result in encrypted1. + /// + /// The ciphertext to subtract from + /// The ciphertext to subtract + /// if either encrypted1 or encrypted2 are null + /// if encrypted1 or encrypted2 is not valid for the + /// encryption parameters + /// if encrypted1 and encrypted2 are in different + /// NTT forms + /// if encrypted1 and encrypted2 have different scale + /// if result ciphertext is transparent + public void SubInplace(Ciphertext encrypted1, Ciphertext encrypted2) + { + Sub(encrypted1, encrypted2, destination: encrypted1); + } + + /// + /// Subtracts two ciphertexts. + /// + /// This function computes the difference of encrypted1 and encrypted2 and stores the result + /// in the destination parameter. + /// + /// The ciphertext to subtract from + /// The ciphertext to subtract + /// The ciphertext to overwrite with the subtraction result + /// if either encrypted1, encrypted2 or destination are null + /// if encrypted1 or encrypted2 is not valid for the + /// encryption parameters + /// if encrypted1 and encrypted2 are in different + /// NTT forms + /// if encrypted1 and encrypted2 have different scale + /// if result ciphertext is transparent + public void Sub(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination) + { + if (null == encrypted1) + throw new ArgumentNullException(nameof(encrypted1)); + if (null == encrypted2) + throw new ArgumentNullException(nameof(encrypted2)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_Sub(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr); + } + + /// + /// Multiplies two ciphertexts. + /// + /// This functions computes the product of encrypted1 and encrypted2 and stores the + /// result in encrypted1. Dynamic memory allocations in the process are allocated from the + /// memory pool pointed to by the given MemoryPoolHandle. + /// + /// The first ciphertext to multiply + /// The second ciphertext to multiply + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted1, encrypted2 are null + /// if encrypted1 or encrypted2 is not valid for the + /// encryption parameters + /// if encrypted1 or encrypted2 is not in the default + /// NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void MultiplyInplace(Ciphertext encrypted1, Ciphertext encrypted2, + MemoryPoolHandle pool = null) + { + Multiply(encrypted1, encrypted2, destination: encrypted1, pool: pool); + } + + /// + /// Multiplies two ciphertexts. + /// + /// + /// This functions computes the product of encrypted1 and encrypted2 and stores the result + /// in the destination parameter. Dynamic memory allocations in the process are allocated + /// from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The first ciphertext to multiply + /// The second ciphertext to multiply + /// The ciphertext to overwrite with the multiplication result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted1, encrypted2, destination are null + /// if encrypted1 or encrypted2 is not valid for the + /// encryption parameters + /// if encrypted1 or encrypted2 is not in the default + /// NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void Multiply(Ciphertext encrypted1, Ciphertext encrypted2, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted1) + throw new ArgumentNullException(nameof(encrypted1)); + if (null == encrypted2) + throw new ArgumentNullException(nameof(encrypted2)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_Multiply(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Squares a ciphertext. + /// + /// + /// This functions computes the square of encrypted. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to square + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted are null + /// if encrypted is not valid for the encryption + /// parameters + /// if encrypted is not in the default NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void SquareInplace(Ciphertext encrypted, MemoryPoolHandle pool = null) + { + Square(encrypted, destination: encrypted, pool: pool); + } + + /// + /// Squares a ciphertext. + /// + /// + /// This functions computes the square of encrypted and stores the result in the destination + /// parameter. Dynamic memory allocations in the process are allocated from the memory pool + /// pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to square + /// The ciphertext to overwrite with the square + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, destination are null + /// if encrypted is not valid for the encryption + /// parameters + /// if encrypted is not in the default NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void Square(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_Square(NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Relinearizes a ciphertext. + /// + /// + /// This functions relinearizes encrypted, reducing its size down to 2. If the size + /// of encrypted is K+1, the given relinearization keys need to have size at least K-1. + /// Dynamic memory allocations in the process are allocated from the memory pool pointed + /// to by the given MemoryPoolHandle. + /// + /// The ciphertext to relinearize + /// The relinearization keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, relinKeys are null + /// if encrypted or relinKeys is not valid for the + /// encryption parameters + /// if encrypted is not in the default NTT form + /// if relinKeys do not correspond to the top level + /// parameters in the current context + /// if the size of relinKeys is too small + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RelinearizeInplace(Ciphertext encrypted, RelinKeys relinKeys, + MemoryPoolHandle pool = null) + { + Relinearize(encrypted, relinKeys, destination: encrypted, pool: pool); + } + + /// + /// Relinearizes a ciphertext. + /// + /// + /// This functions relinearizes encrypted, reducing its size down to 2, and stores the + /// result in the destination parameter. If the size of encrypted is K+1, the given + /// relinearization keys need to have size at least K-1. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to relinearize + /// The relinearization keys + /// The ciphertext to overwrite with the relinearized result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, relinKeys or destination are null + /// if encrypted or relinKeys is not valid for the + /// encryption parameters + /// if encrypted is not in the default NTT form + /// if relinKeys do not correspond to the top level + /// parameters in the current context + /// if the size of relinKeys is too small + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void Relinearize(Ciphertext encrypted, RelinKeys relinKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == relinKeys) + throw new ArgumentNullException(nameof(relinKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_Relinearize( + NativePtr, encrypted.NativePtr, relinKeys.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1} and stores the result in the destination parameter. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1} and stores the result in the destination parameter. Dynamic + /// memory allocations in the process are allocated from the memory pool pointed to by + /// the given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The ciphertext to overwrite with the modulus switched result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or destination are null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if encrypted is already at lowest level + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void ModSwitchToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_ModSwitchToNext( + NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1}. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1}. Dynamic memory allocations in the process are allocated from + /// the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The MemoryPoolHandle pointing to a valid memory pool + /// if encrypted is null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if encrypted is already at lowest level + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void ModSwitchToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null) + { + ModSwitchToNext(encrypted, destination: encrypted, pool: pool); + } + + /// + /// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo + /// q_1...q_{k-1}. + /// + /// The plaintext to be switched to a smaller modulus + /// if plain is null + /// if plain is not in NTT form + /// if plain is not valid for the encryption parameters + /// if plain is already at lowest level + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + public void ModSwitchToNextInplace(Plaintext plain) + { + ModSwitchToNext(plain, destination: plain); + } + + /// + /// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo + /// q_1...q_{k-1} and stores the result in the destination parameter. + /// + /// The plaintext to be switched to a smaller modulus + /// destination The plaintext to overwrite with the modulus switched result + /// if either plain or destination are null + /// if plain is not in NTT form + /// if plain is not valid for the encryption parameters + /// if plain is already at lowest level + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + /// if pool is uninitialized + public void ModSwitchToNext(Plaintext plain, Plaintext destination) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_ModSwitchToNext(NativePtr, plain.NativePtr, destination.NativePtr); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId. Dynamic memory allocations in + /// the process are allocated from the memory pool pointed to by the given + /// MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The target parmsId + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or parmsId are null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if parmsId is not valid for the encryption parameters + /// if encrypted is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void ModSwitchToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null) + { + ModSwitchTo(encrypted, parmsId, destination: encrypted, pool: pool); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId and stores the result in the + /// destination parameter. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId and stores the result in the + /// destination parameter. Dynamic memory allocations in the process are allocated + /// from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The target parmsId + /// The ciphertext to overwrite with the modulus switched result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, parmsId or destination are null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if parmsId is not valid for the encryption parameters + /// if encrypted is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void ModSwitchTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_ModSwitchTo( + NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr); + } + + /// + /// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the + /// modulus down until the parameters reach the given ParmsId. + /// + /// The plaintext to be switched to a smaller modulus + /// The target parmsId + /// if either plain or parmsId is null + /// if plain is not in NTT form + /// if plain is not valid for the encryption parameters + /// if parmsId is not valid for the encryption parameters + /// if plain is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + public void ModSwitchToInplace(Plaintext plain, ParmsId parmsId) + { + ModSwitchTo(plain, parmsId, destination: plain); + } + + /// + /// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the + /// modulus down until the parameters reach the given ParmsId and stores the result in + /// the destination parameter. + /// + /// The plaintext to be switched to a smaller modulus + /// The target parmsId + /// The plaintext to overwrite with the modulus switched result + /// if either plain, parmsId or destination are null + /// if plain is not in NTT form + /// if plain is not valid for the encryption parameters + /// if parmsId is not valid for the encryption parameters + /// if plain is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if, when using SchemeType.CKKS, the scale is too + /// large for the new encryption parameters + public void ModSwitchTo(Plaintext plain, ParmsId parmsId, + Plaintext destination) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_ModSwitchTo(NativePtr, plain.NativePtr, parmsId.Block, destination.NativePtr); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1}, scales the message down accordingly, and stores the + /// result in the destination parameter. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1}, scales the message down accordingly, and stores the + /// result in the destination parameter. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The ciphertext to overwrite with the modulus switched result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or destination are null + /// if the scheme is invalid for rescaling + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if encrypted is already at lowest level + /// if pool is uninitialized + /// if result ciphertext is transparent + public void RescaleToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_RescaleToNext( + NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1} and scales the message down accordingly. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down to q_1...q_{k-1} and scales the message down accordingly. Dynamic memory + /// allocations in the process are allocated from the memory pool pointed to by the + /// given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The MemoryPoolHandle pointing to a valid memory pool + /// if encrypted is null + /// if the scheme is invalid for rescaling + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// guaranteed to be + /// if encrypted is already at lowest level + /// if pool is uninitialized + /// if result ciphertext is transparent + public void RescaleToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null) + { + RescaleToNext(encrypted, destination: encrypted, pool: pool); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId and scales the message down + /// accordingly. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId and scales the message down + /// accordingly. Dynamic memory allocations in the process are allocated from the + /// memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The target parmsId + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or parmsId are null + /// if the scheme is invalid for rescaling + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if parmsId is not valid for the encryption parameters + /// if encrypted is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if pool is uninitialized + /// if result ciphertext is transparent + public void RescaleToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null) + { + RescaleTo(encrypted, parmsId, destination: encrypted, pool: pool); + } + + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId, scales the message down + /// accordingly, and stores the result in the destination parameter. + /// + /// + /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus + /// down until the parameters reach the given ParmsId, scales the message down + /// accordingly, and stores the result in the destination parameter. Dynamic memory + /// allocations in the process are allocated from the memory pool pointed to by the + /// given MemoryPoolHandle. + /// + /// The ciphertext to be switched to a smaller modulus + /// The target parmsId + /// The ciphertext to overwrite with the modulus switched result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, parmsId or destination are null. + /// if the scheme is invalid for rescaling + /// if encrypted is not valid for the encryption parameters + /// if encrypted is not in the default NTT form + /// if parmsId is not valid for the encryption parameters + /// if encrypted is already at lower level in modulus chain + /// than the parameters corresponding to parmsId + /// if pool is uninitialized + /// if result ciphertext is transparent + public void RescaleTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_RescaleTo( + NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr); + } + + /// + /// Multiplies several ciphertexts together. This function computes the product of several + /// ciphertext given as an IEnumerable and stores the result in the destination parameter. + /// + /// + /// Multiplies several ciphertexts together. This function computes the product of several + /// ciphertext given as an IEnumerable and stores the result in the destination parameter. + /// The multiplication is done in a depth-optimal order, and relinearization is performed + /// automatically after every multiplication in the process. In relinearization the given + /// relinearization keys are used. Dynamic memory allocations in the process are allocated + /// from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertexts to multiply + /// The relinearization keys + /// The ciphertext to overwrite with the multiplication result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypteds, relinKeys or destination are null + /// if scheme is not SchemeType.BFV + /// if encrypteds is empty + /// if the ciphertexts or relinKeys are not valid for + /// the encryption parameters + /// if encrypteds are not in the default NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if the size of relinKeys is too small + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void MultiplyMany(IEnumerable encrypteds, RelinKeys relinKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypteds) + throw new ArgumentNullException(nameof(encrypteds)); + if (null == relinKeys) + throw new ArgumentNullException(nameof(relinKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray(); + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_MultiplyMany( + NativePtr, (ulong)encarray.Length, encarray, relinKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Exponentiates a ciphertext. + /// + /// + /// This functions raises encrypted to a power. Dynamic memory allocations in the process + /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. The + /// exponentiation is done in a depth-optimal order, and relinearization is performed + /// automatically after every multiplication in the process. In relinearization the given + /// relinearization keys are used. + /// + /// The ciphertext to exponentiate + /// The power to raise the ciphertext to + /// The relinearization keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or relinKeys are null + /// if scheme is not SchemeType.BFV + /// if encrypted or relinKeys is not valid for the + /// encryption parameters + /// if encrypted is not in the default NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if exponent is zero + /// if the size of relinKeys is too small + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void ExponentiateInplace(Ciphertext encrypted, ulong exponent, + RelinKeys relinKeys, MemoryPoolHandle pool = null) + { + Exponentiate(encrypted, exponent, relinKeys, destination: encrypted, pool: pool); + } + + /// + /// Exponentiates a ciphertext. + /// + /// + /// This functions raises encrypted to a power and stores the result in the destination + /// parameter. Dynamic memory allocations in the process are allocated from the memory pool + /// pointed to by the given MemoryPoolHandle. The exponentiation is done in a depth-optimal + /// order, and relinearization is performed automatically after every multiplication in the + /// process. In relinearization the given relinearization keys are used. + /// + /// The ciphertext to exponentiate + /// The power to raise the ciphertext to + /// The relinearization keys + /// The ciphertext to overwrite with the power + /// The MemoryPoolHandle pointing to a valid memory pool + /// if scheme is not SchemeType.BFV + /// if encrypted or relinKeys is not valid for the + /// encryption parameters + /// if encrypted is not in the default NTT form + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if exponent is zero + /// if the size of relinKeys is too small + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void Exponentiate(Ciphertext encrypted, ulong exponent, RelinKeys relinKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == relinKeys) + throw new ArgumentNullException(nameof(relinKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_Exponentiate( + NativePtr, encrypted.NativePtr, exponent, relinKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Adds a ciphertext and a plaintext. + /// + /// + /// Adds a ciphertext and a plaintext. The plaintext must be valid for the current + /// encryption parameters. + /// + /// The ciphertext to add + /// The plaintext to add + /// if either encrypted or plain are null + /// if encrypted or plain is not valid for the encryption + /// parameters + /// if encrypted or plain is in NTT form + /// if result ciphertext is transparent + public void AddPlainInplace(Ciphertext encrypted, Plaintext plain) + { + AddPlain(encrypted, plain, destination: encrypted); + } + + /// + /// Adds a ciphertext and a plaintext. + /// + /// + /// Adds a ciphertext and a plaintext. This function adds a ciphertext and a plaintext + /// and stores the result in the destination parameter. The plaintext must be valid for + /// the current encryption parameters. + /// + /// The ciphertext to add + /// The plaintext to add + /// The ciphertext to overwrite with the addition result + /// if either encrypted, plain or destination are null + /// if encrypted or plain is not valid for the encryption + /// parameters + /// if encrypted or plain is in NTT form + /// if result ciphertext is transparent + public void AddPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_AddPlain( + NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr); + } + + /// + /// Subtracts a plaintext from a ciphertext. + /// + /// + /// Subtracts a plaintext from a ciphertext. The plaintext must be valid for the current + /// encryption parameters. + /// + /// The ciphertext to subtract from + /// The plaintext to subtract + /// if either encrypted or plain are null + /// if encrypted or plain is not valid for the encryption + /// parameters + /// if encrypted or plain is in NTT form + /// if result ciphertext is transparent + public void SubPlainInplace(Ciphertext encrypted, Plaintext plain) + { + SubPlain(encrypted, plain, destination: encrypted); + } + + /// + /// Subtracts a plaintext from a ciphertext. + /// + /// This function subtracts a plaintext from a ciphertext and stores the result in the + /// destination parameter. The plaintext must be valid for the current encryption parameters. + /// + /// The ciphertext to subtract from + /// The plaintext to subtract + /// The ciphertext to overwrite with the subtraction result + /// if either encrypted, plain or destination are null + /// if encrypted or plain is not valid for the encryption + /// parameters + /// if encrypted or plain is in NTT form + /// if result ciphertext is transparent + public void SubPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_SubPlain( + NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr); + } + + /// + /// Multiplies a ciphertext with a plaintext. + /// + /// Multiplies a ciphertext with a plaintext. The plaintext must be valid for the + /// current encryption parameters, and cannot be identially 0. Dynamic memory allocations in + /// the process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to multiply + /// The plaintext to multiply + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or plain are null. + /// if the encrypted or plain is not valid for the encryption + /// parameters + /// if encrypted and plain are in different NTT forms + /// if plain is zero + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void MultiplyPlainInplace(Ciphertext encrypted, Plaintext plain, MemoryPoolHandle pool = null) + { + MultiplyPlain(encrypted, plain, destination: encrypted, pool: pool); + } + + /// + /// Multiplies a ciphertext with a plaintext. + /// + /// + /// This function multiplies a ciphertext with a plaintext and stores the result in the + /// destination parameter. The plaintext must be valid for the current encryption parameters, + /// and cannot be identially 0. Dynamic memory allocations in the process are allocated from + /// the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to multiply + /// The plaintext to multiply + /// The ciphertext to overwrite with the multiplication result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, plain or destination are null + /// if the encrypted or plain is not valid for the + /// encryption parameters + /// if encrypted and plain are in different NTT forms + /// if plain is zero + /// if, when using SchemeType.CKKS, the output scale + /// is too large for the encryption parameters + /// if pool is uninitialized + /// if result ciphertext is transparent + public void MultiplyPlain(Ciphertext encrypted, Plaintext plain, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_MultiplyPlain( + NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Transforms a plaintext to NTT domain. + /// + /// This functions applies the Number Theoretic Transform to a plaintext by first + /// embedding integers modulo the plaintext modulus to integers modulo the coefficient + /// modulus and then performing David Harvey's NTT on the resulting polynomial. The + /// transformation is done with respect to encryption parameters corresponding to a given + /// parmsId. For the operation to be valid, the plaintext must have degree less than + /// PolyModulusDegree and each coefficient must be less than the plaintext modulus, i.e., + /// the plaintext must be a valid plaintext under the current encryption parameters. + /// Dynamic memory allocations in the process are allocated from the memory pool pointed + /// to by the given MemoryPoolHandle. + /// + /// The plaintext to transform + /// The ParmsId with respect to which the NTT is done + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain or parmsId are null + /// if plain is already in NTT form + /// if plain or parmsId is not valid for the encryption + /// parameters + /// if pool is uninitialized + public void TransformToNTTInplace(Plaintext plain, ParmsId parmsId, MemoryPoolHandle pool = null) + { + TransformToNTT(plain, parmsId, destinationNTT: plain, pool: pool); + } + + /// + /// Transforms a plaintext to NTT domain. + /// + /// + /// This functions applies the Number Theoretic Transform to a plaintext by first + /// embedding integers modulo the plaintext modulus to integers modulo the coefficient + /// modulus and then performing David Harvey's NTT on the resulting polynomial. The + /// transformation is done with respect to encryption parameters corresponding to + /// a given ParmsId. The result is stored in the destinationNTT parameter. For the + /// operation to be valid, the plaintext must have degree less than PolyModulusDegree + /// and each coefficient must be less than the plaintext modulus, i.e., the plaintext + /// must be a valid plaintext under the current encryption parameters. Dynamic memory + /// allocations in the process are allocated from the memory pool pointed to by the + /// given MemoryPoolHandle. + /// + /// The plaintext to transform + /// The ParmsId with respect to which the NTT is done + /// The plaintext to overwrite with the transformed result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either plain, parmsId or destinationNTT are null + /// if plain is already in NTT form + /// if plain or parmsId is not valid for the encryption + /// parameters + /// if pool is uninitialized + public void TransformToNTT(Plaintext plain, ParmsId parmsId, + Plaintext destinationNTT, MemoryPoolHandle pool = null) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + if (null == destinationNTT) + throw new ArgumentNullException(nameof(destinationNTT)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_TransformToNTT(NativePtr, plain.NativePtr, parmsId.Block, destinationNTT.NativePtr, poolPtr); + } + + /// + /// Transforms a ciphertext to NTT domain. + /// + /// + /// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number + /// Theoretic Transform separately to each polynomial of a ciphertext. + /// + /// The ciphertext to transform + /// if encrypted is null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is already in NTT form + /// if result ciphertext is transparent + public void TransformToNTTInplace(Ciphertext encrypted) + { + TransformToNTT(encrypted, destinationNTT: encrypted); + } + + /// + /// Transforms a ciphertext to NTT domain. + /// + /// + /// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number + /// Theoretic Transform separately to each polynomial of a ciphertext. The result is + /// stored in the DestinationNTT parameter. + /// + /// The ciphertext to transform + /// The ciphertext to overwrite with the transformed result + /// if either encrypted or destinationNTT are null + /// if encrypted is not valid for the encryption parameters + /// if encrypted is already in NTT form + /// if result ciphertext is transparent + public void TransformToNTT(Ciphertext encrypted, + Ciphertext destinationNTT) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == destinationNTT) + throw new ArgumentNullException(nameof(destinationNTT)); + + NativeMethods.Evaluator_TransformToNTT( + NativePtr, encrypted.NativePtr, destinationNTT.NativePtr); + } + + /// + /// Transforms a ciphertext back from NTT domain. + /// + /// + /// Transforms a ciphertext back from NTT domain. This functions applies the inverse of + /// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext. + /// + /// The ciphertext to transform + /// if encryptedNTT is null + /// if encryptedNTT is not valid for the encryption parameters + /// if encryptedNTT is not in NTT form + /// if result ciphertext is transparent + public void TransformFromNTTInplace(Ciphertext encryptedNTT) + { + TransformFromNTT(encryptedNTT, destination: encryptedNTT); + } + + /// + /// Transforms a ciphertext back from NTT domain. + /// + /// + /// Transforms a ciphertext back from NTT domain. This functions applies the inverse of + /// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext. + /// The result is stored in the destination parameter. + /// + /// The ciphertext to transform + /// The ciphertext to overwrite with the transformed result + /// if either encryptedNTT or destination are null + /// if encryptedNTT is not valid for the encryption parameters + /// if encryptedNTT is not in NTT form + /// if result ciphertext is transparent + public void TransformFromNTT(Ciphertext encryptedNTT, Ciphertext destination) + { + if (null == encryptedNTT) + throw new ArgumentNullException(nameof(encryptedNTT)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.Evaluator_TransformFromNTT( + NativePtr, encryptedNTT.NativePtr, destination.NativePtr); + } + + /// + /// Applies a Galois automorphism to a ciphertext. + /// + /// + /// + /// Applies a Galois automorphism to a ciphertext. To evaluate the Galois automorphism, + /// an appropriate set of Galois keys must also be provided. Dynamic memory allocations + /// in the process are allocated from the memory pool pointed to by the given + /// MemoryPoolHandle. + /// + /// + /// The desired Galois automorphism is given as a Galois element, and must be an odd + /// integer in the interval [1, M-1], where M = 2*N, and N = PolyModulusDegree. Used + /// with batching, a Galois element 3^i % M corresponds to a cyclic row rotation i steps + /// to the left, and a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation + /// i steps to the right. The Galois element M-1 corresponds to a column rotation (row + /// swap) in BFV, and complex conjugation in CKKS. In the polynomial view (not batching), + /// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). + /// + /// + /// The ciphertext to apply the Galois automorphism to + /// The Galois element + /// The Galois keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or galoisKeys are null + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is not in the default NTT form + /// if encrypted has size larger than 2 + /// if the Galois element is not valid + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void ApplyGaloisInplace(Ciphertext encrypted, uint galoisElt, + GaloisKeys galoisKeys, MemoryPoolHandle pool = null) + { + ApplyGalois(encrypted, galoisElt, galoisKeys, destination: encrypted, pool: pool); + } + + /// + /// Applies a Galois automorphism to a ciphertext and writes the result to the + /// destination parameter. + /// + /// + /// + /// Applies a Galois automorphism to a ciphertext and writes the result to the + /// destination parameter. To evaluate the Galois automorphism, an appropriate set of + /// Galois keys must also be provided. Dynamic memory allocations in the process are + /// allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// + /// The desired Galois automorphism is given as a Galois element, and must be an odd + /// integer in the interval [1, M-1], where M = 2*N, and N = PolyModulusDegree. Used + /// with batching, a Galois element 3^i % M corresponds to a cyclic row rotation i steps + /// to the left, and a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation + /// i steps to the right. The Galois element M-1 corresponds to a column rotation (row + /// swap) in BFV, and complex conjugation in CKKS. In the polynomial view (not batching), + /// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). + /// + /// + /// The ciphertext to apply the Galois automorphism to + /// The Galois element + /// The Galois keys + /// The ciphertext to overwrite with the result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, galoisKeys or destination are null + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is not in the default NTT form + /// if encrypted has size larger than 2 + /// if the Galois element is not valid + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void ApplyGalois(Ciphertext encrypted, uint galoisElt, GaloisKeys galoisKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_ApplyGalois( + NativePtr, encrypted.NativePtr, galoisElt, + galoisKeys.NativePtr, destination.NativePtr, poolPtr); + } + + /// + /// Rotates plaintext matrix rows cyclically. + /// + /// + /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext + /// matrix rows cyclically to the left (steps > 0) or to the right (steps < 0). Since + /// the size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial + /// modulus, the number of steps to rotate must have absolute value at most N/2-1. Dynamic + /// memory allocations in the process are allocated from the memory pool pointed to by the + /// given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The number of steps to rotate (negative left, positive right) + /// The Galois keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or galoisKeys are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.BFV + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is not in the default NTT form + /// if encrypted has size larger than 2 + /// if steps has too big absolute value + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateRowsInplace(Ciphertext encrypted, + int steps, GaloisKeys galoisKeys, MemoryPoolHandle pool = null) + { + RotateRows(encrypted, steps, galoisKeys, destination: encrypted, pool: pool); + } + + /// + /// Rotates plaintext matrix rows cyclically. + /// + /// + /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext + /// matrix rows cyclically to the left (steps > 0) or to the right (steps < 0) and writes + /// the result to the destination parameter. Since the size of the batched matrix is 2-by-(N/2), + /// where N is the degree of the polynomial modulus, the number of steps to rotate must have + /// absolute value at most N/2-1. Dynamic memory allocations in the process are allocated from + /// the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The number of steps to rotate (negative left, positive right) + /// The Galois keys + /// The ciphertext to overwrite with the rotated result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, galoisKeys or destination are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.BFV + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if steps has too big absolute value + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateRows(Ciphertext encrypted, int steps, GaloisKeys galoisKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_RotateRows( + NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Rotates plaintext matrix columns cyclically. + /// + /// + /// When batching is used with the BFV scheme, this function rotates the encrypted + /// plaintext matrix columns cyclically. Since the size of the batched matrix is 2-by-(N/2), + /// where N is the degree of the polynomial modulus, this means simply swapping the two + /// rows. Dynamic memory allocations in the process are allocated from the memory pool + /// pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The Galois keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or galoisKeys are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.BFV + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateColumnsInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null) + { + RotateColumns(encrypted, galoisKeys, destination: encrypted, pool: pool); + } + + /// + /// Rotates plaintext matrix columns cyclically. + /// + /// + /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext + /// matrix columns cyclically, and writes the result to the destination parameter. Since the + /// size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus, + /// this means simply swapping the two rows. Dynamic memory allocations in the process are + /// allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The Galois keys + /// The ciphertext to overwrite with the rotated result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, galoisKeys or destination are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.BFV + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateColumns(Ciphertext encrypted, GaloisKeys galoisKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_RotateColumns( + NativePtr, encrypted.NativePtr, galoisKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Rotates plaintext vector cyclically. + /// + /// + /// When using the CKKS scheme, this function rotates the encrypted plaintext vector + /// cyclically to the left (steps > 0) or to the right (steps < 0). Since the size + /// of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus, + /// the number of steps to rotate must have absolute value at most N/2-1. Dynamic memory + /// allocations in the process are allocated from the memory pool pointed to by the given + /// MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The number of steps to rotate (negative left, positive right) + /// The Galois keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or galoisKeys are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.CKKS + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if steps has too big absolute value + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateVectorInplace(Ciphertext encrypted, int steps, + GaloisKeys galoisKeys, MemoryPoolHandle pool = null) + { + RotateVector(encrypted, steps, galoisKeys, destination: encrypted, pool: pool); + } + + /// + /// Rotates plaintext vector cyclically. + /// + /// + /// When using the CKKS scheme, this function rotates the encrypted plaintext vector + /// cyclically to the left (steps > 0) or to the right (steps < 0) and writes + /// the result to the destination parameter. Since the size of the batched matrix is + /// 2-by-(N/2), where N is the degree of the polynomial modulus, the number of steps + /// to rotate must have absolute value at most N/2-1. Dynamic memory allocations in the + /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The number of steps to rotate (negative left, positive right) + /// The Galois keys + /// The ciphertext to overwrite with the rotated result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted, galoisKeys or destination are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.CKKS + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if steps has too big absolute value + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void RotateVector(Ciphertext encrypted, int steps, GaloisKeys galoisKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_RotateVector( + NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Complex conjugates plaintext slot values. + /// + /// + /// When using the CKKS scheme, this function complex conjugates all values in the + /// underlying plaintext. Dynamic memory allocations in the process are allocated from + /// the memory pool pointed to by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The Galois keys + /// The MemoryPoolHandle pointing to a valid memory pool + /// if either encrypted or galoisKeys are null + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.CKKS + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void ComplexConjugateInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null) + { + ComplexConjugate(encrypted, galoisKeys, destination: encrypted, pool: pool); + } + + /// + /// Complex conjugates plaintext slot values. + /// + /// + /// When using the CKKS scheme, this function complex conjugates all values in the + /// underlying plaintext, and writes the result to the destination parameter. Dynamic + /// memory allocations in the process are allocated from the memory pool pointed to + /// by the given MemoryPoolHandle. + /// + /// The ciphertext to rotate + /// The Galois keys + /// The ciphertext to overwrite with the rotated result + /// The MemoryPoolHandle pointing to a valid memory pool + /// if the encryption parameters do not support batching + /// if scheme is not SchemeType.CKKS + /// if encrypted or galoisKeys is not valid for the + /// encryption parameters + /// if galoisKeys do not correspond to the top level + /// parameters in the current context + /// if encrypted is in NTT form + /// if encrypted has size larger than 2 + /// if necessary Galois keys are not present + /// if pool is uninitialized + /// if keyswitching is not supported by the context + /// if result ciphertext is transparent + public void ComplexConjugate(Ciphertext encrypted, GaloisKeys galoisKeys, + Ciphertext destination, MemoryPoolHandle pool = null) + { + if (null == encrypted) + throw new ArgumentNullException(nameof(encrypted)); + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + if (!ContextUsingKeyswitching) + throw new InvalidOperationException("Keyswitching is not supported by the context"); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + NativeMethods.Evaluator_ComplexConjugate( + NativePtr, encrypted.NativePtr, galoisKeys.NativePtr, + destination.NativePtr, poolPtr); + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.Evaluator_Destroy(NativePtr); + } + + internal bool ContextUsingKeyswitching + { + get + { + NativeMethods.Evaluator_ContextUsingKeyswitching(NativePtr, out bool result); + return result; + } + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs b/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs new file mode 100644 index 0000000000000000000000000000000000000000..2fdfa73290a3fb140d6519cc7ede2b4a5636e2f0 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Research.SEAL +{ + /// + /// Class to store Galois keys. + /// + /// + /// + /// Slot rotations + /// Galois keys are certain types of public keys that are needed to perform encrypted + /// vector rotation operations on batched ciphertexts. Batched ciphertexts encrypt + /// a 2-by-(N/2) matrix of modular integers in the BFV scheme, or an N/2-dimensional + /// vector of complex numbers in the CKKS scheme, where N denotes the degree of the + /// polynomial modulus. In the BFV scheme Galois keys can enable both cyclic rotations + /// of the encrypted matrix rows, as well as row swaps (column rotations). In the CKKS + /// scheme Galois keys can enable cyclic vector rotations, as well as a complex + /// conjugation operation. + /// + /// + /// Thread Safety + /// In general, reading from GaloisKeys is thread-safe as long as no other thread is + /// concurrently mutating it. This is due to the underlying data structure storing + /// the Galois keys not being thread-safe. + /// + /// + public class GaloisKeys : + KSwitchKeys, + ISettable + { + /// + /// Creates an empty set of Galois keys. + /// + public GaloisKeys() : base() + { + } + + /// + /// Creates a new GaloisKeys instance by copying a given instance. + /// + /// The GaloisKeys to copy from + /// if copy is null + public GaloisKeys(GaloisKeys copy) + : base(copy) + { + } + + /// + /// Creates a new GaloisKeys instance initialized with a pointer to a native + /// KSwitchKeys object. + /// + /// Pointer to native KSwitchKeys object + /// Whether this instance owns the native pointer + internal GaloisKeys(IntPtr kswitchKeys, bool owned = true) + : base(kswitchKeys, owned) + { + } + + /// + /// Copies a given GaloisKeys instance to the current one. + /// + /// + /// The GaloisKeys to copy from + /// if assign is null + public void Set(GaloisKeys assign) + { + base.Set(assign); + } + + /// + /// Returns the index of a Galois key in the backing KSwitchKeys instance that + /// corresponds to the given Galois element, assuming that it exists in the + /// backing KSwitchKeys. + /// + /// The Galois element + /// if Galois element is not valid + public static ulong GetIndex(uint galoisElt) + { + NativeMethods.GaloisKeys_GetIndex(galoisElt, out ulong index); + return index; + } + + /// + /// Returns whether a Galois key corresponding to a given Galois key element + /// exists. + /// + /// The Galois element + /// if Galois element is not valid + public bool HasKey(uint galoisElt) + { + ulong index = GetIndex(galoisElt); + return (ulong)Data.LongCount() > index && + Data.ElementAt(checked((int)index)).Count() != 0; + } + + /// + /// Returns a specified Galois key. + /// + /// + /// Returns a specified Galois key. The returned Galois key corresponds to the + /// given Galois element and is valid only as long as the GaloisKeys is valid. + /// + /// The Galois element + /// if the key corresponding to galoisElt + /// does not exist + public IEnumerable Key(uint galoisElt) + { + return Data.ElementAt(checked((int)GetIndex(galoisElt))); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs b/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs new file mode 100644 index 0000000000000000000000000000000000000000..dcfd98dc11ed8a4eb9d1554722a8a595764c540f --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs @@ -0,0 +1,329 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; + +namespace Microsoft.Research.SEAL +{ + /// + /// Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of + /// the IntegerEncoder class converts an integer into a plaintext polynomial by placing its + /// binary digits as the coefficients of the polynomial. Decoding the integer amounts to + /// evaluating the plaintext polynomial at x=2. + /// + /// Addition and multiplication on the integer side translate into addition and multiplication + /// on the encoded plaintext polynomial side, provided that the length of the polynomial + /// never grows to be of the size of the polynomial modulus (PolyModulus), and that the + /// coefficients of the plaintext polynomials appearing throughout the computations never + /// experience coefficients larger than the plaintext modulus (PlainModulus). + /// + /// + /// + /// Negative Integers + /// Negative integers are represented by using -1 instead of 1 in the binary representation, + /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers + /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + /// would be stored as a polynomial coefficient PlainModulus-1. + /// + /// + public class IntegerEncoder : NativeObject + { + /// + /// Creates a IntegerEncoder object. The constructor takes as input a pointer to + /// a SEALContext object which contains the plaintext modulus. + /// + /// The SEALContext + /// if context is null + /// if the context is not set + /// if the PlainModulus set in context is not + /// at least 2 + public IntegerEncoder(SEALContext context) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + + SEALContext.ContextData contextData = context.FirstContextData; + if (contextData.Parms.Scheme != SchemeType.BFV) + throw new ArgumentException("Unsupported scheme"); + + NativeMethods.IntegerEncoder_Create(context.NativePtr, out IntPtr encoderPtr); + NativePtr = encoderPtr; + } + + /// + /// Encodes an unsigned integer (represented by ulong) into a plaintext polynomial. + /// + /// The unsigned integer to encode + public Plaintext Encode(ulong value) + { + Plaintext plain = new Plaintext(); + NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); + return plain; + } + + /// + /// Encodes an unsigned integer(represented by ulong) into a plaintext polynomial. + /// + /// The unsigned integer to encode + /// The plaintext to overwrite with the encoding + /// if destination is null + public void Encode(ulong value, Plaintext destination) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); + } + + /// + /// Decodes a plaintext polynomial and returns the result as uint. Mathematically + /// this amounts to evaluating the input polynomial at X = 2. + /// + /// The plaintext to be decoded + /// if plain is null + /// if plain does not represent a valid plaintext polynomial + /// if the output does not fit in uint + public uint DecodeUInt32(Plaintext plain) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + NativeMethods.IntegerEncoder_DecodeUInt32(NativePtr, plain.NativePtr, out uint result); + return result; + } + + /// + /// Decodes a plaintext polynomial and returns the result as ulong. Mathematically + /// this amounts to evaluating the input polynomial at X=2. + /// + /// The plaintext to be decoded + /// if plain is null + /// if plain does not represent a valid plaintext polynomial + /// if the output does not fit in ulong + public ulong DecodeUInt64(Plaintext plain) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + NativeMethods.IntegerEncoder_DecodeUInt64(NativePtr, plain.NativePtr, out ulong result); + return result; + } + + /// + /// Encodes a signed integer (represented by long) into a plaintext polynomial. + /// + /// + /// + /// Negative Integers + /// Negative integers are represented by using -1 instead of 1 in the binary representation, + /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers + /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + /// would be stored as a polynomial coefficient PlainModulus-1. + /// + /// + /// The signed integer to encode + public Plaintext Encode(long value) + { + Plaintext plain = new Plaintext(); + NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); + return plain; + } + + /// + /// Encodes a signed integer(represented by long) into a plaintext polynomial. + /// + /// + /// + /// Negative Integers + /// Negative integers are represented by using -1 instead of 1 in the binary representation, + /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers + /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + /// would be stored as a polynomial coefficient PlainModulus-1. + /// + /// + /// The signed integer to encode + /// The plaintext to overwrite with the encoding + public void Encode(long value, Plaintext destination) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); + } + + /// + /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial. + /// + /// The unsigned integer to encode + /// if value is null + public Plaintext Encode(BigUInt value) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + + Plaintext plain = new Plaintext(); + NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, plain.NativePtr); + return plain; + } + + /// + /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial. + /// + /// The unsigned integer to encode + /// The plaintext to overwrite with the encoding + /// if either value or destination are null + public void Encode(BigUInt value, Plaintext destination) + { + if (null == value) + throw new ArgumentNullException(nameof(value)); + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, destination.NativePtr); + } + + /// + /// Decodes a plaintext polynomial and returns the result as int. Mathematically + /// this amounts to evaluating the input polynomial at X = 2. + /// + /// The plaintext to be decoded + /// if plain is null + /// if plain does not represent a valid plaintext polynomial + /// if the output does not fit in int + public int DecodeInt32(Plaintext plain) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + NativeMethods.IntegerEncoder_DecodeInt32(NativePtr, plain.NativePtr, out int result); + return result; + } + + /// + /// Decodes a plaintext polynomial and returns the result as long. Mathematically + /// this amounts to evaluating the input polynomial at X = 2. + /// + /// The plaintext to be decoded + /// if plain is null + /// if plain does not represent a valid plaintext polynomial + /// if the output does not fit in long + public long DecodeInt64(Plaintext plain) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + NativeMethods.IntegerEncoder_DecodeInt64(NativePtr, plain.NativePtr, out long result); + return result; + } + + /// + /// Decodes a plaintext polynomial and returns the result as BigUInt. + /// Mathematically this amounts to evaluating the input polynomial at X = 2. + /// + /// The plaintext to be decoded + /// if plain is null + /// if plain does not represent a valid plaintext polynomial + /// if the output is negative + public BigUInt DecodeBigUInt(Plaintext plain) + { + if (null == plain) + throw new ArgumentNullException(nameof(plain)); + + NativeMethods.IntegerEncoder_DecodeBigUInt(NativePtr, plain.NativePtr, out IntPtr buiPtr); + BigUInt bui = new BigUInt(buiPtr); + return bui; + } + + /// + /// Encodes a signed integer(represented by int) into a plaintext polynomial. + /// + /// + /// + /// Negative Integers + /// Negative integers are represented by using -1 instead of 1 in the binary representation, + /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers + /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + /// would be stored as a polynomial coefficient PlainModulus-1. + /// + /// + /// The signed integer to encode + public Plaintext Encode(int value) + { + Plaintext plain = new Plaintext(); + NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); + return plain; + } + + /// + /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial. + /// + /// The unsigned integer to encode + public Plaintext Encode(uint value) + { + Plaintext plain = new Plaintext(); + NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); + return plain; + } + + /// + /// Encodes a signed integer(represented by int) into a plaintext polynomial. + /// + /// + /// + /// Negative Integers + /// Negative integers are represented by using -1 instead of 1 in the binary representation, + /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers + /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + /// would be stored as a polynomial coefficient PlainModulus-1. + /// + /// + /// The signed integer to encode + /// The plaintext to overwrite with the encoding + /// if destination is null + public void Encode(int value, Plaintext destination) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); + } + + /// + /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial. + /// + /// The unsigned integer to encode + /// The plaintext to overwrite with the encoding + /// if destination is null + public void Encode(uint value, Plaintext destination) + { + if (null == destination) + throw new ArgumentNullException(nameof(destination)); + + NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); + } + + /// + /// Get a copy of the plaintext modulus. + /// + public Modulus PlainModulus + { + get + { + NativeMethods.IntegerEncoder_PlainModulus(NativePtr, out IntPtr sm); + Modulus result = new Modulus(sm); + return result; + } + } + + /// + /// Destroy the native object + /// + protected override void DestroyNativeObject() + { + NativeMethods.IntegerEncoder_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs b/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs new file mode 100644 index 0000000000000000000000000000000000000000..872700cbc7e6dcdf4686e85e913a227603cc0756 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Class to store keyswitching keys. + /// + /// + /// + /// + /// Class to store keyswitching keys. It should never be necessary for normal + /// users to create an instance of KSwitchKeys. This class is used strictly as + /// a base class for RelinKeys and GaloisKeys classes. + /// + /// + /// Concretely, keyswitching is used to change a ciphertext encrypted with one + /// key to be encrypted with another key.It is a general technique and is used + /// in relinearization and Galois rotations. A keyswitching key contains a sequence + /// (vector) of keys.In RelinKeys, each key is an encryption of a power of the + /// secret key.In GaloisKeys, each key corresponds to a type of rotation. + /// + /// + /// In general, reading from KSwitchKeys is thread-safe as long as no + /// other thread is concurrently mutating it.This is due to the underlying + /// data structure storing the keyswitching keys not being thread-safe. + /// + /// + public class KSwitchKeys : + NativeObject, + ISerializableObject, + ISettable + { + /// + /// Creates an empty KSwitchKeys. + /// + public KSwitchKeys() + { + NativeMethods.KSwitchKeys_Create(out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates a new KSwitchKeys instance by copying a given instance. + /// + /// The KSwitchKeys to copy from + /// if copy is null + public KSwitchKeys(KSwitchKeys copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.KSwitchKeys_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates a new KSwitchKeys instance initialized with a pointer to a native + /// KSwitchKeys object. + /// + /// Pointer to native KSwitchKeys object + /// Whether this instance owns the native pointer + internal KSwitchKeys(IntPtr kswitchKeys, bool owned = true) + : base(kswitchKeys, owned) + { + } + + /// + /// Copies a given KSwitchKeys instance to the current one. + /// + /// + /// The KSwitchKeys to copy from + /// if assign is null + public void Set(KSwitchKeys assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.KSwitchKeys_Set(NativePtr, assign.NativePtr); + } + + /// + /// Returns the current number of keyswitching keys. Only keys that are non-empty + /// are counted. + /// + public ulong Size + { + get + { + NativeMethods.KSwitchKeys_Size(NativePtr, out ulong size); + return size; + } + } + + /// + /// Returns the KSwitchKeys data. + /// + /// + /// Returns the KSwitchKeys data. The returned object is valid only as long as + /// the KSwitchKeys is valid and not changed. + /// + public IEnumerable> Data + { + get + { + List> result = new List>(); + NativeMethods.KSwitchKeys_RawSize(NativePtr, out ulong size); + + for (ulong i = 0; i < size; i++) + { + ulong count = 0; + NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, null); + + IntPtr[] pointers = new IntPtr[count]; + NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, pointers); + + List key = new List(checked((int)count)); + foreach (IntPtr ptr in pointers) + { + key.Add(new PublicKey(ptr, owned: false)); + } + + result.Add(key); + } + + return result; + } + } + + /// + /// Returns a copy of ParmsId. + /// + public ParmsId ParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.KSwitchKeys_GetParmsId(NativePtr, parms.Block); + return parms; + } + private set + { + NativeMethods.KSwitchKeys_SetParmsId(NativePtr, value.Block); + } + } + + /// + /// Returns an upper bound on the size of the KSwitchKeys, as if it was written + /// to an output stream. + /// + /// The compression mode + /// if the compression mode is not + /// supported + /// if the size does not fit in + /// the return type + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.KSwitchKeys_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// Saves the KSwitchKeys to an output stream. + /// + /// Saves the KSwitchKeys to an output stream. The output is in binary format + /// and not human-readable. + /// + /// The stream to save the KSwitchKeys to + /// The desired compression mode + /// if stream is null + /// if the stream is closed or does not + /// support writing, or if compression mode is not supported + /// if I/O operations failed + /// if the data to be saved + /// is invalid, or if compression failed + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.KSwitchKeys_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// Loads a KSwitchKeys from an input stream overwriting the current + /// KSwitchKeys. + /// + /// Loads a KSwitchKeys from an input stream overwriting the current + /// KSwitchKeys. No checking of the validity of the KSwitchKeys data against + /// encryption parameters is performed. This function should not be used + /// unless the KSwitchKeys comes from a fully trusted source. + /// + /// The SEALContext + /// The stream to load the KSwitchKeys from + /// if context or stream is + /// null + /// if the stream is closed or does not + /// support reading + /// if context is not set or encryption + /// parameters are not valid + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long UnsafeLoad(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.KSwitchKeys_UnsafeLoad(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// Loads a KSwitchKeys from an input stream overwriting the current + /// KSwitchKeys. + /// + /// Loads a KSwitchKeys from an input stream overwriting the current + /// KSwitchKeys. The loaded KSwitchKeys is verified to be valid for the given + /// SEALContext. + /// + /// The SEALContext + /// The stream to load the KSwitchKeys from + /// if context or stream is + /// null + /// if the stream is closed or does not + /// support reading + /// if context is not set or encryption + /// parameters are not valid + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long Load(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.KSwitchKeys_Load(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// + /// Returns the currently used MemoryPoolHandle. + /// + public MemoryPoolHandle Pool + { + get + { + NativeMethods.KSwitchKeys_Pool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.KSwitchKeys_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs b/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..604b56ef6e43c886f9963c3a04e2a9159bb96427 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs @@ -0,0 +1,380 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Research.SEAL +{ + /// + /// Generates matching secret key and public key. + /// + /// + /// Generates matching secret key and public key. An existing KeyGenerator can + /// also at any time be used to generate relinearization keys and Galois keys. + /// Constructing a KeyGenerator requires only a SEALContext. + /// + public class KeyGenerator : NativeObject + { + /// + /// Creates a KeyGenerator initialized with the specified SEALContext. + /// + /// + /// Creates a KeyGenerator initialized with the specified . + /// Dynamically allocated member variables are allocated from the global memory pool. + /// + /// The SEALContext + /// if encryption parameters are not + /// valid + /// if context is null + public KeyGenerator(SEALContext context) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + + NativeMethods.KeyGenerator_Create(context.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates an KeyGenerator instance initialized with the specified + /// SEALContext and specified previously secret key. + /// + /// + /// Creates an KeyGenerator instance initialized with the specified + /// SEALContext and specified previously secret key. This can e.g. be used + /// to increase the number of relinearization keys from what had earlier + /// been generated, or to generate Galois keys in case they had not been + /// generated earlier. + /// + /// The SEALContext + /// A previously generated secret key + /// if either context or secretKey + /// are null + /// if encryption parameters are not + /// valid + /// if secretKey or publicKey is not + /// valid for encryption parameters + public KeyGenerator(SEALContext context, SecretKey secretKey) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + if (null == secretKey) + throw new ArgumentNullException(nameof(secretKey)); + if (!context.ParametersSet) + throw new ArgumentException("Encryption parameters are not set correctly"); + if (!ValCheck.IsValidFor(secretKey, context)) + throw new ArgumentException("Secret key is not valid for encryption parameters"); + + NativeMethods.KeyGenerator_Create(context.NativePtr, + secretKey.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Generates and returns a public key. Every time this function is called, + /// a new public key will be generated. + /// + public PublicKey PublicKey + { + get + { + NativeMethods.KeyGenerator_PublicKey(NativePtr, out IntPtr pubKeyPtr); + PublicKey pubKey = new PublicKey(pubKeyPtr); + return pubKey; + } + } + + /// + /// Returns a copy of the secret key. + /// + public SecretKey SecretKey + { + get + { + NativeMethods.KeyGenerator_SecretKey(NativePtr, out IntPtr secretKeyPtr); + SecretKey secretKey = new SecretKey(secretKeyPtr); + return secretKey; + } + } + + /// + /// Generates and returns relinearization keys. + /// + /// + /// Generates and returns relinearization keys. This function returns + /// relinearization keys in a fully expanded form and is meant to be used + /// primarily for demo, testing, and debugging purposes. + /// + /// if the encryption + /// parameters do not support keyswitching + public RelinKeys RelinKeysLocal() + { + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + NativeMethods.KeyGenerator_RelinKeys(NativePtr, false, out IntPtr relinKeysPtr); + return new RelinKeys(relinKeysPtr); + } + + /// + /// Generates and returns relinearization keys as a serializable object. + /// + /// + /// + /// Generates and returns relinearization keys as a serializable object. + /// + /// + /// Half of the key data is pseudo-randomly generated from a seed to reduce + /// the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// if the encryption + /// parameters do not support keyswitching + public Serializable RelinKeys() + { + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + NativeMethods.KeyGenerator_RelinKeys(NativePtr, true, out IntPtr relinKeysPtr); + RelinKeys relinKeys = new RelinKeys(relinKeysPtr); + return new Serializable(relinKeys); + } + + /// + /// Generates and returns Galois keys. + /// + /// + /// + /// Generates and returns Galois keys. This function returns Galois keys in + /// a fully expanded form and is meant to be used primarily for demo, testing, + /// and debugging purposes. This function creates specific Galois keys that + /// can be used to apply specific Galois automorphisms on encrypted data. The + /// user needs to give as input a vector of Galois elements corresponding to + /// the keys that are to be created. + /// + /// + /// The Galois elements are odd integers in the interval [1, M-1], where + /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element + /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and + /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i + /// steps to the right. The Galois element M-1 corresponds to a column rotation + /// (row swap). In the polynomial view (not batching), a Galois automorphism by + /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). + /// + /// + /// The Galois elements for which to generate keys + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + /// if the Galois elements are not valid + public GaloisKeys GaloisKeysLocal(IEnumerable galoisElts) + { + if (null == galoisElts) + throw new ArgumentNullException(nameof(galoisElts)); + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + uint[] galoisEltsArr = galoisElts.ToArray(); + NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr, + (ulong)galoisEltsArr.Length, galoisEltsArr, false, out IntPtr galoisKeysPtr); + return new GaloisKeys(galoisKeysPtr); + } + + /// + /// Generates and returns Galois keys as a serializable object. + /// + /// + /// + /// Generates and returns Galois keys as a serializable object. This function + /// creates specific Galois keys that can be used to apply specific Galois + /// automorphisms on encrypted data. The user needs to give as input a vector + /// of Galois elements corresponding to the keys that are to be created. + /// + /// + /// The Galois elements are odd integers in the interval [1, M-1], where + /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element + /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and + /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i + /// steps to the right. The Galois element M-1 corresponds to a column rotation + /// (row swap). In the polynomial view (not batching), a Galois automorphism by + /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). + /// + /// + /// Half of the key data is pseudo-randomly generated from a seed to reduce + /// the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// The Galois elements for which to generate keys + /// if galoisElts is null + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + /// if the Galois elements are not valid + public Serializable GaloisKeys(IEnumerable galoisElts) + { + if (null == galoisElts) + throw new ArgumentNullException(nameof(galoisElts)); + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + uint[] galoisEltsArr = galoisElts.ToArray(); + NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr, + (ulong)galoisEltsArr.Length, galoisEltsArr, true, out IntPtr galoisKeysPtr); + GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); + return new Serializable(galoisKeys); + } + + /// + /// Generates and returns Galois keys. + /// + /// + /// Generates and returns Galois keys. This function returns Galois keys in + /// a fully expanded form and is meant to be used primarily for demo, testing, + /// and debugging purposes. The user needs to give as input a vector of desired + /// Galois rotation step counts, where negative step counts correspond to + /// rotations to the right and positive step counts correspond to rotations to + /// the left. A step count of zero can be used to indicate a column rotation + /// in the BFV scheme complex conjugation in the CKKS scheme. + /// + /// The rotation step counts for which to generate keys + /// if steps is null + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + /// if the step counts are not valid + public GaloisKeys GaloisKeysLocal(IEnumerable steps) + { + if (null == steps) + throw new ArgumentNullException(nameof(steps)); + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + int[] stepsArr = steps.ToArray(); + NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr, + (ulong)stepsArr.Length, stepsArr, false, out IntPtr galoisKeysPtr); + return new GaloisKeys(galoisKeysPtr); + } + + /// + /// Generates and returns Galois keys as a serializable object. + /// + /// + /// + /// Generates and returns Galois keys as a serializable object. This function + /// creates specific Galois keys that can be used to apply specific Galois + /// automorphisms on encrypted data. The user needs to give as input a vector + /// of desired Galois rotation step counts, where negative step counts + /// correspond to rotations to the right and positive step counts correspond + /// to rotations to the left. A step count of zero can be used to indicate + /// a column rotation in the BFV scheme complex conjugation in the CKKS scheme. + /// + /// + /// Half of the key data is pseudo-randomly generated from a seed to reduce + /// the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// The rotation step counts for which to generate keys + /// if steps is null + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + /// if the step counts are not valid + public Serializable GaloisKeys(IEnumerable steps) + { + if (null == steps) + throw new ArgumentNullException(nameof(steps)); + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + int[] stepsArr = steps.ToArray(); + NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr, + (ulong)stepsArr.Length, stepsArr, true, out IntPtr galoisKeysPtr); + GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); + return new Serializable(galoisKeys); + } + + /// + /// Generates and returns Galois keys. + /// + /// + /// Generates and returns Galois keys. This function returns Galois keys in + /// a fully expanded form and is meant to be used primarily for demo, testing, + /// and debugging purposes. This function creates logarithmically many (in + /// degree of the polynomial modulus) Galois keys that is sufficient to apply + /// any Galois automorphism (e.g. rotations) on encrypted data. Most users + /// will want to use this overload of the function. + /// + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + public GaloisKeys GaloisKeysLocal() + { + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, false, out IntPtr galoisKeysPtr); + return new GaloisKeys(galoisKeysPtr); + } + + /// + /// Generates and returns Galois keys as a serializable object. + /// + /// + /// + /// Generates and returns Galois keys as a serializable object. This function + /// creates logarithmically many (in degree of the polynomial modulus) Galois + /// keys that is sufficient to apply any Galois automorphism (e.g. rotations) + /// on encrypted data. Most users will want to use this overload of the function. + /// + /// + /// Half of the key data is pseudo-randomly generated from a seed to reduce + /// the object size. The resulting serializable object cannot be used + /// directly and is meant to be serialized for the size reduction to have an + /// impact. + /// + /// + /// if the encryption parameters + /// do not support batching and scheme is SchemeType.BFV + /// if the encryption + /// parameters do not support keyswitching + public Serializable GaloisKeys() + { + if (!UsingKeyswitching()) + throw new InvalidOperationException("Encryption parameters do not support keyswitching"); + + NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, true, out IntPtr galoisKeysPtr); + GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); + return new Serializable(galoisKeys); + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.KeyGenerator_Destroy(NativePtr); + } + + internal bool UsingKeyswitching() + { + NativeMethods.KeyGenerator_ContextUsingKeyswitching(NativePtr, out bool result); + return result; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/MMProf.cs b/bigpiseal3.5.1/dotnet/src/MMProf.cs new file mode 100644 index 0000000000000000000000000000000000000000..9cae5ec69a540df0836bc4625a6db2d77ad9c2bd --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/MMProf.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; + +namespace Microsoft.Research.SEAL +{ + /// + /// The MMProf is a pure virtual class that every profile for the MemoryManager + /// should inherit from. The only functionality this class implements is the + /// GetPool() function that returns a MemoryPoolHandle pointing + /// to a pool selected by internal logic. The returned MemoryPoolHandle must + /// point to a valid memory pool. + /// + public abstract class MMProf : NativeObject + { + /// + /// Returns a MemoryPoolHandle pointing to a pool selected by internal logic + /// in a derived class. + /// + public MemoryPoolHandle GetPool() + { + NativeMethods.MMProf_GetPool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + + /// + /// Destroy native backing object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.MMProf_Destroy(NativePtr); + } + } + + /// + /// A memory manager profile that always returns a MemoryPoolHandle pointing to + /// the global memory pool. Microsoft SEAL uses this memory manager profile by default. + /// + public class MMProfGlobal : MMProf + { + /// + /// Create a new instance of MMProfGlobal + /// + public MMProfGlobal() + { + NativeMethods.MMProf_CreateGlobal(out IntPtr profile); + NativePtr = profile; + } + } + + /// + /// A memory manager profile that always returns a MemoryPoolHandle pointing to + /// specific memory pool. + /// + public class MMProfFixed : MMProf + { + /// + /// Create a new instance of MMProfFixed + /// + /// Fixed memory pool handle to use + /// if pool is null + public MMProfFixed(MemoryPoolHandle pool) + { + if (null == pool) + throw new ArgumentNullException(nameof(pool)); + + // Create a copy of MemoryPoolHandle, as the profile will take ownership + // of the pointer and will attempt to delete it when destroyed. + NativeMethods.MemoryPoolHandle_Create(pool.NativePtr, out IntPtr poolCopy); + NativeMethods.MMProf_CreateFixed(poolCopy, out IntPtr profile); + NativePtr = profile; + } + } + + /// + /// A memory manager profile that always returns a MemoryPoolHandle pointing to + /// the new thread-safe memory pool. This profile should not be used except in + /// special circumstances, as it does not result in any reuse of allocated memory. + /// + public class MMProfNew : MMProf + { + /// + /// Create a new instance of MMProfNew + /// + public MMProfNew() + { + NativeMethods.MMProf_CreateNew(out IntPtr profile); + NativePtr = profile; + } + } + + /// + /// A memory manager profile that always returns a MemoryPoolHandle pointing to + /// the thread-local memory pool. This profile should be used with care, as any + /// memory allocated by it will be released once the thread exits. In other words, + /// the thread-local memory pool cannot be used to share memory across different + /// threads. On the other hand, this profile can be useful when a very high number + /// of threads doing simultaneous allocations would cause contention in the + /// global memory pool. + /// + public class MMProfThreadLocal : MMProf + { + /// + /// Create a new instance of MMProfThreadLocal + /// + public MMProfThreadLocal() + { + NativeMethods.MMProf_CreateThreadLocal(out IntPtr profile); + NativePtr = profile; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/MemoryManager.cs b/bigpiseal3.5.1/dotnet/src/MemoryManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..9b02ba6783eaedac78886714102529ee10596dbf --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/MemoryManager.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Research.SEAL +{ + /// + /// Memory Manager Profile Options used in MemoryManager.GetPool method + /// + public enum MMProfOpt : ulong + { + /// + /// Use default profile + /// + Default = 0, + + /// + /// Force use of the Global profile + /// + ForceGlobal = 1, + + /// + /// Force use of a New profile + /// + ForceNew = 2, + + /// + /// Force use of the Thread Local profile + /// + ForceThreadLocal = 4 + } + + /// + /// The MemoryManager class can be used to create instances of MemoryPoolHandle + /// based on a given "profile". A profile is implemented by inheriting from the + /// MMProf class (pure virtual) and encapsulates internal logic for deciding which + /// memory pool to use. + /// + public static class MemoryManager + { + /// + /// Static initialization of MemoryManager + /// + static MemoryManager() + { + // The default profile is Global + profile_ = new MMProfGlobal(); + } + + /// + /// Sets the current profile to a given one and returns an instance pointing + /// to the previously set profile. + /// + /// New memory manager profile + /// if newProfile is null + public static MMProf SwitchProfile(MMProf newProfile) + { + if (null == newProfile) + throw new ArgumentNullException(nameof(newProfile)); + + NativeMethods.MemoryManager_SwitchProfile(newProfile.NativePtr); + + MMProf oldProfile = profile_; + profile_ = newProfile; + + return oldProfile; + } + + /// + /// Returns a MemoryPoolHandle according to the currently set memory manager + /// profile and profOpt. The following values for profOpt have an effect + /// independent of the current profile: + /// + /// MMProfOpt.ForceNew: return MemoryPoolHandle.New() + /// MMProfOpt.ForceGlobal: return MemoryPoolHandle.Global() + /// MMProfOpt.ForceThreadLocal: return MemoryPoolHandle.ThreadLocal() + /// + /// Other values for profOpt are forwarded to the current profile and, depending + /// on the profile, may or may not have an effect. The value MMProfOpt.Default + /// will always invoke a default behavior for the current profile. + /// + /// A MMProfOpt parameter used to provide additional + /// instructions to the memory manager profile for internal logic. + /// Indicates whether the memory pool data + /// should be cleared when destroyed.This can be important when memory pools + /// are used to store private data. This parameter is only used with MMProfOpt.ForceNew, + /// and ignored in all other cases. + public static MemoryPoolHandle GetPool(MMProfOpt profOpt, bool clearOnDestruction = false) + { + NativeMethods.MemoryManager_GetPool((int)profOpt, clearOnDestruction, out IntPtr handlePtr); + MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr); + return handle; + } + + /// + /// Returns a MemoryPoolHandle according to the currently set memory manager profile. + /// + public static MemoryPoolHandle GetPool() + { + NativeMethods.MemoryManager_GetPool(out IntPtr handlePtr); + MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr); + return handle; + } + + /// + /// Currently set profile + /// + private static MMProf profile_ = null; + } +} diff --git a/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs b/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs new file mode 100644 index 0000000000000000000000000000000000000000..64911c99d0ca0d03c26c0d5dcac17bde4b12a898 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// + /// Manages a shared pointer to a memory pool. Microsoft SEAL uses memory pools for + /// improved performance due to the large number of memory allocations needed + /// by the homomorphic encryption operations, and the underlying polynomial + /// arithmetic. The library automatically creates a shared global memory pool + /// that is used for all dynamic allocations by default, and the user can + /// optionally create any number of custom memory pools to be used instead. + /// + /// + /// + /// Uses in Multi-Threaded Applications + /// Sometimes the user might want to use specific memory pools for dynamic + /// allocations in certain functions. For example, in heavily multi-threaded + /// applications allocating concurrently from a shared memory pool might lead + /// to significant performance issues due to thread contention. For these cases + /// Microsoft SEAL provides overloads of the functions that take a MemoryPoolHandle as an + /// additional argument, and uses the associated memory pool for all dynamic + /// allocations inside the function. Whenever this functions is called, the + /// user can then simply pass a thread-local MemoryPoolHandle to be used. + /// + /// + /// Thread-Unsafe Memory Pools + /// While memory pools are by default thread-safe, in some cases it suffices + /// to have a memory pool be thread-unsafe. To get a little extra performance, + /// the user can optionally create such thread-unsafe memory pools and use them + /// just as they would use thread-safe memory pools. + /// + /// + /// Initialized and Uninitialized Handles + /// A MemoryPoolHandle has to be set to point either to the global memory pool, + /// or to a new memory pool. If this is not done, the MemoryPoolHandle is + /// said to be uninitialized, and cannot be used. Initialization simple means + /// assigning MemoryPoolHandle::Global() or MemoryPoolHandle::New() to it. + /// + /// + /// Managing Lifetime + /// Internally, the MemoryPoolHandle wraps a C++ shared pointer pointing to + /// a memory pool class. Thus, as long as a MemoryPoolHandle pointing to + /// a particular memory pool exists, the pool stays alive. Classes such as + /// Evaluator and Ciphertext store their own local copies of a MemoryPoolHandle + /// to guarantee that the pool stays alive as long as the managing object + /// itself stays alive. The global memory pool is implemented as a global + /// C++ std::shared_ptr to a memory pool class, and is thus expected to stay + /// alive for the entire duration of the program execution. Note that it can + /// be problematic to create other global objects that use the memory pool + /// e.g. in their constructor, as one would have to ensure the initialization + /// order of these global variables to be correct (i.e. global memory pool + /// first). + /// + /// + public class MemoryPoolHandle : NativeObject + { + /// + /// Creates a new uninitialized MemoryPoolHandle. + /// + public MemoryPoolHandle() + { + NativeMethods.MemoryPoolHandle_Create(out IntPtr handlePtr); + NativePtr = handlePtr; + } + + /// + /// Creates a copy of a given MemoryPoolHandle. As a result, the created + /// MemoryPoolHandle will point to the same underlying memory pool as the + /// copied instance. + /// + /// The MemoryPoolHandle to copy from. + /// if copy is null. + public MemoryPoolHandle(MemoryPoolHandle copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.MemoryPoolHandle_Create(copy.NativePtr, out IntPtr handlePtr); + NativePtr = handlePtr; + } + + /// + /// Create a MemoryPoolHandle through a native object pointer. + /// + /// Pointer to native MemoryPoolHandle + /// Whether this instance owns the native pointer + internal MemoryPoolHandle(IntPtr ptr, bool owned = true) + : base(ptr, owned) + { + } + + /// + /// Overwrites the MemoryPoolHandle instance with the specified instance. As + /// a result, the current MemoryPoolHandle will point to the same underlying + /// memory pool as the assigned instance. + /// + /// The MemoryPoolHandle instance to assign to the current + /// instance + /// if assign is null. + public void Set(MemoryPoolHandle assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.MemoryPoolHandle_Set(NativePtr, assign.NativePtr); + } + + /// + /// Returns a MemoryPoolHandle pointing to the global memory pool. + /// + public static MemoryPoolHandle Global() + { + NativeMethods.MemoryPoolHandle_Global(out IntPtr handlePtr); + MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr); + return handle; + } + + /// + /// Returns a MemoryPoolHandle pointing to the thread-local memory pool. + /// + public static MemoryPoolHandle ThreadLocal() + { + NativeMethods.MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr); + MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr); + return handle; + } + + /// + /// Returns a MemoryPoolHandle pointing to a new thread-safe memory pool. + /// + /// Indicates whether the memory pool data + /// should be cleared when destroyed.This can be important when memory pools + /// are used to store private data. + public static MemoryPoolHandle New(bool clearOnDestruction = false) + { + NativeMethods.MemoryPoolHandle_New(clearOnDestruction, out IntPtr handlePtr); + MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr); + return handle; + } + + /// + /// Returns the number of different allocation sizes. + /// + /// + /// This function returns the number of different allocation sizes the memory + /// pool pointed to by the current MemoryPoolHandle has made. For example, + /// if the memory pool has only allocated two allocations of sizes 128 KB, + /// this function returns 1. If it has instead allocated one allocation of + /// size 64 KB and one of 128 KB, this functions returns 2. + /// + public ulong PoolCount + { + get + { + NativeMethods.MemoryPoolHandle_PoolCount(NativePtr, out ulong count); + return count; + } + } + + /// + /// Returns the size of allocated memory. + /// + /// + /// This functions returns the total amount of memory (in bytes) allocated + /// by the memory pool pointed to by the current MemoryPoolHandle. + /// + public ulong AllocByteCount + { + get + { + NativeMethods.MemoryPoolHandle_AllocByteCount(NativePtr, out ulong count); + return count; + } + } + + /// + /// Returns the number of MemoryPoolHandle objects sharing this memory pool. + /// + public long UseCount + { + get + { + NativeMethods.MemoryPoolHandle_UseCount(NativePtr, out long count); + return count; + } + } + + /// + /// Returns whether the MemoryPoolHandle is initialized. + /// + public bool IsInitialized + { + get + { + NativeMethods.MemoryPoolHandle_IsInitialized(NativePtr, out bool result); + return result; + } + } + + /// + /// Compares MemoryPoolHandles. This function returns whether the current + /// MemoryPoolHandle points to the same memory pool as a given MemoryPoolHandle. + /// + /// Object to compare to. + public override bool Equals(object obj) + { + MemoryPoolHandle other = obj as MemoryPoolHandle; + if (null == other) + return false; + + NativeMethods.MemoryPoolHandle_Equals(NativePtr, other.NativePtr, out bool result); + return result; + } + + /// + /// Get hash code for this MemoryPoolHandle + /// + public override int GetHashCode() + { + return base.GetHashCode(); + } + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.MemoryPoolHandle_Destroy(NativePtr); + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/src/Modulus.cs b/bigpiseal3.5.1/dotnet/src/Modulus.cs new file mode 100644 index 0000000000000000000000000000000000000000..0d3adff0ab9274a1a62c5ba215dfc35699d36ef7 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Modulus.cs @@ -0,0 +1,548 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Research.SEAL +{ + /// Represent an integer modulus of up to 61 bits. + /// + /// + /// Represent an integer modulus of up to 61 bits. An instance of the Modulus + /// class represents a non-negative integer modulus up to 61 bits. In particular, + /// the encryption parameter PlainModulus, and the primes in CoeffModulus, are + /// represented by instances of Modulus. The purpose of this class is to + /// perform and store the pre-computation required by Barrett reduction. + /// + /// + /// In general, reading from Modulus is thread-safe as long as no other thread + /// is concurrently mutating it. + /// + /// + /// See EncryptionParameters for a description + /// of the encryption parameters. + public class Modulus : NativeObject, + IEquatable, IEquatable, + IComparable, IComparable + { + /// Creates a Modulus instance. + /// + /// Creates a Modulus instance. The value of the Modulus is set to 0. + /// + public Modulus() + { + NativeMethods.Modulus_Create(value: 0, smallModulus: out IntPtr ptr); + NativePtr = ptr; + } + + /// Creates a Modulus instance. + /// + /// Creates a Modulus instance. The value of the Modulus is set to + /// the given value. + /// + /// The integer modulus + /// if value is 1 or more than + /// 61 bits + public Modulus(ulong value) + { + NativeMethods.Modulus_Create(value, out IntPtr ptr); + NativePtr = ptr; + } + + /// Creates a new Modulus by copying a given one. + /// The Modulus to copy from + /// if copy is null + public Modulus(Modulus copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.Modulus_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// + /// Creates a Modulus from a native pointer + /// + /// Pointer to the native Modulus + /// Whether this instance owns the native pointer + internal Modulus(IntPtr sm, bool owned = true) + : base(sm, owned) + { + } + + /// Copies a given Modulus to the current one. + /// The Modulus to copy from + /// if assign is null + public void Set(Modulus assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.Modulus_Set(NativePtr, assign.NativePtr); + } + + /// Sets the value of the Modulus. + /// The new integer modulus + /// if value is 1 or more than + /// 61 bits + public void Set(ulong value) + { + NativeMethods.Modulus_Set(NativePtr, value); + } + + /// + /// Returns the significant bit count of the value of the current Modulus. + /// + public int BitCount + { + get + { + NativeMethods.Modulus_BitCount(NativePtr, out int result); + return result; + } + } + + /// + /// Returns the size (in 64-bit words) of the value of the current Modulus. + /// + public ulong UInt64Count + { + get + { + NativeMethods.Modulus_UInt64Count(NativePtr, out ulong result); + return result; + } + } + + /// + /// Returns the value of the current Modulus. + /// + public ulong Value + { + get + { + NativeMethods.Modulus_Value(NativePtr, out ulong result); + return result; + } + } + + /// + /// Returns the Barrett ratio computed for the value of the current Modulus. + /// + /// + /// Returns the Barrett ratio computed for the value of the current Modulus. + /// The first two components of the Barrett ratio are the floor of 2^128/value, + /// and the third component is the remainder. + /// + public Tuple ConstRatio + { + get + { + ulong[] ratio = new ulong[3]; + NativeMethods.Modulus_ConstRatio(NativePtr, length: (ulong)3, ratio: ratio); + return new Tuple(ratio[0], ratio[1], ratio[2]); + } + } + + /// + /// Returns whether the value of the current Modulus is zero. + /// + public bool IsZero + { + get + { + NativeMethods.Modulus_IsZero(NativePtr, out bool result); + return result; + } + } + + /// + /// Returns whether the value of the current Modulus is a prime number. + /// + public bool IsPrime + { + get + { + NativeMethods.Modulus_IsPrime(NativePtr, out bool result); + return result; + } + } + + /// + /// Returns an upper bound on the size of the Modulus, as if it was + /// written to an output stream. + /// + /// The compression mode + /// if the compression mode is not + /// supported + /// if the size does not fit in + /// the return type + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.Modulus_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// Saves the Modulus to an output stream. + /// + /// Saves the Modulus to an output stream. The output is in binary format + /// and not human-readable. + /// + /// The stream to save the Modulus to + /// The desired compression mode + /// if stream is null + /// if the stream is closed or does not + /// support writing, or if compression mode is not supported + /// if I/O operations failed + /// if the data to be saved + /// is invalid, or if compression failed + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.Modulus_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// + /// Loads a Modulus from an input stream overwriting the current + /// Modulus. + /// + /// The stream to load the Modulus from + /// if stream is null + /// if the stream is closed or does not + /// support reading + /// if the stream ended + /// unexpectedly + /// if I/O operations failed + /// if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported + public long Load(Stream stream) + { + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.Modulus_Load(NativePtr, outptr, size, + out outBytes), + stream); + } + + /// + /// Returns a hash-code based on the value of the Modulus. + /// + public override int GetHashCode() + { + ulong[] arr = new ulong[1]; + arr[0] = Value; + return Utilities.ComputeArrayHashCode(arr); + } + + /// + /// Compares two Modulus instances. + /// + /// The value to compare against + public override bool Equals(object obj) + { + Modulus sm = obj as Modulus; + return Equals(sm); + } + + /// Creates a Modulus instance. + /// + /// Creates a Modulus instance. The value of the Modulus is set to + /// the given value. + /// + /// The integer modulus + /// if value is 1 or more than 61 bits + public static explicit operator Modulus(ulong value) + { + Modulus sm = new Modulus(value); + return sm; + } + + #region IEquatable methods + + /// + /// Determines whether this instance equals another Modulus instance + /// + /// Instance to compare against + public bool Equals(Modulus other) + { + if (null == other) + return false; + + NativeMethods.Modulus_Equals(NativePtr, other.NativePtr, out bool result); + return result; + } + + #endregion + + #region IEquatable methods + + /// + /// Determines whether the value of this instance equals the given UInt64 value + /// + /// The value to compare against + public bool Equals(ulong other) + { + NativeMethods.Modulus_Equals(NativePtr, other, out bool result); + return result; + } + + #endregion + + #region IComparable methods + + /// + /// Compares two Modulus instances. + /// + /// The Modulus to compare against + public int CompareTo(Modulus compare) + { + if (null == compare) + return 1; + + return Value.CompareTo(compare.Value); + } + + #endregion + + #region IComparable methods + + /// + /// Compares a Modulus value to an unsigned integer. + /// + /// The unsigned integer to compare against + public int CompareTo(ulong compare) + { + return Value.CompareTo(compare); + } + + #endregion + + /// + /// Destroy native object. + /// + protected override void DestroyNativeObject() + { + NativeMethods.Modulus_Destroy(NativePtr); + } + } + + /// + /// Represents a standard security level according to the HomomorphicEncryption.org + /// security standard. + /// + /// + /// Represents a standard security level according to the HomomorphicEncryption.org + /// security standard. The value SecLevelType.None signals that no standard + /// security level should be imposed. The value SecLevelType.TC128 provides + /// a very high level of security and is the default security level enforced by + /// Microsoft SEAL when constructing a SEALContext object. Normal users should not + /// have to specify the security level explicitly anywhere. + /// + public enum SecLevelType : int + { + /// + /// No security level specified. + /// + None = 0, + + /// + /// 128-bit security level according to HomomorphicEncryption.org standard. + /// + TC128 = 128, + + /// + /// 192-bit security level according to HomomorphicEncryption.org standard. + /// + TC192 = 192, + + /// + /// 256-bit security level according to HomomorphicEncryption.org standard. + /// + TC256 = 256 + } + + /// + /// This class contains static methods for creating a coefficient modulus easily. + /// + /// + /// + /// This class contains static methods for creating a coefficient modulus easily. + /// Note that while these functions take a SecLevelType argument, all security + /// guarantees are lost if the output is used with encryption parameters with + /// a mismatching value for the PolyModulusDegree. + /// + /// + /// The default value SecLevelType.TC128 provides a very high level of security + /// and is the default security level enforced by Microsoft SEAL when constructing + /// a SEALContext object. Normal users should not have to specify the security + /// level explicitly anywhere. + /// + /// + public static class CoeffModulus + { + /// + /// Returns the largest bit-length of the coefficient modulus, i.e., bit-length + /// of the product of the primes in the coefficient modulus, that guarantees + /// a given security level when using a given PolyModulusDegree, according + /// to the HomomorphicEncryption.org security standard. + /// + /// The value of the PolyModulusDegree + /// encryption parameter + /// The desired standard security level + static public int MaxBitCount(ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128) + { + NativeMethods.CoeffModulus_MaxBitCount(polyModulusDegree, (int)secLevel, out int result); + return result; + } + + /// + /// Returns a default coefficient modulus for the BFV scheme that guarantees + /// a given security level when using a given PolyModulusDegree, according + /// to the HomomorphicEncryption.org security standard. + /// + /// + /// + /// Returns a default coefficient modulus for the BFV scheme that guarantees + /// a given security level when using a given PolyModulusDegree, according + /// to the HomomorphicEncryption.org security standard. Note that all security + /// guarantees are lost if the output is used with encryption parameters with + /// a mismatching value for the PolyModulusDegree. + /// + /// + /// The coefficient modulus returned by this function will not perform well + /// if used with the CKKS scheme. + /// + /// + /// The value of the PolyModulusDegree + /// encryption parameter + /// The desired standard security level + /// if polyModulusDegree is not + /// a power-of-two or is too large + /// if secLevel is SecLevelType.None + static public IEnumerable BFVDefault( + ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128) + { + List result = null; + + ulong length = 0; + NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, null); + + IntPtr[] coeffArray = new IntPtr[length]; + NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, coeffArray); + + result = new List(checked((int)length)); + foreach (IntPtr sm in coeffArray) + { + result.Add(new Modulus(sm)); + } + + return result; + } + + /// + /// Returns a custom coefficient modulus suitable for use with the specified + /// PolyModulusDegree. + /// + /// + /// Returns a custom coefficient modulus suitable for use with the specified + /// PolyModulusDegree.The return value will be a vector consisting of + /// Modulus elements representing distinct prime numbers of bit-lengths + /// as given in the bitSizes parameter. The bit sizes of the prime numbers + /// can be at most 60 bits. + /// + /// The value of the PolyModulusDegree + /// encryption parameter + /// The bit-lengths of the primes to be generated + /// if polyModulusDegree is not + /// a power-of-two or is too large + /// if bitSizes is too large or if its + /// elements are out of bounds + /// if not enough suitable primes could be found + static public IEnumerable Create( + ulong polyModulusDegree, IEnumerable bitSizes) + { + if (null == bitSizes) + throw new ArgumentNullException(nameof(bitSizes)); + + List result = null; + + int[] bitSizesArr = bitSizes.ToArray(); + int length = bitSizesArr.Length; + + IntPtr[] coeffArray = new IntPtr[length]; + + NativeMethods.CoeffModulus_Create(polyModulusDegree, (ulong)length, bitSizesArr, coeffArray); + + result = new List(length); + foreach (IntPtr sm in coeffArray) + { + result.Add(new Modulus(sm)); + } + + return result; + } + } + + /// + /// This class contains static methods for creating a plaintext modulus easily. + /// + public static class PlainModulus + { + /// + /// Creates a prime number Modulus for use as PlainModulus encryption + /// parameter that supports batching with a given PolyModulusDegree. + /// + /// The value of the PolyModulusDegree + /// encryption parameter + /// The bit-length of the prime to be generated + /// if polyModulusDegree is not + /// a power-of-two or is too large + /// if bitSize is out of bounds + /// if a suitable prime could not be found + static public Modulus Batching(ulong polyModulusDegree, int bitSize) + { + return CoeffModulus.Create( + polyModulusDegree, + new int[] { bitSize }).First(); + } + + /// + /// Creates several prime number Modulus elements that can be used as + /// PlainModulus encryption parameters, each supporting batching with a given + /// PolyModulusDegree. + /// + /// The value of the PolyModulusDegree + /// encryption parameter + /// The bit-lengths of the primes to be generated + /// if polyModulusDegree is not + /// a power-of-two or is too large + /// if bitSizes is too large or if its + /// elements are out of bounds + /// if not enough suitable primes could be found + static public IEnumerable Batching( + ulong polyModulusDegree, IEnumerable bitSizes) + { + return CoeffModulus.Create(polyModulusDegree, bitSizes); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/NativeMethods.cs b/bigpiseal3.5.1/dotnet/src/NativeMethods.cs new file mode 100644 index 0000000000000000000000000000000000000000..729579ff58191bb84fccaee29d8e0974b9a7d624 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/NativeMethods.cs @@ -0,0 +1,1251 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Research.SEAL +{ + [Guid("A7AAD62F-3A48-4188-B6C3-523C294CFDAD")] + static class NativeMethods + { + private const string sealc = "sealc"; + + #region Version methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Version_Major(out byte value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Version_Minor(out byte value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Version_Patch(out byte value); + + #endregion + + #region BigUInt methods + + [DllImport(sealc, EntryPoint = "BigUInt_Create1", PreserveSig = false)] + internal static extern void BigUInt_Create(out IntPtr bigUInt); + + [DllImport(sealc, EntryPoint = "BigUInt_Create2", PreserveSig = false)] + internal static extern void BigUInt_Create(int bitCount, out IntPtr bigUInt); + + [DllImport(sealc, EntryPoint = "BigUInt_Create3", PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_Create(int bitCount, string hexString, out IntPtr bigUInt); + + [DllImport(sealc, EntryPoint = "BigUInt_Create4", PreserveSig = false)] + internal static extern void BigUInt_Create(int bitCount, ulong value, out IntPtr bigUInt); + + [DllImport(sealc, EntryPoint = "BigUInt_Create5", PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_Create(string hexString, out IntPtr bigUInt); + + [DllImport(sealc, EntryPoint = "BigUInt_Create6", PreserveSig = false)] + internal static extern void BigUInt_Create(IntPtr copy, out IntPtr bigUInt); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_IsAlias(IntPtr thisptr, out bool isAlias); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_BitCount(IntPtr thisptr, out int bitCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_ByteCount(IntPtr thisptr, out ulong byteCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_UInt64Count(IntPtr thisptr, out ulong uint64Count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_IsZero(IntPtr thisptr, out bool isZero); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Get(IntPtr thisptr, ulong index, out byte value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_GetU64(IntPtr thisptr, ulong index, out ulong value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_GetSignificantBitCount(IntPtr thisptr, out int significantBitCount); + + [DllImport(sealc, EntryPoint = "BigUInt_Set1", PreserveSig = false)] + internal static extern void BigUInt_Set(IntPtr thisptr, ulong index, byte value); + + [DllImport(sealc, EntryPoint = "BigUInt_Set2", PreserveSig = false)] + internal static extern void BigUInt_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, EntryPoint = "BigUInt_Set3", PreserveSig = false)] + internal static extern void BigUInt_Set(IntPtr thisptr, ulong value); + + [DllImport(sealc, EntryPoint = "BigUInt_Set4", PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_Set(IntPtr thisptr, string assign); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_SetZero(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Resize(IntPtr thisptr, int bitCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Equals(IntPtr thisptr, IntPtr compare, out bool result); + + [DllImport(sealc, EntryPoint = "BigUInt_CompareTo1", PreserveSig = false)] + internal static extern void BigUInt_CompareTo(IntPtr thisptr, IntPtr compare, out int result); + + [DllImport(sealc, EntryPoint = "BigUInt_CompareTo2", PreserveSig = false)] + internal static extern void BigUInt_CompareTo(IntPtr thisptr, ulong compare, out int result); + + [DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder1", PreserveSig = false)] + internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, IntPtr operand2, IntPtr remainder, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder2", PreserveSig = false)] + internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, ulong operand2, IntPtr remainder, out IntPtr result); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_ToDecimalString(IntPtr thisptr, StringBuilder outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_DuplicateTo(IntPtr thisptr, IntPtr destination); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void BigUInt_DuplicateFrom(IntPtr thisptr, IntPtr value); + + [DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert1", PreserveSig = false)] + internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, IntPtr modulus, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert2", PreserveSig = false)] + internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, ulong modulus, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert1", PreserveSig = false)] + internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, IntPtr modulus, IntPtr inverse, out bool result); + + [DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert2", PreserveSig = false)] + internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, ulong modulus, IntPtr inverse, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_OperatorNeg(IntPtr thisptr, out IntPtr result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_OperatorTilde(IntPtr thisptr, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus1", PreserveSig = false)] + internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus2", PreserveSig = false)] + internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus1", PreserveSig = false)] + internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus2", PreserveSig = false)] + internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorMult1", PreserveSig = false)] + internal static extern void BigUInt_OperatorMult(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorMult2", PreserveSig = false)] + internal static extern void BigUInt_OperatorMult(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv1", PreserveSig = false)] + internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv2", PreserveSig = false)] + internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorXor1", PreserveSig = false)] + internal static extern void BigUInt_OperatorXor(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorXor2", PreserveSig = false)] + internal static extern void BigUInt_OperatorXor(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd1", PreserveSig = false)] + internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd2", PreserveSig = false)] + internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorOr1", PreserveSig = false)] + internal static extern void BigUInt_OperatorOr(IntPtr thisptr, IntPtr operand, out IntPtr result); + + [DllImport(sealc, EntryPoint = "BigUInt_OperatorOr2", PreserveSig = false)] + internal static extern void BigUInt_OperatorOr(IntPtr thisptr, ulong operand, out IntPtr result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_OperatorShiftLeft(IntPtr thisptr, int shift, out IntPtr result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_OperatorShiftRight(IntPtr thisptr, int shift, out IntPtr result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_ToDouble(IntPtr thisptr, out double result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BigUInt_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region EncryptionParameterQualifiers methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_Create(IntPtr copy, out IntPtr epq); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_ParametersSet(IntPtr thisptr, out bool parametersSet); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_UsingFFT(IntPtr thisptr, out bool usingFFT); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_UsingNTT(IntPtr thisptr, out bool usingNTT); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_UsingBatching(IntPtr thisptr, out bool usingBatching); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_UsingFastPlainLift(IntPtr thisptr, out bool usingFastPlainLift); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_UsingDescendingModulusChain(IntPtr thisptr, out bool usingDescendingModulusChain); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EPQ_SecLevel(IntPtr thisptr, out int secLevel); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void EPQ_ParameterErrorName(IntPtr thisptr, StringBuilder outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void EPQ_ParameterErrorMessage(IntPtr thisptr, StringBuilder outstr, out ulong length); + + #endregion + + #region Modulus methods + + [DllImport(sealc, EntryPoint = "Modulus_Create1", PreserveSig = false)] + internal static extern void Modulus_Create(ulong value, out IntPtr smallModulus); + + [DllImport(sealc, EntryPoint = "Modulus_Create2", PreserveSig = false)] + internal static extern void Modulus_Create(IntPtr copy, out IntPtr smallModulus); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_IsZero(IntPtr thisptr, out bool isZero); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_IsPrime(IntPtr thisptr, out bool isPrime); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_Value(IntPtr thisptr, out ulong value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_BitCount(IntPtr thisptr, out int bitCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_UInt64Count(IntPtr thisptr, out ulong uint64Count); + + [DllImport(sealc, EntryPoint = "Modulus_Set1", PreserveSig = false)] + internal static extern void Modulus_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, EntryPoint = "Modulus_Set2", PreserveSig = false)] + internal static extern void Modulus_Set(IntPtr thisptr, ulong value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_ConstRatio( + IntPtr thisptr, + ulong length, + [MarshalAs(UnmanagedType.LPArray)] ulong[] ratio); + + [DllImport(sealc, EntryPoint = "Modulus_Equals1", PreserveSig = false)] + internal static extern void Modulus_Equals(IntPtr thisptr, IntPtr other, out bool result); + + [DllImport(sealc, EntryPoint = "Modulus_Equals2", PreserveSig = false)] + internal static extern void Modulus_Equals(IntPtr thisptr, ulong other, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Modulus_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region EncryptionParameters methods + + [DllImport(sealc, EntryPoint = "EncParams_Create1", PreserveSig = false)] + internal static extern void EncParams_Create(byte scheme, out IntPtr encParams); + + [DllImport(sealc, EntryPoint = "EncParams_Create2", PreserveSig = false)] + internal static extern void EncParams_Create(IntPtr copy, out IntPtr encParams); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_GetPolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_SetPolyModulusDegree(IntPtr thisptr, ulong polyModulusDegree); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_GetCoeffModulus( + IntPtr thisptr, + ref ulong length, + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_SetCoeffModulus( + IntPtr thisptr, + ulong length, + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_GetScheme(IntPtr thisptr, out byte scheme); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_GetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_GetPlainModulus(IntPtr thisptr, out IntPtr plainModulus); + + [DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus1", PreserveSig = false)] + internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, IntPtr plainModulus); + + [DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus2", PreserveSig = false)] + internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, ulong plainModulus); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_Equals(IntPtr thisptr, IntPtr otherptr, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void EncParams_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region CoeffModulus methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CoeffModulus_MaxBitCount(ulong polyModulusDegree, int secLevel, out int bitCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CoeffModulus_BFVDefault( + ulong polyModulusDegree, + int secLevel, + ref ulong length, + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CoeffModulus_Create( + ulong polyModulusDegree, + ulong length, + int[] bitSizes, + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray); + + #endregion + + #region SEALContext methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_Create( + IntPtr encryptionParams, + bool expandModChain, + int secLevel, + out IntPtr context); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_KeyParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_FirstParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_LastParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_ParametersSet(IntPtr thisptr, out bool paramsSet); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_ParameterErrorName(IntPtr thisptr, byte[] outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_ParameterErrorMessage(IntPtr thisptr, byte[] outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_KeyContextData(IntPtr thisptr, out IntPtr contextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_FirstContextData(IntPtr thisptr, out IntPtr contextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_LastContextData(IntPtr thisptr, out IntPtr contextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_GetContextData(IntPtr thisptr, ulong[] parmsId, out IntPtr contextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SEALContext_UsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching); + + #endregion + + #region ContextData methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_TotalCoeffModulus(IntPtr thisptr, ref ulong count, ulong[] totalCoeffModulus); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_TotalCoeffModulusBitCount(IntPtr thisptr, out int bitCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_Parms(IntPtr thisptr, out IntPtr parms); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_Qualifiers(IntPtr thisptr, out IntPtr epq); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_CoeffDivPlainModulus(IntPtr thisptr, ref ulong count, ulong[] coefDivPlainMod); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_PlainUpperHalfThreshold(IntPtr thisptr, out ulong puht); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_PlainUpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] puhi); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_UpperHalfThreshold(IntPtr thisptr, ref ulong count, ulong[] uht); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_UpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] uhi); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_PrevContextData(IntPtr thisptr, out IntPtr prevContextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_NextContextData(IntPtr thisptr, out IntPtr nextContextData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ContextData_ChainIndex(IntPtr thisptr, out ulong index); + + #endregion + + #region Evaluator methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Create(IntPtr sealContext, out IntPtr evaluator); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Negate(IntPtr thisptr, IntPtr encrypted, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Add(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_AddMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_AddPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Sub(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_SubPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Multiply(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_MultiplyMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr relinKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_MultiplyPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Square(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Relinearize(IntPtr thisptr, IntPtr encrypted, IntPtr relinKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext1", PreserveSig = false)] + internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext2", PreserveSig = false)] + internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr plain, IntPtr destination); + + [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo1", PreserveSig = false)] + internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo2", PreserveSig = false)] + internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_RescaleToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_RescaleTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_Exponentiate(IntPtr thisptr, IntPtr encrypted, ulong exponent, IntPtr relinKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT1", PreserveSig = false)] + internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destinationNTT, IntPtr pool); + + [DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT2", PreserveSig = false)] + internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr encrypted, IntPtr destinationNTT); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_TransformFromNTT(IntPtr thisptr, IntPtr encryptedNTT, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_ApplyGalois(IntPtr thisptr, IntPtr encrypted, uint galoisElt, IntPtr galoisKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_RotateRows(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_RotateColumns(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_RotateVector(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_ComplexConjugate(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Evaluator_ContextUsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching); + + #endregion + + #region Ciphertext methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Create1(IntPtr pool, out IntPtr cipher); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Create2(IntPtr copy, out IntPtr cipher); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Create3(IntPtr context, IntPtr pool, out IntPtr cipher); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Create4(IntPtr context, ulong[] parmsId, IntPtr pool, out IntPtr cipher); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Create5(IntPtr context, ulong[] parmsId, ulong capacity, IntPtr pool, out IntPtr cipher); + + [DllImport(sealc, EntryPoint = "Ciphertext_Reserve1", PreserveSig = false)] + internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong[] parmsId, ulong sizeCapacity); + + [DllImport(sealc, EntryPoint = "Ciphertext_Reserve2", PreserveSig = false)] + internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong sizeCapacity); + + [DllImport(sealc, EntryPoint = "Ciphertext_Reserve3", PreserveSig = false)] + internal static extern void Ciphertext_Reserve(IntPtr thisptr, ulong sizeCapacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_UInt64Count(IntPtr thisptr, out ulong uint64Count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Size(IntPtr thisptr, out ulong size); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SizeCapacity(IntPtr thisptr, out ulong sizeCapacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_PolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_CoeffModulusSize(IntPtr thisptr, out ulong coeffModCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_ParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, EntryPoint = "Ciphertext_Resize1", PreserveSig = false)] + internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong[] parms_id, ulong size); + + [DllImport(sealc, EntryPoint = "Ciphertext_Resize2", PreserveSig = false)] + internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong size); + + [DllImport(sealc, EntryPoint = "Ciphertext_Resize3", PreserveSig = false)] + internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size); + + [DllImport(sealc, EntryPoint = "Ciphertext_Resize4", PreserveSig = false)] + internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size, ulong polyModulusDegree, ulong coeffModCount); + + [DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt1", PreserveSig = false)] + internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong index, out ulong data); + + [DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt2", PreserveSig = false)] + internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong polyIndex, ulong coeffIndex, out ulong data); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SetDataAt(IntPtr thisptr, ulong index, ulong value); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_IsNTTForm(IntPtr thisptr, out bool isNTTForm); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SetIsNTTForm(IntPtr thisptr, bool isNTTForm); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Scale(IntPtr thisptr, out double scale); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SetScale(IntPtr thisptr, double scale); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Release(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_IsTransparent(IntPtr thisptr, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Pool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Ciphertext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region Plaintext methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Create1(IntPtr memoryPoolHandle, out IntPtr plainText); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Create2(ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Create3(ulong capacity, ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void Plaintext_Create4(string hexPoly, IntPtr memoryPoolHandle, out IntPtr plainText); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Create5(IntPtr copy, out IntPtr plainText); + + [DllImport(sealc, EntryPoint = "Plaintext_Set1", PreserveSig = false)] + internal static extern void Plaintext_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, EntryPoint = "Plaintext_Set2", PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void Plaintext_Set(IntPtr thisptr, string hexPoly); + + [DllImport(sealc, EntryPoint = "Plaintext_Set3", PreserveSig = false)] + internal static extern void Plaintext_Set(IntPtr thisptr, ulong constCoeff); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_CoeffCount(IntPtr thisptr, out ulong coeffCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_CoeffAt(IntPtr thisptr, ulong index, out ulong coeff); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SetCoeffAt(IntPtr thisptr, ulong index, ulong value); + + [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)] + internal static extern void Plaintext_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_IsNTTForm(IntPtr thisptr, out bool isNTTForm); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_IsZero(IntPtr thisptr, out bool isZero); + + [DllImport(sealc, EntryPoint = "Plaintext_SetZero1", PreserveSig = false)] + internal static extern void Plaintext_SetZero(IntPtr thisptr); + + [DllImport(sealc, EntryPoint = "Plaintext_SetZero2", PreserveSig = false)] + internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff); + + [DllImport(sealc, EntryPoint = "Plaintext_SetZero3", PreserveSig = false)] + internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff, ulong length); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_GetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Reserve(IntPtr thisptr, ulong capacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Resize(IntPtr thisptr, ulong coeffCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_ShrinkToFit(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Release(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Capacity(IntPtr thisptr, out ulong capacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_UInt64Count(IntPtr thisptr, out ulong uint64Count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SignificantCoeffCount(IntPtr thisptr, out ulong significantCoeffCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_NonZeroCoeffCount(IntPtr thisptr, out ulong nonZeroCoeffCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Scale(IntPtr thisptr, out double scale); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SetScale(IntPtr thisptr, double scale); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Equals(IntPtr thisptr, IntPtr otherptr, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SwapData(IntPtr thisptr, ulong count, ulong[] newData); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Pool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Plaintext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region KSwitchKeys methods + + [DllImport(sealc, EntryPoint = "KSwitchKeys_Create1", PreserveSig = false)] + internal static extern void KSwitchKeys_Create(out IntPtr kswitchKeys); + + [DllImport(sealc, EntryPoint = "KSwitchKeys_Create2", PreserveSig = false)] + internal static extern void KSwitchKeys_Create(IntPtr copy, out IntPtr kswitchKeys); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Set(IntPtr thisptr, IntPtr assignptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Size(IntPtr thisptr, out ulong size); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_ClearDataAndReserve(IntPtr thisptr, ulong size); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_RawSize(IntPtr thisptr, out ulong keyCount); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_GetKeyList(IntPtr thisptr, ulong index, ref ulong count, IntPtr[] key_list); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_AddKeyList(IntPtr thisptr, ulong count, IntPtr[] key_list); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_GetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_SetParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Pool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KSwitchKeys_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region GaloisKeys methods + + [DllImport(sealc, EntryPoint = "GaloisKeys_GetIndex", PreserveSig = false)] + internal static extern void GaloisKeys_GetIndex(uint galoisElt, out ulong index); + + #endregion + + #region KeyGenerator methods + + [DllImport(sealc, EntryPoint = "KeyGenerator_Create1", PreserveSig = false)] + internal static extern void KeyGenerator_Create(IntPtr sealContext, out IntPtr keyGenerator); + + [DllImport(sealc, EntryPoint = "KeyGenerator_Create2", PreserveSig = false)] + internal static extern void KeyGenerator_Create(IntPtr sealContext, IntPtr secretKey, out IntPtr keyGenerator); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KeyGenerator_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KeyGenerator_RelinKeys(IntPtr thisptr, bool save_seed, out IntPtr relin_keys); + + [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysAll", PreserveSig = false)] + internal static extern void KeyGenerator_GaloisKeysAll(IntPtr thisptr, bool save_seed, out IntPtr galoisKeys); + + [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromElts", PreserveSig = false)] + internal static extern void KeyGenerator_GaloisKeysFromElts(IntPtr thisptr, ulong count, uint[] galoisElts, bool save_seed, out IntPtr galoisKeys); + + [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromSteps", PreserveSig = false)] + internal static extern void KeyGenerator_GaloisKeysFromSteps(IntPtr thisptr, ulong count, int[] steps, bool save_seed, out IntPtr galoisKeys); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KeyGenerator_PublicKey(IntPtr thisptr, out IntPtr publicKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KeyGenerator_SecretKey(IntPtr thisptr, out IntPtr secretKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void KeyGenerator_ContextUsingKeyswitching(IntPtr thisptr, out bool result); + + #endregion + + #region RelinKeys methods + + [DllImport(sealc, EntryPoint = "RelinKeys_GetIndex", PreserveSig = false)] + internal static extern void RelinKeys_GetIndex(ulong keyPower, out ulong index); + + #endregion + + #region PublicKey methods + + [DllImport(sealc, EntryPoint = "PublicKey_Create1", PreserveSig = false)] + internal static extern void PublicKey_Create(out IntPtr publicKey); + + [DllImport(sealc, EntryPoint = "PublicKey_Create2", PreserveSig = false)] + internal static extern void PublicKey_Create(IntPtr copy, out IntPtr publicKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Data(IntPtr thisptr, out IntPtr data); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_ParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Pool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void PublicKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region SecretKey methods + + [DllImport(sealc, EntryPoint = "SecretKey_Create1", PreserveSig = false)] + internal static extern void SecretKey_Create(out IntPtr secretKey); + + [DllImport(sealc, EntryPoint = "SecretKey_Create2", PreserveSig = false)] + internal static extern void SecretKey_Create(IntPtr copy, out IntPtr secretKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Set(IntPtr thisptr, IntPtr assign); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Data(IntPtr thisptr, out IntPtr data); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_ParmsId(IntPtr thisptr, ulong[] parmsId); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Pool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_SaveSize(IntPtr thisptr, byte comprMode, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void SecretKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes); + + #endregion + + #region MemoryManager methods + + [DllImport(sealc, EntryPoint = "MemoryManager_GetPool1", PreserveSig = false)] + internal static extern void MemoryManager_GetPool(int profOpt, bool clearOnDestruction, out IntPtr handle); + + [DllImport(sealc, EntryPoint = "MemoryManager_GetPool2", PreserveSig = false)] + internal static extern void MemoryManager_GetPool(out IntPtr handle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryManager_SwitchProfile(IntPtr newProfile); + + #endregion + + #region MMProf methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_CreateGlobal(out IntPtr profile); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_CreateFixed(IntPtr pool, out IntPtr profile); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_CreateNew(out IntPtr profile); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_CreateThreadLocal(out IntPtr profile); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_GetPool(IntPtr thisptr, out IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MMProf_Destroy(IntPtr thisptr); + + #endregion + + #region MemoryPoolHandle methods + + [DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create1", PreserveSig = false)] + internal static extern void MemoryPoolHandle_Create(out IntPtr handlePtr); + + [DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create2", PreserveSig = false)] + internal static extern void MemoryPoolHandle_Create(IntPtr other, out IntPtr handlePtr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_Set(IntPtr thisptr, IntPtr assignptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_Global(out IntPtr handlePtr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_New(bool clearOnDestruction, out IntPtr handlePtr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_PoolCount(IntPtr thisptr, out ulong count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_AllocByteCount(IntPtr thisptr, out ulong count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_UseCount(IntPtr thisptr, out long count); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_IsInitialized(IntPtr thisptr, out bool initialized); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void MemoryPoolHandle_Equals(IntPtr thisptr, IntPtr otherptr, out bool result); + + #endregion + + #region Encryptor methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_Create(IntPtr context, IntPtr publicKey, IntPtr secretKey, out IntPtr encryptor); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_SetPublicKey(IntPtr thisptr, IntPtr publicKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_SetSecretKey(IntPtr thisptr, IntPtr secretKey); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_Encrypt(IntPtr thisptr, IntPtr plaintext, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_EncryptZero1(IntPtr thisptr, ulong[] parmsId, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_EncryptZero2(IntPtr thisptr, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_EncryptSymmetric(IntPtr thisptr, IntPtr plaintext, bool save_seed, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_EncryptZeroSymmetric1(IntPtr thisptr, ulong[] parmsId, bool save_seed, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_EncryptZeroSymmetric2(IntPtr thisptr, bool save_seed, IntPtr destination, IntPtr poolHandle); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Encryptor_Destroy(IntPtr thisptr); + + #endregion + + #region Decryptor methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Decryptor_Create(IntPtr context, IntPtr secretKey, out IntPtr decryptor); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Decryptor_Destroy(IntPtr thisptr); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Decryptor_Decrypt(IntPtr thisptr, IntPtr encrypted, IntPtr destination); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Decryptor_InvariantNoiseBudget(IntPtr thisptr, IntPtr encrypted, out int invariantNoiseBudget); + + #endregion + + #region CKKSEncoder methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CKKSEncoder_Create(IntPtr context, out IntPtr ckksEncoder); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CKKSEncoder_Destroy(IntPtr thisptr); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode1", PreserveSig = false)] + internal static extern void CKKSEncoder_EncodeDouble(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode2", PreserveSig = false)] + internal static extern void CKKSEncoder_EncodeComplex(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode3", PreserveSig = false)] + internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double value, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode4", PreserveSig = false)] + internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double valueRe, double valueIm, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode5", PreserveSig = false)] + internal static extern void CKKSEncoder_Encode(IntPtr thisptr, long value, ulong[] parms_id, IntPtr destination); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Decode1", PreserveSig = false)] + internal static extern void CKKSEncoder_DecodeDouble(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool); + + [DllImport(sealc, EntryPoint = "CKKSEncoder_Decode2", PreserveSig = false)] + internal static extern void CKKSEncoder_DecodeComplex(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void CKKSEncoder_SlotCount(IntPtr thisptr, out ulong slotCount); + + #endregion + + #region BatchEncoder methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BatchEncoder_Create(IntPtr context, out IntPtr batchEncoder); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BatchEncoder_Destroy(IntPtr thisptr); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Encode1", PreserveSig = false)] + internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, ulong[] values, IntPtr destination); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Encode2", PreserveSig = false)] + internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, long[] values, IntPtr destination); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Encode3", PreserveSig = false)] + internal static extern void BatchEncoder_Encode(IntPtr thisptr, IntPtr plain, IntPtr pool); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Decode1", PreserveSig = false)] + internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, ulong[] destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Decode2", PreserveSig = false)] + internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, long[] destination, IntPtr pool); + + [DllImport(sealc, EntryPoint = "BatchEncoder_Decode3", PreserveSig = false)] + internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, IntPtr pool); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void BatchEncoder_GetSlotCount(IntPtr thisptr, out ulong slotCount); + + #endregion + + #region IntegerEncoder methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_Create(IntPtr context, out IntPtr encoder); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_Destroy(IntPtr thisptr); + + [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode1", PreserveSig = false)] + internal static extern void IntegerEncoder_Encode(IntPtr thisptr, int value, IntPtr plain); + + [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode2", PreserveSig = false)] + internal static extern void IntegerEncoder_Encode(IntPtr thisptr, uint value, IntPtr plain); + + [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode3", PreserveSig = false)] + internal static extern void IntegerEncoder_Encode(IntPtr thisptr, ulong value, IntPtr plain); + + [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode4", PreserveSig = false)] + internal static extern void IntegerEncoder_Encode(IntPtr thisptr, long value, IntPtr plain); + + [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode5", PreserveSig = false)] + internal static extern void IntegerEncoder_Encode(IntPtr thisptr, IntPtr bigUInt, IntPtr plain); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_DecodeUInt32(IntPtr thisptr, IntPtr plain, out uint result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_DecodeUInt64(IntPtr thisptr, IntPtr plain, out ulong result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_DecodeInt32(IntPtr thisptr, IntPtr plain, out int result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_DecodeInt64(IntPtr thisptr, IntPtr plain, out long result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_DecodeBigUInt(IntPtr thisptr, IntPtr plain, out IntPtr bigUInt); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void IntegerEncoder_PlainModulus(IntPtr thisptr, out IntPtr smallModulus); + + #endregion + + #region ValCheck methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_Plaintext_IsValidFor(IntPtr plaintext, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_Ciphertext_IsValidFor(IntPtr ciphertext, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_SecretKey_IsValidFor(IntPtr secretKey, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_PublicKey_IsValidFor(IntPtr publicKey, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_KSwitchKeys_IsValidFor(IntPtr kswitchKeys, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_RelinKeys_IsValidFor(IntPtr relinKeys, IntPtr context, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void ValCheck_GaloisKeys_IsValidFor(IntPtr galoisKeys, IntPtr context, out bool result); + + #endregion + + #region Serialization methods + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_SEALMagic(out ushort result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_SEALHeaderSize(out byte result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_IsSupportedComprMode(byte comprMode, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_ComprModeDefault(out byte result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_IsCompatibleVersion(byte[] headerptr, ulong size, out bool result); + + [DllImport(sealc, PreserveSig = false)] + internal static extern void Serialization_IsValidHeader(byte[] headerptr, ulong size, out bool result); + + #endregion + + public static class Errors + { + public const uint NoError = 0; + public const uint InsufficientBuffer = 122; + public const uint BadArguments = 160; + public const uint InvalidIndex = 1413; + public const uint InvalidOperation = 4317; + public const uint HRPointer = 0x80004003; + public const uint HRInvalidIndex = 0x80070585; + public const uint HRInvalidOperation = 0x800710DD; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/ParmsId.cs b/bigpiseal3.5.1/dotnet/src/ParmsId.cs new file mode 100644 index 0000000000000000000000000000000000000000..223444d9abed2b8e1bf54720bcbdb793a22d1540 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/ParmsId.cs @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Text; + +namespace Microsoft.Research.SEAL +{ + /// + /// Identify a set of Encryption Parameters + /// + public class ParmsId : IEquatable + { + /// + /// Create an instance of ParmsId + /// + public ParmsId() + { + } + + /// + /// Create an instance of ParmsId by copying other instance + /// + /// Instance to copy + public ParmsId(ParmsId other) + { + if (null == other) + throw new ArgumentNullException(nameof(other)); + CopyId(this, other.Block); + } + + /// + /// Create an instance of ParmsId by copying the input array + /// + /// Array to copy + private ParmsId(ulong[] id) + { + if (null == id) + throw new ArgumentNullException(nameof(id)); + if (id.Length != ULongCount) + throw new ArgumentException($"id length should be {ULongCount}"); + + CopyId(this, id); + } + + /// + /// Array that contains the Params Id hash block + /// + public ulong[] Block { get; } = new ulong[4] { 0, 0, 0, 0 }; + + /// + /// Copy an input array to the ParmsId hash block + /// + private static void CopyId(ParmsId dest, ulong[] src) + { + int idx = 0; + foreach (ulong ul in src) + { + dest.Block[idx++] = ul; + } + } + + /// + /// Convert ParmsId to a string representation. + /// + public override string ToString() + { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < ULongCount; i++) + { + byte[] bytes = BitConverter.GetBytes(Block[i]); + for (int b = bytes.Length - 1; b >= 0; b--) + { + result.Append(BitConverter.ToString(bytes, b, length: 1)); + } + if (i < (ULongCount - 1)) + result.Append(" "); + } + + return result.ToString(); + } + + /// + /// Hash code for this object + /// + public override int GetHashCode() + { + return Utilities.ComputeArrayHashCode(Block); + } + + /// + /// Whether the input object is equivalent to this object + /// + public override bool Equals(object obj) + { + return Equals(obj as ParmsId); + } + + /// + /// Whether the input object is equivalent to this object + /// + public bool Equals(ParmsId other) + { + if (null == other) + return false; + + for (int i = 0; i < ULongCount; i++) + { + if (Block[i] != other.Block[i]) + return false; + } + + return true; + } + + /// + /// Return whether parms1 equals parms2. + /// + public static bool operator ==(ParmsId parms1, ParmsId parms2) + { + object obj1 = parms1 as object; + object obj2 = parms2 as object; + + if (null == obj1 && null == obj2) + return true; + if (null == obj1) + return false; + + return parms1.Equals(parms2); + } + + /// + /// Return whether parms1 does not equal parms2. + /// + public static bool operator !=(ParmsId parms1, ParmsId parms2) + { + object obj1 = parms1 as object; + object obj2 = parms2 as object; + + if (null == obj1 && null == obj2) + return false; + if (null == obj1) + return true; + + return !parms1.Equals(parms2); + } + + /// + /// ParmsId with a Zero hash block + /// + public static ParmsId Zero = new ParmsId(new ulong[4] { 0, 0, 0, 0 }); + + /// + /// Number of elements in the hash block array + /// + private const int ULongCount = 4; + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Plaintext.cs b/bigpiseal3.5.1/dotnet/src/Plaintext.cs new file mode 100644 index 0000000000000000000000000000000000000000..210b5dd679a1e0f106e7221ef5c8acb85c148575 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Plaintext.cs @@ -0,0 +1,685 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Research.SEAL +{ + /// + /// Class to store a plaintext element. + /// + /// + /// + /// Class to store a plaintext element. The data for the plaintext is + /// a polynomial with coefficients modulo the plaintext modulus. The degree + /// of the plaintext polynomial must be one less than the degree of the + /// polynomial modulus. The backing array always allocates one 64-bit word + /// per each coefficient of the polynomial. + /// + /// + /// Memory Management + /// The coefficient count of a plaintext refers to the number of word-size + /// coefficients in the plaintext, whereas its capacity refers to the number + /// of word-size coefficients that fit in the current memory allocation. In + /// high-performance applications unnecessary re-allocations should be avoided + /// by reserving enough memory for the plaintext to begin with either by + /// providing the desired capacity to the constructor as an extra argument, or + /// by calling the reserve function at any time. + /// + /// When the scheme is SchemeType.BFV each coefficient of a plaintext is + /// a 64-bit word, but when the scheme is SchemeType.CKKS the plaintext is + /// by default stored in an NTT transformed form with respect to each of the + /// primes in the coefficient modulus. Thus, the size of the allocation that + /// is needed is the size of the coefficient modulus (number of primes) times + /// the degree of the polynomial modulus. In addition, a valid CKKS plaintext + /// will also store the ParmsId for the corresponding encryption parameters. + /// + /// + /// Thread Safety + /// In general, reading from plaintext is thread-safe as long as no other + /// thread is concurrently mutating it. This is due to the underlying data + /// structure storing the plaintext not being thread-safe. + /// + /// + /// See Ciphertext for the class that stores ciphertexts. + public class Plaintext : NativeObject, IEquatable + { + /// <summary> + /// Constructs an empty plaintext allocating no memory. + /// </summary> + /// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param> + /// <exception cref="ArgumentException">if pool is uninitialized</exception> + public Plaintext(MemoryPoolHandle pool = null) + { + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + + NativeMethods.Plaintext_Create1(poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Constructs a plaintext representing a constant polynomial 0. The + /// coefficient count of the polynomial is set to the given value. The + /// capacity is set to the same value. + /// </summary> + /// <param name="coeffCount">The number of (zeroed) coefficients in the + /// plaintext polynomial</param> + /// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param> + /// <exception cref="ArgumentException">if coeffCount is negative</exception> + /// <exception cref="ArgumentException">if pool is uninitialized</exception> + public Plaintext(ulong coeffCount, MemoryPoolHandle pool = null) + { + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + + NativeMethods.Plaintext_Create2(coeffCount, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Constructs a plaintext representing a constant polynomial 0. The + /// coefficient count of the polynomial and the capacity are set to the + /// given values. + /// </summary> + /// <param name="capacity">The capacity</param> + /// <param name="coeffCount">The number of (zeroed) coefficients in the + /// plaintext polynomial</param> + /// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param> + /// <exception cref="ArgumentException">if capacity is less than coeffCount</exception> + /// <exception cref="ArgumentException">if coeffCount is negative</exception> + /// <exception cref="ArgumentException">if pool is uninitialized</exception> + public Plaintext(ulong capacity, ulong coeffCount, MemoryPoolHandle pool = null) + { + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + + NativeMethods.Plaintext_Create3(capacity, coeffCount, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Constructs a plaintext from a given hexadecimal string describing the + /// plaintext polynomial. + /// </summary> + /// <remarks> + /// The string description of the polynomial must adhere to the format + /// returned by ToString(), which is of the form "7FFx^3 + 1x^1 + 3" + /// and summarized by the following + /// rules: + /// 1. Terms are listed in order of strictly decreasing exponent + /// 2. Coefficient values are non-negative and in hexadecimal format (upper + /// and lower case letters are both supported) + /// 3. Exponents are positive and in decimal format + /// 4. Zero coefficient terms (including the constant term) may be (but do + /// not have to be) omitted + /// 5. Term with the exponent value of one must be exactly written as x^1 + /// 6. Term with the exponent value of zero (the constant term) must be written + /// as just a hexadecimal number without exponent + /// 7. Terms must be separated by exactly [space]+[space] and minus is not + /// allowed + /// 8. Other than the +, no other terms should have whitespace + /// </remarks> + /// <param name="hexPoly">The formatted polynomial string specifying the plaintext + /// polynomial</param> + /// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param> + /// <exception cref="ArgumentNullException">if hexPoly is null</exception> + /// <exception cref="ArgumentException">if hexPoly does not adhere to the expected + /// format</exception> + /// <exception cref="ArgumentException">if pool is uninitialized</exception> + public Plaintext(string hexPoly, MemoryPoolHandle pool = null) + { + if (null == hexPoly) + throw new ArgumentNullException(nameof(hexPoly)); + + IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero; + + NativeMethods.Plaintext_Create4(hexPoly, poolPtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Constructs a new plaintext by copying a given one. + /// </summary> + /// <param name="copy">The plaintext to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public Plaintext(Plaintext copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.Plaintext_Create5(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Constructs a new plaintext by copying a given one. + /// </summary> + /// <param name="copy">The plaintext to copy from</param> + /// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param> + /// <exception cref="ArgumentNullException">if either copy or pool are null</exception> + /// <exception cref="ArgumentException">if pool is uninitialized</exception> + public Plaintext(Plaintext copy, MemoryPoolHandle pool) : this(pool) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + Set(copy); + } + + /// <summary> + /// Constructs a plaintext by initializing it with a pointer to a native object. + /// </summary> + /// <param name="plaintextPtr">Pointer to native Plaintext object</param> + /// <param name="owned">Whether this instance owns the native pointer</param> + internal Plaintext(IntPtr plaintextPtr, bool owned = true) + : base(plaintextPtr, owned) + { + } + + /// <summary> + /// Allocates enough memory to accommodate the backing array of a plaintext + /// with given capacity. + /// </summary> + /// <param name="capacity">The capacity</param> + /// <exception cref="InvalidOperationException">if the plaintext is NTT transformed</exception> + public void Reserve(ulong capacity) + { + NativeMethods.Plaintext_Reserve(NativePtr, capacity); + } + + /// <summary> + /// Allocates enough memory to accommodate the backing array of the current + /// plaintext and copies it over to the new location. This function is meant + /// to reduce the memory use of the plaintext to smallest possible and can be + /// particularly important after modulus switching. + /// </summary> + public void ShrinkToFit() + { + NativeMethods.Plaintext_ShrinkToFit(NativePtr); + } + + /// <summary> + /// Resets the plaintext. This function releases any memory allocated by the + /// plaintext, returning it to the memory pool. + /// </summary> + public void Release() + { + NativeMethods.Plaintext_Release(NativePtr); + } + + /// <summary> + /// Resizes the plaintext to have a given coefficient count. The plaintext + /// is automatically reallocated if the new coefficient count does not fit in + /// the current capacity. + /// </summary> + /// <param name="coeffCount">The number of coefficients in the plaintext + /// polynomial</param> + /// <exception cref="InvalidOperationException">if the plaintext is NTT transformed</exception> + public void Resize(ulong coeffCount) + { + NativeMethods.Plaintext_Resize(NativePtr, coeffCount); + } + + /// <summary> + /// Copies a given plaintext to the current one. + /// </summary> + /// + /// <param name="assign">The plaintext to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(Plaintext assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.Plaintext_Set(NativePtr, assign.NativePtr); + } + + /// <summary> + /// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string. + /// </summary> + /// + /// <remarks> + /// <para> + /// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string. + /// </para> + /// <para> + /// The string description of the polynomial must adhere to the format returned by <see cref="ToString()"/>, + /// which is of the form "7FFx^3 + 1x^1 + 3" and summarized by the following rules: + /// <list type="number"> + /// <item><description>Terms are listed in order of strictly decreasing exponent</description></item> + /// <item><description>Coefficient values are non-negative and in hexadecimal format (upper and lower case letters are both supported)</description></item> + /// <item><description>Exponents are positive and in decimal format</description></item> + /// <item><description>Zero coefficient terms (including the constant term) may be (but do not have to be) omitted</description></item> + /// <item><description>Term with the exponent value of one is written as x^1</description></item> + /// <item><description>Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent</description></item> + /// <item><description>Terms are separated exactly by &lt;space&gt;+&lt;space&gt;</description></item> + /// <item><description>Other than the +, no other terms have whitespace</description></item> + /// </list> + /// </para> + /// </remarks> + /// <param name="hexPoly">The formatted polynomial string specifying the plaintext polynomial</param> + /// <exception cref="ArgumentException">if hexPoly does not adhere to the expected format</exception> + /// <exception cref="ArgumentException">if the coefficients of hexPoly are too wide</exception> + /// <exception cref="ArgumentNullException">if hexPoly is null</exception> + public void Set(string hexPoly) + { + if (null == hexPoly) + throw new ArgumentNullException(nameof(hexPoly)); + + NativeMethods.Plaintext_Set(NativePtr, hexPoly); + } + + /// <summary> + /// Sets the value of the current plaintext to a given constant polynomial. + /// </summary> + /// + /// <remarks> + /// Sets the value of the current plaintext to a given constant polynomial. The coefficient count + /// is set to one. + /// </remarks> + /// <param name="constCoeff">The constant coefficient</param> + public void Set(ulong constCoeff) + { + NativeMethods.Plaintext_Set(NativePtr, constCoeff); + } + + + /// <summary> + /// Sets a given range of coefficients of a plaintext polynomial to zero. + /// </summary> + /// + /// <param name="startCoeff">The index of the first coefficient to set to zero</param> + /// <param name="length">The number of coefficients to set to zero</param> + /// <exception cref="ArgumentOutOfRangeException">if startCoeff is not within [0, CoeffCount)</exception> + /// <exception cref="ArgumentOutOfRangeException">if startCoeff + length is not within [0, CoeffCount)</exception> + /// */ + public void SetZero(ulong startCoeff, ulong length) + { + try + { + NativeMethods.Plaintext_SetZero(NativePtr, startCoeff, length); + } + catch(COMException e) + { + if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex) + throw new ArgumentOutOfRangeException("startCoeff or length out of range", e); + throw; + } + } + + /// <summary> + /// Sets the plaintext polynomial coefficients to zero starting at a given + /// index. + /// </summary> + /// <param name="startCoeff">The index of the first coefficient to set to zero</param> + /// <exception cref="ArgumentOutOfRangeException">if startCoeff is not within [0, CoeffCount)</exception> + public void SetZero(ulong startCoeff) + { + try + { + NativeMethods.Plaintext_SetZero(NativePtr, startCoeff); + } + catch (COMException e) + { + if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex) + throw new ArgumentOutOfRangeException("startCoeff or length out of range", e); + throw; + } + } + + /// <summary> + /// Sets the plaintext polynomial to zero. + /// </summary> + public void SetZero() + { + NativeMethods.Plaintext_SetZero(NativePtr); + } + + /// <summary> + /// Gets/set the value of a given coefficient of the plaintext polynomial. + /// </summary> + /// <param name="coeffIndex">The index of the coefficient in the plaintext polynomial</param> + /// <exception cref="ArgumentOutOfRangeException">if coeffIndex is not within [0, CoeffCount)</exception> + public ulong this[ulong coeffIndex] + { + get + { + NativeMethods.Plaintext_CoeffAt(NativePtr, coeffIndex, out ulong result); + return result; + } + set + { + NativeMethods.Plaintext_SetCoeffAt(NativePtr, coeffIndex, value); + } + } + + /// <summary> + /// Returns whether the plaintext polynomial has all zero coefficients. + /// </summary> + public bool IsZero + { + get + { + NativeMethods.Plaintext_IsZero(NativePtr, out bool result); + return result; + } + } + + /// <summary> + /// Returns the capacity of the current allocation. + /// </summary> + public ulong Capacity + { + get + { + NativeMethods.Plaintext_Capacity(NativePtr, out ulong capacity); + return capacity; + } + } + + /// <summary> + /// Returns the coefficient count of the current plaintext polynomial. + /// </summary> + public ulong CoeffCount + { + get + { + NativeMethods.Plaintext_CoeffCount(NativePtr, out ulong result); + return result; + } + } + + /// <summary> + /// Returns the significant coefficient count of the current plaintext polynomial. + /// </summary> + public ulong SignificantCoeffCount + { + get + { + NativeMethods.Plaintext_SignificantCoeffCount(NativePtr, out ulong result); + return result; + } + } + + /// <summary> + /// Returns the non-zero coefficient count of the current plaintext polynomial. + /// </summary> + public ulong NonZeroCoeffCount + { + get + { + NativeMethods.Plaintext_NonZeroCoeffCount(NativePtr, out ulong result); + return result; + } + } + + /// <summary> + /// Returns a human-readable string description of the plaintext polynomial. + /// </summary> + /// <remarks> + /// <para> + /// Returns a human-readable string description of the plaintext polynomial. + /// </para> + /// <para> + /// The returned string is of the form "7FFx^3 + 1x^1 + 3" with a format summarized by the following: + /// <list type="number"> + /// <item><description>Terms are listed in order of strictly decreasing exponent</description></item> + /// <item><description>Coefficient values are non-negative and in hexadecimal format (hexadecimal letters are in upper-case)</description></item> + /// <item><description>Exponents are positive and in decimal format</description></item> + /// <item><description>Zero coefficient terms (including the constant term) are omitted unless the polynomial is exactly 0 (see rule 9)</description></item> + /// <item><description>Term with the exponent value of one is written as x^1</description></item> + /// <item><description>Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent</description></item> + /// <item><description>Terms are separated exactly by &lt;space&gt;+&lt;space&gt;</description></item> + /// <item><description>Other than the +, no other terms have whitespace</description></item> + /// <item><description>If the polynomial is exactly 0, the string "0" is returned</description></item> + /// </list> + /// </para> + /// </remarks> + /// <exception cref="InvalidOperationException">if the plaintext is in NTT transformed form</exception> + public override string ToString() + { + NativeMethods.Plaintext_ToString(NativePtr, null, out ulong length); + StringBuilder buffer = new StringBuilder(checked((int)length)); + NativeMethods.Plaintext_ToString(NativePtr, buffer, out length); + return buffer.ToString(); + } + + /// <summary> + /// Returns a hash-code based on the value of the plaintext polynomial. + /// </summary> + public override int GetHashCode() + { + ulong coeffCount = CoeffCount; + ulong[] coeffs = new ulong[coeffCount]; + + for (ulong i = 0; i < coeffCount; i++) + { + coeffs[i] = this[i]; + } + + return Utilities.ComputeArrayHashCode(coeffs); + } + + /// <summary> + /// Returns an upper bound on the size of the ciphertext, as if it was written + /// to an output stream. + /// </summary> + /// <param name="comprMode">The compression mode</param> + /// <exception cref="ArgumentException">if the compression mode is not + /// supported</exception> + /// <exception cref="InvalidOperationException">if the size does not fit in + /// the return type</exception> + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.Plaintext_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// <summary>Saves the Plaintext to an output stream.</summary> + /// <remarks> + /// Saves the Plaintext to an output stream. The output is in binary format + /// and not human-readable. + /// </remarks> + /// <param name="stream">The stream to save the Plaintext to</param> + /// <param name="comprMode">The desired compression mode</param> + /// <exception cref="ArgumentNullException">if stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support writing, or if compression mode is not supported</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved + /// is invalid, or if compression failed</exception> + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.Plaintext_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// <summary>Loads a plaintext from an input stream overwriting the current + /// plaintext.</summary> + /// <remarks> + /// Loads a plaintext from an input stream overwriting the current plaintext. + /// No checking of the validity of the plaintext data against encryption + /// parameters is performed. This function should not be used unless the + /// plaintext comes from a fully trusted source. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the plaintext from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long UnsafeLoad(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.Plaintext_UnsafeLoad(context.NativePtr, NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary>Loads a plaintext from an input stream overwriting the current + /// plaintext.</summary> + /// <remarks> + /// Loads a plaintext from an input stream overwriting the current plaintext. + /// The loaded plaintext is verified to be valid for the given SEALContext. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the plaintext from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long Load(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.Plaintext_Load(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary> + /// Returns whether the plaintext is in NTT form. + /// </summary> + public bool IsNTTForm + { + get + { + NativeMethods.Plaintext_IsNTTForm(NativePtr, out bool result); + return result; + } + } + + /// <summary> + /// Returns a copy of ParmsId. The ParmsId must remain zero unless the + /// plaintext polynomial is in NTT form. + /// </summary> + /// <seealso cref="EncryptionParameters">see EncryptionParameters for more + /// information about parmsId.</seealso> + public ParmsId ParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.Plaintext_GetParmsId(NativePtr, parms.Block); + return parms; + } + + private set + { + NativeMethods.Plaintext_SetParmsId(NativePtr, value.Block); + } + } + + /// <summary> + /// Returns a reference to the scale. This is only needed when using the + /// CKKS encryption scheme. The user should have little or no reason to ever + /// change the scale by hand. + /// </summary> + public double Scale + { + get + { + NativeMethods.Plaintext_Scale(NativePtr, out double scale); + return scale; + } + + private set + { + NativeMethods.Plaintext_SetScale(NativePtr, value); + } + } + + /// <summary> + /// Returns the currently used MemoryPoolHandle. + /// </summary> + public MemoryPoolHandle Pool + { + get + { + NativeMethods.Plaintext_Pool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + } + + /// <summary> + /// Returns whether or not the plaintext has the same semantic value as a given + /// plaintext. + /// </summary> + /// <remarks> + /// Returns whether or not the plaintext has the same semantic value as a given + /// plaintext. Leading zero coefficients are ignored by the comparison. + /// </remarks> + /// <param name="obj">The object to compare against</param> + public override bool Equals(object obj) + { + Plaintext pt = obj as Plaintext; + return Equals(pt); + } + + /// <summary> + /// Returns whether or not the plaintext has the same semantic value as a given + /// plaintext. + /// </summary> + /// <remarks> + /// Returns whether or not the plaintext has the same semantic value as a given + /// plaintext. Leading zero coefficients are ignored by the comparison. + /// </remarks> + /// <param name="other">The plaintext to compare against</param> + public bool Equals(Plaintext other) + { + if (null == other) + return false; + + NativeMethods.Plaintext_Equals(NativePtr, other.NativePtr, out bool equals); + return equals; + } + + /// <summary> + /// Destroy native object. + /// </summary> + protected override void DestroyNativeObject() + { + NativeMethods.Plaintext_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/PublicKey.cs b/bigpiseal3.5.1/dotnet/src/PublicKey.cs new file mode 100644 index 0000000000000000000000000000000000000000..325c54937e43f6a7f351974f96192aa8a26aaa12 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/PublicKey.cs @@ -0,0 +1,235 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// Class to store a public key. + /// </summary> + /// <remarks> + /// <para> + /// Thread Safety + /// In general, reading from PublicKey is thread-safe as long as no other thread + /// is concurrently mutating it. This is due to the underlying data structure + /// storing the public key not being thread-safe. + /// </para> + /// </remarks> + public class PublicKey : NativeObject + { + /// <summary> + /// Creates an empty public key. + /// </summary> + public PublicKey() + { + NativeMethods.PublicKey_Create(out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Creates a new PublicKey by copying an old one. + /// </summary> + /// <param name="copy">The PublicKey to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public PublicKey(PublicKey copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.PublicKey_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Creates a new PublicKey by initializing with a pointer to a native object. + /// </summary> + /// <param name="publicKeyPtr">Pointer to native PublicKey</param> + /// <param name="owned">Whether this instance owns the native pointer</param> + internal PublicKey(IntPtr publicKeyPtr, bool owned = true) + : base(publicKeyPtr, owned) + { + } + + /// <summary> + /// Copies an old PublicKey to the current one. + /// </summary> + /// <param name="assign">The PublicKey to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(PublicKey assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.PublicKey_Set(NativePtr, assign.NativePtr); + } + + /// <summary> + /// Returns the underlying Ciphertext. + /// </summary> + /// <remarks> + /// Returns the underlying Ciphertext. The returned Ciphertext is valid + /// only as long as the PublicKey is valid and not changed. + /// </remarks> + public Ciphertext Data + { + get + { + NativeMethods.PublicKey_Data(NativePtr, out IntPtr cipherPtr); + Ciphertext cipher = new Ciphertext(cipherPtr, owned: false); + return cipher; + } + } + + /// <summary> + /// Returns an upper bound on the size of the PublicKey, as if it was written + /// to an output stream. + /// </summary> + /// <param name="comprMode">The compression mode</param> + /// <exception cref="ArgumentException">if the compression mode is not + /// supported</exception> + /// <exception cref="InvalidOperationException">if the size does not fit in + /// the return type</exception> + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.PublicKey_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// <summary>Saves the PublicKey to an output stream.</summary> + /// <remarks> + /// Saves the PublicKey to an output stream. The output is in binary format + /// and not human-readable. + /// </remarks> + /// <param name="stream">The stream to save the PublicKey to</param> + /// <param name="comprMode">The desired compression mode</param> + /// <exception cref="ArgumentNullException">if stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support writing, or if compression mode is not supported</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved + /// is invalid, or if compression failed</exception> + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.PublicKey_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// <summary>Loads a PublicKey from an input stream overwriting the current + /// PublicKey.</summary> + /// <remarks> + /// Loads a PublicKey from an input stream overwriting the current PublicKey. + /// No checking of the validity of the PublicKey data against encryption + /// parameters is performed. This function should not be used unless the + /// PublicKey comes from a fully trusted source. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the PublicKey from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long UnsafeLoad(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.PublicKey_UnsafeLoad(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary>Loads a PublicKey from an input stream overwriting the current + /// PublicKey.</summary> + /// <remarks> + /// Loads a PublicKey from an input stream overwriting the current PublicKey. + /// The loaded PublicKey is verified to be valid for the given SEALContext. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the PublicKey from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long Load(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.PublicKey_Load(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary> + /// Returns a copy of ParmsId. + /// </summary> + public ParmsId ParmsId + { + get + { + ParmsId parmsId = new ParmsId(); + NativeMethods.PublicKey_ParmsId(NativePtr, parmsId.Block); + return parmsId; + } + } + + /// <summary> + /// Returns the currently used MemoryPoolHandle. + /// </summary> + public MemoryPoolHandle Pool + { + get + { + NativeMethods.PublicKey_Pool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + } + + /// <summary> + /// Destroy native object. + /// </summary> + protected override void DestroyNativeObject() + { + NativeMethods.PublicKey_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/RelinKeys.cs b/bigpiseal3.5.1/dotnet/src/RelinKeys.cs new file mode 100644 index 0000000000000000000000000000000000000000..d84dfc1c68b58e77885cf96f54f21f4ac439fc5c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/RelinKeys.cs @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// Class to store relinearization keys. + /// </summary> + /// <remarks> + /// <para> + /// Relinearization + /// Freshly encrypted ciphertexts have a size of 2, and multiplying ciphertexts + /// of sizes K and L results in a ciphertext of size K+L-1. Unfortunately, this + /// growth in size slows down further multiplications and increases noise growth. + /// Relinearization is an operation that has no semantic meaning, but it reduces + /// the size of ciphertexts back to 2. Microsoft SEAL can only relinearize size 3 + /// ciphertexts back to size 2, so if the ciphertexts grow larger than size 3, + /// there is no way to reduce their size. Relinearization requires an instance of + /// RelinKeys to be created by the secret key owner and to be shared with the + /// evaluator. Note that plain multiplication is fundamentally different from + /// normal multiplication and does not result in ciphertext size growth. + /// </para> + /// <para> + /// When to Relinearize + /// Typically, one should always relinearize after each multiplications. However, + /// in some cases relinearization should be postponed as late as possible due to + /// its computational cost.For example, suppose the computation involves several + /// homomorphic multiplications followed by a sum of the results. In this case it + /// makes sense to not relinearize each product, but instead add them first and + /// only then relinearize the sum. This is particularly important when using the + /// CKKS scheme, where relinearization is much more computationally costly than + /// multiplications and additions. + /// </para> + /// <para> + /// Thread Safety + /// In general, reading from RelinKeys is thread-safe as long as no other thread + /// is concurrently mutating it. This is due to the underlying data structure + /// storing the relinearization keys not being thread-safe. + /// </para> + /// </remarks> + public class RelinKeys : + KSwitchKeys, + ISerializableObject, + ISettable<RelinKeys> + { + /// <summary> + /// Creates an empty set of relinearization keys. + /// </summary> + public RelinKeys() : base() + { + } + + /// <summary> + /// Creates a new RelinKeys instance by copying a given instance. + /// </summary> + /// <param name="copy">The RelinKeys to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public RelinKeys(RelinKeys copy) + : base(copy) + { + } + + /// <summary> + /// Creates a new RelinKeys instance initialized with a pointer to a native + /// KSwitchKeys object. + /// </summary> + /// <param name="kswitchKeys">Pointer to native KSwitchKeys object</param> + /// <param name="owned">Whether this instance owns the native pointer</param> + internal RelinKeys(IntPtr kswitchKeys, bool owned = true) + : base(kswitchKeys, owned) + { + } + + /// <summary> + /// Copies a given RelinKeys instance to the current one. + /// </summary> + /// + /// <param name="assign">The RelinKeys to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(RelinKeys assign) + { + base.Set(assign); + } + + /// <summary> + /// Returns the index of a relinearization key in the backing KSwitchKeys + /// instance that corresponds to the given secret key power, assuming that + /// it exists in the backing KSwitchKeys. + /// </summary> + /// <param name="keyPower">The power of the secret key</param> + /// <exception cref="ArgumentException">if keyPower is less than 2</exception> + public static ulong GetIndex(ulong keyPower) + { + NativeMethods.RelinKeys_GetIndex(keyPower, out ulong index); + return index; + } + + /// <summary> + /// Returns whether a relinearization key corresponding to a given secret + /// key power exists. + /// </summary> + /// <param name="keyPower">The power of the secret key</param> + /// <exception cref="ArgumentException">if keyPower is less than 2</exception> + public bool HasKey(ulong keyPower) + { + ulong index = GetIndex(keyPower); + return (ulong)Data.LongCount() > index && + Data.ElementAt(checked((int)index)).Count() != 0; + } + + /// <summary> + /// Returns a specified relinearization key. + /// </summary> + /// <remarks> + /// Returns a specified relinearization key. The returned relinearization + /// key corresponds to the given power of the secret key and is valid only + /// as long as the RelinKeys is valid. + /// </remarks> + /// <param name="keyPower">The power of the secret key</param> + /// <exception cref="ArgumentException">if the key corresponding to keyPower + /// does not exist</exception> + public IEnumerable<PublicKey> Key(ulong keyPower) + { + return Data.ElementAt(checked((int)GetIndex(keyPower))); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/SEALContext.cs b/bigpiseal3.5.1/dotnet/src/SEALContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..e7a3d843417097c60ffd66f30e869f9d914786e0 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/SEALContext.cs @@ -0,0 +1,521 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.Text; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// Performs sanity checks (validation) and pre-computations for a given set of encryption + /// parameters. + /// </summary> + /// + /// <remarks> + /// <para> + /// Performs sanity checks (validation) and pre-computations for a given set of encryption + /// parameters. While the EncryptionParameters class is intended to be a light-weight class + /// to store the encryption parameters, the SEALContext class is a heavy-weight class that + /// is constructed from a given set of encryption parameters. It validates the parameters + /// for correctness, evaluates their properties, and performs and stores the results of + /// several costly pre-computations. + /// </para> + /// <para> + /// After the user has set at least the PolyModulus, CoeffModulus, and PlainModulus + /// parameters in a given EncryptionParameters instance, the parameters can be validated + /// for correctness and functionality by constructing an instance of SEALContext. The + /// constructor of SEALContext does all of its work automatically, and concludes by + /// constructing and storing an instance of the EncryptionParameterQualifiers class, with + /// its flags set according to the properties of the given parameters. If the created + /// instance of EncryptionParameterQualifiers has the ParametersSet flag set to true, the + /// given parameter set has been deemed valid and is ready to be used. If the parameters + /// were for some reason not appropriately set, the ParametersSet flag will be false, + /// and a new SEALContext will have to be created after the parameters are corrected. + /// </para> + /// <para> + /// By default, SEALContext creates a chain of SEALContext.ContextData instances. The + /// first one in the chain corresponds to special encryption parameters that are reserved + /// to be used by the various key classes (SecretKey, PublicKey, etc.). These are the + /// exact same encryption parameters that are created by the user and passed to the + /// constructor of SEALContext. The properties KeyContextData and KeyParmsId return the + /// ContextData and the ParmsId corresponding to these special parameters. The rest of the + /// ContextData instances in the chain correspond to encryption parameters that are derived + /// from the first encryption parameters by always removing the last one of the moduli in + /// the CoeffModulus, until the resulting parameters are no longer valid, e.g., there are + /// no more primes left. These derived encryption parameters are used by ciphertexts and + /// plaintexts and their respective ContextData can be accessed through the + /// GetContextData(ParmsId) function. The properties FirstContextData and LastContextData + /// return the ContextData corresponding to the first and the last set of parameters in + /// the "data" part of the chain, i.e., the second and the last element in the full chain. + /// The chain is a doubly linked list and is referred to as the modulus switching chain. + /// </para> + /// </remarks> + /// <see cref="EncryptionParameters">see EncryptionParameters for more details on the parameters.</see> + /// <see cref="EncryptionParameterQualifiers">see EncryptionParameterQualifiers for more details on the qualifiers.</see> + public class SEALContext : NativeObject + { + /// <summary> + /// Creates an instance of SEALContext and performs several pre-computations + /// on the given EncryptionParameters. + /// </summary> + /// <param name="parms">The encryption parameters.</param> + /// <param name="expandModChain">Determines whether the modulus switching chain + /// should be created</param> + /// <param name="secLevel">Determines whether a specific security level should be + /// enforced according to HomomorphicEncryption.org security standard</param> + /// <exception cref="ArgumentNullException">if parms is null</exception> + public SEALContext(EncryptionParameters parms, + bool expandModChain = true, SecLevelType secLevel = SecLevelType.TC128) + { + if (null == parms) + throw new ArgumentNullException(nameof(parms)); + + NativeMethods.SEALContext_Create(parms.NativePtr, + expandModChain, (int)secLevel, out IntPtr context); + NativePtr = context; + } + + /// <summary> + /// Returns the ContextData corresponding to encryption parameters with a given + /// parmsId. If parameters with the given ParmsId are not found then the function + /// returns null. + /// </summary> + /// + /// <param name="parmsId">The ParmsId of the encryption parameters</param> + /// <exception cref="ArgumentNullException">if parmsId is null</exception> + public ContextData GetContextData(ParmsId parmsId) + { + if (null == parmsId) + throw new ArgumentNullException(nameof(parmsId)); + + NativeMethods.SEALContext_GetContextData(NativePtr, parmsId.Block, out IntPtr contextData); + if (IntPtr.Zero.Equals(contextData)) + return null; + + ContextData data = new ContextData(contextData, owned: false); + return data; + } + + /// <summary> + /// Returns the ContextData corresponding to encryption parameters that are + /// used for keys. + /// </summary> + public ContextData KeyContextData + { + get + { + NativeMethods.SEALContext_KeyContextData(NativePtr, out IntPtr contextData); + ContextData data = new ContextData(contextData, owned: false); + return data; + } + } + + /// <summary> + /// Returns the ContextData corresponding to the first encryption parameters + /// that are used for data. + /// </summary> + public ContextData FirstContextData + { + get + { + NativeMethods.SEALContext_FirstContextData(NativePtr, out IntPtr contextData); + ContextData data = new ContextData(contextData, owned: false); + return data; + } + } + + /// <summary> + /// Returns the ContextData corresponding to the last encryption parameters + /// that are used for data. + /// </summary> + public ContextData LastContextData + { + get + { + NativeMethods.SEALContext_LastContextData(NativePtr, out IntPtr contextData); + ContextData data = new ContextData(contextData, owned: false); + return data; + } + } + + /// <summary> + /// Returns whether the encryption parameters are valid. + /// </summary> + public bool ParametersSet + { + get + { + NativeMethods.SEALContext_ParametersSet(NativePtr, out bool paramsSet); + return paramsSet; + } + } + + /// <summary> + /// If the encryption parameters are set in a way that is considered valid by SEAL, return "success". + /// If the encryption parameters are set but not validated yet, return "none". + /// Otherwise, return a brief reason. + /// </summary> + public string ParameterErrorName() + { + NativeMethods.SEALContext_ParameterErrorName(NativePtr, null, out ulong length); + byte[] buffer = new byte[length]; + NativeMethods.SEALContext_ParameterErrorName(NativePtr, buffer, out length); + return Encoding.ASCII.GetString(buffer); + } + + /// <summary> + /// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid". + /// Otherwise, return a comprehensive reason. + /// </summary> + public string ParameterErrorMessage() + { + NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, null, out ulong length); + byte[] buffer = new byte[length]; + NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, buffer, out length); + return Encoding.ASCII.GetString(buffer); + } + + /// <summary> + /// Returns a ParmsId corresponding to the set of encryption parameters + /// that are used for keys. + /// </summary> + public ParmsId KeyParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.SEALContext_KeyParmsId(NativePtr, parms.Block); + return parms; + } + } + + /// <summary> + /// Returns a ParmsId corresponding to the first encryption parameters that + /// are used for data. + /// </summary> + public ParmsId FirstParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.SEALContext_FirstParmsId(NativePtr, parms.Block); + return parms; + } + } + + /// <summary> + /// Returns a ParmsId corresponding to the last encryption parameters that + /// are used for data. + /// </summary> + public ParmsId LastParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.SEALContext_LastParmsId(NativePtr, parms.Block); + return parms; + } + } + + + /// <summary> + /// Returns whether the coefficient modulus supports keyswitching. + /// </summary> + /// <remarks> + /// Returns whether the coefficient modulus supports keyswitching. In + /// practice, support for keyswitching is required by Evaluator.Relinearize, + /// Evaluator.ApplyGalois, and all rotation and conjugation operations. + /// For keyswitching to be available, the coefficient modulus parameter must + /// consist of at least two prime number factors. + /// </remarks> + public bool UsingKeyswitching + { + get + { + NativeMethods.SEALContext_UsingKeyswitching(NativePtr, out bool result); + return result; + } + } + + /// <summary> + /// Destroy native object. + /// </summary> + protected override void DestroyNativeObject() + { + NativeMethods.SEALContext_Destroy(NativePtr); + } + + /// <summary> + /// Class to hold pre-computation data for a given set of encryption parameters. + /// </summary> + public class ContextData : NativeObject + { + /// <summary> + /// Build a ContextData object from a native pointer. + /// </summary> + /// <param name="ptr">Pointer to native object</param> + /// <param name="owned">Whether this instance owns the native object</param> + internal ContextData(IntPtr ptr, bool owned = true) + : base(ptr, owned) + { + } + + /// <summary> + /// Returns a copy of the underlying encryption parameters. + /// </summary> + public EncryptionParameters Parms + { + get + { + NativeMethods.ContextData_Parms(NativePtr, out IntPtr parms); + return new EncryptionParameters(parms); + } + } + + /// <summary> + /// Returns the ParmsId of the current parameters. + /// </summary> + public ParmsId ParmsId + { + get + { + return Parms.ParmsId; + } + } + + + /// <summary> + /// Returns a copy of EncryptionParameterQualifiers corresponding to the + /// current encryption parameters. + /// </summary> + /// <remarks> + /// Returns a copy of EncryptionParameterQualifiers corresponding to the + /// current encryption parameters. Note that to change the qualifiers it is + /// necessary to create a new instance of SEALContext once appropriate changes + /// to the encryption parameters have been made. + /// </remarks> + public EncryptionParameterQualifiers Qualifiers + { + get + { + NativeMethods.ContextData_Qualifiers(NativePtr, out IntPtr epq); + EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(epq); + return qualifiers; + } + } + + /// <summary> + /// Returns a the pre-computed product of all primes in the + /// coefficient modulus. + /// </summary> + /// <remarks> + /// Returns a the pre-computed product of all primes in the + /// coefficient modulus. The security of the encryption parameters largely depends + /// on the bit-length of this product, and on the degree of the polynomial modulus. + /// </remarks> + public ulong[] TotalCoeffModulus + { + get + { + ulong count = 0; + NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, null); + + ulong[] result = new ulong[count]; + NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, result); + + return result; + } + } + + /// <summary> + /// Returns the significant bit count of the total coefficient modulus. + /// </summary> + public int TotalCoeffModulusBitCount + { + get + { + NativeMethods.ContextData_TotalCoeffModulusBitCount(NativePtr, out int bitCount); + return bitCount; + } + } + + /// <summary> + /// Return a copy of BFV "Delta", i.e. coefficient modulus divided by + /// plaintext modulus. + /// </summary> + public ulong[] CoeffDivPlainModulus + { + get + { + ulong count = 0; + NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, null); + + ulong[] cdpm = new ulong[count]; + NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, cdpm); + + return cdpm; + } + } + + /// <summary> + /// Return the threshold for the upper half of integers modulo PlainModulus. + /// This is simply(PlainModulus + 1) / 2. + /// </summary> + public ulong PlainUpperHalfThreshold + { + get + { + NativeMethods.ContextData_PlainUpperHalfThreshold(NativePtr, out ulong puht); + return puht; + } + } + + /// <summary> + /// Return a copy of the plaintext upper half increment, i.e. coeffModulus + /// minus plainModulus. + /// </summary> + /// <remarks> + /// Return a copy of the plaintext upper half increment, i.e. coeffModulus + /// minus plainModulus. The upper half increment is represented as an integer + /// for the full product coeffModulus if UsingFastPlainLift is false and is + /// otherwise represented modulo each of the CoeffModulus primes in order. + /// </remarks> + public ulong[] PlainUpperHalfIncrement + { + get + { + ulong count = 0; + NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, null); + + ulong[] puhi = new ulong[count]; + NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, puhi); + + return puhi; + } + } + + /// <summary> + /// Return a copy of the upper half threshold with respect to the total + /// coefficient modulus. This is needed in CKKS decryption. + /// </summary> + public ulong[] UpperHalfThreshold + { + get + { + ulong count = 0; + NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, null); + + if (count == 0) + return null; + + ulong[] uht = new ulong[count]; + NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, uht); + + return uht; + } + } + + /// <summary> + /// Return a copy of the upper half increment used for computing Delta*m + /// and converting the coefficients to modulo CoeffModulus. + /// </summary> + /// <remarks> + /// Return a copy of the upper half increment used for computing Delta*m + /// and converting the coefficients to modulo CoeffModulus. For example, + /// t-1 in plaintext should change into + /// q - Delta = Delta*t + r_t(q) - Delta = Delta*(t-1) + r_t(q) + /// so multiplying the message by Delta is not enough and requires also an + /// addition of r_t(q). This is precisely the UpperHalfIncrement. Note that + /// this operation is only done for negative message coefficients, i.e. those + /// that exceed PlainUpperHalfThreshold. + /// </remarks> + public ulong[] UpperHalfIncrement + { + get + { + ulong count = 0; + NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, null); + + if (count == 0) + return null; + + ulong[] uhi = new ulong[count]; + NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, uhi); + + return uhi; + } + } + + /// <summary> + /// Returns the context data corresponding to the previous parameters in the + /// modulus switching chain. + /// </summary> + /// <remarks> + /// Returns the context data corresponding to the previous parameters in the + /// modulus switching chain. If the current data is the first one in the chain, + /// then the result is nullptr. + /// </remarks> + public ContextData PrevContextData + { + get + { + NativeMethods.ContextData_PrevContextData(NativePtr, out IntPtr prev); + + if (IntPtr.Zero.Equals(prev)) + return null; + + ContextData data = new ContextData(prev, owned: false); + return data; + } + } + + /// <summary> + /// Returns the context data corresponding to the next parameters in the modulus + /// switching chain. + /// </summary> + /// <remarks> + /// Returns the context data corresponding to the next parameters in the modulus + /// switching chain. If the current data is the last one in the chain, then the + /// result is nullptr. + /// </remarks> + public ContextData NextContextData + { + get + { + NativeMethods.ContextData_NextContextData(NativePtr, out IntPtr next); + + if (IntPtr.Zero.Equals(next)) + return null; + + ContextData data = new ContextData(next, owned: false); + return data; + } + } + + /// <summary> + /// Returns the index of the parameter set in a chain. + /// </summary> + /// <remarks> + /// Returns the index of the parameter set in a chain. The initial parameters + /// have index 0 and the index increases sequentially in the parameter chain. + /// </remarks> + public ulong ChainIndex + { + get + { + NativeMethods.ContextData_ChainIndex(NativePtr, out ulong index); + return index; + } + } + + /// <summary> + /// Destroy native object. + /// </summary> + protected override void DestroyNativeObject() + { + NativeMethods.ContextData_Destroy(NativePtr); + } + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/src/SEALNet.csproj b/bigpiseal3.5.1/dotnet/src/SEALNet.csproj new file mode 100644 index 0000000000000000000000000000000000000000..d7503c5be743392ce968516aebb74d0d4154b0e6 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/SEALNet.csproj @@ -0,0 +1,26 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <GeneratePackageOnBuild>false</GeneratePackageOnBuild> + <Authors>Microsoft Research</Authors> + <Company>Microsoft Corporation</Company> + <Description>.NET wrapper library for Microsoft SEAL</Description> + <Copyright>Microsoft Corporation 2020</Copyright> + <SignAssembly Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">true</SignAssembly> + <AssemblyOriginatorKeyFile Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">SEALNetCert.snk</AssemblyOriginatorKeyFile> + <DelaySign Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">true</DelaySign> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)'=='AnyCPU'"> + <DocumentationFile>$(ProjectDir)../../lib/dotnet/$(Configuration)/SEALNet.xml</DocumentationFile> + <PlatformTarget>x64</PlatformTarget> + <OutputPath>$(ProjectDir)../../lib/dotnet/$(Configuration)</OutputPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> + <DefineConstants /> + <DebugType>pdbonly</DebugType> + <DebugSymbols>true</DebugSymbols> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> + <DefineConstants>DEBUG;TRACE</DefineConstants> + </PropertyGroup> +</Project> diff --git a/bigpiseal3.5.1/dotnet/src/SecretKey.cs b/bigpiseal3.5.1/dotnet/src/SecretKey.cs new file mode 100644 index 0000000000000000000000000000000000000000..59ad22b94776bc168d38fa95bcf3a0c70387324d --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/SecretKey.cs @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// Class to store a secret key. + /// </summary> + /// <remarks> + /// <para> + /// Thread Safety + /// In general, reading from SecretKey is thread-safe as long as no other + /// thread is concurrently mutating it. This is due to the underlying data + /// structure storing the secret key not being thread-safe. + /// </para> + /// </remarks> + /// <see cref="KeyGenerator">see KeyGenerator for the class that generates the secret key.</see> + /// <see cref="PublicKey">see PublicKey for the class that stores the public key.</see> + /// <see cref="RelinKeys">see RelinKeys for the class that stores the relinearization keys.</see> + /// <see cref="GaloisKeys">see GaloisKeys for the class that stores the Galois keys.</see> + public class SecretKey : NativeObject + { + /// <summary> + /// Creates an empty secret key. + /// </summary> + public SecretKey() + { + NativeMethods.SecretKey_Create(out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Creates a new SecretKey by initializing it with a pointer to a native object. + /// </summary> + /// <param name="secretKeyPtr">The native SecretKey pointer</param> + /// <param name="owned">Whether this instance owns the native pointer</param> + internal SecretKey(IntPtr secretKeyPtr, bool owned = true) + : base(secretKeyPtr, owned) + { + } + + /// <summary> + /// Creates a new SecretKey by copying an old one. + /// </summary> + /// <param name="copy">The SecretKey to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public SecretKey(SecretKey copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + NativeMethods.SecretKey_Create(copy.NativePtr, out IntPtr ptr); + NativePtr = ptr; + } + + /// <summary> + /// Copies an old SecretKey to the current one. + /// </summary> + /// <param name="assign">The SecretKey to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(SecretKey assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + NativeMethods.SecretKey_Set(NativePtr, assign.NativePtr); + } + + /// <summary> + /// Returns the underlying Plaintext. + /// </summary> + /// <remarks> + /// Returns the underlying Plaintext. The returned Plaintext is valid + /// only as long as the SecretKey is valid and not changed. + /// </remarks> + public Plaintext Data + { + get + { + NativeMethods.SecretKey_Data(NativePtr, out IntPtr plaintextPtr); + Plaintext plaintext = new Plaintext(plaintextPtr, owned: false); + return plaintext; + } + } + + /// <summary> + /// Returns an upper bound on the size of the SecretKey, as if it was written + /// to an output stream. + /// </summary> + /// <param name="comprMode">The compression mode</param> + /// <exception cref="ArgumentException">if the compression mode is not + /// supported</exception> + /// <exception cref="InvalidOperationException">if the size does not fit in + /// the return type</exception> + public long SaveSize(ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + NativeMethods.SecretKey_SaveSize( + NativePtr, (byte)comprModeValue, out long outBytes); + return outBytes; + } + + /// <summary>Saves the SecretKey to an output stream.</summary> + /// <remarks> + /// Saves the SecretKey to an output stream. The output is in binary format + /// and not human-readable. + /// </remarks> + /// <param name="stream">The stream to save the SecretKey to</param> + /// <param name="comprMode">The desired compression mode</param> + /// <exception cref="ArgumentNullException">if stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support writing, or if compression mode is not supported</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved + /// is invalid, or if compression failed</exception> + public long Save(Stream stream, ComprModeType? comprMode = null) + { + comprMode = comprMode ?? Serialization.ComprModeDefault; + if (!Serialization.IsSupportedComprMode(comprMode.Value)) + throw new ArgumentException("Unsupported compression mode"); + + ComprModeType comprModeValue = comprMode.Value; + return Serialization.Save( + (byte[] outptr, ulong size, byte cm, out long outBytes) => + NativeMethods.SecretKey_Save(NativePtr, outptr, size, + cm, out outBytes), + SaveSize(comprModeValue), comprModeValue, stream); + } + + /// <summary>Loads a SecretKey from an input stream overwriting the current + /// SecretKey.</summary> + /// <remarks> + /// Loads a SecretKey from an input stream overwriting the current SecretKey. + /// No checking of the validity of the SecretKey data against encryption + /// parameters is performed. This function should not be used unless the + /// SecretKey comes from a fully trusted source. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the SecretKey from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long UnsafeLoad(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.SecretKey_UnsafeLoad(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary>Loads a SecretKey from an input stream overwriting the current + /// SecretKey.</summary> + /// <remarks> + /// Loads a SecretKey from an input stream overwriting the current SecretKey. + /// The loaded SecretKey is verified to be valid for the given SEALContext. + /// </remarks> + /// <param name="context">The SEALContext</param> + /// <param name="stream">The stream to load the SecretKey from</param> + /// <exception cref="ArgumentNullException">if context or stream is + /// null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support reading</exception> + /// <exception cref="ArgumentException">if context is not set or encryption + /// parameters are not valid</exception> + /// <exception cref="EndOfStreamException">if the stream ended + /// unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data cannot be loaded + /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the + /// loaded compression mode is not supported</exception> + public long Load(SEALContext context, Stream stream) + { + if (null == context) + throw new ArgumentNullException(nameof(context)); + + return Serialization.Load( + (byte[] outptr, ulong size, out long outBytes) => + NativeMethods.SecretKey_Load(NativePtr, context.NativePtr, + outptr, size, out outBytes), + stream); + } + + /// <summary> + /// Returns a copy of ParmsId. + /// </summary> + public ParmsId ParmsId + { + get + { + ParmsId parms = new ParmsId(); + NativeMethods.SecretKey_ParmsId(NativePtr, parms.Block); + return parms; + } + } + + /// <summary> + /// Returns the currently used MemoryPoolHandle. + /// </summary> + public MemoryPoolHandle Pool + { + get + { + NativeMethods.SecretKey_Pool(NativePtr, out IntPtr pool); + MemoryPoolHandle handle = new MemoryPoolHandle(pool); + return handle; + } + } + + /// <summary> + /// Destroy native object. + /// </summary> + protected override void DestroyNativeObject() + { + NativeMethods.SecretKey_Destroy(NativePtr); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Serializable.cs b/bigpiseal3.5.1/dotnet/src/Serializable.cs new file mode 100644 index 0000000000000000000000000000000000000000..d118d4acf5b4e2fe78181e9c071af6c3d4011ad5 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Serializable.cs @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL.Tools; +using System; +using System.IO; + +namespace Microsoft.Research.SEAL +{ + /// <summary>Interface for classes with a Set function.</summary> + public interface ISettable<T> where T : class + { + /// <summary> + /// Copies a given object to the current one. + /// </summary> + /// <param name="assign">The object to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + void Set(T assign); + } + + /// <summary>Interface for classes that are serializable.</summary> + public interface ISerializableObject + { + /// <summary> + /// Returns an upper bound on the size of the object, as if it was written + /// to an output stream. + /// </summary> + /// <param name="comprMode">The compression mode</param> + /// <exception cref="ArgumentException">if the compression mode is not + /// supported</exception> + /// <exception cref="InvalidOperationException">if the size does not fit in + /// the return type</exception> + long SaveSize(ComprModeType? comprMode); + + /// <summary>Saves the object to an output stream.</summary> + /// <remarks> + /// Saves the object to an output stream. The output is in binary format + /// and not human-readable. + /// </remarks> + /// <param name="stream">The stream to save the object to</param> + /// <param name="comprMode">The desired compression mode</param> + /// <exception cref="ArgumentNullException">if stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support writing, or if compression mode is not supported</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved + /// is invalid, or if compression failed</exception> + long Save(Stream stream, ComprModeType? comprMode); + } + + /// <summary>Class to represent a serializable object.</summary> + /// <remarks> + /// <para> + /// Some functions return serializable objects rather than normal objects. For + /// example, Encryptor can be used in symmetric-key mode to create symmetric-key + /// ciphertexts, where half of the ciphertext data is pseudo-random and can be + /// generated from a seed, reducing the size of the newly created ciphertext + /// object by nearly 50%. However, the compression only has an effect when the + /// object is serialized with compression mode ComprModeType.Deflate due to an + /// implementation detail. This makes sense when, e.g., the ciphertexts need + /// to be communicated from a client to a server for encrypted computation. + /// </para> + /// <para> + /// Serializable objects are created only by the following functions: + /// - Encryptor.EncryptSymmetric + /// - Encryptor.EncryptZeroSymmetric + /// - KeyGenerator.RelinKeys + /// - KeyGenerator.GaloisKeys + /// </para> + /// <para> + /// Serializable objects also expose the SaveSize function that behaves just + /// as the SaveSize functions of other objects in Microsoft SEAL: it returns + /// an upper bound on the size of a buffer needed to hold the serialized data. + /// </para> + /// <para> + /// The following illustrates the use of serializable objects: + /// + /// +--------------------------+ + /// | Serializable{GaloisKeys} | Size 2 MB (example) + /// +------------+-------------+ + /// | + /// | Serializable{GaloisKeys}.Save + /// | with ComprModeType.Deflate + /// | + /// +-------v-------+ + /// | Stream/Buffer | Size ~1 MB (example) + /// +-------+-------+ + /// | + /// | + /// +--v--+ + /// Network Minimized communication + /// +--+--+ + /// | + /// | GaloisKeys.Load + /// | + /// +-----v------+ + /// | GaloisKeys | Size 2 MB (example) + /// +------------+ + /// </para> + /// <typeparam name="T">The type to wrap into a serializable object</typeparam> + /// </remarks> + public class Serializable<T> : DisposableObject + where T : DisposableObject, ISerializableObject, ISettable<T>, new() + { + /// <summary> + /// Constructs a new serializable object by copying a given one. + /// </summary> + /// <param name="copy">The serializable object to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public Serializable(Serializable<T> copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + // Use Activator to get around lack of constructor + obj_ = (T)Activator.CreateInstance(typeof(T), copy.obj_); + } + + /// <summary> + /// Copies a given serializable object to the current one. + /// </summary> + /// <param name="assign">The serializable object to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(Serializable<T> assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + obj_.Set(assign.obj_); + } + + /// <summary> + /// Returns an upper bound on the size of the serializable object, as if it + /// was written to an output stream. + /// </summary> + /// <param name="comprMode">The compression mode</param> + /// <exception cref="ArgumentException">if the compression mode is not + /// supported</exception> + /// <exception cref="InvalidOperationException">if the size does not fit in + /// the return type</exception> + public long SaveSize(ComprModeType? comprMode = null) + => obj_.SaveSize(comprMode); + + /// <summary>Saves the serializable object to an output stream.</summary> + /// <remarks> + /// Saves the serializable object to an output stream. The output is in + /// binary format and not human-readable. + /// </remarks> + /// <param name="stream">The stream to save the serializable object to</param> + /// <param name="comprMode">The desired compression mode</param> + /// <exception cref="ArgumentNullException">if stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not + /// support writing, or if compression mode is not supported</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved + /// is invalid, or if compression failed</exception> + public long Save(Stream stream, ComprModeType? comprMode = null) + => obj_.Save(stream, comprMode); + + /// <summary> + /// Constructs a new serializable object wrapping a given object. + /// </summary> + /// <param name="obj">The object to wrap</param> + /// <exception cref="ArgumentNullException">if obj is null</exception> + internal Serializable(T obj) + { + if (null == obj) + throw new ArgumentNullException(nameof(obj)); + + obj_ = obj; + } + + /// <summary> + /// Destroy wrapped object. + /// </summary> + protected override void DisposeManagedResources() + { + obj_.Dispose(); + } + + /// <summary> + /// The object wrapped by an instance of Serializable. + /// </summary> + private readonly T obj_; + } +} diff --git a/bigpiseal3.5.1/dotnet/src/Serialization.cs b/bigpiseal3.5.1/dotnet/src/Serialization.cs new file mode 100644 index 0000000000000000000000000000000000000000..5865b2cfb0648f94e1433d661a2cc92684eeff5d --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Serialization.cs @@ -0,0 +1,427 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// A type to describe the compression algorithm applied to serialized data. + /// Ciphertext and key data consist of a large number of 64-bit words storing + /// integers modulo prime numbers much smaller than the word size, resulting in + /// a large number of zero bytes in the output. Any compression algorithm should + /// be able to clean up these zero bytes and hence compress both ciphertext and + /// key data. + /// </summary> + public enum ComprModeType : byte + { + /// <summary>No compression is used.</summary> + None = 0, + + /// <summary>Use Deflate compression.</summary> + Deflate = 1, + } + + /// <summary>Class to provide functionality for serialization.</summary> + /// <remarks> + /// Class to provide functionality for serialization. Most users of the library + /// should never have to call these functions explicitly, as they are called + /// internally by functions such as Ciphertext.Save and Ciphertext.Load. + /// </remarks> + public abstract class Serialization + { + /// <summary> + /// The compression mode used by default. + /// </summary> + public static readonly ComprModeType ComprModeDefault = ((Func<ComprModeType>)(() => { + NativeMethods.Serialization_ComprModeDefault(out byte comprMode); + return (ComprModeType)comprMode; + }))(); + + /// <summary>The magic value indicating a Microsoft SEAL header.</summary> + public static readonly ushort SEALMagic = ((Func<ushort>)(() => { + NativeMethods.Serialization_SEALMagic(out ushort sealMagic); + return sealMagic; + }))(); + + /// <summary>The size in bytes of the SEALHeader.</summary> + public static readonly byte SEALHeaderSize = ((Func<byte>)(() => { + NativeMethods.Serialization_SEALHeaderSize(out byte sealHeaderSize); + return sealHeaderSize; + }))(); + + /// <summary>Struct to contain header information for serialization.</summary> + /// <remarks> + /// Struct to contain header information for serialization. The size of the header is 16 bytes and it consists + /// of the following fields: + /// + /// 1. a magic number identifying this is a SEALHeader struct (2 bytes) + /// 2. size in bytes of the SEALHeader struct (1 byte) + /// 3. Microsoft SEAL's major version number (1 byte) + /// 4. Microsoft SEAL's minor version number (1 byte) + /// 5. a ComprModeType indicating whether data after the header is compressed (1 byte) + /// 6. reserved for future use and data alignment (2 bytes) + /// 7. the size in bytes of the entire serialized object, including the header (8 bytes) + /// </remarks> + [StructLayout(LayoutKind.Explicit, Size=16)] + public class SEALHeader : ISettable<SEALHeader> + { + /// <summary>A magic number identifying this is a SEALHeader struct (2 bytes)</summary> + [FieldOffset(0)]public ushort Magic = SEALMagic; + + /// <summary>Size in bytes of the SEALHeader struct (1 byte)</summary> + [FieldOffset(2)]public byte HeaderSize = SEALHeaderSize; + + /// <summary>Microsoft SEAL's major version number (1 byte)</summary> + [FieldOffset(3)]public byte VersionMajor = SEALVersion.Major; + + /// <summary>Microsoft SEAL's minor version number (1 byte)</summary> + [FieldOffset(4)]public byte VersionMinor = SEALVersion.Minor; + + /// <summary>A compr_mode_type indicating whether data after the header is compressed (1 byte)</summary> + [FieldOffset(5)]public ComprModeType ComprMode = ComprModeDefault; + + /// <summary>Reserved for future use and data alignment (2 bytes)</summary> + [FieldOffset(6)]public ushort Reserved = 0; + + /// <summary>The size in bytes of the entire serialized object, including the header (8 bytes)</summary> + [FieldOffset(8)]public ulong Size = 0; + + /// <summary> + /// Copies a given SEALHeader to the current one. + /// </summary> + /// <param name="assign">The SEALHeader to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(SEALHeader assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + Magic = assign.Magic; + HeaderSize = assign.HeaderSize; + VersionMajor = assign.VersionMajor; + VersionMinor = assign.VersionMinor; + ComprMode = assign.ComprMode; + Reserved = assign.Reserved; + Size = assign.Size; + } + }; + + private static bool IsSupportedComprMode(byte comprMode) + { + NativeMethods.Serialization_IsSupportedComprMode(comprMode, out bool result); + return result; + } + + /// <summary>Returns true if the given value corresponds to a supported compression mode.</summary> + /// <param name="comprMode">The compression mode to validate</param> + public static bool IsSupportedComprMode(ComprModeType comprMode) => + IsSupportedComprMode((byte)comprMode); + + /// <summary>Returns true if the SEALHeader has a version number compatible with this version of + /// Microsoft SEAL.</summary> + /// <param name="header">The SEALHeader</param> + public static bool IsCompatibleVersion(SEALHeader header) + { + byte[] headerArray = new byte[SEALHeaderSize]; + using (MemoryStream stream = new MemoryStream(headerArray)) + { + SaveHeader(header, stream); + NativeMethods.Serialization_IsCompatibleVersion( + headerArray, (ulong)headerArray.Length, out bool result); + return result; + } + } + + /// <summary>Returns true if the given SEALHeader is valid for this version of Microsoft SEAL.</summary> + /// <param name="header">The SEALHeader</param> + public static bool IsValidHeader(SEALHeader header) + { + byte[] headerArray = new byte[SEALHeaderSize]; + using (MemoryStream stream = new MemoryStream(headerArray)) + { + SaveHeader(header, stream); + NativeMethods.Serialization_IsValidHeader( + headerArray, (ulong)headerArray.Length, out bool result); + return result; + } + } + + /// <summary>Saves a SEALHeader to a given binary stream.</summary> + /// <remarks> + /// Saves a SEALHeader to a given stream. The output is in binary format and not human-readable. + /// </remarks> + /// <param name="header">The SEALHeader to save to the stream</param> + /// <param name="stream">The stream to save the SEALHeader to</param> + /// <exception cref="ArgumentNullException">if header or stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not support writing</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + public static void SaveHeader(SEALHeader header, Stream stream) + { + if (null == header) + throw new ArgumentNullException(nameof(header)); + if (null == stream) + throw new ArgumentNullException(nameof(stream)); + if (!stream.CanWrite) + throw new ArgumentException(nameof(stream)); + + using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) + { + writer.Write(header.Magic); + writer.Write(header.HeaderSize); + writer.Write(header.VersionMajor); + writer.Write(header.VersionMinor); + writer.Write((byte)header.ComprMode); + writer.Write(header.Reserved); + writer.Write(header.Size); + } + } + + /// <summary>Loads a SEALHeader from a given stream.</summary> + /// <param name="stream">The stream to load the SEALHeader from</param> + /// <param name="header">The SEALHeader to populate with the loaded data</param> + /// <param name="tryUpgradeIfInvalid">If the loaded SEALHeader is invalid, attempt to identify its format and + /// upgrade to the current SEALHeader version</param> + /// <exception cref="ArgumentNullException">if header or stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not support reading</exception> + /// <exception cref="InvalidOperationException">if the loaded data is not a valid SEALHeader or if the loaded + /// compression mode is not supported</exception> + /// <exception cref="EndOfStreamException">if the stream ended unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + public static void LoadHeader(Stream stream, SEALHeader header, bool tryUpgradeIfInvalid = true) + { + if (null == header) + throw new ArgumentNullException(nameof(header)); + if (null == stream) + throw new ArgumentNullException(nameof(stream)); + if (!stream.CanRead) + throw new ArgumentException(nameof(stream)); + + using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) + { + header.Magic = reader.ReadUInt16(); + header.HeaderSize = reader.ReadByte(); + header.VersionMajor = reader.ReadByte(); + header.VersionMinor = reader.ReadByte(); + header.ComprMode = (ComprModeType)reader.ReadByte(); + header.Reserved = reader.ReadUInt16(); + header.Size = reader.ReadUInt64(); + } + + // If header is invalid this may be an older header and we can try to automatically upgrade it + if (tryUpgradeIfInvalid && !IsValidHeader(header)) + { + // Try interpret the data as a Microsoft SEAL 3.4 header + LegacyHeaders.SEALHeader_3_4 header_3_4 = new LegacyHeaders.SEALHeader_3_4(header); + + SEALHeader newHeader = new SEALHeader(); + // Copy over the fields; of course the result may not be valid depending on whether the input was a + // valid version 3.4 header + newHeader.ComprMode = header_3_4.ComprMode; + newHeader.Size = header_3_4.Size; + + // Now validate the new header and discard if still not valid; something else is probably wrong + if (IsValidHeader(newHeader)) + { + header.Set(newHeader); + } + } + } + + internal delegate void SaveDelegate( + byte[] outptr, ulong size, byte comprMode, out long outBytes); + + internal delegate void LoadDelegate( + byte[] inptr, ulong size, out long inBytes); + + /// <summary>Saves data to a given binary stream.</summary> + /// <remarks> + /// First this function allocates a buffer of size <paramref name="size" />. The buffer is used by the + /// <paramref name="SaveData"/> delegate that writes some number of bytes to the buffer and outputs (in + /// out-parameter) the number of bytes written (less than the size of the buffer). The contents of the buffer + /// are then written to <paramref name="stream"/> and the function returns the output value of + /// <paramref name="SaveData"/>. This function is intended only for internal use. + /// </remarks> + /// <param name="SaveData">The delegate that writes some number of bytes to a given buffer</param> + /// <param name="size">An upper bound on the number of bytes that <paramref name="SaveData" /> requires</param> + /// <param name="comprMode">The desired compression mode</param> + /// <param name="stream">The destination stream</param> + /// <exception cref="ArgumentNullException">if SaveData or stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not support writing, or if size is + /// negative or too large</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the data to be saved is invalid, if compression mode is not + /// supported, or if compression failed</exception> + internal static long Save(SaveDelegate SaveData, long size, + ComprModeType comprMode, Stream stream) + { + if (null == stream) + throw new ArgumentNullException(nameof(stream)); + if (null == SaveData) + throw new ArgumentNullException(nameof(SaveData)); + if (!stream.CanWrite) + throw new ArgumentException(nameof(stream)); + if (!IsSupportedComprMode(comprMode)) + throw new InvalidOperationException("Unsupported compression mode"); + + try + { + int sizeInt = checked((int)size); + byte[] buffer = new byte[sizeInt]; + SaveData(buffer, checked((ulong)sizeInt), (byte)comprMode, out long outBytes); + int intOutBytes = checked((int)outBytes); + using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) + { + writer.Write(buffer, 0, intOutBytes); + } + + // Clear the buffer for safety reasons + Array.Clear(buffer, 0, intOutBytes); + + return outBytes; + } + catch (OverflowException ex) + { + throw new ArgumentException($"{nameof(size)} is out of bounds", ex); + } + } + + /// <summary>Loads data from a given binary stream.</summary> + /// <remarks> + /// This function calls the <see cref="LoadHeader" /> function to first load a <see cref="SEALHeader" /> object + /// from <paramref name="stream"/>. The <see cref="SEALHeader.Size"/> is then read from the + /// <see cref="SEALHeader" /> and a buffer of corresponding size is allocated. Next, the buffer is filled with + /// data read from <paramref name="stream"/> and <paramref name="LoadData"/> is called with the buffer as input, + /// which outputs (in out-parameter) the number bytes read from the buffer. This should match exactly the size + /// of the buffer. Finally, the function returns the output value of <paramref name="LoadData"/>. This function + /// is intended only for internal use. + /// </remarks> + /// <param name="LoadData">The delegate that reads some number of bytes to a given buffer</param> + /// <param name="stream">The input stream</param> + /// <exception cref="ArgumentNullException">if LoadData or stream is null</exception> + /// <exception cref="ArgumentException">if the stream is closed or does not support reading</exception> + /// <exception cref="EndOfStreamException">if the stream ended unexpectedly</exception> + /// <exception cref="IOException">if I/O operations failed</exception> + /// <exception cref="InvalidOperationException">if the loaded data is invalid, if the loaded compression mode is + /// not supported, or if size of the object is more than 2 GB</exception> + internal static long Load(LoadDelegate LoadData, Stream stream) + { + if (null == stream) + throw new ArgumentNullException(nameof(stream)); + if (null == LoadData) + throw new ArgumentNullException(nameof(LoadData)); + if (!stream.CanRead) + throw new ArgumentException(nameof(stream)); + + try + { + SEALHeader header = new SEALHeader(); + var pos = stream.Position; + LoadHeader(stream, header); + + // Check the validity of the header + if (!IsCompatibleVersion(header)) + throw new InvalidOperationException("Incompatible version"); + if (!IsSupportedComprMode(header.ComprMode)) + throw new InvalidOperationException("Unsupported compression mode"); + if (!IsValidHeader(header)) + throw new InvalidOperationException("Loaded SEALHeader is invalid"); + if (header.Size > checked((ulong)int.MaxValue)) + throw new InvalidOperationException("Object size is larger than 2 GB"); + + int sizeInt = checked((int)header.Size); + stream.Seek(pos, SeekOrigin.Begin); + + byte[] buffer = null; + using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) + { + buffer = reader.ReadBytes(sizeInt); + } + + LoadData(buffer, header.Size, out long outBytes); + + // Clear the buffer for safety reasons + Array.Clear(buffer, 0, sizeInt); + + return outBytes; + } + catch (OverflowException ex) + { + throw new InvalidOperationException("Size indicated by loaded SEALHeader is out of bounds", ex); + } + } + } + + /// <summary>Class to contain header information for legacy headers.</summary> + public abstract class LegacyHeaders + { + /// <summary>Class to enable compatibility with Microsoft SEAL 3.4 headers.</summary> + [StructLayout(LayoutKind.Explicit, Size=16)] + public class SEALHeader_3_4 : ISettable<SEALHeader_3_4>, ISettable<Serialization.SEALHeader> + { + /// <summary>SEALMagic</summary> + [FieldOffset(0)]public ushort Magic = Serialization.SEALMagic; + + /// <summary>ZeroByte</summary> + [FieldOffset(2)]public byte ZeroByte = 0; + + /// <summary>ComprModeType</summary> + [FieldOffset(3)]public ComprModeType ComprMode = Serialization.ComprModeDefault; + + /// <summary>Size</summary> + [FieldOffset(4)]public uint Size = 0; + + /// <summary>Reserved</summary> + [FieldOffset(8)]public ulong Reserved = 0; + + /// <summary>Creates a new SEALHeader_3_4.</summary> + public SEALHeader_3_4() + { + } + + /// <summary> + /// Constructs a new SEALHeader_3_4 by copying a given one. + /// </summary> + /// <param name="copy">The SEALHeader_3_4 to copy from</param> + /// <exception cref="ArgumentNullException">if copy is null</exception> + public SEALHeader_3_4(Serialization.SEALHeader copy) + { + if (null == copy) + throw new ArgumentNullException(nameof(copy)); + + Set(copy); + } + + /// <summary>Copies a given SEALHeader_3_4 to the current one.</summary> + /// <param name="assign">The SEALHeader_3_4 to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(SEALHeader_3_4 assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + Magic = assign.Magic; + ZeroByte = assign.ZeroByte; + ComprMode = assign.ComprMode; + Size = assign.Size; + Reserved = assign.Reserved; + } + + /// <summary>Copies a given SEALHeader to the current one as a byte array.</summary> + /// <param name="assign">The SEALHeader to copy from</param> + /// <exception cref="ArgumentNullException">if assign is null</exception> + public void Set(Serialization.SEALHeader assign) + { + if (null == assign) + throw new ArgumentNullException(nameof(assign)); + + GCHandle gch = GCHandle.Alloc(this, GCHandleType.Pinned); + Marshal.StructureToPtr(assign, gch.AddrOfPinnedObject(), false); + gch.Free(); + } + }; + } +} diff --git a/bigpiseal3.5.1/dotnet/src/ValCheck.cs b/bigpiseal3.5.1/dotnet/src/ValCheck.cs new file mode 100644 index 0000000000000000000000000000000000000000..01565fbe998eff7a017e93ee64240349c4208b01 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/ValCheck.cs @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// Static methods for object validity checking. + /// </summary> + public static class ValCheck + { + /// <summary> + /// Check whether the given plaintext is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// plaintext data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="plaintext">The plaintext to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either plaintext or context is null</exception> + public static bool IsValidFor(Plaintext plaintext, SEALContext context) + { + if (null == plaintext) + throw new ArgumentNullException(nameof(plaintext)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_Plaintext_IsValidFor(plaintext.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given ciphertext is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// ciphertext data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="ciphertext">The ciphertext to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either ciphertext or context is null</exception> + public static bool IsValidFor(Ciphertext ciphertext, SEALContext context) + { + if (null == ciphertext) + throw new ArgumentNullException(nameof(ciphertext)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_Ciphertext_IsValidFor(ciphertext.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given secret key is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// secret key data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="secretKey">The secret key to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either secretKey or context is null</exception> + public static bool IsValidFor(SecretKey secretKey, SEALContext context) + { + if (null == secretKey) + throw new ArgumentNullException(nameof(secretKey)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_SecretKey_IsValidFor(secretKey.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given public key is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// public key data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="publicKey">The public key to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either publicKey or context is null</exception> + public static bool IsValidFor(PublicKey publicKey, SEALContext context) + { + if (null == publicKey) + throw new ArgumentNullException(nameof(publicKey)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_PublicKey_IsValidFor(publicKey.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given KSwitchKeys is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// KSwitchKeys data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="kswitchKeys">The KSwitchKeys to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either kswitchKeys or context is null</exception> + public static bool IsValidFor(KSwitchKeys kswitchKeys, SEALContext context) + { + if (null == kswitchKeys) + throw new ArgumentNullException(nameof(kswitchKeys)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_KSwitchKeys_IsValidFor(kswitchKeys.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given RelinKeys is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// RelinKeys data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="relinKeys">The RelinKeys to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either relinKeys or context is null</exception> + public static bool IsValidFor(RelinKeys relinKeys, SEALContext context) + { + if (null == relinKeys) + throw new ArgumentNullException(nameof(relinKeys)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_RelinKeys_IsValidFor(relinKeys.NativePtr, context.NativePtr, out bool result); + return result; + } + + /// <summary> + /// Check whether the given GaloisKeys is valid for a given SEALContext. If the + /// given SEALContext is not set, the encryption parameters are invalid, or the + /// GaloisKeys data does not match the SEALContext, this function returns false. + /// Otherwise, returns true. + /// </summary> + /// <param name="galoisKeys">The GaloisKeys to check</param> + /// <param name="context">The SEALContext</param> + /// <exception cref="ArgumentNullException">if either galoisKeys or context is null</exception> + public static bool IsValidFor(GaloisKeys galoisKeys, SEALContext context) + { + if (null == galoisKeys) + throw new ArgumentNullException(nameof(galoisKeys)); + if (null == context) + throw new ArgumentNullException(nameof(context)); + + NativeMethods.ValCheck_GaloisKeys_IsValidFor(galoisKeys.NativePtr, context.NativePtr, out bool result); + return result; + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/src/Version.cs b/bigpiseal3.5.1/dotnet/src/Version.cs new file mode 100644 index 0000000000000000000000000000000000000000..8e2e068d02181c923565fde882735752ebeaea2e --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/Version.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Text; + +namespace Microsoft.Research.SEAL +{ + /// <summary> + /// This class contains static methods for retrieving Microsoft SEAL's version numbers. + /// </summary> + /// <remark> + /// Use the name SEALVersion to distinguish it from System.Version. + /// </remark> + public static class SEALVersion + { + /// <summary> + /// Returns Microsoft SEAL's version number string. + /// </summary> + static public string Version => $"{SEALVersion.Major}.{SEALVersion.Minor}.{SEALVersion.Patch}"; + + /// + /// <summary> + /// Returns Microsoft SEAL's major version number. + /// </summary> + static public byte Major + { + get + { + NativeMethods.Version_Major(out byte result); + return result; + } + } + + /// <summary> + /// Returns Microsoft SEAL's minor version number. + /// </summary> + static public byte Minor + { + get + { + NativeMethods.Version_Minor(out byte result); + return result; + } + } + + /// <summary> + /// Returns Microsoft SEAL's patch version number. + /// </summary> + static public byte Patch + { + get + { + NativeMethods.Version_Patch(out byte result); + return result; + } + } + } +} diff --git a/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs b/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs new file mode 100644 index 0000000000000000000000000000000000000000..8900e9b620da88a8e566f7e47e17acf24f195bfc --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Research.SEAL.Tools +{ + /// <summary> + /// Class that implements the Disposable pattern + /// </summary> + public class DisposableObject : IDisposable + { + /// <summary> + /// Derived classes should override this method to release managed resources. + /// </summary> + protected virtual void DisposeManagedResources() + { + } + + /// <summary> + /// Derived classes should override this method to release native resources. + /// </summary> + protected virtual void DisposeNativeResources() + { + } + + /// <summary> + /// Whether this object is disposed + /// </summary> + public bool IsDisposed + { + get + { + return disposedValue; + } + } + + #region IDisposable Support + + private bool disposedValue = false; // To detect redundant calls + + private void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + DisposeManagedResources(); + } + + DisposeNativeResources(); + + disposedValue = true; + } + } + + /// <summary> + /// DisposableObject destructor + /// </summary> + ~DisposableObject() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + + /// <summary> + /// This code is added to correctly implement the disposable pattern. + /// </summary> + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} diff --git a/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs b/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs new file mode 100644 index 0000000000000000000000000000000000000000..f8090229db31068a378e062df3b57c5bbd7eecb8 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Research.SEAL.Tools +{ + /// <summary> + /// Class that encapsulates the behavior of a class backed by a + /// pointer to a native object. + /// + /// In particular, this class encapsulates the correct disposal + /// of the native pointer. + /// </summary> + public abstract class NativeObject : DisposableObject + { + /// <summary> + /// Construct a NativeObject instance + /// </summary> + public NativeObject() + { + NativePtr = IntPtr.Zero; + owned_ = true; + } + + /// <summary> + /// Construct a NativeObject instance initializing it with a pointer + /// to a native object. + /// </summary> + /// <param name="nativePtr">Pointer to native object.</param> + /// <param name="owned">Whether this instance owns the native pointer.</param> + public NativeObject(IntPtr nativePtr, bool owned = true) + { + NativePtr = nativePtr; + owned_ = owned; + } + + /// <summary> + /// Descendants should call the appropriate method to + /// destroy the backing native object. + /// </summary> + protected abstract void DestroyNativeObject(); + + /// <summary> + /// Destroy native object if necessary + /// </summary> + protected override void DisposeNativeResources() + { + base.DisposeNativeResources(); + + if (owned_ && !IntPtr.Zero.Equals(NativePtr)) + { + DestroyNativeObject(); + } + + NativePtr = IntPtr.Zero; + } + + /// <summary> + /// Get/Set pointer to native object + /// </summary> + internal IntPtr NativePtr + { + get + { + if (IsDisposed) + { + Type objType = this.GetType(); + string objName = objType?.FullName ?? "Unknown object name"; + throw new ObjectDisposedException(objName); + } + + return nativePtr_; + } + set + { + nativePtr_ = value; + } + } + + /// <summary> + /// Whether this instance owns the native pointer. + /// </summary> + private readonly bool owned_ = true; + + /// <summary> + /// Pointer to native object + /// </summary> + private IntPtr nativePtr_ = IntPtr.Zero; + } +} diff --git a/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs b/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs new file mode 100644 index 0000000000000000000000000000000000000000..777fa007c16af0e7fdfcb497adea34e82df0c3c9 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.Research.SEAL.Tools +{ + static class Utilities + { + public static readonly int BitsPerUInt64 = 64; + public static readonly int BitsPerUInt8 = 8; + + public static int DivideRoundUp(int value, int divisor) + { + return (value + divisor - 1) / divisor; + } + + public static int ComputeArrayHashCode(ulong[] array) + { + const int hash_seed = 17; + const int hash_multiply = 23; + int hash = hash_seed; + + unchecked + { + for (int i = 0; i < array.Length; i++) + { + ulong value = array[i]; + if (value != 0) + { + hash *= hash_multiply; + hash += (int)value; + value >>= 32; + hash *= hash_multiply; + hash += (int)value; + } + } + } + + return hash; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs b/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..5db6df61fff4706d57d4f8f3fc4a6b54e72d2e03 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices.ComTypes; + +namespace SEALNetTest +{ + [TestClass] + public class BatchEncoderTests + { + [TestMethod] + public void EncodeULongTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + parms.PolyModulusDegree = 64; + parms.CoeffModulus = CoeffModulus.Create(64, new int[]{ 60 }); + parms.PlainModulus = new Modulus(257); + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + BatchEncoder encoder = new BatchEncoder(context); + + Assert.AreEqual(64ul, encoder.SlotCount); + + List<ulong> plainList = new List<ulong>(); + for (ulong i = 0; i < encoder.SlotCount; i++) + { + plainList.Add((ulong)i); + } + + Plaintext plain = new Plaintext(); + encoder.Encode(plainList, plain); + + List<ulong> plainList2 = new List<ulong>(); + encoder.Decode(plain, plainList2); + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]); + } + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + plainList[checked((int)i)] = 5; + } + + encoder.Encode(plainList, plain); + Assert.AreEqual("5", plain.ToString()); + + encoder.Decode(plain, plainList2); + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]); + } + + List<ulong> shortList = new List<ulong>(); + for (ulong i = 0; i < 20; i++) + { + shortList.Add(i); + } + + encoder.Encode(shortList, plain); + + List<ulong> shortList2 = new List<ulong>(); + encoder.Decode(plain, shortList2); + + Assert.AreEqual(20, shortList.Count); + Assert.AreEqual(64, shortList2.Count); + + for (int i = 0; i < 20; i++) + { + Assert.AreEqual(shortList[i], shortList2[i]); + } + + for (ulong i = 20; i < encoder.SlotCount; i++) + { + Assert.AreEqual(0ul, shortList2[checked((int)i)]); + } + } + + [TestMethod] + public void EncodeLongTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + parms.PolyModulusDegree = 64; + parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }); + parms.PlainModulus = new Modulus(257); + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + BatchEncoder encoder = new BatchEncoder(context); + + Assert.AreEqual(64ul, encoder.SlotCount); + + List<long> plainList = new List<long>(); + for (ulong i = 0; i < encoder.SlotCount; i++) + { + plainList.Add((long)i); + } + + Plaintext plain = new Plaintext(); + encoder.Encode(plainList, plain); + + List<long> plainList2 = new List<long>(); + encoder.Decode(plain, plainList2); + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]); + } + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + plainList[checked((int)i)] = 5; + } + + encoder.Encode(plainList, plain); + Assert.AreEqual("5", plain.ToString()); + + encoder.Decode(plain, plainList2); + + for (ulong i = 0; i < encoder.SlotCount; i++) + { + Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]); + } + + List<long> shortList = new List<long>(); + for (int i = 0; i < 20; i++) + { + shortList.Add((long)i); + } + + encoder.Encode(shortList, plain); + + List<long> shortList2 = new List<long>(); + encoder.Decode(plain, shortList2); + + Assert.AreEqual(20, shortList.Count); + Assert.AreEqual(64, shortList2.Count); + + for (int i = 0; i < 20; i++) + { + Assert.AreEqual(shortList[i], shortList2[i]); + } + + for (ulong i = 20; i < encoder.SlotCount; i++) + { + Assert.AreEqual(0L, shortList2[checked((int)i)]); + } + } + + [TestMethod] + public void EncodeInPlaceTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }), + PlainModulus = new Modulus(257) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + BatchEncoder encoder = new BatchEncoder(context); + + Assert.AreEqual(64ul, encoder.SlotCount); + + Plaintext plain = new Plaintext("6x^5 + 5x^4 + 4x^3 + 3x^2 + 2x^1 + 1"); + Assert.AreEqual(6ul, plain.CoeffCount); + + encoder.Encode(plain); + + Assert.AreEqual(64ul, plain.CoeffCount); + + encoder.Decode(plain); + Assert.AreEqual(64ul, plain.CoeffCount); + + for (ulong i = 0; i < 6; i++) + { + Assert.AreEqual((i + 1), plain[i]); + } + + for (ulong i = 6; i < plain.CoeffCount; i++) + { + Assert.AreEqual(0ul, plain[i]); + } + } + + [TestMethod] + public void SchemeIsCKKSTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 8, + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 }) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + Utilities.AssertThrows<ArgumentException>(() => + { + BatchEncoder encoder = new BatchEncoder(context); + }); + } + + [TestMethod] + public void ExceptionsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }), + PlainModulus = new Modulus(257) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + BatchEncoder enc = new BatchEncoder(context); + List<ulong> valu = new List<ulong>(); + List<ulong> valu_null = null; + List<long> vall = new List<long>(); + List<long> vall_null = null; + Plaintext plain = new Plaintext(); + Plaintext plain_null = null; + MemoryPoolHandle pool_uninit = new MemoryPoolHandle(); + + Utilities.AssertThrows<ArgumentNullException>(() => enc = new BatchEncoder(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(valu, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(valu_null, plain)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(vall, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(vall_null, plain)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(plain_null)); + Utilities.AssertThrows<ArgumentException>(() => enc.Encode(plain, pool_uninit)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain, valu_null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null, valu)); + Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, valu, pool_uninit)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain, vall_null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null, vall)); + Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, vall, pool_uninit)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null)); + Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, pool_uninit)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs b/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..92162e414d241b6d0c14ee15cda5c5afdcf883b7 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs @@ -0,0 +1,985 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Numerics; + +namespace SEALNetTest +{ + [TestClass] + public class BigUIntTests + { + [TestMethod] + public void EmptyConstructorTest() + { + BigUInt bui = new BigUInt(); + + Assert.IsTrue(bui.IsZero); + Assert.AreEqual(0, bui.BitCount); + } + + [TestMethod] + public void BitCountConstructorTest() + { + BigUInt bui = new BigUInt(bitCount: 70); + + Assert.IsTrue(bui.IsZero); + Assert.AreEqual(70, bui.BitCount); + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(0, bui.GetSignificantBitCount()); + } + + [TestMethod] + public void HexStringConstructorTest() + { + BigUInt bui = new BigUInt("1234567890ABCDEF1234567890ABCDEF"); + + Assert.IsFalse(bui.IsZero); + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(125, bui.BitCount); + Assert.AreEqual(125, bui.GetSignificantBitCount()); + + Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(0)); + Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(1)); + + bui = new BigUInt("FEDCBAFEDCBA0987654321"); + + Assert.IsFalse(bui.IsZero); + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(88, bui.BitCount); + Assert.AreEqual(88, bui.GetSignificantBitCount()); + + Assert.AreEqual(0xFEDCBAul, bui.Data(1)); + Assert.AreEqual(0xFEDCBA0987654321ul, bui.Data(0)); + + bui = new BigUInt(bitCount: 80, hexString: "DEADBEEF"); + + Assert.IsFalse(bui.IsZero); + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(80, bui.BitCount); + Assert.AreEqual(32, bui.GetSignificantBitCount()); + Assert.AreEqual(0ul, bui.Data(1)); + Assert.AreEqual(0xDEADBEEFul, bui.Data(0)); + } + + [TestMethod] + public void U64ConstructorTest() + { + BigUInt bui = new BigUInt(bitCount: 80, value: 12345ul); + + Assert.IsFalse(bui.IsZero); + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(14, bui.GetSignificantBitCount()); + Assert.AreEqual(0ul, bui.Data(1)); + Assert.AreEqual(12345ul, bui.Data(0)); + } + + [TestMethod] + public void BigIntegerConstructorTest() + { + BigInteger bi = new BigInteger(12345); + BigUInt bui = new BigUInt(bi); + + Assert.IsFalse(bui.IsZero); + Assert.AreEqual(14, bui.BitCount); + Assert.AreEqual(2ul, bui.ByteCount); + Assert.AreEqual(14, bui.GetSignificantBitCount()); + Assert.AreEqual(1ul, bui.UInt64Count); + Assert.AreEqual(12345ul, bui.Data(0)); + } + + [TestMethod] + public void CopyConstructorTest() + { + BigUInt bui1 = new BigUInt("DEADBEEF"); + BigUInt bui2 = new BigUInt("1234567890ABCDEF1234567890ABCDEF"); + + BigUInt bui3 = new BigUInt(bui1); + + Assert.AreEqual(1ul, bui3.UInt64Count); + Assert.AreEqual(32, bui3.GetSignificantBitCount()); + Assert.AreEqual(0xDEADBEEFul, bui3.Data(0)); + Assert.IsTrue(bui1.Equals(bui3)); + + bui3 = new BigUInt(bui2); + + Assert.AreEqual(2ul, bui3.UInt64Count); + Assert.AreEqual(125, bui3.BitCount); + Assert.AreEqual(125, bui3.GetSignificantBitCount()); + Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(0)); + Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(1)); + Assert.IsTrue(bui2.Equals(bui3)); + } + + [TestMethod] + public void EmptyBigUIntNET() + { + var biguint = new BigUInt(); + Assert.AreEqual(0, biguint.BitCount); + Assert.AreEqual(0ul, biguint.ByteCount); + Assert.AreEqual(0ul, biguint.UInt64Count); + Assert.IsTrue(biguint.UInt64Count == 0ul); + Assert.AreEqual(0, biguint.GetSignificantBitCount()); + Assert.AreEqual("0", biguint.ToString()); + Assert.IsTrue(biguint.IsZero); + Assert.IsFalse(biguint.IsAlias); + biguint.SetZero(); + + var biguint2 = new BigUInt(); + Assert.IsTrue(biguint.Equals(biguint2)); + + biguint.Resize(1); + Assert.AreEqual(1, biguint.BitCount); + Assert.IsTrue(biguint.UInt64Count != 0ul); + Assert.IsFalse(biguint.IsAlias); + + biguint.Resize(0); + Assert.AreEqual(0, biguint.BitCount); + Assert.IsTrue(biguint.UInt64Count == 0ul); + Assert.IsFalse(biguint.IsAlias); + } + + [TestMethod] + public void BigUInt64BitsNET() + { + var biguint = new BigUInt(64); + Assert.AreEqual(64, biguint.BitCount); + Assert.AreEqual(8ul, biguint.ByteCount); + Assert.AreEqual(1ul, biguint.UInt64Count); + Assert.AreEqual(0, biguint.GetSignificantBitCount()); + Assert.AreEqual("0", biguint.ToString()); + Assert.IsTrue(biguint.IsZero); + Assert.IsTrue(biguint.UInt64Count != 0); + Assert.AreEqual(0UL, biguint.Data(0)); + Assert.AreEqual(0, biguint[0]); + Assert.AreEqual(0, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + + biguint.Set(1); + Assert.AreEqual(1, biguint.GetSignificantBitCount()); + Assert.AreEqual("1", biguint.ToString()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual(1UL, biguint.Data(0)); + Assert.AreEqual(1, biguint[0]); + Assert.AreEqual(0, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + biguint.SetZero(); + Assert.IsTrue(biguint.IsZero); + Assert.AreEqual(0UL, biguint.Data(0)); + + biguint.Set("7FFFFFFFFFFFFFFF"); + Assert.AreEqual(63, biguint.GetSignificantBitCount()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual("7FFFFFFFFFFFFFFF", biguint.ToString()); + Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, biguint.Data(0)); + Assert.AreEqual(0xFF, biguint[0]); + Assert.AreEqual(0xFF, biguint[1]); + Assert.AreEqual(0xFF, biguint[2]); + Assert.AreEqual(0xFF, biguint[3]); + Assert.AreEqual(0xFF, biguint[4]); + Assert.AreEqual(0xFF, biguint[5]); + Assert.AreEqual(0xFF, biguint[6]); + Assert.AreEqual(0x7F, biguint[7]); + + biguint.Set("FFFFFFFFFFFFFFFF"); + Assert.AreEqual(64, biguint.GetSignificantBitCount()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual("FFFFFFFFFFFFFFFF", biguint.ToString()); + Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0)); + Assert.AreEqual(0xFF, biguint[0]); + Assert.AreEqual(0xFF, biguint[1]); + Assert.AreEqual(0xFF, biguint[2]); + Assert.AreEqual(0xFF, biguint[3]); + Assert.AreEqual(0xFF, biguint[4]); + Assert.AreEqual(0xFF, biguint[5]); + Assert.AreEqual(0xFF, biguint[6]); + Assert.AreEqual(0xFF, biguint[7]); + + biguint.Set(0x8001); + Assert.AreEqual(16, biguint.GetSignificantBitCount()); + Assert.AreEqual("8001", biguint.ToString()); + Assert.AreEqual(0x8001UL, biguint.Data(0)); + Assert.AreEqual(0x01, biguint[0]); + Assert.AreEqual(0x80, biguint[1]); + Assert.AreEqual(0x00, biguint[2]); + Assert.AreEqual(0x00, biguint[3]); + Assert.AreEqual(0x00, biguint[4]); + Assert.AreEqual(0x00, biguint[5]); + Assert.AreEqual(0x00, biguint[6]); + Assert.AreEqual(0x00, biguint[7]); + } + + [TestMethod] + public void BigUInt99BitsNET() + { + var biguint = new BigUInt(99); + Assert.AreEqual(99, biguint.BitCount); + Assert.IsTrue(biguint.UInt64Count != 0ul); + Assert.AreEqual(13ul, biguint.ByteCount); + Assert.AreEqual(2ul, biguint.UInt64Count); + Assert.AreEqual(0, biguint.GetSignificantBitCount()); + Assert.AreEqual("0", biguint.ToString()); + Assert.IsTrue(biguint.IsZero); + Assert.AreEqual(0UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + Assert.AreEqual(0, biguint[0]); + Assert.AreEqual(0, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + Assert.AreEqual(0, biguint[8]); + Assert.AreEqual(0, biguint[9]); + Assert.AreEqual(0, biguint[10]); + Assert.AreEqual(0, biguint[11]); + Assert.AreEqual(0, biguint[12]); + + biguint.Set(1); + Assert.AreEqual(1, biguint.GetSignificantBitCount()); + Assert.AreEqual("1", biguint.ToString()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual(13ul, biguint.ByteCount); + Assert.AreEqual(2ul, biguint.UInt64Count); + Assert.AreEqual(1UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + Assert.AreEqual(1, biguint[0]); + Assert.AreEqual(0, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + Assert.AreEqual(0, biguint[8]); + Assert.AreEqual(0, biguint[9]); + Assert.AreEqual(0, biguint[10]); + Assert.AreEqual(0, biguint[11]); + Assert.AreEqual(0, biguint[12]); + biguint.SetZero(); + Assert.IsTrue(biguint.IsZero); + Assert.AreEqual(0UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + + biguint.Set("7FFFFFFFFFFFFFFFFFFFFFFFF"); + Assert.AreEqual(99, biguint.GetSignificantBitCount()); + Assert.AreEqual("7FFFFFFFFFFFFFFFFFFFFFFFF", biguint.ToString()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0)); + Assert.AreEqual(0x7FFFFFFFFUL, biguint.Data(1)); + Assert.AreEqual(0xFF, biguint[0]); + Assert.AreEqual(0xFF, biguint[1]); + Assert.AreEqual(0xFF, biguint[2]); + Assert.AreEqual(0xFF, biguint[3]); + Assert.AreEqual(0xFF, biguint[4]); + Assert.AreEqual(0xFF, biguint[5]); + Assert.AreEqual(0xFF, biguint[6]); + Assert.AreEqual(0xFF, biguint[7]); + Assert.AreEqual(0xFF, biguint[8]); + Assert.AreEqual(0xFF, biguint[9]); + Assert.AreEqual(0xFF, biguint[10]); + Assert.AreEqual(0xFF, biguint[11]); + Assert.AreEqual(0x07, biguint[12]); + biguint.SetZero(); + Assert.IsTrue(biguint.IsZero); + Assert.AreEqual(0UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + + biguint.Set("4000000000000000000000000"); + Assert.AreEqual(99, biguint.GetSignificantBitCount()); + Assert.AreEqual("4000000000000000000000000", biguint.ToString()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual(0UL, biguint.Data(0)); + Assert.AreEqual(0x400000000UL, biguint.Data(1)); + Assert.AreEqual(0, biguint[0]); + Assert.AreEqual(0, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + Assert.AreEqual(0, biguint[8]); + Assert.AreEqual(0, biguint[9]); + Assert.AreEqual(0, biguint[10]); + Assert.AreEqual(0, biguint[11]); + Assert.AreEqual(0x04, biguint[12]); + + biguint.Set(0x8001); + Assert.AreEqual(16, biguint.GetSignificantBitCount()); + Assert.AreEqual("8001", biguint.ToString()); + Assert.IsFalse(biguint.IsZero); + Assert.AreEqual(0x8001UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + Assert.AreEqual(0x01, biguint[0]); + Assert.AreEqual(0x80, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + Assert.AreEqual(0, biguint[8]); + Assert.AreEqual(0, biguint[9]); + Assert.AreEqual(0, biguint[10]); + Assert.AreEqual(0, biguint[11]); + Assert.AreEqual(0, biguint[12]); + + var biguint2 = new BigUInt("123"); + Assert.IsFalse(biguint.Equals(biguint2)); + Assert.IsFalse(biguint2.Equals(biguint)); + Assert.AreNotEqual(biguint.GetHashCode(), biguint2.GetHashCode()); + + biguint.Set(biguint2); + Assert.IsTrue(biguint.Equals(biguint2)); + Assert.IsTrue(biguint2.Equals(biguint)); + Assert.AreEqual(biguint.GetHashCode(), biguint2.GetHashCode()); + Assert.AreEqual(9, biguint.GetSignificantBitCount()); + Assert.AreEqual("123", biguint.ToString()); + Assert.AreEqual(0x123UL, biguint.Data(0)); + Assert.AreEqual(0UL, biguint.Data(1)); + Assert.AreEqual(0x23, biguint[0]); + Assert.AreEqual(0x01, biguint[1]); + Assert.AreEqual(0, biguint[2]); + Assert.AreEqual(0, biguint[3]); + Assert.AreEqual(0, biguint[4]); + Assert.AreEqual(0, biguint[5]); + Assert.AreEqual(0, biguint[6]); + Assert.AreEqual(0, biguint[7]); + Assert.AreEqual(0, biguint[8]); + Assert.AreEqual(0, biguint[9]); + Assert.AreEqual(0, biguint[10]); + Assert.AreEqual(0, biguint[11]); + Assert.AreEqual(0, biguint[12]); + + biguint.Resize(8); + Assert.AreEqual(8, biguint.BitCount); + Assert.AreEqual(1ul, biguint.UInt64Count); + Assert.AreEqual("23", biguint.ToString()); + + biguint.Resize(100); + Assert.AreEqual(100, biguint.BitCount); + Assert.AreEqual(2ul, biguint.UInt64Count); + Assert.AreEqual("23", biguint.ToString()); + + biguint.Resize(0); + Assert.AreEqual(0, biguint.BitCount); + Assert.AreEqual(0ul, biguint.UInt64Count); + Assert.IsTrue(biguint.UInt64Count == 0); + } + + [TestMethod] + public void SaveLoadUIntNET() + { + using (MemoryStream stream = new MemoryStream()) + { + var value = new BigUInt(); + var value2 = new BigUInt("100"); + stream.Seek(0, SeekOrigin.Begin); + value.Save(stream); + stream.Seek(0, SeekOrigin.Begin); + value2.Load(stream); + Assert.AreEqual(value, value2); + + value.Set("123"); + stream.Seek(0, SeekOrigin.Begin); + value.Save(stream); + stream.Seek(0, SeekOrigin.Begin); + value2.Load(stream); + Assert.AreEqual(value, value2); + + value.Set("FFFFFFFFFFFFFFFFFFFFFFFFFF"); + stream.Seek(0, SeekOrigin.Begin); + value.Save(stream); + stream.Seek(0, SeekOrigin.Begin); + value2.Load(stream); + Assert.AreEqual(value, value2); + + value.Set("0"); + stream.Seek(0, SeekOrigin.Begin); + value.Save(stream); + stream.Seek(0, SeekOrigin.Begin); + value2.Load(stream); + Assert.AreEqual(value, value2); + } + } + + [TestMethod] + public void DuplicateToNET() + { + var original = new BigUInt(123); + original.Set(56789); + + var target = new BigUInt(); + + original.DuplicateTo(target); + Assert.AreEqual(target.BitCount, original.BitCount); + Assert.IsTrue(target.Equals(original)); + } + + [TestMethod] + public void DuplicateFromNET() + { + var original = new BigUInt(123); + original.Set(56789); + + var target = new BigUInt(); + + target.DuplicateFrom(original); + Assert.AreEqual(target.BitCount, original.BitCount); + Assert.IsTrue(target.Equals(original)); + } + + [TestMethod] + public void ToBigIntegerTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigInteger bi = bui.ToBigInteger(); + Assert.IsNotNull(bi); + Assert.IsFalse(bi.IsEven); + Assert.IsFalse(bi.IsZero); + Assert.AreEqual(0, bi.CompareTo(0xDEADBEEFul)); + } + + [TestMethod] + public void ToDecimalStringTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + string decStr = bui.ToDecimalString(); + Assert.IsNotNull(decStr); + Assert.IsTrue("3735928559".Equals(decStr)); + } + + [TestMethod] + public void CompareToTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt other = new BigUInt("DEADBFFF"); + Assert.IsTrue(bui.CompareTo(other) < 0); + Assert.IsTrue(other.CompareTo(bui) > 0); + + BigUInt third = new BigUInt(bui); + Assert.AreNotSame(bui, third); + Assert.AreEqual(0, bui.CompareTo(third)); + Assert.IsTrue(bui.CompareTo(null) > 0); + } + + [TestMethod] + public void ModuloInvertFail1Test() + { + // Should fail when modulus is zero + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt mod = new BigUInt(); + + Assert.IsTrue(mod.IsZero); + Assert.IsFalse(bui.IsZero); + + Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod)); + } + + [TestMethod] + public void ModuloInvertFail2Test() + { + // Should fail when modulus is not greater than the BigUInt value + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt mod = new BigUInt("BEEF"); + + Assert.IsFalse(mod.IsZero); + Assert.IsFalse(bui.IsZero); + + Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod)); + } + + [TestMethod] + public void ModuloInvertFail3Test() + { + // Should fail when biguint value and modulus are not coprime + BigUInt bui = new BigUInt(bitCount: 64, value: 12); + BigUInt mod = new BigUInt(bitCount: 64, value: 24); + + Assert.IsFalse(mod.IsZero); + Assert.IsFalse(bui.IsZero); + + Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod)); + } + + [TestMethod] + public void ModuloInvertTest() + { + BigUInt bui = new BigUInt(bitCount: 64, value: 12); + BigUInt mod = new BigUInt(bitCount: 64, value: 25); + + BigUInt inverse1 = bui.ModuloInvert(mod); + + Assert.AreEqual(23ul, inverse1.Data(0)); + + BigUInt inverse2 = bui.ModuloInvert(modulus: 25ul); + + Assert.AreEqual(23ul, inverse2.Data(0)); + } + + [TestMethod] + public void TryModuloInvertFail1Test() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt mod = new BigUInt(); + BigUInt inverse = new BigUInt(); + + // Should fail when modulus is zero + Assert.IsTrue(mod.IsZero); + Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(mod, inverse)); + } + + [TestMethod] + public void TryModuloInvertFail2Test() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt mod = new BigUInt("BEEF"); + BigUInt inverse = new BigUInt(); + + // Should fail when biguint is bigger than modulus + Assert.IsFalse(mod.IsZero); + Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(mod, inverse)); + } + + [TestMethod] + public void TryModuloInvertTest() + { + BigUInt bui = new BigUInt(bitCount: 64, value: 12); + BigUInt mod = new BigUInt(bitCount: 64, value: 25); + BigUInt inverse1 = new BigUInt(); + BigUInt inverse2 = new BigUInt(); + + Assert.IsTrue(bui.TryModuloInvert(mod, inverse1)); + + Assert.AreEqual(23ul, inverse1.Data(0)); + + Assert.IsTrue(bui.TryModuloInvert(modulus: 25ul, inverse: inverse2)); + + Assert.AreEqual(23ul, inverse2.Data(0)); + + // Should fail (but not throw) when biguint value and modulus are not coprime + BigUInt bui2 = new BigUInt(bitCount: 64, value: 12); + BigUInt mod2 = new BigUInt(bitCount: 64, value: 24); + + Assert.IsFalse(mod2.IsZero); + Assert.IsFalse(bui2.IsZero); + + Assert.IsFalse(bui2.TryModuloInvert(mod2, inverse1)); + } + + [TestMethod] + public void DivideRemainderTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt op = new BigUInt("BEEF"); + BigUInt remainder = new BigUInt(); + + BigUInt result = bui.DivideRemainder(op, remainder); + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x12a90ul, result.Data(0)); + Assert.AreEqual(1ul, remainder.UInt64Count); + Assert.AreEqual(0x227Ful, remainder.Data(0)); + + BigUInt result2 = bui.DivideRemainder(0xDEADul, remainder); + + Assert.AreEqual(1ul, result2.UInt64Count); + Assert.AreEqual(0x10000ul, result2.Data(0)); + Assert.AreEqual(1ul, remainder.UInt64Count); + Assert.AreEqual(0xBEEFul, remainder.Data(0)); + } + + [TestMethod] + public void OperatorPlusTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt newone = +bui; + + Assert.AreEqual(1ul, newone.UInt64Count); + Assert.AreEqual(0xDEADBEEFul, newone.Data(0)); + } + + [TestMethod] + public void OperatorMinusTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt newone = -bui; + + Assert.AreEqual(1ul, newone.UInt64Count); + Assert.AreEqual(0x21524111ul, newone.Data(0)); + } + + [TestMethod] + public void OperatorTildeTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt newone = ~bui; + + Assert.AreEqual(1ul, newone.UInt64Count); + Assert.AreEqual(0x21524110ul, newone.Data(0)); + } + + [TestMethod] + public void OperatorPlusPlusTest() + { + BigUInt bui = new BigUInt("12345678901234567890"); + bui++; + + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(0x1234ul, bui.Data(1)); + Assert.AreEqual(0x5678901234567891ul, bui.Data(0)); + } + + [TestMethod] + public void OperatorMinusMinusTest() + { + BigUInt bui = new BigUInt("12345678901234567890"); + bui--; + + Assert.AreEqual(2ul, bui.UInt64Count); + Assert.AreEqual(0x1234ul, bui.Data(1)); + Assert.AreEqual(0x567890123456788Ful, bui.Data(0)); + } + + [TestMethod] + public void OperatorAddTest() + { + BigUInt bui = new BigUInt("1234567890"); + BigUInt op = new BigUInt("6543210"); + + BigUInt result = bui + op; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x123AAAAAA0ul, result.Data(0)); + + BigUInt result2 = bui + 0x9876543210ul; + + Assert.AreEqual(1ul, result2.UInt64Count); + Assert.AreEqual(0xAAAAAAAAA0ul, result2.Data(0)); + } + + [TestMethod] + public void OperatorSubTest() + { + BigUInt bui = new BigUInt("1234567890"); + BigUInt op = new BigUInt("6543210"); + + BigUInt result = bui - op; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x122E024680ul, result.Data(0)); + + result = bui - 0x76543210ul; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x11BE024680ul, result.Data(0)); + } + + [TestMethod] + public void OperatorMultTest() + { + BigUInt bui = new BigUInt("12345"); + BigUInt op = new BigUInt("ABCDEF"); + + BigUInt result = bui * op; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0xC379652E6Bul, result.Data(0)); + + result = bui * 0xFEDCBAul; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x121F998EC22ul, result.Data(0)); + } + + [TestMethod] + public void OperatorDivTest() + { + BigUInt bui = new BigUInt("1234567890"); + BigUInt op = new BigUInt("BEEF"); + + BigUInt result = bui / op; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x18687Dul, result.Data(0)); + + result = bui / 0xDEAD; + + Assert.AreEqual(1ul, result.UInt64Count); + Assert.AreEqual(0x14EDC6ul, result.Data(0)); + } + + [TestMethod] + public void OperatorAndTest() + { + BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB"); + BigUInt op = new BigUInt("FEFEFEFEFEFEFEFEFEFEFEFE"); + + BigUInt result = bui & op; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0xCCCCCCCCul, result.Data(1)); + Assert.AreEqual(0xAAAAAAAAAAAAAAAAul, result.Data(0)); + + result = bui & 0xF0F0F0F0F0; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0ul, result.Data(1)); + Assert.AreEqual(0xA0A0A0A0A0ul, result.Data(0)); + } + + [TestMethod] + public void OperatorOrTest() + { + BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB"); + BigUInt op = new BigUInt("E0E0E0E0E0E0E0E0E0E0E0E0"); + + BigUInt result = bui | op; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0xEDEDEDEDul, result.Data(1)); + Assert.AreEqual(0xEBEBEBEBEBEBEBEBul, result.Data(0)); + + result = bui | 0x1010101010; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0xCDCDCDCDul, result.Data(1)); + Assert.AreEqual(0xABABABBBBBBBBBBBul, result.Data(0)); + } + + [TestMethod] + public void OperatorXorTest() + { + BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB"); + BigUInt op = new BigUInt("0000FFFFFFFF000000000000"); + + BigUInt result = bui ^ op; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0xCDCD3232ul, result.Data(1)); + Assert.AreEqual(0x5454ABABABABABABul, result.Data(0)); + + result = bui ^ 0xF0F0F0F0F0; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0xCDCDCDCDul, result.Data(1)); + Assert.AreEqual(0xABABAB5B5B5B5B5Bul, result.Data(0)); + } + + [TestMethod] + public void OperatorShiftLeftTest() + { + BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB"); + + BigUInt result = bui << 1; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0x19B9B9B9Bul, result.Data(1)); + Assert.AreEqual(0x5757575757575756ul, result.Data(0)); + + result = bui << 2; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0x337373736ul, result.Data(1)); + Assert.AreEqual(0xAEAEAEAEAEAEAEACul, result.Data(0)); + } + + [TestMethod] + public void OperatorShiftRightTest() + { + BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB"); + + BigUInt result = bui >> 1; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0x66E6E6E6ul, result.Data(1)); + Assert.AreEqual(0xD5D5D5D5D5D5D5D5ul, result.Data(0)); + + result = bui >> 2; + + Assert.AreEqual(2ul, result.UInt64Count); + Assert.AreEqual(0x33737373ul, result.Data(1)); + Assert.AreEqual(0x6AEAEAEAEAEAEAEAul, result.Data(0)); + } + + [TestMethod] + public void OperatorDoubleTest() + { + BigUInt bui = new BigUInt("12345"); + + double value = (double)bui; + + Assert.AreEqual(74565.0, value, delta: 0.1); + + bui = new BigUInt("12345678901234567890"); + + value = (double)bui; + + Assert.AreEqual(8.59680582719788E+22, value, delta: 3.5e7); + } + + [TestMethod] + public void OperatorFloatTest() + { + BigUInt bui = new BigUInt("12345"); + float value = (float)bui; + + Assert.AreEqual(74565.0f, value, delta: 0.1); + + bui.Set("12345678901234567890"); + + value = (float)bui; + + Assert.AreEqual(8.59680582719788E+22f, value, delta: 0.1f); + } + + [TestMethod] + public void OperatorUInt64Test() + { + BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF"); + ulong value = (ulong)bui; + + Assert.AreEqual(0x1234567890ABCDEFul, value); + } + + [TestMethod] + public void OperatorInt64Test() + { + BigUInt bui = new BigUInt("ABCDEF124567890ABCDEF"); + long value = (long)bui; + + Assert.AreEqual(-1070635735584092689, value); + } + + [TestMethod] + public void OperatorUInt32Test() + { + BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF"); + uint value = (uint)bui; + + Assert.AreEqual(0x90ABCDEFu, value); + } + + [TestMethod] + public void OperatorInt32Test() + { + BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF"); + int value = (int)bui; + + Assert.AreEqual(-1867788817, value); + } + + [TestMethod] + public void ExceptionsTest() + { + BigUInt bui = new BigUInt("DEADBEEF"); + BigUInt bui1 = null; + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt((BigUInt)null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt((string)null)); + Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1)); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt(bitCount: 64, hexString: null)); + Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1, hexString: "ABCDEF")); + Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1, value: 10ul)); + + bui1 = new BigUInt(); + BigUInt bui2 = new BigUInt(); + + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui.Data(1)); + + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui[5] ); + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui[5] = 2); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(bui1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(null, bui2)); + Utilities.AssertThrows<ArgumentException>(() => bui.DivideRemainder(bui1, bui2)); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(1ul, null)); + Utilities.AssertThrows<ArgumentException>(() => bui.DivideRemainder(0ul, bui2)); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.DuplicateFrom(null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.DuplicateTo(null)); + + Assert.IsFalse(bui.Equals(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.Load(null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.ModuloInvert(null)); + Utilities.AssertThrows<ArgumentException>(() => bui.Resize(bitCount: -1)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.Set((BigUInt)null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.Set((string)null)); + + Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(bui1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(null, bui2)); + Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(bui1, bui2)); + Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(1ul, null)); + + bui2 = null; + + Utilities.AssertThrows<ArgumentNullException>(() => bui2 = +bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui2 = -bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui2 = ~bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui2++); + Utilities.AssertThrows<ArgumentNullException>(() => bui2--); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui + bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 + bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 + 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui - bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 - bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 - 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui * bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 * bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 * 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui / bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 / bui); + Utilities.AssertThrows<ArgumentException>(() => bui1 = bui / bui1); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 / 1ul); + Utilities.AssertThrows<ArgumentException>(() => bui1 = bui / 0ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui ^ bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 ^ bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 ^ 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui & bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 & bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 & 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui | bui2); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 | bui); + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 | 1ul); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 << 5); + Utilities.AssertThrows<ArgumentException>(() => bui1 = bui1 << -1); + + Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 >> 5); + Utilities.AssertThrows<ArgumentException>(() => bui1 = bui1 >> -1); + + Utilities.AssertThrows<ArgumentNullException>(() => { double d = (double)bui2; }); + Utilities.AssertThrows<ArgumentNullException>(() => { float f = (float)bui2; }); + Utilities.AssertThrows<ArgumentNullException>(() => { ulong u = (ulong)bui2; }); + Utilities.AssertThrows<ArgumentNullException>(() => { long l = (long)bui2; }); + Utilities.AssertThrows<ArgumentNullException>(() => { uint u = (uint)bui2; }); + Utilities.AssertThrows<ArgumentNullException>(() => { int i = (int)bui2; }); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs b/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..72d3bc0d398d09a1ead6714cab09096f7d4c3d3f --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs @@ -0,0 +1,231 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Numerics; + +namespace SEALNetTest +{ + [TestClass] + public class CKKSEncoderTests + { + [TestMethod] + public void EncodeDecodeDoubleTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + parms.PolyModulusDegree = 64; + parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }); + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + int slots = 16; + Plaintext plain = new Plaintext(); + double delta = 1 << 16; + List<Complex> result = new List<Complex>(); + + CKKSEncoder encoder = new CKKSEncoder(context); + Assert.AreEqual(32ul, encoder.SlotCount); + + double value = 10d; + encoder.Encode(value, delta, plain); + encoder.Decode(plain, result); + + for (int i = 0; i < slots; i++) + { + double tmp = Math.Abs(value - result[i].Real); + Assert.IsTrue(tmp < 0.5); + } + } + + [TestMethod] + public void EncodeDecodeUlongTest() + { + + int slots = 32; + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + parms.PolyModulusDegree = (ulong)slots * 2; + parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }); + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + + Plaintext plain = new Plaintext(); + List<Complex> result = new List<Complex>(); + + long value = 15; + encoder.Encode(value, plain); + encoder.Decode(plain, result); + + for (int i = 0; i < slots; i++) + { + double tmp = Math.Abs(value - result[i].Real); + Assert.IsTrue(tmp < 0.5); + } + } + + [TestMethod] + public void EncodeDecodeComplexTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + + Plaintext plain = new Plaintext(); + Complex value = new Complex(3.1415, 2.71828); + + encoder.Encode(value, scale: Math.Pow(2, 20), destination: plain); + + List<Complex> result = new List<Complex>(); + encoder.Decode(plain, result); + + Assert.IsTrue(result.Count > 0); + Assert.AreEqual(3.1415, result[0].Real, delta: 0.0001); + Assert.AreEqual(2.71828, result[0].Imaginary, delta: 0.0001); + } + + [TestMethod] + public void EncodeDecodeVectorTest() + { + int slots = 32; + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + parms.PolyModulusDegree = (ulong)slots * 2; + parms.CoeffModulus = CoeffModulus.Create((ulong)slots * 2, new int[] { 60, 60, 60, 60 }); + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + + List<Complex> values = new List<Complex>(slots); + Random rnd = new Random(); + int dataBound = 1 << 30; + double delta = 1ul << 40; + + for (int i = 0; i < slots; i++) + { + values.Add(new Complex(rnd.Next() % dataBound, 0)); + } + + Plaintext plain = new Plaintext(); + encoder.Encode(values, delta, plain); + + List<Complex> result = new List<Complex>(); + encoder.Decode(plain, result); + + for (int i = 0; i < slots; i++) + { + double tmp = Math.Abs(values[i].Real - result[i].Real); + Assert.IsTrue(tmp < 0.5); + } + } + + [TestMethod] + public void EncodeDecodeVectorDoubleTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 }) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + Plaintext plain = new Plaintext(); + + double[] values = new double[] { 0.1, 2.3, 34.4 }; + encoder.Encode(values, scale: Math.Pow(2, 20), destination: plain); + + List<double> result = new List<double>(); + encoder.Decode(plain, result); + + Assert.IsNotNull(result); + Assert.AreEqual(0.1, result[0], delta: 0.001); + Assert.AreEqual(2.3, result[1], delta: 0.001); + Assert.AreEqual(34.4, result[2], delta: 0.001); + } + + [TestMethod] + public void ExceptionsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 }) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + List<double> vald = new List<double>(); + List<double> vald_null = null; + List<Complex> valc = new List<Complex>(); + List<Complex> valc_null = null; + Plaintext plain = new Plaintext(); + Plaintext plain_null = null; + MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal); + Complex complex = new Complex(1, 2); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder = new CKKSEncoder(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, ParmsId.Zero, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, null, 10.0, plain)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald_null, ParmsId.Zero, 10.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(vald, ParmsId.Zero, 10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, ParmsId.Zero, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, null, 10.0, plain)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc_null, ParmsId.Zero, 10.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(valc, ParmsId.Zero, 10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald_null, 10.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(vald, -10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc_null, 10.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(valc, -10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, ParmsId.Zero, 20.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, null, 20.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10.0, ParmsId.Zero, 20.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, 20.0, plain_null)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10.0, -20.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, ParmsId.Zero, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, null, 10.0, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(complex, ParmsId.Zero, 10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, 10.0, plain_null)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(complex, -10.0, plain, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, ParmsId.Zero, plain_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, null, plain)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10, ParmsId.Zero, plain)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, plain_null)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain, vald_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain_null, vald)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Decode(plain, vald, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain, valc_null)); + Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain_null, valc)); + Utilities.AssertThrows<ArgumentException>(() => encoder.Decode(plain, valc, pool)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/CiphertextTests.cs b/bigpiseal3.5.1/dotnet/tests/CiphertextTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..ec4fba942502f30ff332fa3481201e53d5e05c0c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/CiphertextTests.cs @@ -0,0 +1,333 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Numerics; + +namespace SEALNetTest +{ + [TestClass] + public class CiphertextTests + { + [TestMethod] + public void CreateTest() + { + Ciphertext cipher = new Ciphertext(); + Assert.IsNotNull(cipher); + Assert.AreEqual(0ul, cipher.Size); + Assert.AreEqual(0ul, cipher.PolyModulusDegree); + Assert.AreEqual(0ul, cipher.CoeffModulusSize); + + Ciphertext copy = new Ciphertext(cipher); + Assert.IsNotNull(copy); + Assert.AreEqual(0ul, copy.Size); + Assert.AreEqual(0ul, copy.PolyModulusDegree); + Assert.AreEqual(0ul, copy.CoeffModulusSize); + } + + [TestMethod] + public void Create2Test() + { + SEALContext context = GlobalContext.BFVContext; + ParmsId parms = context.FirstParmsId; + + Assert.AreNotEqual(0ul, parms.Block[0]); + Assert.AreNotEqual(0ul, parms.Block[1]); + Assert.AreNotEqual(0ul, parms.Block[2]); + Assert.AreNotEqual(0ul, parms.Block[3]); + + Ciphertext cipher = new Ciphertext(context, parms); + + Assert.AreEqual(parms, cipher.ParmsId); + } + + [TestMethod] + public void Create3Test() + { + SEALContext context = GlobalContext.BFVContext; + ParmsId parms = context.FirstParmsId; + + Assert.AreNotEqual(0ul, parms.Block[0]); + Assert.AreNotEqual(0ul, parms.Block[1]); + Assert.AreNotEqual(0ul, parms.Block[2]); + Assert.AreNotEqual(0ul, parms.Block[3]); + + Ciphertext cipher = new Ciphertext(context, parms, sizeCapacity: 5); + + Assert.AreEqual(5ul, cipher.SizeCapacity); + } + + [TestMethod] + public void ResizeTest() + { + SEALContext context = GlobalContext.BFVContext; + ParmsId parms = context.FirstParmsId; + + Ciphertext cipher = new Ciphertext(context, parms); + + Assert.AreEqual(2ul, cipher.SizeCapacity); + + cipher.Reserve(context, parms, sizeCapacity: 10); + Assert.AreEqual(10ul, cipher.SizeCapacity); + + Ciphertext cipher2 = new Ciphertext(); + + Assert.AreEqual(0ul, cipher2.SizeCapacity); + + cipher2.Reserve(context, 5); + Assert.AreEqual(5ul, cipher2.SizeCapacity); + + Ciphertext cipher3 = new Ciphertext(); + + Assert.AreEqual(0ul, cipher3.SizeCapacity); + + cipher3.Reserve(4); + Assert.AreEqual(0ul, cipher3.SizeCapacity); + + Ciphertext cipher4 = new Ciphertext(context); + cipher4.Resize(context, context.GetContextData(context.FirstParmsId).NextContextData.ParmsId, 4); + Assert.AreEqual(10ul, cipher.SizeCapacity); + + Ciphertext cipher5 = new Ciphertext(context); + cipher5.Resize(context, 6ul); + Assert.AreEqual(6ul, cipher5.SizeCapacity); + } + + [TestMethod] + public void ReleaseTest() + { + Ciphertext cipher = new Ciphertext(); + + Assert.AreEqual(0ul, cipher.Size); + cipher.Resize(4); + Assert.AreEqual(4ul, cipher.Size); + cipher.Release(); + Assert.AreEqual(0ul, cipher.Size); + } + + [TestMethod] + public void SaveLoadTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("2x^3 + 4x^2 + 5x^1 + 6"); + Ciphertext cipher = new Ciphertext(); + + encryptor.Encrypt(plain, cipher); + + Assert.AreEqual(2ul, cipher.Size); + Assert.AreEqual(8192ul, cipher.PolyModulusDegree); + Assert.AreEqual(4ul, cipher.CoeffModulusSize); + + Ciphertext loaded = new Ciphertext(); + + Assert.AreEqual(0ul, loaded.Size); + Assert.AreEqual(0ul, loaded.PolyModulusDegree); + Assert.AreEqual(0ul, loaded.CoeffModulusSize); + + using (MemoryStream mem = new MemoryStream()) + { + cipher.Save(mem); + + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + + loaded.Load(context, mem); + } + + Assert.AreEqual(2ul, loaded.Size); + Assert.AreEqual(8192ul, loaded.PolyModulusDegree); + Assert.AreEqual(4ul, loaded.CoeffModulusSize); + Assert.IsTrue(ValCheck.IsValidFor(loaded, context)); + + ulong ulongCount = cipher.Size * cipher.PolyModulusDegree * cipher.CoeffModulusSize; + for (ulong i = 0; i < ulongCount; i++) + { + Assert.AreEqual(cipher[i], loaded[i]); + } + } + + [TestMethod] + public void IndexTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("1"); + Ciphertext cipher = new Ciphertext(); + + encryptor.Encrypt(plain, cipher); + + Assert.AreEqual(2ul, cipher.Size); + Assert.AreNotEqual(0ul, cipher[0, 0]); + Assert.AreNotEqual(0ul, cipher[0, 1]); + Assert.AreNotEqual(0ul, cipher[0, 2]); + Assert.AreNotEqual(0ul, cipher[1, 0]); + Assert.AreNotEqual(0ul, cipher[1, 1]); + Assert.AreNotEqual(0ul, cipher[1, 2]); + } + + [TestMethod] + public void IndexRangeFail1Test() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("1"); + Ciphertext cipher = new Ciphertext(context); + + encryptor.Encrypt(plain, cipher); + + Utilities.AssertThrows<IndexOutOfRangeException>(() => + { + // We only have 2 polynomials + ulong data = cipher[2, 0]; + }); + } + + [TestMethod] + public void IndexRangeFail2Test() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("1"); + Ciphertext cipher = new Ciphertext(); + + encryptor.Encrypt(plain, cipher); + + // We only have 2 polynomials + ulong data = cipher[1, 0]; + + // We should have 8192 coefficients + data = cipher[0, 32767]; // This will succeed + + Utilities.AssertThrows<IndexOutOfRangeException>(() => + { + data = cipher[0, 32768]; // This will fail + }); + } + + [TestMethod] + public void IndexRangeFail3Test() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("1"); + Ciphertext cipher = new Ciphertext(); + + encryptor.Encrypt(plain, cipher); + ulong data = 0; + + Utilities.AssertThrows<IndexOutOfRangeException>(() => data = cipher[65536]); + Utilities.AssertThrows<IndexOutOfRangeException>(() => cipher[65536] = 10ul); + } + + [TestMethod] + public void ScaleTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 8, + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Evaluator evaluator = new Evaluator(context); + CKKSEncoder encoder = new CKKSEncoder(context); + + MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew); + Assert.AreEqual(0ul, pool.AllocByteCount); + + Ciphertext encrypted = new Ciphertext(pool); + Plaintext plain = new Plaintext(); + + MemoryPoolHandle cipherPool = encrypted.Pool; + Assert.IsNotNull(cipherPool); + Assert.AreEqual(0ul, cipherPool.AllocByteCount); + + List<Complex> input = new List<Complex>() + { + new Complex(1, 1), + new Complex(2, 2), + new Complex(3, 3), + new Complex(4, 4) + }; + double delta = Math.Pow(2, 70); + encoder.Encode(input, context.FirstParmsId, delta, plain); + encryptor.Encrypt(plain, encrypted); + + Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60)); + + Ciphertext encrypted2 = new Ciphertext(); + encrypted2.Set(encrypted); + Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60)); + + evaluator.RescaleToNextInplace(encrypted); + + Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000); + Assert.AreNotEqual(0ul, cipherPool.AllocByteCount); + + double newScale = Math.Pow(2, 10); + encrypted.Scale = newScale; + Assert.AreEqual(newScale, encrypted.Scale, delta: 100); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal); + MemoryPoolHandle poolu = new MemoryPoolHandle(); + Ciphertext cipher = new Ciphertext(); + Ciphertext copy = null; + + Utilities.AssertThrows<ArgumentNullException>(() => copy = new Ciphertext((Ciphertext)null)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(context, null, pool)); + Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(null, context.FirstParmsId, pool)); + Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, ParmsId.Zero, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext((SEALContext)null, poolu)); + Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, poolu)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(context, null, 6ul)); + Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(null, context.FirstParmsId, 6ul, poolu)); + Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, ParmsId.Zero, 6ul, poolu)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(context, null, 10ul)); + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(null, ParmsId.Zero, 10ul)); + Utilities.AssertThrows<ArgumentException>(() => cipher.Reserve(context, ParmsId.Zero, 10ul)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(null, 10ul)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(context, null, 10ul)); + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(null, ParmsId.Zero, 10ul)); + Utilities.AssertThrows<ArgumentException>(() => cipher.Resize(context, ParmsId.Zero, 10ul)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(null, 10ul)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Set(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(cipher, null)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.UnsafeLoad(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => cipher.UnsafeLoad(null, new MemoryStream())); + Utilities.AssertThrows<EndOfStreamException>(() => cipher.UnsafeLoad(context, new MemoryStream())); + + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Load(null, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => cipher.Load(context, null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/DecryptorTests.cs b/bigpiseal3.5.1/dotnet/tests/DecryptorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..189e654562359b77d6f85a7d14bffa82aff26b8c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/DecryptorTests.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace SEALNetTest +{ + [TestClass] + public class DecryptorTests + { + SEALContext context_; + KeyGenerator keyGen_; + SecretKey secretKey_; + PublicKey publicKey_; + + [TestInitialize] + public void TestInit() + { + context_ = GlobalContext.BFVContext; + keyGen_ = new KeyGenerator(context_); + secretKey_ = keyGen_.SecretKey; + publicKey_ = keyGen_.PublicKey; + } + + [TestMethod] + public void CreateTest() + { + Decryptor decryptor = new Decryptor(context_, secretKey_); + + Assert.IsNotNull(decryptor); + } + + [TestMethod] + public void DecryptTest() + { + Encryptor encryptor = new Encryptor(context_, publicKey_); + Decryptor decryptor = new Decryptor(context_, secretKey_); + + Plaintext plain = new Plaintext("1x^1 + 2"); + Ciphertext cipher = new Ciphertext(); + + Assert.AreEqual(0ul, cipher.Size); + + encryptor.Encrypt(plain, cipher); + + Assert.AreEqual(2ul, cipher.Size); + + Plaintext decrypted = new Plaintext(); + Assert.AreEqual(0ul, decrypted.CoeffCount); + + decryptor.Decrypt(cipher, decrypted); + + Assert.AreEqual(2ul, decrypted.CoeffCount); + Assert.AreEqual(2ul, decrypted[0]); + Assert.AreEqual(1ul, decrypted[1]); + } + + [TestMethod] + public void InvariantNoiseBudgetTest() + { + Encryptor encryptor = new Encryptor(context_, publicKey_); + Decryptor decryptor = new Decryptor(context_, secretKey_); + + Plaintext plain = new Plaintext("1"); + Ciphertext cipher = new Ciphertext(); + + encryptor.Encrypt(plain, cipher); + + int budget = decryptor.InvariantNoiseBudget(cipher); + Assert.IsTrue(budget > 80); + } + + [TestMethod] + public void ExceptionsTest() + { + Decryptor decryptor = new Decryptor(context_, secretKey_); + SecretKey secret = new SecretKey(); + Ciphertext cipher = new Ciphertext(); + Plaintext plain = new Plaintext(); + + Utilities.AssertThrows<ArgumentNullException>(() => decryptor = new Decryptor(context_, null)); + Utilities.AssertThrows<ArgumentNullException>(() => decryptor = new Decryptor(null, secretKey_)); + Utilities.AssertThrows<ArgumentException>(() => decryptor = new Decryptor(context_, secret)); + + Utilities.AssertThrows<ArgumentNullException>(() => decryptor.Decrypt(cipher, null)); + Utilities.AssertThrows<ArgumentNullException>(() => decryptor.Decrypt(null, plain)); + Utilities.AssertThrows<ArgumentException>(() => decryptor.Decrypt(cipher, plain)); + + Utilities.AssertThrows<ArgumentNullException>(() => decryptor.InvariantNoiseBudget(null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/EncryptionParameterQualifiersTests.cs b/bigpiseal3.5.1/dotnet/tests/EncryptionParameterQualifiersTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..a026da1be43981020093504304e6c815bf7648b1 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/EncryptionParameterQualifiersTests.cs @@ -0,0 +1,85 @@ +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SEALNetTest +{ + [TestClass] + public class EncryptionParameterQualifiersTests + { + [TestMethod] + public void PropertiesTest() + { + SEALContext context = GlobalContext.BFVContext; + + Assert.IsTrue(context.FirstContextData.Qualifiers.ParametersSet); + Assert.IsTrue(context.FirstContextData.Qualifiers.UsingBatching); + Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFastPlainLift); + Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFFT); + Assert.AreEqual(SecLevelType.TC128, context.FirstContextData.Qualifiers.SecLevel); + Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain); + Assert.IsTrue(context.FirstContextData.Qualifiers.UsingNTT); + Assert.IsTrue(context.UsingKeyswitching); + + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 4096, + CoeffModulus = CoeffModulus.BFVDefault(4096) + }; + + SEALContext context2 = new SEALContext(parms); + + Assert.IsTrue(context2.FirstContextData.Qualifiers.ParametersSet); + Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingBatching); + Assert.IsFalse(context2.FirstContextData.Qualifiers.UsingFastPlainLift); + Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingFFT); + Assert.AreEqual(SecLevelType.TC128, context2.FirstContextData.Qualifiers.SecLevel); + Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain); + Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingNTT); + Assert.IsTrue(context.UsingKeyswitching); + + EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(context2.FirstContextData.Qualifiers); + + Assert.IsNotNull(qualifiers); + Assert.IsTrue(qualifiers.ParametersSet); + Assert.IsTrue(qualifiers.UsingBatching); + Assert.IsFalse(qualifiers.UsingFastPlainLift); + Assert.IsTrue(qualifiers.UsingFFT); + Assert.AreEqual(SecLevelType.TC128, qualifiers.SecLevel); + Assert.IsTrue(qualifiers.UsingDescendingModulusChain); + Assert.IsTrue(qualifiers.UsingNTT); + } + + [TestMethod] + public void ParameterErrorTest() + { + SEALContext context = GlobalContext.BFVContext; + EncryptionParameterQualifiers qualifiers = context.FirstContextData.Qualifiers; + + Assert.AreEqual(qualifiers.ParametersErrorName(), "success"); + Assert.AreEqual(qualifiers.ParametersErrorMessage(), "valid"); + + EncryptionParameters encParam = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 127, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 }) + }; + context = new SEALContext(encParam, expandModChain: true, secLevel: SecLevelType.None); + qualifiers = context.FirstContextData.Qualifiers; + Assert.AreEqual(qualifiers.ParametersErrorName(), "invalid_poly_modulus_degree_non_power_of_two"); + Assert.AreEqual(qualifiers.ParametersErrorMessage(), "poly_modulus_degree is not a power of two"); + } + + [TestMethod] + public void ExceptionsTest() + { + EncryptionParameterQualifiers epq1 = GlobalContext.BFVContext.FirstContextData.Qualifiers; + EncryptionParameterQualifiers epq2 = null; + + Utilities.AssertThrows<ArgumentNullException>(() => epq2 = new EncryptionParameterQualifiers(null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/EncryptionParametersTests.cs b/bigpiseal3.5.1/dotnet/tests/EncryptionParametersTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..ee4778a22de6c7995e7b319ee77fdfe5605bf6ab --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/EncryptionParametersTests.cs @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; + +namespace SEALNetTest +{ + public delegate void TestDelegate(SchemeType scheme); + + [TestClass] + public class EncryptionParametersTests + { + [TestMethod] + public void CreateTest() + { + EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV); + + Assert.IsNotNull(encParams); + Assert.AreEqual(SchemeType.BFV, encParams.Scheme); + + EncryptionParameters encParams2 = new EncryptionParameters(SchemeType.CKKS); + + Assert.IsNotNull(encParams2); + Assert.AreEqual(SchemeType.CKKS, encParams2.Scheme); + + EncryptionParameters encParams3 = new EncryptionParameters(SchemeType.CKKS); + + Assert.IsNotNull(encParams3); + Assert.AreEqual(SchemeType.CKKS, encParams3.Scheme); + + EncryptionParameters copy = new EncryptionParameters(encParams); + + Assert.AreEqual(SchemeType.BFV, copy.Scheme); + Assert.AreEqual(encParams, copy); + Assert.AreEqual(encParams.GetHashCode(), copy.GetHashCode()); + + EncryptionParameters third = new EncryptionParameters(SchemeType.CKKS); + third.Set(copy); + + Assert.AreEqual(SchemeType.BFV, third.Scheme); + Assert.AreEqual(encParams, third); + Assert.AreEqual(encParams.GetHashCode(), third.GetHashCode()); + } + + [TestMethod] + public void SetPlainModulusCKKSTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); + + Utilities.AssertThrows<InvalidOperationException>(() => + { + parms.PlainModulus = new Modulus(8192); + }); + + Utilities.AssertThrows<InvalidOperationException>(() => + { + parms.SetPlainModulus(8192); + }); + } + + [TestMethod] + public void CoeffModulusTest() + { + EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV); + + Assert.IsNotNull(encParams); + + List<Modulus> coeffs = new List<Modulus>(encParams.CoeffModulus); + Assert.IsNotNull(coeffs); + Assert.AreEqual(0, coeffs.Count); + + encParams.CoeffModulus = CoeffModulus.BFVDefault(4096); + + List<Modulus> newCoeffs = new List<Modulus>(encParams.CoeffModulus); + Assert.IsNotNull(newCoeffs); + Assert.AreEqual(3, newCoeffs.Count); + Assert.AreEqual(0xffffee001ul, newCoeffs[0].Value); + Assert.AreEqual(0xffffc4001ul, newCoeffs[1].Value); + Assert.AreEqual(0x1ffffe0001ul, newCoeffs[2].Value); + } + + [TestMethod] + public void SaveLoadTest() + { + TestDelegate save_load_test = delegate(SchemeType scheme) + { + List<Modulus> coeffModulus = (List<Modulus>)CoeffModulus.Create(8, new int[] { 40, 40 }); + EncryptionParameters parms = new EncryptionParameters(scheme) + { + PolyModulusDegree = 8, + CoeffModulus = coeffModulus + }; + if (scheme == SchemeType.BFV) + parms.SetPlainModulus(257); + + EncryptionParameters loaded = new EncryptionParameters(); + + using (MemoryStream stream = new MemoryStream()) + { + parms.Save(stream); + stream.Seek(offset: 0, loc: SeekOrigin.Begin); + loaded.Load(stream); + } + + Assert.AreEqual(scheme, loaded.Scheme); + Assert.AreEqual(8ul, loaded.PolyModulusDegree); + if (scheme == SchemeType.BFV) + Assert.AreEqual(257ul, loaded.PlainModulus.Value); + else if (scheme == SchemeType.CKKS) + Assert.AreEqual(0ul, loaded.PlainModulus.Value); + + List<Modulus> loadedCoeffModulus = new List<Modulus>(loaded.CoeffModulus); + Assert.AreEqual(2, loadedCoeffModulus.Count); + Assert.AreNotSame(coeffModulus[0], loadedCoeffModulus[0]); + Assert.AreNotSame(coeffModulus[1], loadedCoeffModulus[1]); + Assert.AreEqual(coeffModulus[0], loadedCoeffModulus[0]); + Assert.AreEqual(coeffModulus[1], loadedCoeffModulus[1]); + }; + save_load_test(SchemeType.BFV); + save_load_test(SchemeType.CKKS); + } + + [TestMethod] + public void EqualsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 8, + PlainModulus = new Modulus(257), + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) + }; + + EncryptionParameters parms2 = new EncryptionParameters(SchemeType.CKKS); + + Assert.AreNotEqual(parms, parms2); + Assert.IsFalse(parms.Equals(null)); + } + + [TestMethod] + public void ExceptionsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); + Utilities.AssertThrows<ArgumentNullException>(() => parms = new EncryptionParameters(null)); + Utilities.AssertThrows<ArgumentNullException>(() => parms.Set(null)); + Utilities.AssertThrows<ArgumentNullException>(() => parms.CoeffModulus = null); + Utilities.AssertThrows<ArgumentNullException>(() => parms.Save(null)); + Utilities.AssertThrows<ArgumentNullException>(() => parms.Load(null)); + Utilities.AssertThrows<EndOfStreamException>(() => parms.Load(new MemoryStream())); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/EncryptorTests.cs b/bigpiseal3.5.1/dotnet/tests/EncryptorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..0938f2851f6d3873f4dedf3b78b65d5d00daa7b4 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/EncryptorTests.cs @@ -0,0 +1,301 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Numerics; + +namespace SEALNetTest +{ + [TestClass] + public class EncryptorTests + { + [TestMethod] + public void EncryptTest() + { + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keyGen = new KeyGenerator(context); + PublicKey publicKey = keyGen.PublicKey; + SecretKey secretKey = keyGen.SecretKey; + Encryptor encryptor = new Encryptor(context, publicKey, secretKey); + + Assert.IsNotNull(encryptor); + + Plaintext plain = new Plaintext("1x^1 + 1"); + + Ciphertext cipher = new Ciphertext(); + Assert.AreEqual(0ul, cipher.Size); + encryptor.Encrypt(plain, cipher); + Assert.IsNotNull(cipher); + Assert.AreEqual(2ul, cipher.Size); + } + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keyGen = new KeyGenerator(context); + SecretKey secretKey = keyGen.SecretKey; + Encryptor encryptor = new Encryptor(context, secretKey); + + Assert.IsNotNull(encryptor); + + Plaintext plain = new Plaintext("1x^1 + 1"); + + Ciphertext cipher = new Ciphertext(); + Assert.AreEqual(0ul, cipher.Size); + encryptor.EncryptSymmetric(plain, cipher); + Assert.IsNotNull(cipher); + Assert.AreEqual(2ul, cipher.Size); + } + } + + [TestMethod] + public void EncryptZeroTest() + { + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keyGen = new KeyGenerator(context); + PublicKey publicKey = keyGen.PublicKey; + SecretKey secretKey = keyGen.SecretKey; + Decryptor decryptor = new Decryptor(context, secretKey); + + Assert.IsNotNull(decryptor); + + Ciphertext cipher = new Ciphertext(); + Plaintext plain = new Plaintext(); + ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId; + + { + Encryptor encryptor = new Encryptor(context, publicKey); + Assert.IsNotNull(encryptor); + + encryptor.EncryptZero(cipher); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + + encryptor.EncryptZero(nextParms, cipher); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + } + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric(cipher); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + + encryptor.EncryptZeroSymmetric(nextParms, cipher); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + } + using (MemoryStream stream = new MemoryStream()) + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric().Save(stream); + stream.Seek(0, SeekOrigin.Begin); + cipher.Load(context, stream); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + } + using (MemoryStream stream = new MemoryStream()) + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric(nextParms).Save(stream); + stream.Seek(0, SeekOrigin.Begin); + cipher.Load(context, stream); + Assert.IsFalse(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.IsTrue(plain.IsZero); + } + } + { + SEALContext context = GlobalContext.CKKSContext; + KeyGenerator keyGen = new KeyGenerator(context); + PublicKey publicKey = keyGen.PublicKey; + SecretKey secretKey = keyGen.SecretKey; + Decryptor decryptor = new Decryptor(context, secretKey); + CKKSEncoder encoder = new CKKSEncoder(context); + + Assert.IsNotNull(decryptor); + + Ciphertext cipher = new Ciphertext(); + Plaintext plain = new Plaintext(); + ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId; + List<Complex> res = new List<Complex>(); + + { + Encryptor encryptor = new Encryptor(context, publicKey); + Assert.IsNotNull(encryptor); + + encryptor.EncryptZero(cipher); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + decryptor.Decrypt(cipher, plain); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + + encryptor.EncryptZero(nextParms, cipher); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.AreEqual(plain.ParmsId, nextParms); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + } + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric(cipher); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + decryptor.Decrypt(cipher, plain); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + + encryptor.EncryptZeroSymmetric(nextParms, cipher); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.AreEqual(plain.ParmsId, nextParms); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + } + using (MemoryStream stream = new MemoryStream()) + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric().Save(stream); + stream.Seek(0, SeekOrigin.Begin); + cipher.Load(context, stream); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + decryptor.Decrypt(cipher, plain); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + } + using (MemoryStream stream = new MemoryStream()) + { + Encryptor encryptor = new Encryptor(context, secretKey); + + encryptor.EncryptZeroSymmetric(nextParms).Save(stream); + stream.Seek(0, SeekOrigin.Begin); + cipher.Load(context, stream); + Assert.IsTrue(cipher.IsNTTForm); + Assert.IsFalse(cipher.IsTransparent); + Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); + cipher.Scale = Math.Pow(2.0, 30); + Assert.AreEqual(cipher.ParmsId, nextParms); + decryptor.Decrypt(cipher, plain); + Assert.AreEqual(plain.ParmsId, nextParms); + + encoder.Decode(plain, res); + foreach (Complex val in res) + { + Assert.AreEqual(val.Real, 0.0, 0.01); + Assert.AreEqual(val.Imaginary, 0.0, 0.01); + } + } + } + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + PublicKey pubKey = keygen.PublicKey; + PublicKey pubKey_invalid = new PublicKey(); + SecretKey secKey = keygen.SecretKey; + SecretKey secKey_invalid = new SecretKey(); + Encryptor encryptor = new Encryptor(context, pubKey); + Plaintext plain = new Plaintext(); + Ciphertext cipher = new Ciphertext(); + MemoryPoolHandle pool_invalid = new MemoryPoolHandle(); + ParmsId parmsId_invalid = new ParmsId(); + + Utilities.AssertThrows<ArgumentNullException>(() => encryptor = new Encryptor(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => encryptor = new Encryptor(null, pubKey)); + Utilities.AssertThrows<ArgumentException>(() => encryptor = new Encryptor(context, pubKey_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor = new Encryptor(context, pubKey_invalid, secKey)); + encryptor = new Encryptor(context, pubKey, secKey); + Utilities.AssertThrows<ArgumentException>(() => encryptor.SetPublicKey(pubKey_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.SetSecretKey(secKey_invalid)); + + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.Encrypt(plain, null)); + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.Encrypt(null, cipher)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.Encrypt(plain, cipher, pool_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZero(cipher, pool_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZero(parmsId_invalid, cipher)); + + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(plain, destination: null)); + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(null, cipher)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptSymmetric(plain, cipher, pool_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZeroSymmetric(cipher, pool_invalid)); + Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZeroSymmetric(parmsId_invalid, cipher)); + + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(plain).Save(null)); + Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptZeroSymmetric().Save(null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/EvaluatorTests.cs b/bigpiseal3.5.1/dotnet/tests/EvaluatorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..34843c86e9e0fcf32a95458b1a43b2806202a531 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/EvaluatorTests.cs @@ -0,0 +1,1411 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace SEALNetTest +{ + [TestClass] + public class EvaluatorTests + { + [TestMethod] + public void CreateTest() + { + Evaluator evaluator = new Evaluator(GlobalContext.BFVContext); + Assert.IsNotNull(evaluator); + } + + [TestMethod] + public void NegateTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Assert.IsTrue(context.ParametersSet); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdestination = new Ciphertext(); + Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1"); + Plaintext plaindest = new Plaintext(); + encryptor.Encrypt(plain, encrypted); + evaluator.Negate(encrypted, encdestination); + decryptor.Decrypt(encdestination, plaindest); + + // coefficients are negated (modulo 64) + Assert.AreEqual(0x3Ful, plaindest[0]); + Assert.AreEqual(0x3Eul, plaindest[1]); + Assert.AreEqual(0x3Dul, plaindest[2]); + + plain = new Plaintext("6x^3 + 7x^2 + 8x^1 + 9"); + encryptor.Encrypt(plain, encrypted); + evaluator.NegateInplace(encrypted); + decryptor.Decrypt(encrypted, plain); + + // coefficients are negated (modulo 64) + Assert.AreEqual(0x37ul, plain[0]); + Assert.AreEqual(0x38ul, plain[1]); + Assert.AreEqual(0x39ul, plain[2]); + Assert.AreEqual(0x3Aul, plain[3]); + } + + [TestMethod] + public void AddTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted1 = new Ciphertext(); + Ciphertext encrypted2 = new Ciphertext(); + Ciphertext encdestination = new Ciphertext(); + + Plaintext plain1 = new Plaintext("5x^4 + 4x^3 + 3x^2 + 2x^1 + 1"); + Plaintext plain2 = new Plaintext("4x^7 + 5x^6 + 6x^5 + 7x^4 + 8x^3 + 9x^2 + Ax^1 + B"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + evaluator.Add(encrypted1, encrypted2, encdestination); + decryptor.Decrypt(encdestination, plaindest); + + Assert.AreEqual(12ul, plaindest[0]); + Assert.AreEqual(12ul, plaindest[1]); + Assert.AreEqual(12ul, plaindest[2]); + Assert.AreEqual(12ul, plaindest[3]); + Assert.AreEqual(12ul, plaindest[4]); + Assert.AreEqual(6ul, plaindest[5]); + Assert.AreEqual(5ul, plaindest[6]); + Assert.AreEqual(4ul, plaindest[7]); + + plain1 = new Plaintext("1x^2 + 2x^1 + 3"); + plain2 = new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"); + + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + evaluator.AddInplace(encrypted1, encrypted2); + decryptor.Decrypt(encrypted1, plaindest); + + Assert.AreEqual(5ul, plaindest[0]); + Assert.AreEqual(4ul, plaindest[1]); + Assert.AreEqual(3ul, plaindest[2]); + Assert.AreEqual(2ul, plaindest[3]); + } + + [TestMethod] + public void AddPlainTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("2x^2 + 2x^1 + 2"), encrypted); + evaluator.AddPlain(encrypted, plain, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.AreEqual(3ul, plaindest[0]); + Assert.AreEqual(4ul, plaindest[1]); + Assert.AreEqual(5ul, plaindest[2]); + + plain.Set("1x^2 + 1x^1 + 1"); + encryptor.Encrypt(new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"), encrypted); + evaluator.AddPlainInplace(encrypted, plain); + decryptor.Decrypt(encrypted, plaindest); + + Assert.AreEqual(4ul, plaindest.CoeffCount); + Assert.AreEqual(3ul, plaindest[0]); + Assert.AreEqual(3ul, plaindest[1]); + Assert.AreEqual(3ul, plaindest[2]); + Assert.AreEqual(2ul, plaindest[3]); + } + + [TestMethod] + public void AddManyTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext[] encrypteds = new Ciphertext[6]; + + for(int i = 0; i < encrypteds.Length; i++) + { + encrypteds[i] = new Ciphertext(); + encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]); + } + + Ciphertext encdest = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + evaluator.AddMany(encrypteds, encdest); + decryptor.Decrypt(encdest, plaindest); + + // 1+2+3+4+5+6 + Assert.AreEqual(21ul, plaindest[0]); + } + + [TestMethod] + public void SubTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted1 = new Ciphertext(); + Ciphertext encrypted2 = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain1 = new Plaintext("Ax^2 + Bx^1 + C"); + Plaintext plain2 = new Plaintext("5x^3 + 5x^2 + 5x^1 + 5"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + evaluator.Sub(encrypted1, encrypted2, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.AreEqual(7ul, plaindest[0]); + Assert.AreEqual(6ul, plaindest[1]); + Assert.AreEqual(5ul, plaindest[2]); + Assert.AreEqual(0x3Bul, plaindest[3]); + + plain1.Set("Ax^3 + Bx^2 + Cx^1 + D"); + plain2.Set("5x^2 + 5x^1 + 5"); + + encryptor.Encrypt(plain1, encrypted1); + encryptor.Encrypt(plain2, encrypted2); + evaluator.SubInplace(encrypted1, encrypted2); + decryptor.Decrypt(encrypted1, plaindest); + + Assert.AreEqual(8ul, plaindest[0]); + Assert.AreEqual(7ul, plaindest[1]); + Assert.AreEqual(6ul, plaindest[2]); + Assert.AreEqual(10ul, plaindest[3]); + } + + [TestMethod] + public void SubPlainTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext("5x^2 + 4x^1 + 3"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("3x^1 + 4"), encrypted); + evaluator.SubPlain(encrypted, plain, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.AreEqual(3ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + Assert.AreEqual(0x3Ful, plaindest[1]); // -1 + Assert.AreEqual(0x3Bul, plaindest[2]); // -5 + + plain.Set("6x^3 + 1x^2 + 7x^1 + 2"); + encryptor.Encrypt(new Plaintext("Ax^2 + Bx^1 + C"), encrypted); + evaluator.SubPlainInplace(encrypted, plain); + decryptor.Decrypt(encrypted, plaindest); + + Assert.AreEqual(4ul, plaindest.CoeffCount); + Assert.AreEqual(10ul, plaindest[0]); + Assert.AreEqual(4ul, plaindest[1]); + Assert.AreEqual(9ul, plaindest[2]); + Assert.AreEqual(0x3Aul, plaindest[3]); // -6 + } + + [TestMethod] + public void MultiplyTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted1 = new Ciphertext(); + Ciphertext encrypted2 = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"), encrypted1); + encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted2); + evaluator.Multiply(encrypted1, encrypted2, encdest); + decryptor.Decrypt(encdest, plaindest); + + // {3x^6 + 8x^5 + Ex^4 + 14x^3 + 1Ax^2 + Ex^1 + 5} + Assert.AreEqual(7ul, plaindest.CoeffCount); + Assert.AreEqual(5ul, plaindest[0]); + Assert.AreEqual(14ul, plaindest[1]); + Assert.AreEqual(26ul, plaindest[2]); + Assert.AreEqual(20ul, plaindest[3]); + Assert.AreEqual(14ul, plaindest[4]); + Assert.AreEqual(8ul, plaindest[5]); + Assert.AreEqual(3ul, plaindest[6]); + + encryptor.Encrypt(new Plaintext("2x^2 + 3x^1 + 4"), encrypted1); + encryptor.Encrypt(new Plaintext("4x^1 + 5"), encrypted2); + evaluator.MultiplyInplace(encrypted1, encrypted2); + decryptor.Decrypt(encrypted1, plaindest); + + // {8x^3 + 16x^2 + 1Fx^1 + 14} + Assert.AreEqual(4ul, plaindest.CoeffCount); + Assert.AreEqual(20ul, plaindest[0]); + Assert.AreEqual(31ul, plaindest[1]); + Assert.AreEqual(22ul, plaindest[2]); + Assert.AreEqual(8ul, plaindest[3]); + } + + [TestMethod] + public void MultiplyManyTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Ciphertext[] encrypteds = new Ciphertext[4]; + Ciphertext encdest = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + + for (int i = 0; i < encrypteds.Length; i++) + { + encrypteds[i] = new Ciphertext(); + encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]); + } + + evaluator.MultiplyMany(encrypteds, relinKeys, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(24ul, plaindest[0]); + + Utilities.AssertThrows<ArgumentException>(() => + { + // Uninitialized memory pool handle + MemoryPoolHandle pool = new MemoryPoolHandle(); + evaluator.MultiplyMany(encrypteds, relinKeys, encdest, pool); + }); + } + + [TestMethod] + public void MultiplyPlainTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext("2x^2 + 1"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("3x^2 + 2"), encrypted); + evaluator.MultiplyPlain(encrypted, plain, encdest); + decryptor.Decrypt(encdest, plaindest); + + // {6x^4 + 7x^2 + 2} + Assert.AreEqual(5ul, plaindest.CoeffCount); + Assert.AreEqual(2ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(7ul, plaindest[2]); + Assert.AreEqual(0ul, plaindest[3]); + Assert.AreEqual(6ul, plaindest[4]); + + encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted); + plain.Set("2x^2 + 1"); + evaluator.MultiplyPlainInplace(encrypted, plain); + decryptor.Decrypt(encrypted, plaindest); + + // {8x^3 + 6x^2 + 4x^1 + 3} + Assert.AreEqual(4ul, plaindest.CoeffCount); + Assert.AreEqual(3ul, plaindest[0]); + Assert.AreEqual(4ul, plaindest[1]); + Assert.AreEqual(6ul, plaindest[2]); + Assert.AreEqual(8ul, plaindest[3]); + + encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted); + plain.Set("3x^5"); + evaluator.MultiplyPlainInplace(encrypted, plain); + decryptor.Decrypt(encrypted, plaindest); + + // {Cx^6 + 9x^5} + Assert.AreEqual(7ul, plaindest.CoeffCount); + Assert.AreEqual(2ul, plaindest.NonZeroCoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(0ul, plaindest[2]); + Assert.AreEqual(0ul, plaindest[3]); + Assert.AreEqual(0ul, plaindest[4]); + Assert.AreEqual(9ul, plaindest[5]); + Assert.AreEqual(12ul, plaindest[6]); + + Utilities.AssertThrows<ArgumentException>(() => + { + // Uninitialized pool + MemoryPoolHandle pool = new MemoryPoolHandle(); + evaluator.MultiplyPlain(encrypted, plain, encdest, pool); + }); + } + + [TestMethod] + public void SquareTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext("2x^2 + 3x^1 + 4"); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(plain, encrypted); + evaluator.Square(encrypted, encdest); + decryptor.Decrypt(encdest, plaindest); + + // {4x^4 + Cx^3 + 19x^2 + 18x^1 + 10} + Assert.AreEqual(5ul, plaindest.CoeffCount); + Assert.AreEqual(16ul, plaindest[0]); + Assert.AreEqual(24ul, plaindest[1]); + Assert.AreEqual(25ul, plaindest[2]); + Assert.AreEqual(12ul, plaindest[3]); + Assert.AreEqual(4ul, plaindest[4]); + + encryptor.Encrypt(new Plaintext("3x^1 + 2"), encrypted); + evaluator.SquareInplace(encrypted); + decryptor.Decrypt(encrypted, plaindest); + + // {9x^2 + Cx^1 + 4} + Assert.AreEqual(3ul, plaindest.CoeffCount); + Assert.AreEqual(4ul, plaindest[0]); + Assert.AreEqual(12ul, plaindest[1]); + Assert.AreEqual(9ul, plaindest[2]); + } + + [TestMethod] + public void ExponentiateTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext(); + + encryptor.Encrypt(new Plaintext("2x^2 + 1"), encrypted); + evaluator.Exponentiate(encrypted, 3, relinKeys, encdest); + decryptor.Decrypt(encdest, plain); + + // {8x^6 + Cx^4 + 6x^2 + 1} + Assert.AreEqual(7ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(0ul, plain[1]); + Assert.AreEqual(6ul, plain[2]); + Assert.AreEqual(0ul, plain[3]); + Assert.AreEqual(12ul, plain[4]); + Assert.AreEqual(0ul, plain[5]); + Assert.AreEqual(8ul, plain[6]); + + encryptor.Encrypt(new Plaintext("3x^3 + 2"), encrypted); + evaluator.ExponentiateInplace(encrypted, 4, relinKeys); + decryptor.Decrypt(encrypted, plain); + + // {11x^12 + 18x^9 + 18x^6 + 20x^3 + 10} + Assert.AreEqual(13ul, plain.CoeffCount); + Assert.AreEqual(16ul, plain[0]); + Assert.AreEqual(0ul, plain[1]); + Assert.AreEqual(0ul, plain[2]); + Assert.AreEqual(32ul, plain[3]); + Assert.AreEqual(0ul, plain[4]); + Assert.AreEqual(0ul, plain[5]); + Assert.AreEqual(24ul, plain[6]); + Assert.AreEqual(0ul, plain[7]); + Assert.AreEqual(0ul, plain[8]); + Assert.AreEqual(24ul, plain[9]); + Assert.AreEqual(0ul, plain[10]); + Assert.AreEqual(0ul, plain[11]); + Assert.AreEqual(17ul, plain[12]); + } + + [TestMethod] + public void ApplyGaloisTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 8, + PlainModulus = new Modulus(257), + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(galoisElts: new uint[] { 1u, 3u, 5u, 15u }); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Plaintext plain = new Plaintext("1"); + Plaintext plaindest = new Plaintext(); + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + + encryptor.Encrypt(plain, encrypted); + evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + + plain.Set("1x^1"); + encryptor.Encrypt(plain, encrypted); + evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest); + decryptor.Decrypt(encdest, plaindest); + + // {1x^1} + Assert.AreEqual(2ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(1ul, plaindest[1]); + + evaluator.ApplyGalois(encdest, galoisElt: 3, galoisKeys: galoisKeys, destination: encrypted); + decryptor.Decrypt(encrypted, plaindest); + + // {1x^3} + Assert.AreEqual(4ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(0ul, plaindest[2]); + Assert.AreEqual(1ul, plaindest[3]); + + evaluator.ApplyGalois(encrypted, galoisElt: 5, galoisKeys: galoisKeys, destination: encdest); + decryptor.Decrypt(encdest, plaindest); + + // {100x^7} + Assert.AreEqual(8ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(0ul, plaindest[2]); + Assert.AreEqual(0ul, plaindest[3]); + Assert.AreEqual(0ul, plaindest[4]); + Assert.AreEqual(0ul, plaindest[5]); + Assert.AreEqual(0ul, plaindest[6]); + Assert.AreEqual(256ul, plaindest[7]); + + plain.Set("1x^2"); + encryptor.Encrypt(plain, encrypted); + evaluator.ApplyGaloisInplace(encrypted, 1, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + + // {1x^2} + Assert.AreEqual(3ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(1ul, plaindest[2]); + + evaluator.ApplyGaloisInplace(encrypted, 3, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + + // {1x^6} + Assert.AreEqual(7ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(0ul, plaindest[2]); + Assert.AreEqual(0ul, plaindest[3]); + Assert.AreEqual(0ul, plaindest[4]); + Assert.AreEqual(0ul, plaindest[5]); + Assert.AreEqual(1ul, plaindest[6]); + + evaluator.ApplyGaloisInplace(encrypted, 5, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + + // {100x^6} + Assert.AreEqual(7ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(0ul, plaindest[1]); + Assert.AreEqual(0ul, plaindest[2]); + Assert.AreEqual(0ul, plaindest[3]); + Assert.AreEqual(0ul, plaindest[4]); + Assert.AreEqual(0ul, plaindest[5]); + Assert.AreEqual(256ul, plaindest[6]); + } + + [TestMethod] + public void TransformPlainToNTTTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + Evaluator evaluator = new Evaluator(context); + + Plaintext plain = new Plaintext("0"); + Plaintext plaindest = new Plaintext(); + Assert.IsFalse(plain.IsNTTForm); + + evaluator.TransformToNTT(plain, context.FirstParmsId, plaindest); + Assert.IsTrue(plaindest.IsZero); + Assert.IsTrue(plaindest.IsNTTForm); + Assert.IsTrue(plaindest.ParmsId == context.FirstParmsId); + + plain = new Plaintext("1"); + Assert.IsFalse(plain.IsNTTForm); + + evaluator.TransformToNTTInplace(plain, context.FirstParmsId); + Assert.IsTrue(plain.IsNTTForm); + + for (ulong i = 0; i < 256; i++) + { + Assert.AreEqual(1ul, plain[i]); + } + } + + [TestMethod] + public void TransformEncryptedToNTTTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Ciphertext encdest2 = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("0"), encrypted); + Assert.IsFalse(encrypted.IsNTTForm); + + evaluator.TransformToNTT(encrypted, encdest); + Assert.IsTrue(encdest.IsNTTForm); + + evaluator.TransformFromNTT(encdest, encdest2); + Assert.IsFalse(encdest2.IsNTTForm); + + decryptor.Decrypt(encdest2, plaindest); + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(0ul, plaindest[0]); + Assert.AreEqual(context.FirstParmsId, encdest2.ParmsId); + + encryptor.Encrypt(new Plaintext("1"), encrypted); + Assert.IsFalse(encrypted.IsNTTForm); + + evaluator.TransformToNTTInplace(encrypted); + Assert.IsTrue(encrypted.IsNTTForm); + + evaluator.TransformFromNTTInplace(encrypted); + Assert.IsFalse(encrypted.IsNTTForm); + + decryptor.Decrypt(encrypted, plaindest); + + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + Assert.AreEqual(context.FirstParmsId, encrypted.ParmsId); + } + + [TestMethod] + public void ModSwitchToNextTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(context); + Ciphertext encdest = new Ciphertext(); + Plaintext plain = new Plaintext(); + + plain.Set("0"); + encryptor.Encrypt(plain, encrypted); + evaluator.ModSwitchToNext(encrypted, encdest); + decryptor.Decrypt(encdest, plain); + + Assert.AreEqual(1ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain[0]); + + plain.Set("1"); + encryptor.Encrypt(plain, encrypted); + evaluator.ModSwitchToNextInplace(encrypted); + decryptor.Decrypt(encrypted, plain); + + Assert.AreEqual(1ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + } + + [TestMethod] + public void ModSwitchToTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30, 30 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted = new Ciphertext(context); + Ciphertext encdest = new Ciphertext(context); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(new Plaintext("1"), encrypted); + ParmsId destParmsId = context.FirstContextData.NextContextData + .NextContextData.ParmsId; + + evaluator.ModSwitchTo(encrypted, context.FirstParmsId, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); + Assert.IsTrue(encdest.ParmsId == context.FirstParmsId); + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + + evaluator.ModSwitchTo(encrypted, destParmsId, encdest); + decryptor.Decrypt(encdest, plaindest); + + Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); + Assert.IsTrue(encdest.ParmsId == destParmsId); + Assert.AreEqual(1ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + + encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted); + evaluator.ModSwitchToInplace(encrypted, context.FirstParmsId); + decryptor.Decrypt(encrypted, plaindest); + + Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); + Assert.AreEqual(3ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + Assert.AreEqual(2ul, plaindest[1]); + Assert.AreEqual(3ul, plaindest[2]); + + evaluator.ModSwitchToInplace(encrypted, destParmsId); + decryptor.Decrypt(encrypted, plaindest); + + Assert.IsTrue(encrypted.ParmsId == destParmsId); + Assert.AreEqual(3ul, plaindest.CoeffCount); + Assert.AreEqual(1ul, plaindest[0]); + Assert.AreEqual(2ul, plaindest[1]); + Assert.AreEqual(3ul, plaindest[2]); + } + + [TestMethod] + public void ModSwitchToPlainTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 1024, + CoeffModulus = CoeffModulus.Create(1024, new int[] { 40, 40, 40, 40, 40 }) + }; + + SEALContext context = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + CKKSEncoder encoder = new CKKSEncoder(context); + KeyGenerator keygen = new KeyGenerator(context); + SecretKey secretKey = keygen.SecretKey; + PublicKey publicKey = keygen.PublicKey; + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Encryptor encryptor = new Encryptor(context, publicKey); + Evaluator evaluator = new Evaluator(context); + Decryptor decryptor = new Decryptor(context, secretKey); + + double scale = parms.CoeffModulus.Last().Value; + Plaintext coeff1 = new Plaintext(); + Plaintext coeff2 = new Plaintext(); + Plaintext coeff3 = new Plaintext(); + encoder.Encode(2.0, scale, coeff1); + encoder.Encode(3.0, scale, coeff2); + encoder.Encode(1.0, scale, coeff3); + + Ciphertext encX1 = new Ciphertext(); + Ciphertext encX2 = new Ciphertext(); + Ciphertext encX3 = new Ciphertext(); + encryptor.Encrypt(coeff1, encX1); + evaluator.Square(encX1, encX3); + evaluator.MultiplyPlain(encX1, coeff2, encX2); + evaluator.RelinearizeInplace(encX3, relinKeys); + evaluator.RescaleToNextInplace(encX3); + evaluator.RelinearizeInplace(encX2, relinKeys); + evaluator.RescaleToInplace(encX2, encX3.ParmsId); + + evaluator.ModSwitchToInplace(coeff3, encX3.ParmsId); + evaluator.ModSwitchToNextInplace(coeff2); + + evaluator.MultiplyPlainInplace(encX3, coeff3); + + Plaintext result = new Plaintext(); + decryptor.Decrypt(encX3, result); + Assert.IsNotNull(result); + + List<double> destination = new List<double>(); + encoder.Decode(result, destination); + + Assert.IsNotNull(destination); + foreach(double val in destination) + { + Assert.AreEqual(4.0, val, delta: 0.001); + } + + encoder.Decode(coeff2, destination); + + foreach(double val in destination) + { + Assert.AreEqual(3.0, val, delta: 0.001); + } + + decryptor.Decrypt(encX2, result); + encoder.Decode(result, destination); + + foreach (double val in destination) + { + Assert.AreEqual(6.0, val, delta: 0.001); + } + } + + [TestMethod] + public void RotateMatrixTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 8, + PlainModulus = new Modulus(257), + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + BatchEncoder encoder = new BatchEncoder(context); + + Plaintext plain = new Plaintext(); + List<ulong> vec = new List<ulong> + { + 1, 2, 3, 4, + 5, 6, 7, 8 + }; + + encoder.Encode(vec, plain); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(plain, encrypted); + evaluator.RotateColumns(encrypted, galoisKeys, encdest); + decryptor.Decrypt(encdest, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 5, 6, 7, 8, + 1, 2, 3, 4 + })); + + evaluator.RotateRows(encdest, -1, galoisKeys, encrypted); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 8, 5, 6, 7, + 4, 1, 2, 3 + })); + + evaluator.RotateRowsInplace(encrypted, 2, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 6, 7, 8, 5, + 2, 3, 4, 1 + })); + + evaluator.RotateColumnsInplace(encrypted, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 2, 3, 4, 1, + 6, 7, 8, 5 + })); + } + + [TestMethod] + public void RelinearizeTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted1 = new Ciphertext(context); + Ciphertext encrypted2 = new Ciphertext(context); + Plaintext plain1 = new Plaintext(); + Plaintext plain2 = new Plaintext(); + + plain1.Set(0); + encryptor.Encrypt(plain1, encrypted1); + evaluator.SquareInplace(encrypted1); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + decryptor.Decrypt(encrypted1, plain2); + + Assert.AreEqual(1ul, plain2.CoeffCount); + Assert.AreEqual(0ul, plain2[0]); + + plain1.Set("1x^10 + 2"); + encryptor.Encrypt(plain1, encrypted1); + evaluator.SquareInplace(encrypted1); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + evaluator.SquareInplace(encrypted1); + evaluator.Relinearize(encrypted1, relinKeys, encrypted2); + decryptor.Decrypt(encrypted2, plain2); + + // {1x^40 + 8x^30 + 18x^20 + 20x^10 + 10} + Assert.AreEqual(41ul, plain2.CoeffCount); + Assert.AreEqual(16ul, plain2[0]); + Assert.AreEqual(32ul, plain2[10]); + Assert.AreEqual(24ul, plain2[20]); + Assert.AreEqual(8ul, plain2[30]); + Assert.AreEqual(1ul, plain2[40]); + } + + [TestMethod] + public void RotateVectorTest() + { + int slotSize = 4; + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 2 * (ulong)slotSize, + CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + CKKSEncoder encoder = new CKKSEncoder(context); + + const double delta = 1ul << 30; + + Ciphertext encrypted = new Ciphertext(); + Plaintext plain = new Plaintext(); + + List<Complex> input = new List<Complex> + { + new Complex(1, 1), + new Complex(2, 2), + new Complex(3, 3), + new Complex(4, 4) + }; + + List<Complex> output = new List<Complex>(); + + encoder.Encode(input, context.FirstParmsId, delta, plain); + + int shift = 1; + encryptor.Encrypt(plain, encrypted); + evaluator.RotateVectorInplace(encrypted, shift, galoisKeys); + decryptor.Decrypt(encrypted, plain); + encoder.Decode(plain, output); + + for (int i = 0; i < slotSize; i++) + { + Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1); + Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1); + } + + encoder.Encode(input, context.FirstParmsId, delta, plain); + shift = 3; + encryptor.Encrypt(plain, encrypted); + evaluator.RotateVectorInplace(encrypted, shift, galoisKeys); + decryptor.Decrypt(encrypted, plain); + encoder.Decode(plain, output); + + for (int i = 0; i < slotSize; i++) + { + Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1); + Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1); + } + } + + [TestMethod] + public void ComplexConjugateTest() + { + int slotSize = 4; + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 2 * (ulong)slotSize, + CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + CKKSEncoder encoder = new CKKSEncoder(context); + + const double delta = 1ul << 30; + + Ciphertext encrypted = new Ciphertext(); + Plaintext plain = new Plaintext(); + + List<Complex> input = new List<Complex> + { + new Complex(1, 1), + new Complex(2, 2), + new Complex(3, 3), + new Complex(4, 4) + }; + + List<Complex> output = new List<Complex>(); + + encoder.Encode(input, context.FirstParmsId, delta, plain); + encryptor.Encrypt(plain, encrypted); + evaluator.ComplexConjugateInplace(encrypted, galoisKeys); + decryptor.Decrypt(encrypted, plain); + encoder.Decode(plain, output); + + for (int i = 0; i < slotSize; i++) + { + Assert.AreEqual(input[i].Real, output[i].Real, delta: 0.1); + Assert.AreEqual(-input[i].Imaginary, output[i].Imaginary, delta: 0.1); + } + } + + [TestMethod] + public void ExceptionsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(65537ul), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + + Evaluator evaluator = null; + Utilities.AssertThrows<ArgumentNullException>(() => evaluator = new Evaluator(null)); + evaluator = new Evaluator(context); + + KeyGenerator keygen = new KeyGenerator(context); + GaloisKeys galoisKeys = keygen.GaloisKeysLocal(); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Ciphertext encrypted1 = new Ciphertext(); + Ciphertext encrypted2 = new Ciphertext(); + Ciphertext encrypted3 = new Ciphertext(); + Plaintext plain1 = new Plaintext(); + Plaintext plain2 = new Plaintext(); + List<Ciphertext> encrypteds = new List<Ciphertext>(); + + MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(null, encrypted2, encrypted3)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, null, encrypted3)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, encrypted2, null)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Add(encrypted1, encrypted2, encrypted3)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(null, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(encrypteds, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(null, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(null, plain1, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.AddPlain(encrypted1, plain1, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(null, plain1)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(null, 1, galoisKeys, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(encrypted1, 1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(null, 1, galoisKeys)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, galoisKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(null, galoisKeys, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(null, galoisKeys)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, relinKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(null, 2, relinKeys, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(encrypted1, 2, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(null, 2, relinKeys)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, ParmsId.Zero, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, null, plain2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, plain2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted: null, parmsId: ParmsId.Zero)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToInplace(encrypted1, ParmsId.Zero, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain: null, parmsId: ParmsId.Zero)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, plain2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNext(encrypted1, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(encrypted: null)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNextInplace(encrypted1, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, encrypted2, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, null, encrypted3)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(null, encrypted2, encrypted3)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Multiply(encrypted1, encrypted2, encrypted3, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyInplace(encrypted1, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(null, relinKeys, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(null, plain1, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyPlain(encrypted1, plain1, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(null, plain1)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Negate(encrypted1, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.NegateInplace(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, relinKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(null, relinKeys, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Relinearize(encrypted1, relinKeys, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(null, relinKeys)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RelinearizeInplace(encrypted1, relinKeys, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(null, ParmsId.Zero, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(null, ParmsId.Zero)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToInplace(encrypted1, ParmsId.Zero, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNext(encrypted1, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNextInplace(null)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNextInplace(encrypted1, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(null, galoisKeys, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(null, galoisKeys)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumnsInplace(encrypted1, galoisKeys, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(null, 1, galoisKeys, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(encrypted1, 1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(null, 1, galoisKeys)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRowsInplace(encrypted1, 1, galoisKeys, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, galoisKeys, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(null, 1, galoisKeys, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(encrypted1, 1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(null, 1, galoisKeys)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Square(encrypted1, encrypted2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SquareInplace(null)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.SquareInplace(encrypted1, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, encrypted2, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, null, encrypted3)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(null, encrypted2, encrypted3)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.Sub(encrypted1, encrypted2, encrypted3)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(null, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, null, encrypted2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(null, plain1, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlain(encrypted1, plain1, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(null, plain1)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlainInplace(encrypted1, plain1)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(null, encrypted2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformFromNTT(encrypted1, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTTInplace(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(encrypted1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, encrypted2)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, null, plain2)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, ParmsId.Zero, plain2)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, plain2, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(plain1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null, ParmsId.Zero)); + Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTTInplace(plain1, ParmsId.Zero, pool)); + } + + /// <summary> + /// Returns true if the two given collections have equivalent elements, false otherwise + /// </summary> + private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2) + { + int size1 = coll1.Count(); + int size2 = coll2.Count(); + + if (size1 != size2) + return false; + + IEnumerator<T> en1 = coll1.GetEnumerator(); + IEnumerator<T> en2 = coll2.GetEnumerator(); + + while (en1.MoveNext() && en2.MoveNext()) + { + if (!en1.Current.Equals(en2.Current)) + return false; + } + + return true; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/GaloisKeysTests.cs b/bigpiseal3.5.1/dotnet/tests/GaloisKeysTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..1464a9078c868f9facf3f4bc10c5df455b7bcacb --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/GaloisKeysTests.cs @@ -0,0 +1,321 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace SEALNetTest +{ + [TestClass] + public class GaloisKeysTests + { + [TestMethod] + public void CreateTest() + { + GaloisKeys keys = new GaloisKeys(); + + Assert.IsNotNull(keys); + Assert.AreEqual(0ul, keys.Size); + } + + [TestMethod] + public void CreateNonEmptyTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + GaloisKeys keys = keygen.GaloisKeysLocal(); + + Assert.IsNotNull(keys); + Assert.AreEqual(24ul, keys.Size); + + GaloisKeys copy = new GaloisKeys(keys); + + Assert.IsNotNull(copy); + Assert.AreEqual(24ul, copy.Size); + } + + [TestMethod] + public void SaveLoadTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keyGen = new KeyGenerator(context); + + GaloisKeys keys = keyGen.GaloisKeysLocal(); + GaloisKeys other = new GaloisKeys(); + + Assert.IsNotNull(keys); + Assert.AreEqual(24ul, keys.Size); + + using (MemoryStream ms = new MemoryStream()) + { + keys.Save(ms); + + ms.Seek(offset: 0, loc: SeekOrigin.Begin); + + other.Load(context, ms); + } + + Assert.AreEqual(24ul, other.Size); + Assert.IsTrue(ValCheck.IsValidFor(other, context)); + + List<IEnumerable<PublicKey>> keysData = new List<IEnumerable<PublicKey>>(keys.Data); + List<IEnumerable<PublicKey>> otherData = new List<IEnumerable<PublicKey>>(other.Data); + + Assert.AreEqual(keysData.Count, otherData.Count); + for (int i = 0; i < keysData.Count; i++) + { + List<PublicKey> keysCiphers = new List<PublicKey>(keysData[i]); + List<PublicKey> otherCiphers = new List<PublicKey>(otherData[i]); + + Assert.AreEqual(keysCiphers.Count, otherCiphers.Count); + + for (int j = 0; j < keysCiphers.Count; j++) + { + PublicKey keysCipher = keysCiphers[j]; + PublicKey otherCipher = otherCiphers[j]; + + Assert.AreEqual(keysCipher.Data.Size, otherCipher.Data.Size); + Assert.AreEqual(keysCipher.Data.PolyModulusDegree, otherCipher.Data.PolyModulusDegree); + Assert.AreEqual(keysCipher.Data.CoeffModulusSize, otherCipher.Data.CoeffModulusSize); + + ulong coeffCount = keysCipher.Data.Size * keysCipher.Data.PolyModulusDegree * keysCipher.Data.CoeffModulusSize; + for (ulong k = 0; k < coeffCount; k++) + { + Assert.AreEqual(keysCipher.Data[k], otherCipher.Data[k]); + } + } + } + } + + [TestMethod] + public void SeededKeyTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 8, + PlainModulus = new Modulus(257), + CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + BatchEncoder encoder = new BatchEncoder(context); + + GaloisKeys galoisKeys = new GaloisKeys(); + using (MemoryStream stream = new MemoryStream()) + { + keygen.GaloisKeys().Save(stream); + stream.Seek(0, SeekOrigin.Begin); + galoisKeys.Load(context, stream); + } + + Plaintext plain = new Plaintext(); + List<ulong> vec = new List<ulong> + { + 1, 2, 3, 4, + 5, 6, 7, 8 + }; + + encoder.Encode(vec, plain); + + Ciphertext encrypted = new Ciphertext(); + Ciphertext encdest = new Ciphertext(); + Plaintext plaindest = new Plaintext(); + + encryptor.Encrypt(plain, encrypted); + evaluator.RotateColumns(encrypted, galoisKeys, encdest); + decryptor.Decrypt(encdest, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 5, 6, 7, 8, + 1, 2, 3, 4 + })); + + evaluator.RotateRows(encdest, -1, galoisKeys, encrypted); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 8, 5, 6, 7, + 4, 1, 2, 3 + })); + + evaluator.RotateRowsInplace(encrypted, 2, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 6, 7, 8, 5, + 2, 3, 4, 1 + })); + + evaluator.RotateColumnsInplace(encrypted, galoisKeys); + decryptor.Decrypt(encrypted, plaindest); + encoder.Decode(plaindest, vec); + + Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> + { + 2, 3, 4, 1, + 6, 7, 8, 5 + })); + } + + [TestMethod] + public void SetTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + GaloisKeys keys = keygen.GaloisKeysLocal(); + + Assert.IsNotNull(keys); + Assert.AreEqual(24ul, keys.Size); + + GaloisKeys keys2 = new GaloisKeys(); + + Assert.IsNotNull(keys2); + Assert.AreEqual(0ul, keys2.Size); + + keys2.Set(keys); + + Assert.AreNotSame(keys, keys2); + Assert.AreEqual(24ul, keys2.Size); + } + + [TestMethod] + public void KeyTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + GaloisKeys keys = keygen.GaloisKeysLocal(); + MemoryPoolHandle handle = keys.Pool; + + Assert.IsNotNull(keys); + Assert.AreEqual(24ul, keys.Size); + + Assert.IsFalse(keys.HasKey(galoisElt: 1)); + Assert.IsTrue(keys.HasKey(galoisElt: 3)); + Assert.IsFalse(keys.HasKey(galoisElt: 5)); + Assert.IsFalse(keys.HasKey(galoisElt: 7)); + Assert.IsTrue(keys.HasKey(galoisElt: 9)); + Assert.IsFalse(keys.HasKey(galoisElt: 11)); + + IEnumerable<PublicKey> key = keys.Key(3); + Assert.AreEqual(4, key.Count()); + + IEnumerable<PublicKey> key2 = keys.Key(9); + Assert.AreEqual(4, key2.Count()); + + Assert.IsTrue(handle.AllocByteCount > 0ul); + } + + [TestMethod] + public void KeyEltTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + GaloisKeys keys = keygen.GaloisKeysLocal(galoisElts: new uint[] { 1, 3 }); + Assert.IsNotNull(keys); + + Assert.AreEqual(2ul, keys.Size); + + Assert.IsTrue(keys.HasKey(1)); + Assert.IsTrue(keys.HasKey(3)); + Assert.IsFalse(keys.HasKey(5)); + } + + [TestMethod] + public void KeyStepTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 64, + CoeffModulus = CoeffModulus.Create(64, new int[] { 60, 60 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + GaloisKeys keys = keygen.GaloisKeysLocal(steps: new int[] { 1, 2, 3 }); + Assert.IsNotNull(keys); + + Assert.AreEqual(3ul, keys.Size); + + Assert.IsFalse(keys.HasKey(1)); + Assert.IsTrue(keys.HasKey(3)); + Assert.IsFalse(keys.HasKey(5)); + Assert.IsFalse(keys.HasKey(7)); + Assert.IsTrue(keys.HasKey(9)); + Assert.IsFalse(keys.HasKey(11)); + Assert.IsFalse(keys.HasKey(13)); + Assert.IsFalse(keys.HasKey(15)); + Assert.IsFalse(keys.HasKey(17)); + Assert.IsFalse(keys.HasKey(19)); + Assert.IsFalse(keys.HasKey(21)); + Assert.IsFalse(keys.HasKey(23)); + Assert.IsFalse(keys.HasKey(25)); + Assert.IsTrue(keys.HasKey(27)); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + GaloisKeys keys = new GaloisKeys(); + + Utilities.AssertThrows<ArgumentNullException>(() => keys = new GaloisKeys(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.Set(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(keys, null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(context, null)); + Utilities.AssertThrows<EndOfStreamException>(() => keys.UnsafeLoad(context, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(null, new MemoryStream())); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(null, new MemoryStream())); + } + + /// <summary> + /// Returns true if the two given collections have equivalent elements, false otherwise + /// </summary> + private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2) + { + int size1 = coll1.Count(); + int size2 = coll2.Count(); + + if (size1 != size2) + return false; + + IEnumerator<T> en1 = coll1.GetEnumerator(); + IEnumerator<T> en2 = coll2.GetEnumerator(); + + while (en1.MoveNext() && en2.MoveNext()) + { + if (!en1.Current.Equals(en2.Current)) + return false; + } + + return true; + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/GlobalContext.cs b/bigpiseal3.5.1/dotnet/tests/GlobalContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..81294d0e5978e70ed0323d44b62f1e068250f9fa --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/GlobalContext.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; + +namespace SEALNetTest +{ + /// <summary> + /// Provides a global SEALContext that can be used by Tests. + /// Necessary to run tests fast, as creating a SEALContext can take around + /// 2 seconds. + /// </summary> + static class GlobalContext + { + static GlobalContext() + { + EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 8192, + CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192) + }; + encParams.SetPlainModulus(65537ul); + BFVContext = new SEALContext(encParams); + + encParams = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 8192, + CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192) + }; + CKKSContext = new SEALContext(encParams); + } + + public static SEALContext BFVContext { get; private set; } = null; + public static SEALContext CKKSContext { get; private set; } = null; + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/IntegerEncoderTests.cs b/bigpiseal3.5.1/dotnet/tests/IntegerEncoderTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..6c7d14bca184dd86a04a5305023751b4808f5a16 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/IntegerEncoderTests.cs @@ -0,0 +1,161 @@ +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace SEALNetTest +{ + [TestClass] + public class IntegerEncoderTests + { + [TestMethod] + public void CreateTest() + { + IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext); + Assert.IsNotNull(encoder); + Assert.AreEqual(65537ul, encoder.PlainModulus.Value); + } + + [TestMethod] + public void EncodeTest() + { + IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext); + + Plaintext plain = encoder.Encode(10); + Assert.IsNotNull(plain); + Assert.AreEqual(4ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain[0]); + Assert.AreEqual(1ul, plain[1]); + Assert.AreEqual(0ul, plain[2]); + Assert.AreEqual(1ul, plain[3]); + + plain = encoder.Encode(13u); + Assert.AreEqual(4ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(0ul, plain[1]); + Assert.AreEqual(1ul, plain[2]); + Assert.AreEqual(1ul, plain[3]); + + plain = encoder.Encode(20L); + Assert.AreEqual(5ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain[0]); + Assert.AreEqual(0ul, plain[1]); + Assert.AreEqual(1ul, plain[2]); + Assert.AreEqual(0ul, plain[3]); + Assert.AreEqual(1ul, plain[4]); + + plain = encoder.Encode(15ul); + Assert.AreEqual(4ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(1ul, plain[1]); + Assert.AreEqual(1ul, plain[2]); + Assert.AreEqual(1ul, plain[3]); + + BigUInt bui = new BigUInt("AB"); + plain = encoder.Encode(bui); + Assert.AreEqual(8ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(1ul, plain[1]); + Assert.AreEqual(0ul, plain[2]); + Assert.AreEqual(1ul, plain[3]); + Assert.AreEqual(0ul, plain[4]); + Assert.AreEqual(1ul, plain[5]); + Assert.AreEqual(0ul, plain[6]); + Assert.AreEqual(1ul, plain[7]); + + Plaintext plain2 = new Plaintext(); + + encoder.Encode(10, plain2); + Assert.AreEqual(4ul, plain2.CoeffCount); + Assert.AreEqual(0ul, plain2[0]); + Assert.AreEqual(1ul, plain2[1]); + Assert.AreEqual(0ul, plain2[2]); + Assert.AreEqual(1ul, plain2[3]); + + encoder.Encode(13u, plain2); + Assert.AreEqual(4ul, plain2.CoeffCount); + Assert.AreEqual(1ul, plain2[0]); + Assert.AreEqual(0ul, plain2[1]); + Assert.AreEqual(1ul, plain2[2]); + Assert.AreEqual(1ul, plain2[3]); + + encoder.Encode(20L, plain2); + Assert.AreEqual(5ul, plain2.CoeffCount); + Assert.AreEqual(0ul, plain2[0]); + Assert.AreEqual(0ul, plain2[1]); + Assert.AreEqual(1ul, plain2[2]); + Assert.AreEqual(0ul, plain2[3]); + Assert.AreEqual(1ul, plain2[4]); + + encoder.Encode(15ul, plain2); + Assert.AreEqual(4ul, plain2.CoeffCount); + Assert.AreEqual(1ul, plain2[0]); + Assert.AreEqual(1ul, plain2[1]); + Assert.AreEqual(1ul, plain2[2]); + Assert.AreEqual(1ul, plain2[3]); + + encoder.Encode(bui, plain2); + Assert.AreEqual(8ul, plain2.CoeffCount); + Assert.AreEqual(1ul, plain2[0]); + Assert.AreEqual(1ul, plain2[1]); + Assert.AreEqual(0ul, plain2[2]); + Assert.AreEqual(1ul, plain2[3]); + Assert.AreEqual(0ul, plain2[4]); + Assert.AreEqual(1ul, plain2[5]); + Assert.AreEqual(0ul, plain2[6]); + Assert.AreEqual(1ul, plain2[7]); + } + + [TestMethod] + public void DecodeTest() + { + IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext); + + Plaintext plain = new Plaintext("0x^5 + 1x^4 + 1x^3 + 1x^1 + 0"); + Assert.AreEqual(6ul, plain.CoeffCount); + + ulong resultU64 = encoder.DecodeUInt64(plain); + Assert.AreEqual(26UL, resultU64); + + long resultI64 = encoder.DecodeInt64(plain); + Assert.AreEqual(26L, resultI64); + + uint resultU32 = encoder.DecodeUInt32(plain); + Assert.AreEqual(26U, resultU32); + + int resultI32 = encoder.DecodeInt32(plain); + Assert.AreEqual(26, resultI32); + + BigUInt bui = encoder.DecodeBigUInt(plain); + Assert.IsNotNull(bui); + Assert.AreEqual(0, bui.CompareTo(26ul)); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + SEALContext context_null = null; + IntegerEncoder enc = new IntegerEncoder(context); + BigUInt bui_null = null; + BigUInt bui = new BigUInt(5ul); + Plaintext plain = new Plaintext(); + + Utilities.AssertThrows<ArgumentNullException>(() => enc = new IntegerEncoder(context_null)); + Utilities.AssertThrows<ArgumentException>(() => enc = new IntegerEncoder(GlobalContext.CKKSContext)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1ul, null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1L, null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1, null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1u, null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui_null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui, null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui_null, plain)); + + Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeUInt32(null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeUInt64(null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeInt32(null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeInt64(null)); + Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeBigUInt(null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/KeyGeneratorTests.cs b/bigpiseal3.5.1/dotnet/tests/KeyGeneratorTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..e99b7bd427bef70c0ce1bb1f4f496ba972ec0240 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/KeyGeneratorTests.cs @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; + +namespace SEALNetTest +{ + [TestClass] + public class KeyGeneratorTests + { + [TestMethod] + public void CreateTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + Assert.IsNotNull(keygen); + + PublicKey pubKey = keygen.PublicKey; + SecretKey secKey = keygen.SecretKey; + + Assert.IsNotNull(pubKey); + Assert.IsNotNull(secKey); + + Ciphertext cipher = pubKey.Data; + Assert.IsNotNull(cipher); + + Plaintext plain = secKey.Data; + Assert.IsNotNull(plain); + Assert.AreEqual(40960ul, plain.CoeffCount); + } + + [TestMethod] + public void Create2Test() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen1 = new KeyGenerator(context); + Encryptor encryptor1 = new Encryptor(context, keygen1.PublicKey); + Decryptor decryptor1 = new Decryptor(context, keygen1.SecretKey); + + Ciphertext cipher = new Ciphertext(); + Plaintext plain = new Plaintext("2x^1 + 5"); + Plaintext plain2 = new Plaintext(); + + encryptor1.Encrypt(plain, cipher); + decryptor1.Decrypt(cipher, plain2); + + Assert.AreNotSame(plain, plain2); + Assert.AreEqual(plain, plain2); + + KeyGenerator keygen2 = new KeyGenerator(context, keygen1.SecretKey); + Encryptor encryptor2 = new Encryptor(context, keygen2.PublicKey); + Decryptor decryptor2 = new Decryptor(context, keygen2.SecretKey); + + Plaintext plain3 = new Plaintext(); + decryptor2.Decrypt(cipher, plain3); + + Assert.AreNotSame(plain, plain3); + Assert.AreEqual(plain, plain3); + } + + [TestMethod] + public void KeyCopyTest() + { + SEALContext context = GlobalContext.BFVContext; + PublicKey pk = null; + SecretKey sk = null; + + using (KeyGenerator keygen = new KeyGenerator(context)) + { + pk = keygen.PublicKey; + sk = keygen.SecretKey; + } + + ParmsId parmsIdPK = pk.ParmsId; + ParmsId parmsIdSK = sk.ParmsId; + Assert.AreEqual(parmsIdPK, parmsIdSK); + Assert.AreEqual(parmsIdPK, context.KeyParmsId); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + SecretKey secret = new SecretKey(); + List<uint> elts = new List<uint> { 16385 }; + List<uint> elts_null = null; + List<int> steps = new List<int> { 4096 }; + List<int> steps_null = null; + + Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(null, keygen.SecretKey)); + Utilities.AssertThrows<ArgumentException>(() => keygen = new KeyGenerator(context, secret)); + + Utilities.AssertThrows<ArgumentNullException>(() => keygen.GaloisKeys(elts_null)); + Utilities.AssertThrows<ArgumentException>(() => keygen.GaloisKeys(elts)); + Utilities.AssertThrows<ArgumentNullException>(() => keygen.GaloisKeys(steps_null)); + Utilities.AssertThrows<ArgumentException>(() => keygen.GaloisKeys(steps)); + + EncryptionParameters smallParms = new EncryptionParameters(SchemeType.CKKS); + smallParms.PolyModulusDegree = 128; + smallParms.CoeffModulus = CoeffModulus.Create(smallParms.PolyModulusDegree, new int[] { 60 }); + context = new SEALContext(smallParms, true, SecLevelType.None); + keygen = new KeyGenerator(context); + Utilities.AssertThrows<InvalidOperationException>(() => keygen.RelinKeys()); + Utilities.AssertThrows<InvalidOperationException>(() => keygen.GaloisKeys()); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/MemoryManagerTests.cs b/bigpiseal3.5.1/dotnet/tests/MemoryManagerTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..565391f62398b157cb59fe4d8527fbbee73c6006 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/MemoryManagerTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace SEALNetTest +{ + [TestClass] + public class MemoryManagerTests + { + [TestMethod] + public void SwitchProfileTest() + { + MemoryPoolHandle handle = MemoryManager.GetPool(MMProfOpt.ForceNew); + MMProfFixed fixedProfile = new MMProfFixed(handle); + + MMProf oldProfile = MemoryManager.SwitchProfile(fixedProfile); + Assert.IsInstanceOfType(oldProfile, typeof(MMProfGlobal)); + + MMProfNew newProfile = new MMProfNew(); + oldProfile = MemoryManager.SwitchProfile(newProfile); + + Assert.IsInstanceOfType(oldProfile, typeof(MMProfFixed)); + + MMProfGlobal globalProfile = new MMProfGlobal(); + oldProfile = MemoryManager.SwitchProfile(globalProfile); + + Assert.IsInstanceOfType(oldProfile, typeof(MMProfNew)); + + MemoryPoolHandle globalHandle = globalProfile.GetPool(); + Assert.IsNotNull(globalHandle); + Assert.IsTrue(globalHandle.IsInitialized); + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/tests/MemoryPoolHandleTests.cs b/bigpiseal3.5.1/dotnet/tests/MemoryPoolHandleTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..6d9f81e637a322b87aeaed1123b1c96321b3db10 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/MemoryPoolHandleTests.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace SEALNetTest +{ + [TestClass] + public class MemoryPoolHandleTests + { + [TestMethod] + public void CreateTest() + { + MemoryPoolHandle handle = MemoryManager.GetPool(); + Assert.IsNotNull(handle); + Assert.IsTrue(handle.IsInitialized); + + MemoryPoolHandle handle2 = new MemoryPoolHandle(handle); + Assert.IsTrue(handle2.IsInitialized); + Assert.AreEqual(handle.PoolCount, handle2.PoolCount); + Assert.AreEqual(handle.AllocByteCount, handle2.AllocByteCount); + + MemoryPoolHandle handle5 = new MemoryPoolHandle(); + handle5.Set(handle); + Assert.IsTrue(handle5.IsInitialized); + Assert.AreEqual(handle.PoolCount, handle5.PoolCount); + Assert.AreEqual(handle.AllocByteCount, handle5.AllocByteCount); + + MemoryPoolHandle handle3 = MemoryManager.GetPool(MMProfOpt.ForceNew, clearOnDestruction: true); + Assert.IsNotNull(handle3); + Assert.AreEqual(0ul, handle3.PoolCount); + Assert.AreEqual(0ul, handle3.AllocByteCount); + + MemoryPoolHandle handle4 = MemoryManager.GetPool(MMProfOpt.ForceThreadLocal); + Assert.IsNotNull(handle4); + Assert.AreEqual(0ul, handle4.PoolCount); + Assert.AreEqual(0ul, handle4.AllocByteCount); + } + + [TestMethod] + public void EqualsTest() + { + MemoryPoolHandle handle1 = MemoryManager.GetPool(MMProfOpt.ForceNew); + MemoryPoolHandle handle2 = MemoryManager.GetPool(MMProfOpt.Default); + MemoryPoolHandle handle3 = MemoryManager.GetPool(); + + Assert.IsNotNull(handle1); + Assert.IsNotNull(handle2); + Assert.IsNotNull(handle3); + + Assert.AreNotEqual(handle1, handle2); + Assert.AreNotEqual(handle1, handle3); + Assert.AreEqual(handle2, handle3); + + Assert.AreNotEqual(handle1.GetHashCode(), handle2.GetHashCode()); + + Assert.IsFalse(handle3.Equals(null)); + } + + [TestMethod] + public void StaticMethodsTest() + { + MemoryPoolHandle handle1 = MemoryPoolHandle.Global(); + Assert.IsNotNull(handle1); + + MemoryPoolHandle handle2 = MemoryPoolHandle.New(clearOnDestruction: true); + Assert.IsNotNull(handle2); + + MemoryPoolHandle handle3 = MemoryPoolHandle.ThreadLocal(); + Assert.IsNotNull(handle3); + } + + [TestMethod] + public void UseCountTest() + { + MemoryPoolHandle pool = MemoryPoolHandle.New(); + Assert.AreEqual(1L, pool.UseCount); + Plaintext plain = new Plaintext(pool); + Assert.AreEqual(2L, pool.UseCount); + Plaintext plain2 = new Plaintext(pool); + Assert.AreEqual(3L, pool.UseCount); + plain.Dispose(); + plain2.Dispose(); + Assert.AreEqual(1L, pool.UseCount); + } + + [TestMethod] + public void ExceptionsTest() + { + MemoryPoolHandle handle = new MemoryPoolHandle(); + + Utilities.AssertThrows<ArgumentNullException>(() => handle = new MemoryPoolHandle(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => handle.Set(null)); + } + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/dotnet/tests/ModulusTests.cs b/bigpiseal3.5.1/dotnet/tests/ModulusTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..a459de058308ece91d5ca8677f664e2187bff10c --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/ModulusTests.cs @@ -0,0 +1,288 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using System; +using System.IO; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace SEALNetTest +{ + [TestClass] + public class ModulusTests + { + [TestMethod] + public void EmptyConstructorTest() + { + Modulus sm = new Modulus(); + + Assert.IsNotNull(sm); + Assert.IsTrue(sm.IsZero); + Assert.AreEqual(0ul, sm.Value); + Assert.AreEqual(0, sm.BitCount); + Assert.AreEqual(1ul, sm.UInt64Count); + Assert.IsFalse(sm.IsPrime); + } + + [TestMethod] + public void ValueConstructorTest() + { + Modulus sm = new Modulus(5); + + Assert.IsNotNull(sm); + Assert.IsFalse(sm.IsZero); + Assert.AreEqual(5ul, sm.Value); + Assert.AreEqual(3, sm.BitCount); + Assert.IsTrue(sm.IsPrime); + + // Value is exactly 61 bits + Modulus sm2 = new Modulus(0x1FFFFFFFFFFFFFFFul); + + Assert.IsNotNull(sm2); + Assert.IsFalse(sm2.IsZero); + Assert.AreEqual(0x1FFFFFFFFFFFFFFFul, sm2.Value); + Assert.AreEqual(61, sm2.BitCount); + Assert.AreEqual(1ul, sm2.UInt64Count); + Assert.IsTrue(sm2.IsPrime); + + Modulus sm3 = new Modulus(0xF00000F000079ul); + + Assert.IsNotNull(sm3); + Assert.IsFalse(sm3.IsZero); + Assert.AreEqual(0xF00000F000079ul, sm3.Value); + Assert.AreEqual(52, sm3.BitCount); + Assert.AreEqual(1ul, sm3.UInt64Count); + Assert.IsTrue(sm3.IsPrime); + } + + [TestMethod] + public void CopyConstructorTest() + { + Modulus sm = new Modulus(10); + Modulus copy = new Modulus(sm); + + Assert.IsNotNull(copy); + Assert.IsFalse(copy.IsZero); + Assert.AreEqual(10ul, copy.Value); + } + + [TestMethod] + public void ExplicitCreateTest() + { + Modulus sm = (Modulus)34ul; + Assert.IsNotNull(sm); + Assert.AreEqual(34ul, sm.Value); + } + + [TestMethod] + public void ConstructorFail1Test() + { + // Should fail if value is 1 + Utilities.AssertThrows<ArgumentException>(() => { Modulus sm = new Modulus(1); }); + } + + [TestMethod] + public void ConstructorFail2Test() + { + // Should fail if value is larger than 61 bits + Utilities.AssertThrows<ArgumentException>(() => { Modulus sm = new Modulus(0x2000000000000000ul); }); + } + + [TestMethod] + public void SetTest() + { + Modulus sm1 = new Modulus(456); + Modulus sm2 = new Modulus(); + + Assert.IsFalse(sm1.IsZero); + Assert.AreEqual(456ul, sm1.Value); + Assert.IsFalse(sm1.IsPrime); + Assert.IsTrue(sm2.IsZero); + Assert.AreEqual(0ul, sm2.Value); + Assert.IsFalse(sm2.IsPrime); + + sm2.Set(sm1); + + Assert.IsFalse(sm2.IsZero); + Assert.AreEqual(456ul, sm2.Value); + Assert.IsFalse(sm2.IsPrime); + + sm2.Set(value: 65537ul); + + Assert.IsFalse(sm2.IsZero); + Assert.AreEqual(65537ul, sm2.Value); + Assert.IsTrue(sm2.IsPrime); + } + + [TestMethod] + public void SetFail1Test() + { + // Should faile if set to 1 + Modulus sm = new Modulus(); + Utilities.AssertThrows<ArgumentException>(() => sm.Set(1)); + } + + [TestMethod] + public void SetFail2Test() + { + // Should fail if set to bigger than 61 bits + Modulus sm = new Modulus(); + Utilities.AssertThrows<ArgumentException>(() => sm.Set(0x2000000000000000ul)); + } + + [TestMethod] + public void ConstRatioTest() + { + Modulus sm = new Modulus(); + sm.Set(0x1234567890ABCDEFul); + + Tuple<ulong, ulong, ulong> ratio = sm.ConstRatio; + + Assert.IsNotNull(ratio); + Assert.AreNotEqual(0ul, ratio.Item1); + Assert.AreNotEqual(0ul, ratio.Item2); + Assert.AreNotEqual(0ul, ratio.Item3); + + sm.Set(0xF00000F000079ul); + ratio = sm.ConstRatio; + + Assert.IsNotNull(ratio); + Assert.AreEqual(1224979096621368355ul, ratio.Item1); + Assert.AreEqual(4369ul, ratio.Item2); + Assert.AreEqual(1144844808538997ul, ratio.Item3); + } + + [TestMethod] + public void EqualsTest() + { + Modulus sm1 = new Modulus(0x12345ul); + Modulus sm2 = new Modulus(0x12345ul); + + Assert.AreEqual(sm1, sm2); + Assert.AreEqual(sm1.GetHashCode(), sm2.GetHashCode()); + Assert.IsTrue(sm1.Equals(0x12345ul)); + Assert.IsFalse(sm1.Equals(0x1234ul)); + + Assert.IsFalse(sm1.Equals(null)); + } + + [TestMethod] + public void CompareToTest() + { + Modulus sminv = null; + Modulus sm0 = new Modulus(); + Modulus sm2 = new Modulus(2); + Modulus sm5 = new Modulus(5); + Modulus smbig = new Modulus(0xFFFFFFF); + Assert.AreEqual(1, sm0.CompareTo(sminv)); + Assert.AreEqual(0, sm0.CompareTo(sm0)); + Assert.AreEqual(-1, sm2.CompareTo(sm5)); + Assert.AreEqual(-1, sm2.CompareTo(smbig)); + Assert.AreEqual(1, sm2.CompareTo(sminv)); + Assert.AreEqual(0, sm5.CompareTo(sm5)); + Assert.AreEqual(0, smbig.CompareTo(smbig)); + Assert.AreEqual(1, smbig.CompareTo(sm0)); + Assert.AreEqual(1, smbig.CompareTo(sm5)); + Assert.AreEqual(1, smbig.CompareTo(sminv)); + Assert.AreEqual(-1, sm5.CompareTo(6)); + Assert.AreEqual(0, sm5.CompareTo(5)); + Assert.AreEqual(1, sm5.CompareTo(4)); + Assert.AreEqual(1, sm5.CompareTo(0)); + } + + [TestMethod] + public void SaveLoadTest() + { + Modulus sm1 = new Modulus(65537ul); + Modulus sm2 = new Modulus(); + + Assert.AreNotSame(sm1, sm2); + Assert.AreNotEqual(sm1, sm2); + Assert.AreNotEqual(sm1.IsPrime, sm2.IsPrime); + + using (MemoryStream stream = new MemoryStream()) + { + sm1.Save(stream); + stream.Seek(offset: 0, loc: SeekOrigin.Begin); + sm2.Load(stream); + } + + Assert.AreNotSame(sm1, sm2); + Assert.AreEqual(sm1, sm2); + Assert.AreEqual(sm1.BitCount, sm2.BitCount); + Assert.AreEqual(sm1.UInt64Count, sm2.UInt64Count); + Assert.AreEqual(sm1.ConstRatio.Item1, sm2.ConstRatio.Item1); + Assert.AreEqual(sm1.ConstRatio.Item2, sm2.ConstRatio.Item2); + Assert.AreEqual(sm1.ConstRatio.Item3, sm2.ConstRatio.Item3); + Assert.AreEqual(sm1.IsPrime, sm2.IsPrime); + } + + [TestMethod] + public void CreateTest() + { + List<Modulus> cm = (List<Modulus>)CoeffModulus.Create(2, new int[]{ }); + Assert.AreEqual(0, cm.Count); + + cm = (List<Modulus>)CoeffModulus.Create(2, new int[] { 3 }); + Assert.AreEqual(1, cm.Count); + Assert.AreEqual(5ul, cm[0].Value); + + cm = (List<Modulus>)CoeffModulus.Create(2, new int[] { 3, 4 }); + Assert.AreEqual(2, cm.Count); + Assert.AreEqual(5ul, cm[0].Value); + Assert.AreEqual(13ul, cm[1].Value); + + cm = (List<Modulus>)CoeffModulus.Create(2, new int[] { 3, 5, 4, 5 }); + Assert.AreEqual(4, cm.Count); + Assert.AreEqual(5ul, cm[0].Value); + Assert.AreEqual(17ul, cm[1].Value); + Assert.AreEqual(13ul, cm[2].Value); + Assert.AreEqual(29ul, cm[3].Value); + + cm = (List<Modulus>)CoeffModulus.Create(32, new int[] { 30, 40, 30, 30, 40 }); + Assert.AreEqual(5, cm.Count); + Assert.AreEqual(30, (int)(Math.Log(cm[0].Value, 2)) + 1); + Assert.AreEqual(40, (int)(Math.Log(cm[1].Value, 2)) + 1); + Assert.AreEqual(30, (int)(Math.Log(cm[2].Value, 2)) + 1); + Assert.AreEqual(30, (int)(Math.Log(cm[3].Value, 2)) + 1); + Assert.AreEqual(40, (int)(Math.Log(cm[4].Value, 2)) + 1); + Assert.AreEqual(1ul, cm[0].Value % 64); + Assert.AreEqual(1ul, cm[1].Value % 64); + Assert.AreEqual(1ul, cm[2].Value % 64); + Assert.AreEqual(1ul, cm[3].Value % 64); + Assert.AreEqual(1ul, cm[4].Value % 64); + } + + [TestMethod] + public void ExceptionsTest() + { + Modulus sm = new Modulus(0x12345ul); + + Utilities.AssertThrows<ArgumentNullException>(() => sm = new Modulus(null)); + Utilities.AssertThrows<ArgumentNullException>(() => sm.Set(null)); + Utilities.AssertThrows<ArgumentNullException>(() => sm.Save(null)); + Utilities.AssertThrows<ArgumentNullException>(() => sm.Load(null)); + Utilities.AssertThrows<EndOfStreamException>(() => sm.Load(new MemoryStream())); + + // Too small polyModulusDegree + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(1, new int[] { 2 })); + + // Too large polyModulusDegree + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(262144, new int[] { 30 })); + + // Invalid polyModulusDegree + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(1023, new int[] { 20 })); + + // Invalid bitSize + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(2048, new int[] { 0 })); + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(2048, new int[] { -30 })); + Utilities.AssertThrows<ArgumentException>(() => CoeffModulus.Create(2048, new int[] { 30, -30 })); + + // Too small primes requested + Utilities.AssertThrows<InvalidOperationException>(() => CoeffModulus.Create(2, new int[] { 2 })); + Utilities.AssertThrows<InvalidOperationException>(() => CoeffModulus.Create(2, new int[] { 3, 3, 3 })); + Utilities.AssertThrows<InvalidOperationException>(() => CoeffModulus.Create(1024, new int[] { 8 })); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/NativeObjectTests.cs b/bigpiseal3.5.1/dotnet/tests/NativeObjectTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..f482d6396acf1f9b5c1ddffd126ae102c589f653 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/NativeObjectTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.Research.SEAL.Tools; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SEALNetTest +{ + [TestClass] + public class NativeObjectTests + { + [TestMethod] + public void IsDisposedTest() + { + Ciphertext cipher = new Ciphertext(); + Assert.IsNotNull(cipher); + Assert.AreEqual(0ul, cipher.Size); + Assert.AreEqual(0ul, cipher.PolyModulusDegree); + Assert.AreEqual(0ul, cipher.CoeffModulusSize); + + // After disposing object, accessing any field should fail. + cipher.Dispose(); + Utilities.AssertThrows<ObjectDisposedException>(() => cipher.Size); + Utilities.AssertThrows<ObjectDisposedException>(() => cipher.PolyModulusDegree); + Utilities.AssertThrows<ObjectDisposedException>(() => cipher.CoeffModulusSize); + Utilities.AssertThrows<ObjectDisposedException>(() => cipher.IsTransparent); + Utilities.AssertThrows<ObjectDisposedException>(() => cipher.IsNTTForm); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/ParmsIdTests.cs b/bigpiseal3.5.1/dotnet/tests/ParmsIdTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..4f979876f62ebb6e078aa0d949289acd38c04d27 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/ParmsIdTests.cs @@ -0,0 +1,88 @@ +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SEALNetTest +{ + [TestClass] + public class ParmsIdTests + { + [TestMethod] + public void ParamIDConstructorTest() + { + ParmsId id = new ParmsId(); + + Assert.AreEqual(0ul, id.Block[0]); + Assert.AreEqual(0ul, id.Block[1]); + Assert.AreEqual(0ul, id.Block[2]); + Assert.AreEqual(0ul, id.Block[3]); + + id.Block[0] = 5; + id.Block[1] = 4; + id.Block[2] = 3; + id.Block[3] = 2; + + ParmsId id2 = new ParmsId(id); + + id.Block[1] = 7; + + Assert.AreEqual(5ul, id2.Block[0]); + Assert.AreEqual(4ul, id2.Block[1]); + Assert.AreEqual(3ul, id2.Block[2]); + Assert.AreEqual(2ul, id2.Block[3]); + Assert.AreEqual(7ul, id.Block[1]); + + Assert.IsFalse(id2.Equals(null)); + Assert.AreNotEqual(id.GetHashCode(), id2.GetHashCode()); + } + + [TestMethod] + public void ToStringTest() + { + ParmsId id = new ParmsId(); + + id.Block[0] = 1; + id.Block[1] = 2; + id.Block[2] = 3; + id.Block[3] = 4; + + Assert.AreEqual("0000000000000001 0000000000000002 0000000000000003 0000000000000004", id.ToString()); + } + + [TestMethod] + public void OperatorsTest() + { + ParmsId id = new ParmsId(); + + id.Block[0] = 1; + id.Block[1] = 2; + id.Block[2] = 3; + id.Block[3] = 4; + + ParmsId id2 = new ParmsId(id); + + ParmsId id3 = new ParmsId(id); + id3.Block[0] = 2; + + Assert.IsTrue(id == id2); + Assert.IsFalse(id == id3); + + ParmsId id_null1 = null; + ParmsId id_null2 = null; + + Assert.IsFalse(id_null1 != id_null2); + Assert.IsTrue(id_null1 != id); + } + + [TestMethod] + public void ExceptionsTest() + { + ParmsId id = new ParmsId(); + ParmsId id_null = null; + + Utilities.AssertThrows<ArgumentNullException>(() => id = new ParmsId(id_null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/PlaintextTests.cs b/bigpiseal3.5.1/dotnet/tests/PlaintextTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..fe46849876b275bf06bf1916453fa656696fd9cc --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/PlaintextTests.cs @@ -0,0 +1,343 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; + +namespace SEALNetTest +{ + [TestClass] + public class PlaintextTests + { + [TestMethod] + public void CreateTest() + { + Plaintext plain = new Plaintext(); + Assert.IsNotNull(plain); + Assert.AreEqual(0ul, plain.CoeffCount); + + Plaintext plain2 = new Plaintext(capacity: 20, coeffCount: 10); + Assert.IsNotNull(plain2); + Assert.AreEqual(20ul, plain2.Capacity); + Assert.AreEqual(10ul, plain2.CoeffCount); + + Plaintext plain3 = new Plaintext(); + plain3.Set(plain2); + + Assert.IsNotNull(plain3); + Assert.AreEqual(10ul, plain3.Capacity); + Assert.AreEqual(10ul, plain3.CoeffCount); + } + + [TestMethod] + public void CreateWithHexTest() + { + Plaintext plain = new Plaintext("6x^5 + 5x^4 + 3x^2 + 2x^1 + 1"); + Assert.IsNotNull(plain); + Assert.AreEqual(6ul, plain.CoeffCount); + Assert.AreEqual(5ul, plain.NonZeroCoeffCount); + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(2ul, plain[1]); + Assert.AreEqual(3ul, plain[2]); + Assert.AreEqual(0ul, plain[3]); + Assert.AreEqual(5ul, plain[4]); + Assert.AreEqual(6ul, plain[5]); + + Plaintext plain2 = new Plaintext("6x^5 + 5x^4 + 3x^2 + 2x^1"); + Assert.IsNotNull(plain); + Assert.AreEqual(6ul, plain2.CoeffCount); + Assert.AreEqual(4ul, plain2.NonZeroCoeffCount); + Assert.AreEqual(0ul, plain2[0]); + Assert.AreEqual(2ul, plain2[1]); + Assert.AreEqual(3ul, plain2[2]); + Assert.AreEqual(0ul, plain2[3]); + Assert.AreEqual(5ul, plain2[4]); + Assert.AreEqual(6ul, plain2[5]); + } + + [TestMethod] + public void CopyTest() + { + Plaintext plain = new Plaintext("6x^5 + 5x^4 + 3x^2 + 2x^1 + 1"); + Assert.IsFalse(plain.IsNTTForm); + Plaintext plain2 = new Plaintext(plain); + Assert.AreEqual(plain, plain2); + Assert.IsFalse(plain2.IsNTTForm); + Assert.AreEqual(plain.ParmsId, plain2.ParmsId); + + SEALContext context = GlobalContext.BFVContext; + Evaluator evaluator = new Evaluator(context); + evaluator.TransformToNTTInplace(plain, context.FirstParmsId); + Assert.IsTrue(plain.IsNTTForm); + Assert.IsFalse(plain2.IsNTTForm); + Assert.AreNotEqual(plain.ParmsId, plain2.ParmsId); + Assert.AreEqual(plain.ParmsId, context.FirstParmsId); + + Plaintext plain3 = new Plaintext(plain); + Assert.AreEqual(plain3, plain); + Assert.IsTrue(plain3.IsNTTForm); + Assert.AreEqual(plain3.ParmsId, context.FirstParmsId); + } + + [TestMethod] + public void ToStringTest() + { + Plaintext plain = new Plaintext(coeffCount: 6); + plain[0] = 1; + plain[1] = 2; + plain[2] = 3; + plain[3] = 0; + plain[4] = 5; + plain[5] = 6; + + Assert.AreEqual(6ul, plain.CoeffCount); + Assert.AreEqual(5ul, plain.NonZeroCoeffCount); + + string str = plain.ToString(); + Assert.AreEqual("6x^5 + 5x^4 + 3x^2 + 2x^1 + 1", str); + } + + [TestMethod] + public void SetZeroTest() + { + Plaintext plain = new Plaintext(coeffCount: 10); + plain[0] = 1; + plain[1] = 2; + plain[2] = 3; + plain[3] = 4; + plain[4] = 5; + plain[5] = 6; + plain[6] = 7; + plain[7] = 8; + plain[8] = 9; + plain[9] = 10; + + plain.SetZero(6, 3); + + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(2ul, plain[1]); + Assert.AreEqual(3ul, plain[2]); + Assert.AreEqual(4ul, plain[3]); + Assert.AreEqual(5ul, plain[4]); + Assert.AreEqual(6ul, plain[5]); + Assert.AreEqual(0ul, plain[6]); + Assert.AreEqual(0ul, plain[7]); + Assert.AreEqual(0ul, plain[8]); + Assert.AreEqual(10ul, plain[9]); + + plain[0] = 1; + plain[1] = 2; + plain[2] = 3; + plain[3] = 4; + plain[4] = 5; + plain[5] = 6; + plain[6] = 7; + plain[7] = 8; + plain[8] = 9; + plain[9] = 10; + + plain.SetZero(4); + + Assert.AreEqual(1ul, plain[0]); + Assert.AreEqual(2ul, plain[1]); + Assert.AreEqual(3ul, plain[2]); + Assert.AreEqual(4ul, plain[3]); + Assert.AreEqual(0ul, plain[4]); + Assert.AreEqual(0ul, plain[5]); + Assert.AreEqual(0ul, plain[6]); + Assert.AreEqual(0ul, plain[7]); + Assert.AreEqual(0ul, plain[8]); + Assert.AreEqual(0ul, plain[9]); + + plain[0] = 1; + plain[1] = 2; + plain[2] = 3; + plain[3] = 4; + plain[4] = 5; + plain[5] = 6; + plain[6] = 7; + plain[7] = 8; + plain[8] = 9; + plain[9] = 10; + + plain.SetZero(); + + Assert.AreEqual(0ul, plain[0]); + Assert.AreEqual(0ul, plain[1]); + Assert.AreEqual(0ul, plain[2]); + Assert.AreEqual(0ul, plain[3]); + Assert.AreEqual(0ul, plain[4]); + Assert.AreEqual(0ul, plain[5]); + Assert.AreEqual(0ul, plain[6]); + Assert.AreEqual(0ul, plain[7]); + Assert.AreEqual(0ul, plain[8]); + Assert.AreEqual(0ul, plain[9]); + } + + [TestMethod] + public void ReserveResizeTest() + { + Plaintext plain = new Plaintext(); + MemoryPoolHandle handle = plain.Pool; + + Assert.AreEqual(0ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain.NonZeroCoeffCount); + Assert.AreEqual(0ul, plain.Capacity); + + plain.Reserve(capacity: 10); + + ulong alloced = handle.AllocByteCount; + Assert.IsTrue(alloced > 0ul); + + Assert.AreEqual(0ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain.NonZeroCoeffCount); + Assert.AreEqual(10ul, plain.Capacity); + + plain.Resize(coeffCount: 11); + + Assert.AreEqual(11ul, plain.CoeffCount); + Assert.AreEqual(11ul, plain.Capacity); + Assert.AreEqual(0ul, plain.SignificantCoeffCount); + Assert.AreEqual(0ul, plain.NonZeroCoeffCount); + Assert.IsTrue(handle.AllocByteCount > 0ul); + } + + [TestMethod] + public void ShrinkToFitTest() + { + Plaintext plain = new Plaintext(); + + plain.Reserve(10000); + + Assert.AreEqual(10000ul, plain.Capacity); + Assert.AreEqual(0ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain.NonZeroCoeffCount); + + plain.Set("1"); + + Assert.AreEqual(10000ul, plain.Capacity); + Assert.AreEqual(1ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain.NonZeroCoeffCount); + Assert.AreEqual(1ul, plain.SignificantCoeffCount); + + plain.ShrinkToFit(); + + Assert.AreEqual(1ul, plain.Capacity); + Assert.AreEqual(1ul, plain.CoeffCount); + Assert.AreEqual(1ul, plain[0]); + } + + [TestMethod] + public void ReleaseTest() + { + Plaintext plain = new Plaintext(); + plain.Reserve(10000); + + plain.Set("3x^2 + 4x^1"); + + Assert.AreEqual(10000ul, plain.Capacity); + Assert.AreEqual(3ul, plain.CoeffCount); + Assert.AreEqual(2ul, plain.NonZeroCoeffCount); + + plain.Release(); + + Assert.AreEqual(0ul, plain.Capacity); + Assert.AreEqual(0ul, plain.CoeffCount); + Assert.AreEqual(0ul, plain.NonZeroCoeffCount); + } + + [TestMethod] + public void EqualsTest() + { + Plaintext plain1 = new Plaintext(); + Plaintext plain2 = new Plaintext(); + + plain1.Reserve(10000); + plain2.Reserve(500); + + plain1.Set("4x^3 + 5x^2 + 6x^1 + 7"); + plain2.Set("4x^3 + 5x^2 + 6x^1 + 7"); + + Assert.AreEqual(10000ul, plain1.Capacity); + Assert.AreEqual(500ul, plain2.Capacity); + + Assert.AreNotSame(plain1, plain2); + Assert.AreEqual(plain1, plain2); + + Assert.IsFalse(plain1.Equals(null)); + } + + [TestMethod] + public void SaveLoadTest() + { + SEALContext context = GlobalContext.BFVContext; + Plaintext plain = new Plaintext("6x^5 + 5x^4 + 4x^3 + 3x^2 + 2x^1 + 5"); + Plaintext other = new Plaintext(); + + Assert.AreNotSame(plain, other); + Assert.AreNotEqual(plain, other); + + using (MemoryStream stream = new MemoryStream()) + { + plain.Save(stream); + + stream.Seek(offset: 0, loc: SeekOrigin.Begin); + + other.Load(context, stream); + } + + Assert.AreNotSame(plain, other); + Assert.AreEqual(plain, other); + Assert.IsTrue(ValCheck.IsValidFor(other, context)); + } + + [TestMethod] + public void HashCodeTest() + { + Plaintext plain1 = new Plaintext("6x^40 + 5x^35 + 4x^30 + 3x^20 + 2x^10 + 5"); + Plaintext plain2 = new Plaintext("1"); + Plaintext plain3 = new Plaintext("0"); + Plaintext plain4 = new Plaintext("6x^40 + 5x^35 + 4x^30 + 3x^20 + 2x^10 + 5"); + + Assert.AreNotEqual(plain1.GetHashCode(), plain2.GetHashCode()); + Assert.AreNotEqual(plain1.GetHashCode(), plain3.GetHashCode()); + Assert.AreNotEqual(plain2.GetHashCode(), plain3.GetHashCode()); + Assert.AreNotEqual(plain2.GetHashCode(), plain4.GetHashCode()); + Assert.AreNotEqual(plain3.GetHashCode(), plain4.GetHashCode()); + + Assert.AreEqual(plain1.GetHashCode(), plain4.GetHashCode()); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + Plaintext plain = new Plaintext(); + MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal); + MemoryPoolHandle pool_uninit = new MemoryPoolHandle(); + + Utilities.AssertThrows<ArgumentException>(() => plain = new Plaintext(pool_uninit)); + Utilities.AssertThrows<ArgumentNullException>(() => plain = new Plaintext((string)null, pool)); + + Utilities.AssertThrows<ArgumentNullException>(() => plain.Set((Plaintext)null)); + Utilities.AssertThrows<ArgumentNullException>(() => plain.Set((string)null)); + + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => plain.SetZero(100000)); + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => plain.SetZero(1, 100000)); + Utilities.AssertThrows<ArgumentOutOfRangeException>(() => plain.SetZero(100000, 1)); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(plain, null)); + + Utilities.AssertThrows<ArgumentNullException>(() => plain.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => plain.UnsafeLoad(null, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => plain.UnsafeLoad(context, null)); + Utilities.AssertThrows<EndOfStreamException>(() => plain.UnsafeLoad(context, new MemoryStream())); + + Utilities.AssertThrows<ArgumentNullException>(() => plain.Load(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => plain.Load(null, new MemoryStream())); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/PublicKeyTests.cs b/bigpiseal3.5.1/dotnet/tests/PublicKeyTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..eedfa6058614e51a37c53804eebe8846d0ba5be9 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/PublicKeyTests.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; + +namespace SEALNetTest +{ + [TestClass] + public class PublicKeyTests + { + [TestMethod] + public void CreateTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + PublicKey pub = keygen.PublicKey; + PublicKey copy = new PublicKey(pub); + + Assert.IsNotNull(copy); + Assert.AreEqual(2ul, copy.Data.Size); + Assert.IsTrue(copy.Data.IsNTTForm); + + PublicKey copy2 = new PublicKey(); + copy2.Set(copy); + + Assert.AreEqual(2ul, copy2.Data.Size); + Assert.IsTrue(copy2.Data.IsNTTForm); + } + + [TestMethod] + public void SaveLoadTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + PublicKey pub = keygen.PublicKey; + + Assert.IsNotNull(pub); + Assert.AreEqual(2ul, pub.Data.Size); + Assert.IsTrue(pub.Data.IsNTTForm); + + PublicKey pub2 = new PublicKey(); + MemoryPoolHandle handle = pub2.Pool; + + Assert.AreEqual(0ul, pub2.Data.Size); + Assert.IsFalse(pub2.Data.IsNTTForm); + Assert.AreEqual(ParmsId.Zero, pub2.ParmsId); + + using (MemoryStream stream = new MemoryStream()) + { + pub.Save(stream); + + stream.Seek(offset: 0, loc: SeekOrigin.Begin); + + pub2.Load(context, stream); + } + + Assert.AreNotSame(pub, pub2); + Assert.AreEqual(2ul, pub2.Data.Size); + Assert.IsTrue(pub2.Data.IsNTTForm); + Assert.AreEqual(pub.ParmsId, pub2.ParmsId); + Assert.AreNotEqual(ParmsId.Zero, pub2.ParmsId); + Assert.IsTrue(handle.AllocByteCount != 0ul); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + PublicKey key = new PublicKey(); + + Utilities.AssertThrows<ArgumentNullException>(() => key = new PublicKey(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => key.Set(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => key.Save(null)); + Utilities.AssertThrows<ArgumentNullException>(() => key.UnsafeLoad(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => key.UnsafeLoad(null, new MemoryStream())); + + Utilities.AssertThrows<ArgumentNullException>(() => key.Load(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => key.Load(null, new MemoryStream())); + Utilities.AssertThrows<EndOfStreamException>(() => key.Load(context, new MemoryStream())); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(key, null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/RelinKeysTests.cs b/bigpiseal3.5.1/dotnet/tests/RelinKeysTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..74bf814f2e8ad5b5102a492a542e0bc16349a2ac --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/RelinKeysTests.cs @@ -0,0 +1,199 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; + +namespace SEALNetTest +{ + [TestClass] + public class RelinKeysTests + { + [TestMethod] + public void CreateRelinKeysTest() + { + RelinKeys keys = new RelinKeys(); + + Assert.IsNotNull(keys); + Assert.AreEqual(0ul, keys.Size); + } + + [TestMethod] + public void CreateNonEmptyRelinKeysTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + RelinKeys keys = keygen.RelinKeysLocal(); + + Assert.IsNotNull(keys); + Assert.AreEqual(1ul, keys.Size); + + RelinKeys copy = new RelinKeys(keys); + + Assert.IsNotNull(copy); + Assert.AreEqual(1ul, copy.Size); + + RelinKeys copy2 = new RelinKeys(); + + copy2.Set(keys); + Assert.IsNotNull(copy2); + Assert.AreEqual(1ul, copy2.Size); + } + + [TestMethod] + public void SaveLoadTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + + RelinKeys keys = keygen.RelinKeysLocal(); + + Assert.IsNotNull(keys); + Assert.AreEqual(1ul, keys.Size); + + RelinKeys other = new RelinKeys(); + MemoryPoolHandle handle = other.Pool; + + Assert.AreEqual(0ul, other.Size); + ulong alloced = handle.AllocByteCount; + + using (MemoryStream ms = new MemoryStream()) + { + keys.Save(ms); + ms.Seek(offset: 0, loc: SeekOrigin.Begin); + other.Load(context, ms); + } + + Assert.AreEqual(1ul, other.Size); + Assert.IsTrue(ValCheck.IsValidFor(other, context)); + Assert.IsTrue(handle.AllocByteCount > 0ul); + + List<IEnumerable<PublicKey>> keysData = new List<IEnumerable<PublicKey>>(keys.Data); + List<IEnumerable<PublicKey>> otherData = new List<IEnumerable<PublicKey>>(other.Data); + + Assert.AreEqual(keysData.Count, otherData.Count); + for (int i = 0; i < keysData.Count; i++) + { + List<PublicKey> keysCiphers = new List<PublicKey>(keysData[i]); + List<PublicKey> otherCiphers = new List<PublicKey>(otherData[i]); + + Assert.AreEqual(keysCiphers.Count, otherCiphers.Count); + + for (int j = 0; j < keysCiphers.Count; j++) + { + PublicKey keysCipher = keysCiphers[j]; + PublicKey otherCipher = otherCiphers[j]; + + Assert.AreEqual(keysCipher.Data.Size, otherCipher.Data.Size); + Assert.AreEqual(keysCipher.Data.PolyModulusDegree, otherCipher.Data.PolyModulusDegree); + Assert.AreEqual(keysCipher.Data.CoeffModulusSize, otherCipher.Data.CoeffModulusSize); + + ulong coeffCount = keysCipher.Data.Size * keysCipher.Data.PolyModulusDegree * keysCipher.Data.CoeffModulusSize; + for (ulong k = 0; k < coeffCount; k++) + { + Assert.AreEqual(keysCipher.Data[k], otherCipher.Data[k]); + } + } + } + } + + [TestMethod] + public void SeededKeyTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + RelinKeys relinKeys = new RelinKeys(); + using (MemoryStream stream = new MemoryStream()) + { + keygen.RelinKeys().Save(stream); + stream.Seek(0, SeekOrigin.Begin); + relinKeys.Load(context, stream); + } + + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Decryptor decryptor = new Decryptor(context, keygen.SecretKey); + Evaluator evaluator = new Evaluator(context); + + Ciphertext encrypted1 = new Ciphertext(context); + Ciphertext encrypted2 = new Ciphertext(context); + Plaintext plain1 = new Plaintext(); + Plaintext plain2 = new Plaintext(); + + plain1.Set(0); + encryptor.Encrypt(plain1, encrypted1); + evaluator.SquareInplace(encrypted1); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + decryptor.Decrypt(encrypted1, plain2); + + Assert.AreEqual(1ul, plain2.CoeffCount); + Assert.AreEqual(0ul, plain2[0]); + + plain1.Set("1x^10 + 2"); + encryptor.Encrypt(plain1, encrypted1); + evaluator.SquareInplace(encrypted1); + evaluator.RelinearizeInplace(encrypted1, relinKeys); + evaluator.SquareInplace(encrypted1); + evaluator.Relinearize(encrypted1, relinKeys, encrypted2); + decryptor.Decrypt(encrypted2, plain2); + + // {1x^40 + 8x^30 + 18x^20 + 20x^10 + 10} + Assert.AreEqual(41ul, plain2.CoeffCount); + Assert.AreEqual(16ul, plain2[0]); + Assert.AreEqual(32ul, plain2[10]); + Assert.AreEqual(24ul, plain2[20]); + Assert.AreEqual(8ul, plain2[30]); + Assert.AreEqual(1ul, plain2[40]); + } + + [TestMethod] + public void GetKeyTest() + { + SEALContext context = GlobalContext.BFVContext; + KeyGenerator keygen = new KeyGenerator(context); + RelinKeys relinKeys = keygen.RelinKeysLocal(); + + Assert.IsTrue(relinKeys.HasKey(2)); + Assert.IsFalse(relinKeys.HasKey(3)); + + Utilities.AssertThrows<ArgumentException>(() => relinKeys.Key(0)); + Utilities.AssertThrows<ArgumentException>(() => relinKeys.Key(1)); + + List<PublicKey> key1 = new List<PublicKey>(relinKeys.Key(2)); + Assert.AreEqual(4, key1.Count); + Assert.AreEqual(5ul, key1[0].Data.CoeffModulusSize); + } + + [TestMethod] + public void ExceptionsTest() + { + RelinKeys keys = new RelinKeys(); + SEALContext context = GlobalContext.BFVContext; + + Utilities.AssertThrows<ArgumentNullException>(() => keys = new RelinKeys(null)); + Utilities.AssertThrows<ArgumentNullException>(() => keys.Set(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(keys, null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(null, new MemoryStream())); + Utilities.AssertThrows<EndOfStreamException>(() => keys.Load(context, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(null, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(context, null)); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/SEALContextTests.cs b/bigpiseal3.5.1/dotnet/tests/SEALContextTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..2438ace7690b5f433289ce778e630aa9cd0683ca --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/SEALContextTests.cs @@ -0,0 +1,190 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; + +namespace SEALNetTest +{ + [TestClass] + public class SEALContextTests + { + [TestMethod] + public void SEALContextCreateTest() + { + EncryptionParameters encParams1 = new EncryptionParameters(SchemeType.BFV); + EncryptionParameters encParams2 = new EncryptionParameters(SchemeType.CKKS); + + SEALContext context1 = new SEALContext(encParams1); + SEALContext context2 = new SEALContext(encParams2); + + Assert.IsNotNull(context1); + Assert.IsNotNull(context2); + + Assert.IsFalse(context1.ParametersSet); + Assert.IsFalse(context2.ParametersSet); + + Assert.AreNotSame(context1.FirstParmsId, context1.LastParmsId); + Assert.AreEqual(context1.FirstParmsId, context1.LastParmsId); + + SEALContext.ContextData data1 = context2.FirstContextData; + SEALContext.ContextData data2 = context2.GetContextData(context2.FirstParmsId); + + Assert.AreNotSame(data1, data2); + ulong[] totalCoeffMod1 = data1.TotalCoeffModulus; + ulong[] totalCoeffMod2 = data2.TotalCoeffModulus; + + int bitCount1 = data1.TotalCoeffModulusBitCount; + int bitCount2 = data2.TotalCoeffModulusBitCount; + + Assert.AreEqual(bitCount1, bitCount2); + Assert.AreEqual(totalCoeffMod1.Length, totalCoeffMod2.Length); + + for (int i = 0; i < totalCoeffMod1.Length; i++) + { + Assert.AreEqual(totalCoeffMod1[i], totalCoeffMod2[i]); + } + } + + [TestMethod] + public void SEALContextParamsTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 128, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 }) + }; + SEALContext context = new SEALContext(parms, expandModChain: true, secLevel: SecLevelType.None); + + SEALContext.ContextData data = context.KeyContextData; + Assert.IsNotNull(data); + + EncryptionParameters parms2 = data.Parms; + Assert.AreEqual(parms.PolyModulusDegree, parms2.PolyModulusDegree); + + EncryptionParameterQualifiers qualifiers = data.Qualifiers; + Assert.IsNotNull(qualifiers); + + Assert.IsTrue(qualifiers.ParametersSet); + Assert.IsFalse(qualifiers.UsingBatching); + Assert.IsTrue(qualifiers.UsingFastPlainLift); + Assert.IsTrue(qualifiers.UsingFFT); + Assert.IsTrue(qualifiers.UsingNTT); + Assert.AreEqual(SecLevelType.None, qualifiers.SecLevel); + Assert.IsFalse(qualifiers.UsingDescendingModulusChain); + Assert.IsTrue(context.UsingKeyswitching); + + ulong[] cdpm = data.CoeffDivPlainModulus; + Assert.AreEqual(3, cdpm.Length); + + Assert.AreEqual(32ul, data.PlainUpperHalfThreshold); + + Assert.AreEqual(3, data.PlainUpperHalfIncrement.Length); + Assert.IsNull(data.UpperHalfThreshold); + Assert.IsNotNull(data.UpperHalfIncrement); + Assert.AreEqual(3, data.UpperHalfIncrement.Length); + Assert.AreEqual(2ul, data.ChainIndex); + + Assert.IsNull(data.PrevContextData); + SEALContext.ContextData data2 = data.NextContextData; + Assert.IsNotNull(data2); + Assert.AreEqual(1ul, data2.ChainIndex); + Assert.AreEqual(2ul, data2.PrevContextData.ChainIndex); + + SEALContext.ContextData data3 = data2.NextContextData; + Assert.IsNotNull(data3); + Assert.AreEqual(0ul, data3.ChainIndex); + Assert.AreEqual(1ul, data3.PrevContextData.ChainIndex); + Assert.IsNull(data3.NextContextData); + + parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 127, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 }) + }; + context = new SEALContext(parms, expandModChain: true, secLevel: SecLevelType.None); + Assert.AreEqual(context.ParameterErrorName(), "invalid_poly_modulus_degree_non_power_of_two"); + Assert.AreEqual(context.ParameterErrorMessage(), "poly_modulus_degree is not a power of two"); + } + + [TestMethod] + public void SEALContextCKKSParamsTest() + { + int slotSize = 4; + EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) + { + PolyModulusDegree = 2 * (ulong)slotSize, + CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + + SEALContext.ContextData data = context.KeyContextData; + Assert.IsNotNull(data); + + // This should be available in CKKS + Assert.IsNotNull(data.UpperHalfThreshold); + Assert.AreEqual(4, data.UpperHalfThreshold.Length); + Assert.IsNull(data.UpperHalfIncrement); + Assert.AreEqual(3ul, data.ChainIndex); + + Assert.IsNull(data.PrevContextData); + SEALContext.ContextData data2 = data.NextContextData; + Assert.IsNotNull(data2); + Assert.AreEqual(2ul, data2.ChainIndex); + Assert.AreEqual(3ul, data2.PrevContextData.ChainIndex); + + SEALContext.ContextData data3 = data2.NextContextData; + Assert.IsNotNull(data3); + Assert.AreEqual(1ul, data3.ChainIndex); + Assert.AreEqual(2ul, data3.PrevContextData.ChainIndex); + + SEALContext.ContextData data4 = data3.NextContextData; + Assert.IsNotNull(data4); + Assert.AreEqual(0ul, data4.ChainIndex); + Assert.AreEqual(1ul, data4.PrevContextData.ChainIndex); + + Assert.IsNull(data4.NextContextData); + } + + [TestMethod] + public void ExpandModChainTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 4096, + CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 4096), + PlainModulus = new Modulus(1 << 20) + }; + + SEALContext context1 = new SEALContext(parms, + expandModChain: true, + secLevel: SecLevelType.None); + + // By default there is a chain + SEALContext.ContextData contextData = context1.KeyContextData; + Assert.IsNotNull(contextData); + Assert.IsNull(contextData.PrevContextData); + Assert.IsNotNull(contextData.NextContextData); + contextData = context1.FirstContextData; + Assert.IsNotNull(contextData); + Assert.IsNotNull(contextData.PrevContextData); + Assert.IsNotNull(contextData.NextContextData); + + // This should not create a chain + SEALContext context2 = new SEALContext(parms, expandModChain: false); + contextData = context2.KeyContextData; + Assert.IsNotNull(contextData); + Assert.IsNull(contextData.PrevContextData); + Assert.IsNotNull(contextData.NextContextData); + contextData = context2.FirstContextData; + Assert.IsNotNull(contextData); + Assert.IsNotNull(contextData.PrevContextData); + Assert.IsNull(contextData.NextContextData); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/SEALNetTest.csproj b/bigpiseal3.5.1/dotnet/tests/SEALNetTest.csproj new file mode 100644 index 0000000000000000000000000000000000000000..2f9fbd19c8efa896bad7b9b50ff5041018db99e3 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/SEALNetTest.csproj @@ -0,0 +1,37 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netcoreapp3.1</TargetFramework> + <IsPackable>false</IsPackable> + <Authors>Microsoft Research</Authors> + <Company>Microsoft Corporation</Company> + <Description>.NET wrapper unit tests for Microsoft SEAL</Description> + <Copyright>Microsoft Corporation 2020</Copyright> + </PropertyGroup> + + <PropertyGroup Condition="'$(Platform)'=='AnyCPU'"> + <PlatformTarget>x64</PlatformTarget> + <OutputPath>$(ProjectDir)../../bin/dotnet/$(Configuration)</OutputPath> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> + <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" /> + <PackageReference Include="MSTest.TestFramework" Version="2.0.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="$(ProjectDir)../src/SEALNet.csproj" /> + </ItemGroup> + + <ItemGroup> + <SEALCBinaryFiles Condition="$([MSBuild]::IsOsPlatform(Windows))" Include="$(ProjectDir)..\..\lib\x64\$(Configuration)\sealc.dll" /> + <SEALCBinaryFiles Condition="$([MSBuild]::IsOsPlatform(Linux))" Include="$(ProjectDir)../../lib/libsealc.so.*" /> + <SEALCBinaryFiles Condition="$([MSBuild]::IsOsPlatform(OSX))" Include="$(ProjectDir)../../lib/libsealc*.dylib" /> + </ItemGroup> + + <Target Name="PostBuild" AfterTargets="PostBuildEvent"> + <Copy SourceFiles="@(SEALCBinaryFiles)" DestinationFolder="$(TargetDir)" /> + </Target> + +</Project> diff --git a/bigpiseal3.5.1/dotnet/tests/SecretKeyTests.cs b/bigpiseal3.5.1/dotnet/tests/SecretKeyTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..968b47f2a573561b78ca708a4a4da1f7887bb19f --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/SecretKeyTests.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Research.SEAL; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; + +namespace SEALNetTest +{ + [TestClass] + public class SecretKeyTests + { + [TestMethod] + public void CreateTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + SecretKey secret = keygen.SecretKey; + SecretKey copy = new SecretKey(secret); + + Assert.AreEqual(64ul, copy.Data.CoeffCount); + Assert.IsTrue(copy.Data.IsNTTForm); + + SecretKey copy2 = new SecretKey(); + copy2.Set(copy); + + Assert.AreEqual(64ul, copy2.Data.CoeffCount); + Assert.IsTrue(copy2.Data.IsNTTForm); + } + + [TestMethod] + public void SaveLoadTest() + { + EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) + { + PolyModulusDegree = 64, + PlainModulus = new Modulus(1 << 6), + CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) + }; + SEALContext context = new SEALContext(parms, + expandModChain: false, + secLevel: SecLevelType.None); + KeyGenerator keygen = new KeyGenerator(context); + + SecretKey secret = keygen.SecretKey; + + Assert.AreEqual(64ul, secret.Data.CoeffCount); + Assert.IsTrue(secret.Data.IsNTTForm); + Assert.AreNotEqual(ParmsId.Zero, secret.ParmsId); + + SecretKey secret2 = new SecretKey(); + Assert.IsNotNull(secret2); + Assert.AreEqual(0ul, secret2.Data.CoeffCount); + Assert.IsFalse(secret2.Data.IsNTTForm); + + using (MemoryStream stream = new MemoryStream()) + { + secret.Save(stream); + stream.Seek(offset: 0, loc: SeekOrigin.Begin); + secret2.Load(context, stream); + } + + Assert.AreNotSame(secret, secret2); + Assert.AreEqual(64ul, secret2.Data.CoeffCount); + Assert.IsTrue(secret2.Data.IsNTTForm); + Assert.AreNotEqual(ParmsId.Zero, secret2.ParmsId); + Assert.AreEqual(secret.ParmsId, secret2.ParmsId); + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + SecretKey key = new SecretKey(); + + Utilities.AssertThrows<ArgumentNullException>(() => key = new SecretKey(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => key.Set(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(key, null)); + + Utilities.AssertThrows<ArgumentNullException>(() => key.Save(null)); + + Utilities.AssertThrows<ArgumentNullException>(() => key.UnsafeLoad(null, new MemoryStream())); + Utilities.AssertThrows<ArgumentNullException>(() => key.UnsafeLoad(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => key.Load(context, null)); + Utilities.AssertThrows<ArgumentNullException>(() => key.Load(null, new MemoryStream())); + Utilities.AssertThrows<EndOfStreamException>(() => key.Load(context, new MemoryStream())); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/SerializationTests.cs b/bigpiseal3.5.1/dotnet/tests/SerializationTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..fd2a7ebea6ad446a42405ef16543911189ca7701 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/SerializationTests.cs @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Research.SEAL; +using System; +using System.IO; +using System.Text; + +namespace SEALNetTest +{ + [TestClass] + public class SerializationTests + { + [TestMethod] + public void IsValidHeader() + { + Assert.AreEqual(Serialization.SEALHeaderSize, 0x10); + + Serialization.SEALHeader header = new Serialization.SEALHeader(); + Assert.IsTrue(Serialization.IsValidHeader(header)); + + Serialization.SEALHeader invalidHeader = new Serialization.SEALHeader(); + invalidHeader.Magic = 0x1212; + Assert.IsFalse(Serialization.IsValidHeader(invalidHeader)); + invalidHeader.Magic = Serialization.SEALMagic; + Assert.AreEqual(Serialization.SEALHeaderSize, invalidHeader.HeaderSize); + invalidHeader.VersionMajor = 0x02; + Assert.IsFalse(Serialization.IsValidHeader(invalidHeader)); + invalidHeader.VersionMajor = SEALVersion.Major; + invalidHeader.ComprMode = (ComprModeType)0x02; + Assert.IsFalse(Serialization.IsValidHeader(invalidHeader)); + } + + [TestMethod] + public void SEALHeaderSaveLoad() + { + Serialization.SEALHeader header = new Serialization.SEALHeader(); + Serialization.SEALHeader loaded = new Serialization.SEALHeader(); + using (MemoryStream mem = new MemoryStream()) + { + header.ComprMode = Serialization.ComprModeDefault; + header.Size = 256; + Assert.IsTrue(Serialization.IsValidHeader(header)); + + Serialization.SaveHeader(header, mem); + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + Serialization.LoadHeader(mem, loaded); + + Assert.AreEqual(loaded.Magic, header.Magic); + Assert.AreEqual(loaded.HeaderSize, header.HeaderSize); + Assert.AreEqual(loaded.VersionMajor, header.VersionMajor); + Assert.AreEqual(loaded.VersionMinor, header.VersionMinor); + Assert.AreEqual(loaded.ComprMode, header.ComprMode); + Assert.AreEqual(loaded.Reserved, header.Reserved); + Assert.AreEqual(loaded.Size, header.Size); + } + } + + [TestMethod] + public void SEALHeaderUpgrade() + { + LegacyHeaders.SEALHeader_3_4 header_3_4 = new LegacyHeaders.SEALHeader_3_4(); + + using MemoryStream mem = new MemoryStream(); + using BinaryWriter writer = new BinaryWriter(mem, Encoding.UTF8, true); + writer.Write(header_3_4.Magic); + writer.Write(header_3_4.ZeroByte); + writer.Write((byte)header_3_4.ComprMode); + writer.Write(header_3_4.Size); + writer.Write(header_3_4.Reserved); + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + + { + Serialization.SEALHeader loaded = new Serialization.SEALHeader(); + Serialization.LoadHeader(mem, loaded); + Assert.IsTrue(Serialization.IsValidHeader(loaded)); + Assert.AreEqual(header_3_4.ComprMode, loaded.ComprMode); + Assert.AreEqual(header_3_4.Size, loaded.Size); + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + } + { + Serialization.SEALHeader loaded = new Serialization.SEALHeader(); + Serialization.LoadHeader(mem, loaded, false); + Assert.IsFalse(Serialization.IsValidHeader(loaded)); + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + } + } + + [TestMethod] + public void ExceptionsTest() + { + SEALContext context = GlobalContext.BFVContext; + Ciphertext cipher = new Ciphertext(); + + using (MemoryStream mem = new MemoryStream()) + { + KeyGenerator keygen = new KeyGenerator(context); + Encryptor encryptor = new Encryptor(context, keygen.PublicKey); + Plaintext plain = new Plaintext("2x^3 + 4x^2 + 5x^1 + 6"); + encryptor.Encrypt(plain, cipher); + cipher.Save(mem); + mem.Seek(offset: 8, loc: SeekOrigin.Begin); + BinaryWriter writer = new BinaryWriter(mem, Encoding.UTF8, true); + writer.Write((ulong)0x80000000); + + mem.Seek(offset: 0, loc: SeekOrigin.Begin); + Utilities.AssertThrows<InvalidOperationException>(() => cipher.Load(context, mem)); + } + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/TestAssemblyCleanup.cs b/bigpiseal3.5.1/dotnet/tests/TestAssemblyCleanup.cs new file mode 100644 index 0000000000000000000000000000000000000000..91cc2ddb073e6be85f8d0c4c8ee593880444a213 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/TestAssemblyCleanup.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace SEALNetTest +{ + [TestClass] + public class TestAssemblyCleanup + { + [AssemblyCleanup] + public static void AssemblyCleanup() + { + // Check that our Assert.Throw workaround is not getting out of hand + Assert.IsTrue(Utilities.WorkaroundInstanceCount <= 2, $"WorkaroundInstanceCount should be <= 2, it is: {Utilities.WorkaroundInstanceCount}"); + Trace.WriteLine($"Assert.Throw workaround instances found: {Utilities.WorkaroundInstanceCount}"); + } + } +} diff --git a/bigpiseal3.5.1/dotnet/tests/Utilities.cs b/bigpiseal3.5.1/dotnet/tests/Utilities.cs new file mode 100644 index 0000000000000000000000000000000000000000..18621f7039150afcb9e52279a4b18cde57f8cae5 --- /dev/null +++ b/bigpiseal3.5.1/dotnet/tests/Utilities.cs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; + +namespace SEALNetTest +{ + /// <summary> + /// Test utilities + /// </summary> + public static class Utilities + { + internal static int WorkaroundInstanceCount { get; private set; } = 0; + + /// <summary> + /// Assert that an exception of the given type is thrown. + /// + /// This is a workaround for a unit testing issue in VS 2019. + /// When running unit tests a couple of them fail because of a FileNotFoundException being thrown instead + /// of the expected exception. The FileNotFoundException is thrown in the boundary between a .Net call + /// and a native method, so there is not really much we can do to fix it. As a workaround this method + /// works as Assert.ThrowsException, but allows FileNotFoundException as well, and outputs a warning when + /// it is found. + /// </summary> + /// <typeparam name="T">Expected exception type</typeparam> + /// <param name="action">Function to run that should throw an exception</param> + /// <param name="caller">Path to the source file that called this method</param> + /// <param name="line">Line in the source file that called this method</param> + public static void AssertThrows<T>(Func<object> action, [CallerFilePath] string caller = "", [CallerLineNumber] int line = 0) where T : Exception + { + DoAssertThrow<T>(() => { var result = action(); }, caller, line); + } + + /// <summary> + /// Assert that an exception of the given type is thrown. + /// + /// This is a workaround for a unit testing issue in VS 2019. + /// When running unit tests a couple of them fail because of a FileNotFoundException being thrown instead + /// of the expected exception. The FileNotFoundException is thrown in the boundary between a .Net call + /// and a native method, so there is not really much we can do to fix it. As a workaround this method + /// works as Assert.ThrowsException, but allows FileNotFoundException as well, and outputs a warning when + /// it is found. + /// </summary> + /// <typeparam name="T">Expected exception type</typeparam> + /// <param name="action">Action to run that should throw an exception</param> + /// <param name="caller">Path to the source file that called this method</param> + /// <param name="line">Line in the source file that called this method</param> + public static void AssertThrows<T>(Action action, [CallerFilePath] string caller = "", [CallerLineNumber] int line = 0) where T : Exception + { + DoAssertThrow<T>(action, caller, line); + } + + private static void DoAssertThrow<T>(Action action, string caller, int line) where T : Exception + { + string expectedStr = typeof(T).ToString(); + + try + { + action(); + } + catch (Exception ex) + { + if (ex is T) + { + // Expected exception has been thrown + return; + } + + // Workaround: Check if exception is FileNotFoundException + if (ex is FileNotFoundException workaroundExc) + { + string workaroundStr = workaroundExc.GetType().ToString(); + Trace.WriteLine($"WARNING: {caller}:{line}: Expected exception of type '{expectedStr}', got type '{workaroundStr}' instead."); + WorkaroundInstanceCount++; + return; + } + + // Any other exception should fail. + string actualStr = ex.GetType().ToString(); + Assert.Fail($"{caller}:{line}: Expected exception of type '{expectedStr}', got type '{actualStr}' instead."); + } + + Assert.Fail($"{caller}:{line}: Expected exception of type '{expectedStr}', no exception thrown."); + } + } +} diff --git a/bigpiseal3.5.1/native/examples/1_bfv_basics.cpp b/bigpiseal3.5.1/native/examples/1_bfv_basics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76c8061edb1f6387c1d2bcdc5c1db394d5d830a1 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/1_bfv_basics.cpp @@ -0,0 +1,428 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +void example_bfv_basics() +{ + print_example_banner("Example: BFV Basics"); + + /* + In this example, we demonstrate performing simple computations (a polynomial + evaluation) on encrypted integers using the BFV encryption scheme. + + The first task is to set up an instance of the EncryptionParameters class. + It is critical to understand how the different parameters behave, how they + affect the encryption scheme, performance, and the security level. There are + three encryption parameters that are necessary to set: + + - poly_modulus_degree (degree of polynomial modulus); + - coeff_modulus ([ciphertext] coefficient modulus); + - plain_modulus (plaintext modulus; only for the BFV scheme). + + The BFV scheme cannot perform arbitrary computations on encrypted data. + Instead, each ciphertext has a specific quantity called the `invariant noise + budget' -- or `noise budget' for short -- measured in bits. The noise budget + in a freshly encrypted ciphertext (initial noise budget) is determined by + the encryption parameters. Homomorphic operations consume the noise budget + at a rate also determined by the encryption parameters. In BFV the two basic + operations allowed on encrypted data are additions and multiplications, of + which additions can generally be thought of as being nearly free in terms of + noise budget consumption compared to multiplications. Since noise budget + consumption compounds in sequential multiplications, the most significant + factor in choosing appropriate encryption parameters is the multiplicative + depth of the arithmetic circuit that the user wants to evaluate on encrypted + data. Once the noise budget of a ciphertext reaches zero it becomes too + corrupted to be decrypted. Thus, it is essential to choose the parameters to + be large enough to support the desired computation; otherwise the result is + impossible to make sense of even with the secret key. + */ + EncryptionParameters parms(scheme_type::BFV); + + /* + The first parameter we set is the degree of the `polynomial modulus'. This + must be a positive power of 2, representing the degree of a power-of-two + cyclotomic polynomial; it is not necessary to understand what this means. + + Larger poly_modulus_degree makes ciphertext sizes larger and all operations + slower, but enables more complicated encrypted computations. Recommended + values are 1024, 2048, 4096, 8192, 16384, 32768, but it is also possible + to go beyond this range. + + In this example we use a relatively small polynomial modulus. Anything + smaller than this will enable only very restricted encrypted computations. + */ + size_t poly_modulus_degree = 4096; + parms.set_poly_modulus_degree(poly_modulus_degree); + + /* + Next we set the [ciphertext] `coefficient modulus' (coeff_modulus). This + parameter is a large integer, which is a product of distinct prime numbers, + each up to 60 bits in size. It is represented as a vector of these prime + numbers, each represented by an instance of the Modulus class. The + bit-length of coeff_modulus means the sum of the bit-lengths of its prime + factors. + + A larger coeff_modulus implies a larger noise budget, hence more encrypted + computation capabilities. However, an upper bound for the total bit-length + of the coeff_modulus is determined by the poly_modulus_degree, as follows: + + +----------------------------------------------------+ + | poly_modulus_degree | max coeff_modulus bit-length | + +---------------------+------------------------------+ + | 1024 | 27 | + | 2048 | 54 | + | 4096 | 109 | + | 8192 | 218 | + | 16384 | 438 | + | 32768 | 881 | + +---------------------+------------------------------+ + + These numbers can also be found in native/src/seal/util/hestdparms.h encoded + in the function SEAL_HE_STD_PARMS_128_TC, and can also be obtained from the + function + + CoeffModulus::MaxBitCount(poly_modulus_degree). + + For example, if poly_modulus_degree is 4096, the coeff_modulus could consist + of three 36-bit primes (108 bits). + + Microsoft SEAL comes with helper functions for selecting the coeff_modulus. + For new users the easiest way is to simply use + + CoeffModulus::BFVDefault(poly_modulus_degree), + + which returns std::vector<Modulus> consisting of a generally good choice + for the given poly_modulus_degree. + */ + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + + /* + The plaintext modulus can be any positive integer, even though here we take + it to be a power of two. In fact, in many cases one might instead want it + to be a prime number; we will see this in later examples. The plaintext + modulus determines the size of the plaintext data type and the consumption + of noise budget in multiplications. Thus, it is essential to try to keep the + plaintext data type as small as possible for best performance. The noise + budget in a freshly encrypted ciphertext is + + ~ log2(coeff_modulus/plain_modulus) (bits) + + and the noise budget consumption in a homomorphic multiplication is of the + form log2(plain_modulus) + (other terms). + + The plaintext modulus is specific to the BFV scheme, and cannot be set when + using the CKKS scheme. + */ + parms.set_plain_modulus(1024); + + /* + Now that all parameters are set, we are ready to construct a SEALContext + object. This is a heavy class that checks the validity and properties of the + parameters we just set. + */ + auto context = SEALContext::Create(parms); + + /* + Print the parameters that we have chosen. + */ + print_line(__LINE__); + cout << "Set encryption parameters and print" << endl; + print_parameters(context); + + /* + When parameters are used to create SEALContext, Microsoft SEAL will first + validate those parameters. The parameters chosen here are valid. + */ + cout << "Parameter validation (success): " << context->parameter_error_message() << endl; + + cout << endl; + cout << "~~~~~~ A naive way to calculate 4(x^2+1)(x+1)^2. ~~~~~~" << endl; + + /* + The encryption schemes in Microsoft SEAL are public key encryption schemes. + For users unfamiliar with this terminology, a public key encryption scheme + has a separate public key for encrypting data, and a separate secret key for + decrypting data. This way multiple parties can encrypt data using the same + shared public key, but only the proper recipient of the data can decrypt it + with the secret key. + + We are now ready to generate the secret and public keys. For this purpose + we need an instance of the KeyGenerator class. Constructing a KeyGenerator + automatically generates the public and secret key, which can immediately be + read to local variables. + */ + KeyGenerator keygen(context); + PublicKey public_key = keygen.public_key(); + SecretKey secret_key = keygen.secret_key(); + + /* + To be able to encrypt we need to construct an instance of Encryptor. Note + that the Encryptor only requires the public key, as expected. + */ + Encryptor encryptor(context, public_key); + + /* + Computations on the ciphertexts are performed with the Evaluator class. In + a real use-case the Evaluator would not be constructed by the same party + that holds the secret key. + */ + Evaluator evaluator(context); + + /* + We will of course want to decrypt our results to verify that everything worked, + so we need to also construct an instance of Decryptor. Note that the Decryptor + requires the secret key. + */ + Decryptor decryptor(context, secret_key); + + /* + As an example, we evaluate the degree 4 polynomial + + 4x^4 + 8x^3 + 8x^2 + 8x + 4 + + over an encrypted x = 6. The coefficients of the polynomial can be considered + as plaintext inputs, as we will see below. The computation is done modulo the + plain_modulus 1024. + + While this examples is simple and easy to understand, it does not have much + practical value. In later examples we will demonstrate how to compute more + efficiently on encrypted integers and real or complex numbers. + + Plaintexts in the BFV scheme are polynomials of degree less than the degree + of the polynomial modulus, and coefficients integers modulo the plaintext + modulus. For readers with background in ring theory, the plaintext space is + the polynomial quotient ring Z_T[X]/(X^N + 1), where N is poly_modulus_degree + and T is plain_modulus. + + To get started, we create a plaintext containing the constant 6. For the + plaintext element we use a constructor that takes the desired polynomial as + a string with coefficients represented as hexadecimal numbers. + */ + print_line(__LINE__); + int x = 6; + Plaintext x_plain(to_string(x)); + cout << "Express x = " + to_string(x) + " as a plaintext polynomial 0x" + x_plain.to_string() + "." << endl; + + /* + We then encrypt the plaintext, producing a ciphertext. + */ + print_line(__LINE__); + Ciphertext x_encrypted; + cout << "Encrypt x_plain to x_encrypted." << endl; + encryptor.encrypt(x_plain, x_encrypted); + + /* + In Microsoft SEAL, a valid ciphertext consists of two or more polynomials + whose coefficients are integers modulo the product of the primes in the + coeff_modulus. The number of polynomials in a ciphertext is called its `size' + and is given by Ciphertext::size(). A freshly encrypted ciphertext always + has size 2. + */ + cout << " + size of freshly encrypted x: " << x_encrypted.size() << endl; + + /* + There is plenty of noise budget left in this freshly encrypted ciphertext. + */ + cout << " + noise budget in freshly encrypted x: " << decryptor.invariant_noise_budget(x_encrypted) << " bits" + << endl; + + /* + We decrypt the ciphertext and print the resulting plaintext in order to + demonstrate correctness of the encryption. + */ + Plaintext x_decrypted; + cout << " + decryption of x_encrypted: "; + decryptor.decrypt(x_encrypted, x_decrypted); + cout << "0x" << x_decrypted.to_string() << " ...... Correct." << endl; + + /* + When using Microsoft SEAL, it is typically advantageous to compute in a way + that minimizes the longest chain of sequential multiplications. In other + words, encrypted computations are best evaluated in a way that minimizes + the multiplicative depth of the computation, because the total noise budget + consumption is proportional to the multiplicative depth. For example, for + our example computation it is advantageous to factorize the polynomial as + + 4x^4 + 8x^3 + 8x^2 + 8x + 4 = 4(x + 1)^2 * (x^2 + 1) + + to obtain a simple depth 2 representation. Thus, we compute (x + 1)^2 and + (x^2 + 1) separately, before multiplying them, and multiplying by 4. + + First, we compute x^2 and add a plaintext "1". We can clearly see from the + print-out that multiplication has consumed a lot of noise budget. The user + can vary the plain_modulus parameter to see its effect on the rate of noise + budget consumption. + */ + print_line(__LINE__); + cout << "Compute x_sq_plus_one (x^2+1)." << endl; + Ciphertext x_sq_plus_one; + evaluator.square(x_encrypted, x_sq_plus_one); + Plaintext plain_one("1"); + evaluator.add_plain_inplace(x_sq_plus_one, plain_one); + + /* + Encrypted multiplication results in the output ciphertext growing in size. + More precisely, if the input ciphertexts have size M and N, then the output + ciphertext after homomorphic multiplication will have size M+N-1. In this + case we perform a squaring, and observe both size growth and noise budget + consumption. + */ + cout << " + size of x_sq_plus_one: " << x_sq_plus_one.size() << endl; + cout << " + noise budget in x_sq_plus_one: " << decryptor.invariant_noise_budget(x_sq_plus_one) << " bits" + << endl; + + /* + Even though the size has grown, decryption works as usual as long as noise + budget has not reached 0. + */ + Plaintext decrypted_result; + cout << " + decryption of x_sq_plus_one: "; + decryptor.decrypt(x_sq_plus_one, decrypted_result); + cout << "0x" << decrypted_result.to_string() << " ...... Correct." << endl; + + /* + Next, we compute (x + 1)^2. + */ + print_line(__LINE__); + cout << "Compute x_plus_one_sq ((x+1)^2)." << endl; + Ciphertext x_plus_one_sq; + evaluator.add_plain(x_encrypted, plain_one, x_plus_one_sq); + evaluator.square_inplace(x_plus_one_sq); + cout << " + size of x_plus_one_sq: " << x_plus_one_sq.size() << endl; + cout << " + noise budget in x_plus_one_sq: " << decryptor.invariant_noise_budget(x_plus_one_sq) << " bits" + << endl; + cout << " + decryption of x_plus_one_sq: "; + decryptor.decrypt(x_plus_one_sq, decrypted_result); + cout << "0x" << decrypted_result.to_string() << " ...... Correct." << endl; + + /* + Finally, we multiply (x^2 + 1) * (x + 1)^2 * 4. + */ + print_line(__LINE__); + cout << "Compute encrypted_result (4(x^2+1)(x+1)^2)." << endl; + Ciphertext encrypted_result; + Plaintext plain_four("4"); + evaluator.multiply_plain_inplace(x_sq_plus_one, plain_four); + evaluator.multiply(x_sq_plus_one, x_plus_one_sq, encrypted_result); + cout << " + size of encrypted_result: " << encrypted_result.size() << endl; + cout << " + noise budget in encrypted_result: " << decryptor.invariant_noise_budget(encrypted_result) << " bits" + << endl; + cout << "NOTE: Decryption can be incorrect if noise budget is zero." << endl; + + cout << endl; + cout << "~~~~~~ A better way to calculate 4(x^2+1)(x+1)^2. ~~~~~~" << endl; + + /* + Noise budget has reached 0, which means that decryption cannot be expected + to give the correct result. This is because both ciphertexts x_sq_plus_one + and x_plus_one_sq consist of 3 polynomials due to the previous squaring + operations, and homomorphic operations on large ciphertexts consume much more + noise budget than computations on small ciphertexts. Computing on smaller + ciphertexts is also computationally significantly cheaper. + + `Relinearization' is an operation that reduces the size of a ciphertext after + multiplication back to the initial size, 2. Thus, relinearizing one or both + input ciphertexts before the next multiplication can have a huge positive + impact on both noise growth and performance, even though relinearization has + a significant computational cost itself. It is only possible to relinearize + size 3 ciphertexts down to size 2, so often the user would want to relinearize + after each multiplication to keep the ciphertext sizes at 2. + + Relinearization requires special `relinearization keys', which can be thought + of as a kind of public key. Relinearization keys can easily be created with + the KeyGenerator. + + Relinearization is used similarly in both the BFV and the CKKS schemes, but + in this example we continue using BFV. We repeat our computation from before, + but this time relinearize after every multiplication. + + Here we use the function KeyGenerator::relin_keys_local(). In production + code it is much better to use KeyGenerator::relin_keys() instead. We will + explain and discuss these differences in `6_serialization.cpp'. + */ + print_line(__LINE__); + cout << "Generate locally usable relinearization keys." << endl; + auto relin_keys = keygen.relin_keys_local(); + + /* + We now repeat the computation relinearizing after each multiplication. + */ + print_line(__LINE__); + cout << "Compute and relinearize x_squared (x^2)," << endl; + cout << string(13, ' ') << "then compute x_sq_plus_one (x^2+1)" << endl; + Ciphertext x_squared; + evaluator.square(x_encrypted, x_squared); + cout << " + size of x_squared: " << x_squared.size() << endl; + evaluator.relinearize_inplace(x_squared, relin_keys); + cout << " + size of x_squared (after relinearization): " << x_squared.size() << endl; + evaluator.add_plain(x_squared, plain_one, x_sq_plus_one); + cout << " + noise budget in x_sq_plus_one: " << decryptor.invariant_noise_budget(x_sq_plus_one) << " bits" + << endl; + cout << " + decryption of x_sq_plus_one: "; + decryptor.decrypt(x_sq_plus_one, decrypted_result); + cout << "0x" << decrypted_result.to_string() << " ...... Correct." << endl; + + print_line(__LINE__); + Ciphertext x_plus_one; + cout << "Compute x_plus_one (x+1)," << endl; + cout << string(13, ' ') << "then compute and relinearize x_plus_one_sq ((x+1)^2)." << endl; + evaluator.add_plain(x_encrypted, plain_one, x_plus_one); + evaluator.square(x_plus_one, x_plus_one_sq); + cout << " + size of x_plus_one_sq: " << x_plus_one_sq.size() << endl; + evaluator.relinearize_inplace(x_plus_one_sq, relin_keys); + cout << " + noise budget in x_plus_one_sq: " << decryptor.invariant_noise_budget(x_plus_one_sq) << " bits" + << endl; + cout << " + decryption of x_plus_one_sq: "; + decryptor.decrypt(x_plus_one_sq, decrypted_result); + cout << "0x" << decrypted_result.to_string() << " ...... Correct." << endl; + + print_line(__LINE__); + cout << "Compute and relinearize encrypted_result (4(x^2+1)(x+1)^2)." << endl; + evaluator.multiply_plain_inplace(x_sq_plus_one, plain_four); + evaluator.multiply(x_sq_plus_one, x_plus_one_sq, encrypted_result); + cout << " + size of encrypted_result: " << encrypted_result.size() << endl; + evaluator.relinearize_inplace(encrypted_result, relin_keys); + cout << " + size of encrypted_result (after relinearization): " << encrypted_result.size() << endl; + cout << " + noise budget in encrypted_result: " << decryptor.invariant_noise_budget(encrypted_result) << " bits" + << endl; + + cout << endl; + cout << "NOTE: Notice the increase in remaining noise budget." << endl; + + /* + Relinearization clearly improved our noise consumption. We have still plenty + of noise budget left, so we can expect the correct answer when decrypting. + */ + print_line(__LINE__); + cout << "Decrypt encrypted_result (4(x^2+1)(x+1)^2)." << endl; + decryptor.decrypt(encrypted_result, decrypted_result); + cout << " + decryption of 4(x^2+1)(x+1)^2 = 0x" << decrypted_result.to_string() << " ...... Correct." << endl; + cout << endl; + + /* + For x=6, 4(x^2+1)(x+1)^2 = 7252. Since the plaintext modulus is set to 1024, + this result is computed in integers modulo 1024. Therefore the expected output + should be 7252 % 1024 == 84, or 0x54 in hexadecimal. + */ + + /* + Sometimes we create customized encryption parameters which turn out to be invalid. + Microsoft SEAL can interpret the reason why parameters are considered invalid. + Here we simply reduce the polynomial modulus degree to make the parameters not + compliant with the HomomorphicEncryption.org security standard. + */ + print_line(__LINE__); + cout << "An example of invalid parameters" << endl; + parms.set_poly_modulus_degree(2048); + context = SEALContext::Create(parms); + print_parameters(context); + cout << "Parameter validation (failed): " << context->parameter_error_message() << endl; + + /* + This information is helpful to fix invalid encryption parameters. + */ +} diff --git a/bigpiseal3.5.1/native/examples/2_encoders.cpp b/bigpiseal3.5.1/native/examples/2_encoders.cpp new file mode 100644 index 0000000000000000000000000000000000000000..319ef3c7f375119b71f35683ece9e8001d96f4a8 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/2_encoders.cpp @@ -0,0 +1,475 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +/* +In `1_bfv_basics.cpp' we showed how to perform a very simple computation using the +BFV scheme. The computation was performed modulo the plain_modulus parameter, and +utilized only one coefficient from a BFV plaintext polynomial. This approach has +two notable problems: + + (1) Practical applications typically use integer or real number arithmetic, + not modular arithmetic; + (2) We used only one coefficient of the plaintext polynomial. This is really + wasteful, as the plaintext polynomial is large and will in any case be + encrypted in its entirety. + +For (1), one may ask why not just increase the plain_modulus parameter until no +overflow occurs, and the computations behave as in integer arithmetic. The problem +is that increasing plain_modulus increases noise budget consumption, and decreases +the initial noise budget too. + +In these examples we will discuss other ways of laying out data into plaintext +elements (encoding) that allow more computations without data type overflow, and +can allow the full plaintext polynomial to be utilized. +*/ +void example_integer_encoder() +{ + print_example_banner("Example: Encoders / Integer Encoder"); + + /* + [IntegerEncoder] (For BFV scheme only) + + The IntegerEncoder encodes integers to BFV plaintext polynomials as follows. + First, a binary expansion of the integer is computed. Next, a polynomial is + created with the bits as coefficients. For example, the integer + + 26 = 2^4 + 2^3 + 2^1 + + is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext + polynomials are decoded by evaluating them at x=2. For negative numbers the + IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is + represented by the unsigned integer plain_modulus - 1 in memory. + + Since encrypted computations operate on the polynomials rather than on the + encoded integers themselves, the polynomial coefficients will grow in the + course of such computations. For example, computing the sum of the encrypted + encoded integer 26 with itself will result in an encrypted polynomial with + larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded + integer 26 results also in increased coefficients due to cross-terms, namely, + + (1x^4 + 1x^3 + 1x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2; + + further computations will quickly increase the coefficients much more. + Decoding will still work correctly in this case (evaluating the polynomial + at x=2), but since the coefficients of plaintext polynomials are really + integers modulo plain_modulus, implicit reduction modulo plain_modulus may + yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself + plain_modulus many times will result in the constant polynomial 0, which is + clearly not equal to 26 * plain_modulus. It can be difficult to predict when + such overflow will take place especially when computing several sequential + multiplications. + + The IntegerEncoder is easy to understand and use for simple computations, + and can be a good tool to experiment with for users new to Microsoft SEAL. + However, advanced users will probably prefer more efficient approaches, + such as the BatchEncoder or the CKKSEncoder. + */ + EncryptionParameters parms(scheme_type::BFV); + size_t poly_modulus_degree = 4096; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + + /* + There is no hidden logic behind our choice of the plain_modulus. The only + thing that matters is that the plaintext polynomial coefficients will not + exceed this value at any point during our computation; otherwise the result + will be incorrect. + */ + parms.set_plain_modulus(512); + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + KeyGenerator keygen(context); + PublicKey public_key = keygen.public_key(); + SecretKey secret_key = keygen.secret_key(); + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + /* + We create an IntegerEncoder. + */ + IntegerEncoder encoder(context); + + /* + First, we encode two integers as plaintext polynomials. Note that encoding + is not encryption: at this point nothing is encrypted. + */ + int value1 = 5; + Plaintext plain1 = encoder.encode(value1); + print_line(__LINE__); + cout << "Encode " << value1 << " as polynomial " << plain1.to_string() << " (plain1)," << endl; + + int value2 = -7; + Plaintext plain2 = encoder.encode(value2); + cout << string(13, ' ') << "encode " << value2 << " as polynomial " << plain2.to_string() << " (plain2)." << endl; + + /* + Now we can encrypt the plaintext polynomials. + */ + Ciphertext encrypted1, encrypted2; + print_line(__LINE__); + cout << "Encrypt plain1 to encrypted1 and plain2 to encrypted2." << endl; + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + cout << " + Noise budget in encrypted1: " << decryptor.invariant_noise_budget(encrypted1) << " bits" << endl; + cout << " + Noise budget in encrypted2: " << decryptor.invariant_noise_budget(encrypted2) << " bits" << endl; + + /* + As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2. + */ + encryptor.encrypt(plain2, encrypted2); + Ciphertext encrypted_result; + print_line(__LINE__); + cout << "Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2." << endl; + evaluator.negate(encrypted1, encrypted_result); + evaluator.add_inplace(encrypted_result, encrypted2); + evaluator.multiply_inplace(encrypted_result, encrypted2); + cout << " + Noise budget in encrypted_result: " << decryptor.invariant_noise_budget(encrypted_result) << " bits" + << endl; + Plaintext plain_result; + print_line(__LINE__); + cout << "Decrypt encrypted_result to plain_result." << endl; + decryptor.decrypt(encrypted_result, plain_result); + + /* + Print the result plaintext polynomial. The coefficients are not even close + to exceeding our plain_modulus, 512. + */ + cout << " + Plaintext polynomial: " << plain_result.to_string() << endl; + + /* + Decode to obtain an integer result. + */ + print_line(__LINE__); + cout << "Decode plain_result." << endl; + cout << " + Decoded integer: " << encoder.decode_int32(plain_result); + cout << "...... Correct." << endl; +} + +void example_batch_encoder() +{ + print_example_banner("Example: Encoders / Batch Encoder"); + + /* + [BatchEncoder] (For BFV scheme only) + + Let N denote the poly_modulus_degree and T denote the plain_modulus. Batching + allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with + each element an integer modulo T. In the matrix view, encrypted operations act + element-wise on encrypted matrices, allowing the user to obtain speeds-ups of + several orders of magnitude in fully vectorizable computations. Thus, in all + but the simplest computations, batching should be the preferred method to use + with BFV, and when used properly will result in implementations outperforming + anything done with the IntegerEncoder. + */ + EncryptionParameters parms(scheme_type::BFV); + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + + /* + To enable batching, we need to set the plain_modulus to be a prime number + congruent to 1 modulo 2*poly_modulus_degree. Microsoft SEAL provides a helper + method for finding such a prime. In this example we create a 20-bit prime + that supports batching. + */ + parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20)); + + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + /* + We can verify that batching is indeed enabled by looking at the encryption + parameter qualifiers created by SEALContext. + */ + auto qualifiers = context->first_context_data()->qualifiers(); + cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + KeyGenerator keygen(context); + PublicKey public_key = keygen.public_key(); + SecretKey secret_key = keygen.secret_key(); + RelinKeys relin_keys = keygen.relin_keys_local(); + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + /* + Batching is done through an instance of the BatchEncoder class. + */ + BatchEncoder batch_encoder(context); + + /* + The total number of batching `slots' equals the poly_modulus_degree, N, and + these slots are organized into 2-by-(N/2) matrices that can be encrypted and + computed on. Each slot contains an integer modulo plain_modulus. + */ + size_t slot_count = batch_encoder.slot_count(); + size_t row_size = slot_count / 2; + cout << "Plaintext matrix row size: " << row_size << endl; + + /* + The matrix plaintext is simply given to BatchEncoder as a flattened vector + of numbers. The first `row_size' many numbers form the first row, and the + rest form the second row. Here we create the following matrix: + + [ 0, 1, 2, 3, 0, 0, ..., 0 ] + [ 4, 5, 6, 7, 0, 0, ..., 0 ] + */ + vector<uint64_t> pod_matrix(slot_count, 0ULL); + pod_matrix[0] = 0ULL; + pod_matrix[1] = 1ULL; + pod_matrix[2] = 2ULL; + pod_matrix[3] = 3ULL; + pod_matrix[row_size] = 4ULL; + pod_matrix[row_size + 1] = 5ULL; + pod_matrix[row_size + 2] = 6ULL; + pod_matrix[row_size + 3] = 7ULL; + + cout << "Input plaintext matrix:" << endl; + print_matrix(pod_matrix, row_size); + + /* + First we use BatchEncoder to encode the matrix into a plaintext polynomial. + */ + Plaintext plain_matrix; + print_line(__LINE__); + cout << "Encode plaintext matrix:" << endl; + batch_encoder.encode(pod_matrix, plain_matrix); + + /* + We can instantly decode to verify correctness of the encoding. Note that no + encryption or decryption has yet taken place. + */ + vector<uint64_t> pod_result; + cout << " + Decode plaintext matrix ...... Correct." << endl; + batch_encoder.decode(plain_matrix, pod_result); + print_matrix(pod_result, row_size); + + /* + Next we encrypt the encoded plaintext. + */ + Ciphertext encrypted_matrix; + print_line(__LINE__); + cout << "Encrypt plain_matrix to encrypted_matrix." << endl; + encryptor.encrypt(plain_matrix, encrypted_matrix); + cout << " + Noise budget in encrypted_matrix: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" + << endl; + + /* + Operating on the ciphertext results in homomorphic operations being performed + simultaneously in all 8192 slots (matrix elements). To illustrate this, we + form another plaintext matrix + + [ 1, 2, 1, 2, 1, 2, ..., 2 ] + [ 1, 2, 1, 2, 1, 2, ..., 2 ] + + and encode it into a plaintext. + */ + vector<uint64_t> pod_matrix2; + for (size_t i = 0; i < slot_count; i++) + { + pod_matrix2.push_back((i % 2) + 1); + } + Plaintext plain_matrix2; + batch_encoder.encode(pod_matrix2, plain_matrix2); + cout << endl; + cout << "Second input plaintext matrix:" << endl; + print_matrix(pod_matrix2, row_size); + + /* + We now add the second (plaintext) matrix to the encrypted matrix, and square + the sum. + */ + print_line(__LINE__); + cout << "Sum, square, and relinearize." << endl; + evaluator.add_plain_inplace(encrypted_matrix, plain_matrix2); + evaluator.square_inplace(encrypted_matrix); + evaluator.relinearize_inplace(encrypted_matrix, relin_keys); + + /* + How much noise budget do we have left? + */ + cout << " + Noise budget in result: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" << endl; + + /* + We decrypt and decompose the plaintext to recover the result as a matrix. + */ + Plaintext plain_result; + print_line(__LINE__); + cout << "Decrypt and decode result." << endl; + decryptor.decrypt(encrypted_matrix, plain_result); + batch_encoder.decode(plain_result, pod_result); + cout << " + Result plaintext matrix ...... Correct." << endl; + print_matrix(pod_result, row_size); + + /* + Batching allows us to efficiently use the full plaintext polynomial when the + desired encrypted computation is highly parallelizable. However, it has not + solved the other problem mentioned in the beginning of this file: each slot + holds only an integer modulo plain_modulus, and unless plain_modulus is very + large, we can quickly encounter data type overflow and get unexpected results + when integer computations are desired. Note that overflow cannot be detected + in encrypted form. The CKKS scheme (and the CKKSEncoder) addresses the data + type overflow issue, but at the cost of yielding only approximate results. + */ +} + +void example_ckks_encoder() +{ + print_example_banner("Example: Encoders / CKKS Encoder"); + + /* + [CKKSEncoder] (For CKKS scheme only) + + In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for + computing on encrypted real or complex numbers. We start by creating + encryption parameters for the CKKS scheme. There are two important + differences compared to the BFV scheme: + + (1) CKKS does not use the plain_modulus encryption parameter; + (2) Selecting the coeff_modulus in a specific way can be very important + when using the CKKS scheme. We will explain this further in the file + `ckks_basics.cpp'. In this example we use CoeffModulus::Create to + generate 5 40-bit prime numbers. + */ + EncryptionParameters parms(scheme_type::CKKS); + + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 40, 40, 40, 40, 40 })); + + /* + We create the SEALContext as usual and print the parameters. + */ + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + /* + Keys are created the same way as for the BFV scheme. + */ + KeyGenerator keygen(context); + auto public_key = keygen.public_key(); + auto secret_key = keygen.secret_key(); + auto relin_keys = keygen.relin_keys_local(); + + /* + We also set up an Encryptor, Evaluator, and Decryptor as usual. + */ + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + /* + To create CKKS plaintexts we need a special encoder: there is no other way + to create them. The IntegerEncoder and BatchEncoder cannot be used with the + CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into + Plaintext objects, which can subsequently be encrypted. At a high level this + looks a lot like what BatchEncoder does for the BFV scheme, but the theory + behind it is completely different. + */ + CKKSEncoder encoder(context); + + /* + In CKKS the number of slots is poly_modulus_degree / 2 and each slot encodes + one real or complex number. This should be contrasted with BatchEncoder in + the BFV scheme, where the number of slots is equal to poly_modulus_degree + and they are arranged into a matrix with two rows. + */ + size_t slot_count = encoder.slot_count(); + cout << "Number of slots: " << slot_count << endl; + + /* + We create a small vector to encode; the CKKSEncoder will implicitly pad it + with zeros to full size (poly_modulus_degree / 2) when encoding. + */ + vector<double> input{ 0.0, 1.1, 2.2, 3.3 }; + cout << "Input vector: " << endl; + print_vector(input); + + /* + Now we encode it with CKKSEncoder. The floating-point coefficients of `input' + will be scaled up by the parameter `scale'. This is necessary since even in + the CKKS scheme the plaintext elements are fundamentally polynomials with + integer coefficients. It is instructive to think of the scale as determining + the bit-precision of the encoding; naturally it will affect the precision of + the result. + + In CKKS the message is stored modulo coeff_modulus (in BFV it is stored modulo + plain_modulus), so the scaled message must not get too close to the total size + of coeff_modulus. In this case our coeff_modulus is quite large (200 bits) so + we have little to worry about in this regard. For this simple example a 30-bit + scale is more than enough. + */ + Plaintext plain; + double scale = pow(2.0, 30); + print_line(__LINE__); + cout << "Encode input vector." << endl; + encoder.encode(input, scale, plain); + + /* + We can instantly decode to check the correctness of encoding. + */ + vector<double> output; + cout << " + Decode input vector ...... Correct." << endl; + encoder.decode(plain, output); + print_vector(output); + + /* + The vector is encrypted the same was as in BFV. + */ + Ciphertext encrypted; + print_line(__LINE__); + cout << "Encrypt input vector, square, and relinearize." << endl; + encryptor.encrypt(plain, encrypted); + + /* + Basic operations on the ciphertexts are still easy to do. Here we square the + ciphertext, decrypt, decode, and print the result. We note also that decoding + returns a vector of full size (poly_modulus_degree / 2); this is because of + the implicit zero-padding mentioned above. + */ + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, relin_keys); + + /* + We notice that the scale in the result has increased. In fact, it is now the + square of the original scale: 2^60. + */ + cout << " + Scale in squared input: " << encrypted.scale() << " (" << log2(encrypted.scale()) << " bits)" + << endl; + + print_line(__LINE__); + cout << "Decrypt and decode." << endl; + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + cout << " + Result vector ...... Correct." << endl; + print_vector(output); + + /* + The CKKS scheme allows the scale to be reduced between encrypted computations. + This is a fundamental and critical feature that makes CKKS very powerful and + flexible. We will discuss it in great detail in `3_levels.cpp' and later in + `4_ckks_basics.cpp'. + */ +} + +void example_encoders() +{ + print_example_banner("Example: Encoders"); + + /* + Run all encoder examples. + */ + example_integer_encoder(); + example_batch_encoder(); + example_ckks_encoder(); +} diff --git a/bigpiseal3.5.1/native/examples/3_levels.cpp b/bigpiseal3.5.1/native/examples/3_levels.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac4d7f41c583080d23fe1693478dea49b8e0434c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/3_levels.cpp @@ -0,0 +1,338 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +void example_levels() +{ + print_example_banner("Example: Levels"); + + /* + In this examples we describe the concept of `levels' in BFV and CKKS and the + related objects that represent them in Microsoft SEAL. + + In Microsoft SEAL a set of encryption parameters (excluding the random number + generator) is identified uniquely by a 256-bit hash of the parameters. This + hash is called the `parms_id' and can be easily accessed and printed at any + time. The hash will change as soon as any of the parameters is changed. + + When a SEALContext is created from a given EncryptionParameters instance, + Microsoft SEAL automatically creates a so-called `modulus switching chain', + which is a chain of other encryption parameters derived from the original set. + The parameters in the modulus switching chain are the same as the original + parameters with the exception that size of the coefficient modulus is + decreasing going down the chain. More precisely, each parameter set in the + chain attempts to remove the last coefficient modulus prime from the + previous set; this continues until the parameter set is no longer valid + (e.g., plain_modulus is larger than the remaining coeff_modulus). It is easy + to walk through the chain and access all the parameter sets. Additionally, + each parameter set in the chain has a `chain index' that indicates its + position in the chain so that the last set has index 0. We say that a set + of encryption parameters, or an object carrying those encryption parameters, + is at a higher level in the chain than another set of parameters if its the + chain index is bigger, i.e., it is earlier in the chain. + + Each set of parameters in the chain involves unique pre-computations performed + when the SEALContext is created, and stored in a SEALContext::ContextData + object. The chain is basically a linked list of SEALContext::ContextData + objects, and can easily be accessed through the SEALContext at any time. Each + node can be identified by the parms_id of its specific encryption parameters + (poly_modulus_degree remains the same but coeff_modulus varies). + */ + EncryptionParameters parms(scheme_type::BFV); + + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + + /* + In this example we use a custom coeff_modulus, consisting of 5 primes of + sizes 50, 30, 30, 50, and 50 bits. Note that this is still OK according to + the explanation in `1_bfv_basics.cpp'. Indeed, + + CoeffModulus::MaxBitCount(poly_modulus_degree) + + returns 218 (greater than 50+30+30+50+50=210). + + Due to the modulus switching chain, the order of the 5 primes is significant. + The last prime has a special meaning and we call it the `special prime'. Thus, + the first parameter set in the modulus switching chain is the only one that + involves the special prime. All key objects, such as SecretKey, are created + at this highest level. All data objects, such as Ciphertext, can be only at + lower levels. The special prime should be as large as the largest of the + other primes in the coeff_modulus, although this is not a strict requirement. + + special prime +---------+ + | + v + coeff_modulus: { 50, 30, 30, 50, 50 } +---+ Level 4 (all keys; `key level') + | + | + coeff_modulus: { 50, 30, 30, 50 } +---+ Level 3 (highest `data level') + | + | + coeff_modulus: { 50, 30, 30 } +---+ Level 2 + | + | + coeff_modulus: { 50, 30 } +---+ Level 1 + | + | + coeff_modulus: { 50 } +---+ Level 0 (lowest level) + */ + parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 50, 30, 30, 50, 50 })); + + /* + In this example the plain_modulus does not play much of a role; we choose + some reasonable value. + */ + parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20)); + + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + /* + There are convenience method for accessing the SEALContext::ContextData for + some of the most important levels: + + SEALContext::key_context_data(): access to key level ContextData + SEALContext::first_context_data(): access to highest data level ContextData + SEALContext::last_context_data(): access to lowest level ContextData + + We iterate over the chain and print the parms_id for each set of parameters. + */ + print_line(__LINE__); + cout << "Print the modulus switching chain." << endl; + + /* + First print the key level parameter information. + */ + auto context_data = context->key_context_data(); + cout << "----> Level (chain index): " << context_data->chain_index(); + cout << " ...... key_context_data()" << endl; + cout << " parms_id: " << context_data->parms_id() << endl; + cout << " coeff_modulus primes: "; + cout << hex; + for (const auto &prime : context_data->parms().coeff_modulus()) + { + cout << prime.value() << " "; + } + cout << dec << endl; + cout << "\\" << endl; + cout << " \\-->"; + + /* + Next iterate over the remaining (data) levels. + */ + context_data = context->first_context_data(); + while (context_data) + { + cout << " Level (chain index): " << context_data->chain_index(); + if (context_data->parms_id() == context->first_parms_id()) + { + cout << " ...... first_context_data()" << endl; + } + else if (context_data->parms_id() == context->last_parms_id()) + { + cout << " ...... last_context_data()" << endl; + } + else + { + cout << endl; + } + cout << " parms_id: " << context_data->parms_id() << endl; + cout << " coeff_modulus primes: "; + cout << hex; + for (const auto &prime : context_data->parms().coeff_modulus()) + { + cout << prime.value() << " "; + } + cout << dec << endl; + cout << "\\" << endl; + cout << " \\-->"; + + /* + Step forward in the chain. + */ + context_data = context_data->next_context_data(); + } + cout << " End of chain reached" << endl << endl; + + /* + We create some keys and check that indeed they appear at the highest level. + */ + KeyGenerator keygen(context); + auto public_key = keygen.public_key(); + auto secret_key = keygen.secret_key(); + auto relin_keys = keygen.relin_keys_local(); + + /* + In this example we create a local version of the GaloisKeys object using + KeyGenerator::galois_keys_local(). In a production setting where the Galois + keys would need to be communicated to a server, it would be much better to + use KeyGenerator::galois_keys(), which outputs a Serializable<GaloisKeys> + object for compressed serialization. + */ + auto galois_keys = keygen.galois_keys_local(); + print_line(__LINE__); + cout << "Print the parameter IDs of generated elements." << endl; + cout << " + public_key: " << public_key.parms_id() << endl; + cout << " + secret_key: " << secret_key.parms_id() << endl; + cout << " + relin_keys: " << relin_keys.parms_id() << endl; + cout << " + galois_keys: " << galois_keys.parms_id() << endl; + + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + /* + In the BFV scheme plaintexts do not carry a parms_id, but ciphertexts do. Note + how the freshly encrypted ciphertext is at the highest data level. + */ + Plaintext plain("1x^3 + 2x^2 + 3x^1 + 4"); + Ciphertext encrypted; + encryptor.encrypt(plain, encrypted); + cout << " + plain: " << plain.parms_id() << " (not set in BFV)" << endl; + cout << " + encrypted: " << encrypted.parms_id() << endl << endl; + + /* + `Modulus switching' is a technique of changing the ciphertext parameters down + in the chain. The function Evaluator::mod_switch_to_next always switches to + the next level down the chain, whereas Evaluator::mod_switch_to switches to + a parameter set down the chain corresponding to a given parms_id. However, it + is impossible to switch up in the chain. + */ + print_line(__LINE__); + cout << "Perform modulus switching on encrypted and print." << endl; + context_data = context->first_context_data(); + cout << "---->"; + while (context_data->next_context_data()) + { + cout << " Level (chain index): " << context_data->chain_index() << endl; + cout << " parms_id of encrypted: " << encrypted.parms_id() << endl; + cout << " Noise budget at this level: " << decryptor.invariant_noise_budget(encrypted) << " bits" << endl; + cout << "\\" << endl; + cout << " \\-->"; + evaluator.mod_switch_to_next_inplace(encrypted); + context_data = context_data->next_context_data(); + } + cout << " Level (chain index): " << context_data->chain_index() << endl; + cout << " parms_id of encrypted: " << encrypted.parms_id() << endl; + cout << " Noise budget at this level: " << decryptor.invariant_noise_budget(encrypted) << " bits" << endl; + cout << "\\" << endl; + cout << " \\-->"; + cout << " End of chain reached" << endl << endl; + + /* + At this point it is hard to see any benefit in doing this: we lost a huge + amount of noise budget (i.e., computational power) at each switch and seemed + to get nothing in return. Decryption still works. + */ + print_line(__LINE__); + cout << "Decrypt still works after modulus switching." << endl; + decryptor.decrypt(encrypted, plain); + cout << " + Decryption of encrypted: " << plain.to_string(); + cout << " ...... Correct." << endl << endl; + + /* + However, there is a hidden benefit: the size of the ciphertext depends + linearly on the number of primes in the coefficient modulus. Thus, if there + is no need or intention to perform any further computations on a given + ciphertext, we might as well switch it down to the smallest (last) set of + parameters in the chain before sending it back to the secret key holder for + decryption. + + Also the lost noise budget is actually not an issue at all, if we do things + right, as we will see below. + + First we recreate the original ciphertext and perform some computations. + */ + cout << "Computation is more efficient with modulus switching." << endl; + print_line(__LINE__); + cout << "Compute the 8th power." << endl; + encryptor.encrypt(plain, encrypted); + cout << " + Noise budget fresh: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, relin_keys); + cout << " + Noise budget of the 2nd power: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, relin_keys); + cout << " + Noise budget of the 4th power: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + + /* + Surprisingly, in this case modulus switching has no effect at all on the + noise budget. + */ + evaluator.mod_switch_to_next_inplace(encrypted); + cout << " + Noise budget after modulus switching: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + /* + This means that there is no harm at all in dropping some of the coefficient + modulus after doing enough computations. In some cases one might want to + switch to a lower level slightly earlier, actually sacrificing some of the + noise budget in the process, to gain computational performance from having + smaller parameters. We see from the print-out that the next modulus switch + should be done ideally when the noise budget is down to around 25 bits. + */ + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, relin_keys); + cout << " + Noise budget of the 8th power: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + evaluator.mod_switch_to_next_inplace(encrypted); + cout << " + Noise budget after modulus switching: " << decryptor.invariant_noise_budget(encrypted) << " bits" + << endl; + + /* + At this point the ciphertext still decrypts correctly, has very small size, + and the computation was as efficient as possible. Note that the decryptor + can be used to decrypt a ciphertext at any level in the modulus switching + chain. + */ + decryptor.decrypt(encrypted, plain); + cout << " + Decryption of the 8th power (hexadecimal) ...... Correct." << endl; + cout << " " << plain.to_string() << endl << endl; + + /* + In BFV modulus switching is not necessary and in some cases the user might + not want to create the modulus switching chain, except for the highest two + levels. This can be done by passing a bool `false' to SEALContext::Create. + */ + context = SEALContext::Create(parms, false); + + /* + We can check that indeed the modulus switching chain has been created only + for the highest two levels (key level and highest data level). The following + loop should execute only once. + */ + cout << "Optionally disable modulus switching chain expansion." << endl; + print_line(__LINE__); + cout << "Print the modulus switching chain." << endl; + cout << "---->"; + for (context_data = context->key_context_data(); context_data; context_data = context_data->next_context_data()) + { + cout << " Level (chain index): " << context_data->chain_index() << endl; + cout << " parms_id: " << context_data->parms_id() << endl; + cout << " coeff_modulus primes: "; + cout << hex; + for (const auto &prime : context_data->parms().coeff_modulus()) + { + cout << prime.value() << " "; + } + cout << dec << endl; + cout << "\\" << endl; + cout << " \\-->"; + } + cout << " End of chain reached" << endl << endl; + + /* + It is very important to understand how this example works since in the CKKS + scheme modulus switching has a much more fundamental purpose and the next + examples will be difficult to understand unless these basic properties are + totally clear. + */ +} diff --git a/bigpiseal3.5.1/native/examples/4_ckks_basics.cpp b/bigpiseal3.5.1/native/examples/4_ckks_basics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..120f5c332186454d6a0c565c38c46f014dc2fc30 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/4_ckks_basics.cpp @@ -0,0 +1,312 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +void example_ckks_basics() +{ + print_example_banner("Example: CKKS Basics"); + + /* + In this example we demonstrate evaluating a polynomial function + + PI*x^3 + 0.4*x + 1 + + on encrypted floating-point input data x for a set of 4096 equidistant points + in the interval [0, 1]. This example demonstrates many of the main features + of the CKKS scheme, but also the challenges in using it. + + We start by setting up the CKKS scheme. + */ + EncryptionParameters parms(scheme_type::CKKS); + + /* + We saw in `2_encoders.cpp' that multiplication in CKKS causes scales + in ciphertexts to grow. The scale of any ciphertext must not get too close + to the total size of coeff_modulus, or else the ciphertext simply runs out of + room to store the scaled-up plaintext. The CKKS scheme provides a `rescale' + functionality that can reduce the scale, and stabilize the scale expansion. + + Rescaling is a kind of modulus switch operation (recall `3_levels.cpp'). + As modulus switching, it removes the last of the primes from coeff_modulus, + but as a side-effect it scales down the ciphertext by the removed prime. + Usually we want to have perfect control over how the scales are changed, + which is why for the CKKS scheme it is more common to use carefully selected + primes for the coeff_modulus. + + More precisely, suppose that the scale in a CKKS ciphertext is S, and the + last prime in the current coeff_modulus (for the ciphertext) is P. Rescaling + to the next level changes the scale to S/P, and removes the prime P from the + coeff_modulus, as usual in modulus switching. The number of primes limits + how many rescalings can be done, and thus limits the multiplicative depth of + the computation. + + It is possible to choose the initial scale freely. One good strategy can be + to is to set the initial scale S and primes P_i in the coeff_modulus to be + very close to each other. If ciphertexts have scale S before multiplication, + they have scale S^2 after multiplication, and S^2/P_i after rescaling. If all + P_i are close to S, then S^2/P_i is close to S again. This way we stabilize the + scales to be close to S throughout the computation. Generally, for a circuit + of depth D, we need to rescale D times, i.e., we need to be able to remove D + primes from the coefficient modulus. Once we have only one prime left in the + coeff_modulus, the remaining prime must be larger than S by a few bits to + preserve the pre-decimal-point value of the plaintext. + + Therefore, a generally good strategy is to choose parameters for the CKKS + scheme as follows: + + (1) Choose a 60-bit prime as the first prime in coeff_modulus. This will + give the highest precision when decrypting; + (2) Choose another 60-bit prime as the last element of coeff_modulus, as + this will be used as the special prime and should be as large as the + largest of the other primes; + (3) Choose the intermediate primes to be close to each other. + + We use CoeffModulus::Create to generate primes of the appropriate size. Note + that our coeff_modulus is 200 bits total, which is below the bound for our + poly_modulus_degree: CoeffModulus::MaxBitCount(8192) returns 218. + */ + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60, 40, 40, 60 })); + + /* + We choose the initial scale to be 2^40. At the last level, this leaves us + 60-40=20 bits of precision before the decimal point, and enough (roughly + 10-20 bits) of precision after the decimal point. Since our intermediate + primes are 40 bits (in fact, they are very close to 2^40), we can achieve + scale stabilization as described above. + */ + double scale = pow(2.0, 40); + + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + KeyGenerator keygen(context); + auto public_key = keygen.public_key(); + auto secret_key = keygen.secret_key(); + auto relin_keys = keygen.relin_keys_local(); + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + CKKSEncoder encoder(context); + size_t slot_count = encoder.slot_count(); + cout << "Number of slots: " << slot_count << endl; + + vector<double> input; + input.reserve(slot_count); + double curr_point = 0; + double step_size = 1.0 / (static_cast<double>(slot_count) - 1); + for (size_t i = 0; i < slot_count; i++, curr_point += step_size) + { + input.push_back(curr_point); + } + cout << "Input vector: " << endl; + print_vector(input, 3, 7); + + cout << "Evaluating polynomial PI*x^3 + 0.4x + 1 ..." << endl; + + /* + We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder::encode + that encodes the given floating-point value to every slot in the vector. + */ + Plaintext plain_coeff3, plain_coeff1, plain_coeff0; + encoder.encode(3.14159265, scale, plain_coeff3); + encoder.encode(0.4, scale, plain_coeff1); + encoder.encode(1.0, scale, plain_coeff0); + + Plaintext x_plain; + print_line(__LINE__); + cout << "Encode input vectors." << endl; + encoder.encode(input, scale, x_plain); + Ciphertext x1_encrypted; + encryptor.encrypt(x_plain, x1_encrypted); + + /* + To compute x^3 we first compute x^2 and relinearize. However, the scale has + now grown to 2^80. + */ + Ciphertext x3_encrypted; + print_line(__LINE__); + cout << "Compute x^2 and relinearize:" << endl; + evaluator.square(x1_encrypted, x3_encrypted); + evaluator.relinearize_inplace(x3_encrypted, relin_keys); + cout << " + Scale of x^2 before rescale: " << log2(x3_encrypted.scale()) << " bits" << endl; + + /* + Now rescale; in addition to a modulus switch, the scale is reduced down by + a factor equal to the prime that was switched away (40-bit prime). Hence, the + new scale should be close to 2^40. Note, however, that the scale is not equal + to 2^40: this is because the 40-bit prime is only close to 2^40. + */ + print_line(__LINE__); + cout << "Rescale x^2." << endl; + evaluator.rescale_to_next_inplace(x3_encrypted); + cout << " + Scale of x^2 after rescale: " << log2(x3_encrypted.scale()) << " bits" << endl; + + /* + Now x3_encrypted is at a different level than x1_encrypted, which prevents us + from multiplying them to compute x^3. We could simply switch x1_encrypted to + the next parameters in the modulus switching chain. However, since we still + need to multiply the x^3 term with PI (plain_coeff3), we instead compute PI*x + first and multiply that with x^2 to obtain PI*x^3. To this end, we compute + PI*x and rescale it back from scale 2^80 to something close to 2^40. + */ + print_line(__LINE__); + cout << "Compute and rescale PI*x." << endl; + Ciphertext x1_encrypted_coeff3; + evaluator.multiply_plain(x1_encrypted, plain_coeff3, x1_encrypted_coeff3); + cout << " + Scale of PI*x before rescale: " << log2(x1_encrypted_coeff3.scale()) << " bits" << endl; + evaluator.rescale_to_next_inplace(x1_encrypted_coeff3); + cout << " + Scale of PI*x after rescale: " << log2(x1_encrypted_coeff3.scale()) << " bits" << endl; + + /* + Since x3_encrypted and x1_encrypted_coeff3 have the same exact scale and use + the same encryption parameters, we can multiply them together. We write the + result to x3_encrypted, relinearize, and rescale. Note that again the scale + is something close to 2^40, but not exactly 2^40 due to yet another scaling + by a prime. We are down to the last level in the modulus switching chain. + */ + print_line(__LINE__); + cout << "Compute, relinearize, and rescale (PI*x)*x^2." << endl; + evaluator.multiply_inplace(x3_encrypted, x1_encrypted_coeff3); + evaluator.relinearize_inplace(x3_encrypted, relin_keys); + cout << " + Scale of PI*x^3 before rescale: " << log2(x3_encrypted.scale()) << " bits" << endl; + evaluator.rescale_to_next_inplace(x3_encrypted); + cout << " + Scale of PI*x^3 after rescale: " << log2(x3_encrypted.scale()) << " bits" << endl; + + /* + Next we compute the degree one term. All this requires is one multiply_plain + with plain_coeff1. We overwrite x1_encrypted with the result. + */ + print_line(__LINE__); + cout << "Compute and rescale 0.4*x." << endl; + evaluator.multiply_plain_inplace(x1_encrypted, plain_coeff1); + cout << " + Scale of 0.4*x before rescale: " << log2(x1_encrypted.scale()) << " bits" << endl; + evaluator.rescale_to_next_inplace(x1_encrypted); + cout << " + Scale of 0.4*x after rescale: " << log2(x1_encrypted.scale()) << " bits" << endl; + + /* + Now we would hope to compute the sum of all three terms. However, there is + a serious problem: the encryption parameters used by all three terms are + different due to modulus switching from rescaling. + + Encrypted addition and subtraction require that the scales of the inputs are + the same, and also that the encryption parameters (parms_id) match. If there + is a mismatch, Evaluator will throw an exception. + */ + cout << endl; + print_line(__LINE__); + cout << "Parameters used by all three terms are different." << endl; + cout << " + Modulus chain index for x3_encrypted: " + << context->get_context_data(x3_encrypted.parms_id())->chain_index() << endl; + cout << " + Modulus chain index for x1_encrypted: " + << context->get_context_data(x1_encrypted.parms_id())->chain_index() << endl; + cout << " + Modulus chain index for plain_coeff0: " + << context->get_context_data(plain_coeff0.parms_id())->chain_index() << endl; + cout << endl; + + /* + Let us carefully consider what the scales are at this point. We denote the + primes in coeff_modulus as P_0, P_1, P_2, P_3, in this order. P_3 is used as + the special modulus and is not involved in rescalings. After the computations + above the scales in ciphertexts are: + + - Product x^2 has scale 2^80 and is at level 2; + - Product PI*x has scale 2^80 and is at level 2; + - We rescaled both down to scale 2^80/P_2 and level 1; + - Product PI*x^3 has scale (2^80/P_2)^2; + - We rescaled it down to scale (2^80/P_2)^2/P_1 and level 0; + - Product 0.4*x has scale 2^80; + - We rescaled it down to scale 2^80/P_2 and level 1; + - The contant term 1 has scale 2^40 and is at level 2. + + Although the scales of all three terms are approximately 2^40, their exact + values are different, hence they cannot be added together. + */ + print_line(__LINE__); + cout << "The exact scales of all three terms are different:" << endl; + ios old_fmt(nullptr); + old_fmt.copyfmt(cout); + cout << fixed << setprecision(10); + cout << " + Exact scale in PI*x^3: " << x3_encrypted.scale() << endl; + cout << " + Exact scale in 0.4*x: " << x1_encrypted.scale() << endl; + cout << " + Exact scale in 1: " << plain_coeff0.scale() << endl; + cout << endl; + cout.copyfmt(old_fmt); + + /* + There are many ways to fix this problem. Since P_2 and P_1 are really close + to 2^40, we can simply "lie" to Microsoft SEAL and set the scales to be the + same. For example, changing the scale of PI*x^3 to 2^40 simply means that we + scale the value of PI*x^3 by 2^120/(P_2^2*P_1), which is very close to 1. + This should not result in any noticeable error. + + Another option would be to encode 1 with scale 2^80/P_2, do a multiply_plain + with 0.4*x, and finally rescale. In this case we would need to additionally + make sure to encode 1 with appropriate encryption parameters (parms_id). + + In this example we will use the first (simplest) approach and simply change + the scale of PI*x^3 and 0.4*x to 2^40. + */ + print_line(__LINE__); + cout << "Normalize scales to 2^40." << endl; + x3_encrypted.scale() = pow(2.0, 40); + x1_encrypted.scale() = pow(2.0, 40); + + /* + We still have a problem with mismatching encryption parameters. This is easy + to fix by using traditional modulus switching (no rescaling). CKKS supports + modulus switching just like the BFV scheme, allowing us to switch away parts + of the coefficient modulus when it is simply not needed. + */ + print_line(__LINE__); + cout << "Normalize encryption parameters to the lowest level." << endl; + parms_id_type last_parms_id = x3_encrypted.parms_id(); + evaluator.mod_switch_to_inplace(x1_encrypted, last_parms_id); + evaluator.mod_switch_to_inplace(plain_coeff0, last_parms_id); + + /* + All three ciphertexts are now compatible and can be added. + */ + print_line(__LINE__); + cout << "Compute PI*x^3 + 0.4*x + 1." << endl; + Ciphertext encrypted_result; + evaluator.add(x3_encrypted, x1_encrypted, encrypted_result); + evaluator.add_plain_inplace(encrypted_result, plain_coeff0); + + /* + First print the true result. + */ + Plaintext plain_result; + print_line(__LINE__); + cout << "Decrypt and decode PI*x^3 + 0.4x + 1." << endl; + cout << " + Expected result:" << endl; + vector<double> true_result; + for (size_t i = 0; i < input.size(); i++) + { + double x = input[i]; + true_result.push_back((3.14159265 * x * x + 0.4) * x + 1); + } + print_vector(true_result, 3, 7); + + /* + Decrypt, decode, and print the result. + */ + decryptor.decrypt(encrypted_result, plain_result); + vector<double> result; + encoder.decode(plain_result, result); + cout << " + Computed result ...... Correct." << endl; + print_vector(result, 3, 7); + + /* + While we did not show any computations on complex numbers in these examples, + the CKKSEncoder would allow us to have done that just as easily. Additions + and multiplications of complex numbers behave just as one would expect. + */ +} diff --git a/bigpiseal3.5.1/native/examples/5_rotation.cpp b/bigpiseal3.5.1/native/examples/5_rotation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de550d2f5238cad3db99815d0c0537485caa115b --- /dev/null +++ b/bigpiseal3.5.1/native/examples/5_rotation.cpp @@ -0,0 +1,200 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +/* +Both the BFV scheme (with BatchEncoder) as well as the CKKS scheme support native +vectorized computations on encrypted numbers. In addition to computing slot-wise, +it is possible to rotate the encrypted vectors cyclically. +*/ +void example_rotation_bfv() +{ + print_example_banner("Example: Rotation / Rotation in BFV"); + + EncryptionParameters parms(scheme_type::BFV); + + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20)); + + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + KeyGenerator keygen(context); + PublicKey public_key = keygen.public_key(); + SecretKey secret_key = keygen.secret_key(); + RelinKeys relin_keys = keygen.relin_keys_local(); + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + BatchEncoder batch_encoder(context); + size_t slot_count = batch_encoder.slot_count(); + size_t row_size = slot_count / 2; + cout << "Plaintext matrix row size: " << row_size << endl; + + vector<uint64_t> pod_matrix(slot_count, 0ULL); + pod_matrix[0] = 0ULL; + pod_matrix[1] = 1ULL; + pod_matrix[2] = 2ULL; + pod_matrix[3] = 3ULL; + pod_matrix[row_size] = 4ULL; + pod_matrix[row_size + 1] = 5ULL; + pod_matrix[row_size + 2] = 6ULL; + pod_matrix[row_size + 3] = 7ULL; + + cout << "Input plaintext matrix:" << endl; + print_matrix(pod_matrix, row_size); + + /* + First we use BatchEncoder to encode the matrix into a plaintext. We encrypt + the plaintext as usual. + */ + Plaintext plain_matrix; + print_line(__LINE__); + cout << "Encode and encrypt." << endl; + batch_encoder.encode(pod_matrix, plain_matrix); + Ciphertext encrypted_matrix; + encryptor.encrypt(plain_matrix, encrypted_matrix); + cout << " + Noise budget in fresh encryption: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" + << endl; + cout << endl; + + /* + Rotations require yet another type of special key called `Galois keys'. These + are easily obtained from the KeyGenerator. + */ + GaloisKeys gal_keys = keygen.galois_keys_local(); + + /* + Now rotate both matrix rows 3 steps to the left, decrypt, decode, and print. + */ + print_line(__LINE__); + cout << "Rotate rows 3 steps left." << endl; + evaluator.rotate_rows_inplace(encrypted_matrix, 3, gal_keys); + Plaintext plain_result; + cout << " + Noise budget after rotation: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" + << endl; + cout << " + Decrypt and decode ...... Correct." << endl; + decryptor.decrypt(encrypted_matrix, plain_result); + batch_encoder.decode(plain_result, pod_matrix); + print_matrix(pod_matrix, row_size); + + /* + We can also rotate the columns, i.e., swap the rows. + */ + print_line(__LINE__); + cout << "Rotate columns." << endl; + evaluator.rotate_columns_inplace(encrypted_matrix, gal_keys); + cout << " + Noise budget after rotation: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" + << endl; + cout << " + Decrypt and decode ...... Correct." << endl; + decryptor.decrypt(encrypted_matrix, plain_result); + batch_encoder.decode(plain_result, pod_matrix); + print_matrix(pod_matrix, row_size); + + /* + Finally, we rotate the rows 4 steps to the right, decrypt, decode, and print. + */ + print_line(__LINE__); + cout << "Rotate rows 4 steps right." << endl; + evaluator.rotate_rows_inplace(encrypted_matrix, -4, gal_keys); + cout << " + Noise budget after rotation: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" + << endl; + cout << " + Decrypt and decode ...... Correct." << endl; + decryptor.decrypt(encrypted_matrix, plain_result); + batch_encoder.decode(plain_result, pod_matrix); + print_matrix(pod_matrix, row_size); + + /* + Note that rotations do not consume any noise budget. However, this is only + the case when the special prime is at least as large as the other primes. The + same holds for relinearization. Microsoft SEAL does not require that the + special prime is of any particular size, so ensuring this is the case is left + for the user to do. + */ +} + +void example_rotation_ckks() +{ + print_example_banner("Example: Rotation / Rotation in CKKS"); + + /* + Rotations in the CKKS scheme work very similarly to rotations in BFV. + */ + EncryptionParameters parms(scheme_type::CKKS); + + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 40, 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms); + print_parameters(context); + cout << endl; + + KeyGenerator keygen(context); + PublicKey public_key = keygen.public_key(); + SecretKey secret_key = keygen.secret_key(); + RelinKeys relin_keys = keygen.relin_keys_local(); + GaloisKeys gal_keys = keygen.galois_keys_local(); + Encryptor encryptor(context, public_key); + Evaluator evaluator(context); + Decryptor decryptor(context, secret_key); + + CKKSEncoder ckks_encoder(context); + + size_t slot_count = ckks_encoder.slot_count(); + cout << "Number of slots: " << slot_count << endl; + vector<double> input; + input.reserve(slot_count); + double curr_point = 0; + double step_size = 1.0 / (static_cast<double>(slot_count) - 1); + for (size_t i = 0; i < slot_count; i++, curr_point += step_size) + { + input.push_back(curr_point); + } + cout << "Input vector:" << endl; + print_vector(input, 3, 7); + + auto scale = pow(2.0, 50); + + print_line(__LINE__); + cout << "Encode and encrypt." << endl; + Plaintext plain; + ckks_encoder.encode(input, scale, plain); + Ciphertext encrypted; + encryptor.encrypt(plain, encrypted); + + Ciphertext rotated; + print_line(__LINE__); + cout << "Rotate 2 steps left." << endl; + evaluator.rotate_vector(encrypted, 2, gal_keys, rotated); + cout << " + Decrypt and decode ...... Correct." << endl; + decryptor.decrypt(rotated, plain); + vector<double> result; + ckks_encoder.decode(plain, result); + print_vector(result, 3, 7); + + /* + With the CKKS scheme it is also possible to evaluate a complex conjugation on + a vector of encrypted complex numbers, using Evaluator::complex_conjugate. + This is in fact a kind of rotation, and requires also Galois keys. + */ +} + +void example_rotation() +{ + print_example_banner("Example: Rotation"); + + /* + Run all rotation examples. + */ + example_rotation_bfv(); + example_rotation_ckks(); +} diff --git a/bigpiseal3.5.1/native/examples/6_serialization.cpp b/bigpiseal3.5.1/native/examples/6_serialization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1ae6d14385ab5b61aba763bcc37245975381e97 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/6_serialization.cpp @@ -0,0 +1,415 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +/* +In this example we show how serialization works in Microsoft SEAL. Specifically, +we present important concepts that enable the user to optimize the data size when +communicating ciphertexts and keys for outsourced computation. Unlike the previous +examples, we organize this one in a client-server style for maximal clarity. The +server selects encryption parameters, the client generates keys, the server does +the encrypted computation, and the client decrypts. +*/ +void example_serialization() +{ + print_example_banner("Example: Serialization"); + + /* + We require ZLIB support for this example to be available. + */ +#ifndef SEAL_USE_ZLIB + cout << "ZLIB support is not enabled; this example is not available." << endl; + cout << endl; + return; +#else + /* + To simulate client-server interaction, we set up a shared C++ stream. In real + use-cases this can be a network buffer, a filestream, or any shared resource. + + It is critical to note that all data serialized by Microsoft SEAL is in binary + form, so it is not meaningful to print the data as ASCII characters. Encodings + such as Base64 would increase the data size, which is already a bottleneck in + homomorphic encryption. Hence, serialization into text is not supported or + recommended. + + We feel it is important to remind users that filestream serialization will + always require the ios::binary flag to signal that the serialized data is + binary data and not text. For example, an appropriate output filestream could + be set up as: + + ofstream ofs("filename", ios::binary); + + In this example we use an std::stringstream, where the ios::binary flag is + not needed. Note that the default constructor of std::stringstream opens the + stream with ios::in | ios::out so both reading and writing will be possible. + */ + stringstream parms_stream; + stringstream data_stream; + stringstream sk_stream; + + /* + The server first determines the computation and sets encryption parameters + accordingly. + */ + { + EncryptionParameters parms(scheme_type::CKKS); + size_t poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 50, 20, 50 })); + + /* + Serialization of the encryption parameters to our shared stream is very + simple with the EncryptionParameters::save function. + */ + auto size = parms.save(parms_stream); + + /* + The return value of this function is the actual byte count of data written + to the stream. + */ + print_line(__LINE__); + cout << "EncryptionParameters: wrote " << size << " bytes" << endl; + + /* + Before moving on, we will take some time to discuss further options in + serialization. These will become particularly important when the user + needs to optimize communication and storage sizes. + */ + + /* + It is possible to enable or disable ZLIB ("deflate") compression for + serialization by providing EncryptionParameters::save with the desired + compression mode as in the following examples: + + auto size = parms.save(shared_stream, compr_mode_type::none); + auto size = parms.save(shared_stream, compr_mode_type::deflate); + + If Microsoft SEAL is compiled with ZLIB support, the default is to use + compr_mode_type::deflate, so to instead disable compression one would use + the first version of the two. + */ + + /* + It is also possible to serialize data directly to a buffer. For this, one + needs to know an upper bound for the required buffer size, which can be + obtained using the EncryptionParameters::save_size function. This function + also accepts the desired compression mode, with compr_mode_type::deflate + being the default when Microsoft SEAL is compiled with ZLIB support. + + In more detail, the output of EncryptionParameters::save_size is as follows: + + - Exact buffer size required for compr_mode_type::none; + - Upper bound on the size required for compr_mode_type::deflate. + + As we can see from the print-out, the sizes returned by these functions + are significantly larger than the compressed size written into the shared + stream in the beginning. This is normal: compression yielded a significant + improvement in the data size, yet it is hard to estimate the size of the + compressed data. + */ + print_line(__LINE__); + cout << "EncryptionParameters: data size upper bound (compr_mode_type::none): " + << parms.save_size(compr_mode_type::none) << endl; + cout << " " + << "EncryptionParameters: data size upper bound (compr_mode_type::deflate): " + << parms.save_size(compr_mode_type::deflate) << endl; + + /* + As an example, we now serialize the encryption parameters to a fixed size + buffer. + */ + vector<SEAL_BYTE> byte_buffer(static_cast<size_t>(parms.save_size())); + parms.save(reinterpret_cast<SEAL_BYTE *>(byte_buffer.data()), byte_buffer.size()); + + /* + To illustrate deserialization, we load back the encryption parameters + from our buffer into another instance of EncryptionParameters. Note how + EncryptionParameters::load in this case requires the size of the buffer, + which is larger than the actual data size of the compressed parameters. + The serialization format includes the true size of the data and the size + of the buffer is only used for a sanity check. + */ + EncryptionParameters parms2; + parms2.load(reinterpret_cast<const SEAL_BYTE *>(byte_buffer.data()), byte_buffer.size()); + + /* + We can check that the saved and loaded encryption parameters indeed match. + */ + print_line(__LINE__); + cout << "EncryptionParameters: parms == parms2: " << boolalpha << (parms == parms2) << endl; + + /* + The functions presented and used here exist for all Microsoft SEAL objects + that are meaningful to serialize. However, it is important to understand + more advanced techniques that can be used for further compressing the data + size. We will present these techniques below. + */ + } + + /* + Client starts by loading the encryption parameters, sets up the SEALContext, + and creates the required keys. + */ + { + EncryptionParameters parms; + parms.load(parms_stream); + + /* + Seek the parms_stream get head back to beginning of the stream because we + will use the same stream to read the parameters repeatedly. + */ + parms_stream.seekg(0, parms_stream.beg); + + auto context = SEALContext::Create(parms); + + KeyGenerator keygen(context); + auto sk = keygen.secret_key(); + auto pk = keygen.public_key(); + + /* + We need to save the secret key so we can decrypt later. + */ + sk.save(sk_stream); + + /* + In this example we will also use relinearization keys. For realinearization + and Galois keys the KeyGenerator::relin_keys and KeyGenerator::galois_keys + functions return special Serializable<T> objects. These objects are meant + to be serialized and never used locally. On the other hand, for local use + of RelinKeys and GaloisKeys, the functions KeyGenerator::relin_keys_local + and KeyGenerator::galois_keys_local can be used to create the RelinKeys + and GaloisKeys objects directly. The difference is that the Serializable<T> + objects contain a partly seeded version of the RelinKeys (or GaloisKeys) + that will result in a significantly smaller size when serialized. Using + this method has no impact on security. Such seeded RelinKeys (GaloisKeys) + must be expanded before being used in computations; this is automatically + done by deserialization. + */ + Serializable<RelinKeys> rlk = keygen.relin_keys(); + + /* + Before continuing, we demonstrate the significant space saving from this + method. + */ + auto size_rlk = rlk.save(data_stream); + + RelinKeys rlk_local = keygen.relin_keys_local(); + auto size_rlk_local = rlk_local.save(data_stream); + + /* + Now compare the serialized sizes of rlk and rlk_local. + */ + print_line(__LINE__); + cout << "Serializable<RelinKeys>: wrote " << size_rlk << " bytes" << endl; + cout << " " + << "RelinKeys (local): wrote " << size_rlk_local << " bytes" << endl; + + /* + Seek back in data_stream to where rlk data ended, i.e., size_rlk_local + bytes backwards from current position. + */ + data_stream.seekp(-size_rlk_local, data_stream.cur); + + /* + Next set up the CKKSEncoder and Encryptor, and encrypt some numbers. + */ + double scale = pow(2.0, 20); + CKKSEncoder encoder(context); + Plaintext plain1, plain2; + encoder.encode(2.3, scale, plain1); + encoder.encode(4.5, scale, plain2); + + Encryptor encryptor(context, pk); + Ciphertext encrypted1, encrypted2; + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + /* + Now, we could serialize both encrypted1 and encrypted2 to data_stream + using Ciphertext::save. However, for this example, we demonstrate another + size-saving trick that can come in handy. + + As you noticed, we set up the Encryptor using the public key. Clearly this + indicates that the CKKS scheme is a public-key encryption scheme. However, + both BFV and CKKS can operate also in a symmetric-key mode. This can be + beneficial when the public-key functionality is not exactly needed, like + in simple outsourced computation scenarios. The benefit is that in these + cases it is possible to produce ciphertexts that are partly seeded, hence + significantly smaller. Such ciphertexts must be expanded before being used + in computations; this is automatically done by deserialization. + + To use symmetric-key encryption, we need to set up the Encryptor with the + secret key instead. + */ + Encryptor sym_encryptor(context, sk); + Serializable<Ciphertext> sym_encrypted1 = sym_encryptor.encrypt_symmetric(plain1); + Serializable<Ciphertext> sym_encrypted2 = sym_encryptor.encrypt_symmetric(plain2); + + /* + Before continuing, we demonstrate the significant space saving from this + method. + */ + auto size_sym_encrypted1 = sym_encrypted1.save(data_stream); + auto size_encrypted1 = encrypted1.save(data_stream); + + /* + Now compare the serialized sizes of encrypted1 and sym_encrypted1. + */ + print_line(__LINE__); + cout << "Serializable<Ciphertext> (symmetric-key): wrote " << size_sym_encrypted1 << " bytes" << endl; + cout << " " + << "Ciphertext (public-key): wrote " << size_encrypted1 << " bytes" << endl; + + /* + Seek back in data_stream to where sym_encrypted1 data ended, i.e., + size_encrypted1 bytes backwards from current position and write + sym_encrypted2 right after sym_encrypted1. + */ + data_stream.seekp(-size_encrypted1, data_stream.cur); + sym_encrypted2.save(data_stream); + + /* + We have seen how using KeyGenerator::relin_keys (KeyGenerator::galois_keys) + can result in huge space savings over the local variants when the objects + are not needed for local use. We have seen how symmetric-key encryption + can be used to achieve much smaller ciphertext sizes when the public-key + functionality is not needed. + + We would also like to draw attention to the fact there we could easily + serialize multiple Microsoft SEAL objects sequentially in a stream. Each + object writes its own size into the stream, so deserialization knows + exactly how many bytes to read. We will see this working next. + + Finally, we would like to point out that none of these methods provide any + space savings unless Microsoft SEAL is compiled with ZLIB support, or when + serialized with compr_mode_type::none. + */ + } + + /* + The server can now compute on the encrypted data. We will recreate the + SEALContext and set up an Evaluator here. + */ + { + EncryptionParameters parms; + parms.load(parms_stream); + parms_stream.seekg(0, parms_stream.beg); + auto context = SEALContext::Create(parms); + + Evaluator evaluator(context); + + /* + Next we need to load relinearization keys and the ciphertexts from our + data_stream. + */ + RelinKeys rlk; + Ciphertext encrypted1, encrypted2; + + /* + Deserialization is as easy as serialization. + */ + rlk.load(context, data_stream); + encrypted1.load(context, data_stream); + encrypted2.load(context, data_stream); + + /* + Compute the product, rescale, and relinearize. + */ + Ciphertext encrypted_prod; + evaluator.multiply(encrypted1, encrypted2, encrypted_prod); + evaluator.relinearize_inplace(encrypted_prod, rlk); + evaluator.rescale_to_next_inplace(encrypted_prod); + + /* + We use data_stream to communicate encrypted_prod back to the client. There + is no way to save the encrypted_prod as Serializable<Ciphertext> even + though it is still a symmetric-key encryption: only freshly encrypted + ciphertexts can be seeded. Note how the size of the result ciphertext is + smaller than the size of a fresh ciphertext because it is at a lower level + due to the rescale operation. + */ + data_stream.seekp(0, parms_stream.beg); + data_stream.seekg(0, parms_stream.beg); + auto size_encrypted_prod = encrypted_prod.save(data_stream); + + print_line(__LINE__); + cout << "Ciphertext (symmetric-key): wrote " << size_encrypted_prod << " bytes" << endl; + } + + /* + In the final step the client decrypts the result. + */ + { + EncryptionParameters parms; + parms.load(parms_stream); + parms_stream.seekg(0, parms_stream.beg); + auto context = SEALContext::Create(parms); + + /* + Load back the secret key from sk_stream. + */ + SecretKey sk; + sk.load(context, sk_stream); + Decryptor decryptor(context, sk); + CKKSEncoder encoder(context); + + Ciphertext encrypted_result; + encrypted_result.load(context, data_stream); + + Plaintext plain_result; + decryptor.decrypt(encrypted_result, plain_result); + vector<double> result; + encoder.decode(plain_result, result); + + print_line(__LINE__); + cout << "Result: " << endl; + print_vector(result, 3, 7); + } + + /* + Finally, we give a little bit more explanation of the structure of data + serialized by Microsoft SEAL. Serialized data always starts with a 16-byte + SEALHeader struct, as defined in native/src/seal/serialization.h, and is + followed by the possibly compressed data for the object. + + A SEALHeader contains the following data: + + [offset 0] 2-byte magic number 0xA15E (Serialization::seal_magic) + [offset 2] 1-byte indicating the header size in bytes (always 16) + [offset 3] 1-byte indicating the Microsoft SEAL major version number + [offset 4] 1-byte indicating the Microsoft SEAL minor version number + [offset 5] 1-byte indicating the compression mode type + [offset 6] 2-byte reserved field (unused) + [offset 8] 8-byte size in bytes of the serialized data, including the header + + Currently Microsoft SEAL supports only little-endian systems. + + As an example, we demonstrate the SEALHeader created by saving a plaintext. + Note that the SEALHeader is never compressed, so there is no need to specify + the compression mode. + */ + Plaintext pt("1x^2 + 3"); + stringstream stream; + auto data_size = pt.save(stream); + + /* + We can now load just the SEALHeader back from the stream as follows. + */ + Serialization::SEALHeader header; + Serialization::LoadHeader(stream, header); + + /* + Now confirm that the size of data written to stream matches with what is + indicated by the SEALHeader. + */ + print_line(__LINE__); + cout << "Size written to stream: " << data_size << " bytes" << endl; + cout << " " + << "Size indicated in SEALHeader: " << header.size << " bytes" << endl; + cout << endl; +#endif +} diff --git a/bigpiseal3.5.1/native/examples/7_performance.cpp b/bigpiseal3.5.1/native/examples/7_performance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..697cabc7f47c3018583a7e0f1193354c6cf8fdee --- /dev/null +++ b/bigpiseal3.5.1/native/examples/7_performance.cpp @@ -0,0 +1,728 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +void bfv_performance_test(shared_ptr<SEALContext> context) +{ + chrono::high_resolution_clock::time_point time_start, time_end; + + print_parameters(context); + cout << endl; + + auto &parms = context->first_context_data()->parms(); + auto &plain_modulus = parms.plain_modulus(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + + cout << "Generating secret/public keys: "; + KeyGenerator keygen(context); + cout << "Done" << endl; + + auto secret_key = keygen.secret_key(); + auto public_key = keygen.public_key(); + + RelinKeys relin_keys; + GaloisKeys gal_keys; + chrono::microseconds time_diff; + if (context->using_keyswitching()) + { + /* + Generate relinearization keys. + */ + cout << "Generating relinearization keys: "; + time_start = chrono::high_resolution_clock::now(); + relin_keys = keygen.relin_keys_local(); + time_end = chrono::high_resolution_clock::now(); + time_diff = chrono::duration_cast<chrono::microseconds>(time_end - time_start); + cout << "Done [" << time_diff.count() << " microseconds]" << endl; + + if (!context->key_context_data()->qualifiers().using_batching) + { + cout << "Given encryption parameters do not support batching." << endl; + return; + } + + /* + Generate Galois keys. In larger examples the Galois keys can use a lot of + memory, which can be a problem in constrained systems. The user should + try some of the larger runs of the test and observe their effect on the + memory pool allocation size. The key generation can also take a long time, + as can be observed from the print-out. + */ + cout << "Generating Galois keys: "; + time_start = chrono::high_resolution_clock::now(); + gal_keys = keygen.galois_keys_local(); + time_end = chrono::high_resolution_clock::now(); + time_diff = chrono::duration_cast<chrono::microseconds>(time_end - time_start); + cout << "Done [" << time_diff.count() << " microseconds]" << endl; + } + + Encryptor encryptor(context, public_key); + Decryptor decryptor(context, secret_key); + Evaluator evaluator(context); + BatchEncoder batch_encoder(context); + IntegerEncoder encoder(context); + + /* + These will hold the total times used by each operation. + */ + chrono::microseconds time_batch_sum(0); + chrono::microseconds time_unbatch_sum(0); + chrono::microseconds time_encrypt_sum(0); + chrono::microseconds time_decrypt_sum(0); + chrono::microseconds time_add_sum(0); + chrono::microseconds time_multiply_sum(0); + chrono::microseconds time_multiply_plain_sum(0); + chrono::microseconds time_square_sum(0); + chrono::microseconds time_relinearize_sum(0); + chrono::microseconds time_rotate_rows_one_step_sum(0); + chrono::microseconds time_rotate_rows_random_sum(0); + chrono::microseconds time_rotate_columns_sum(0); + + /* + How many times to run the test? + */ + long long count = 10; + + /* + Populate a vector of values to batch. + */ + size_t slot_count = batch_encoder.slot_count(); + vector<uint64_t> pod_vector; + random_device rd; + for (size_t i = 0; i < slot_count; i++) + { + pod_vector.push_back(rd() % plain_modulus.value()); + } + + cout << "Running tests "; + for (long long i = 0; i < count; i++) + { + /* + [Batching] + There is nothing unusual here. We batch our random plaintext matrix + into the polynomial. Note how the plaintext we create is of the exactly + right size so unnecessary reallocations are avoided. + */ + Plaintext plain(parms.poly_modulus_degree(), 0); + time_start = chrono::high_resolution_clock::now(); + batch_encoder.encode(pod_vector, plain); + time_end = chrono::high_resolution_clock::now(); + time_batch_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Unbatching] + We unbatch what we just batched. + */ + vector<uint64_t> pod_vector2(slot_count); + time_start = chrono::high_resolution_clock::now(); + batch_encoder.decode(plain, pod_vector2); + time_end = chrono::high_resolution_clock::now(); + time_unbatch_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + if (pod_vector2 != pod_vector) + { + throw runtime_error("Batch/unbatch failed. Something is wrong."); + } + + /* + [Encryption] + We make sure our ciphertext is already allocated and large enough + to hold the encryption with these encryption parameters. We encrypt + our random batched matrix here. + */ + Ciphertext encrypted(context); + time_start = chrono::high_resolution_clock::now(); + encryptor.encrypt(plain, encrypted); + time_end = chrono::high_resolution_clock::now(); + time_encrypt_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Decryption] + We decrypt what we just encrypted. + */ + Plaintext plain2(poly_modulus_degree, 0); + time_start = chrono::high_resolution_clock::now(); + decryptor.decrypt(encrypted, plain2); + time_end = chrono::high_resolution_clock::now(); + time_decrypt_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + if (plain2 != plain) + { + throw runtime_error("Encrypt/decrypt failed. Something is wrong."); + } + + /* + [Add] + We create two ciphertexts and perform a few additions with them. + */ + Ciphertext encrypted1(context); + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(i)), encrypted1); + Ciphertext encrypted2(context); + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(i + 1)), encrypted2); + time_start = chrono::high_resolution_clock::now(); + evaluator.add_inplace(encrypted1, encrypted1); + evaluator.add_inplace(encrypted2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_add_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Multiply] + We multiply two ciphertexts. Since the size of the result will be 3, + and will overwrite the first argument, we reserve first enough memory + to avoid reallocating during multiplication. + */ + encrypted1.reserve(3); + time_start = chrono::high_resolution_clock::now(); + evaluator.multiply_inplace(encrypted1, encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_multiply_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Multiply Plain] + We multiply a ciphertext with a random plaintext. Recall that + multiply_plain does not change the size of the ciphertext so we use + encrypted2 here. + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.multiply_plain_inplace(encrypted2, plain); + time_end = chrono::high_resolution_clock::now(); + time_multiply_plain_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Square] + We continue to use encrypted2. Now we square it; this should be + faster than generic homomorphic multiplication. + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.square_inplace(encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_square_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + if (context->using_keyswitching()) + { + /* + [Relinearize] + Time to get back to encrypted1. We now relinearize it back + to size 2. Since the allocation is currently big enough to + contain a ciphertext of size 3, no costly reallocations are + needed in the process. + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.relinearize_inplace(encrypted1, relin_keys); + time_end = chrono::high_resolution_clock::now(); + time_relinearize_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Rotate Rows One Step] + We rotate matrix rows by one step left and measure the time. + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.rotate_rows_inplace(encrypted, 1, gal_keys); + evaluator.rotate_rows_inplace(encrypted, -1, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_rotate_rows_one_step_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + ; + + /* + [Rotate Rows Random] + We rotate matrix rows by a random number of steps. This is much more + expensive than rotating by just one step. + */ + size_t row_size = batch_encoder.slot_count() / 2; + int random_rotation = static_cast<int>(rd() % row_size); + time_start = chrono::high_resolution_clock::now(); + evaluator.rotate_rows_inplace(encrypted, random_rotation, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_rotate_rows_random_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Rotate Columns] + Nothing surprising here. + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.rotate_columns_inplace(encrypted, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_rotate_columns_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + } + + /* + Print a dot to indicate progress. + */ + cout << "."; + cout.flush(); + } + + cout << " Done" << endl << endl; + cout.flush(); + + auto avg_batch = time_batch_sum.count() / count; + auto avg_unbatch = time_unbatch_sum.count() / count; + auto avg_encrypt = time_encrypt_sum.count() / count; + auto avg_decrypt = time_decrypt_sum.count() / count; + auto avg_add = time_add_sum.count() / (3 * count); + auto avg_multiply = time_multiply_sum.count() / count; + auto avg_multiply_plain = time_multiply_plain_sum.count() / count; + auto avg_square = time_square_sum.count() / count; + auto avg_relinearize = time_relinearize_sum.count() / count; + auto avg_rotate_rows_one_step = time_rotate_rows_one_step_sum.count() / (2 * count); + auto avg_rotate_rows_random = time_rotate_rows_random_sum.count() / count; + auto avg_rotate_columns = time_rotate_columns_sum.count() / count; + + cout << "Average batch: " << avg_batch << " microseconds" << endl; + cout << "Average unbatch: " << avg_unbatch << " microseconds" << endl; + cout << "Average encrypt: " << avg_encrypt << " microseconds" << endl; + cout << "Average decrypt: " << avg_decrypt << " microseconds" << endl; + cout << "Average add: " << avg_add << " microseconds" << endl; + cout << "Average multiply: " << avg_multiply << " microseconds" << endl; + cout << "Average multiply plain: " << avg_multiply_plain << " microseconds" << endl; + cout << "Average square: " << avg_square << " microseconds" << endl; + if (context->using_keyswitching()) + { + cout << "Average relinearize: " << avg_relinearize << " microseconds" << endl; + cout << "Average rotate rows one step: " << avg_rotate_rows_one_step << " microseconds" << endl; + cout << "Average rotate rows random: " << avg_rotate_rows_random << " microseconds" << endl; + cout << "Average rotate columns: " << avg_rotate_columns << " microseconds" << endl; + } + cout.flush(); +} + +void ckks_performance_test(shared_ptr<SEALContext> context) +{ + chrono::high_resolution_clock::time_point time_start, time_end; + + print_parameters(context); + cout << endl; + + auto &parms = context->first_context_data()->parms(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + + cout << "Generating secret/public keys: "; + KeyGenerator keygen(context); + cout << "Done" << endl; + + auto secret_key = keygen.secret_key(); + auto public_key = keygen.public_key(); + + RelinKeys relin_keys; + GaloisKeys gal_keys; + chrono::microseconds time_diff; + if (context->using_keyswitching()) + { + cout << "Generating relinearization keys: "; + time_start = chrono::high_resolution_clock::now(); + relin_keys = keygen.relin_keys_local(); + time_end = chrono::high_resolution_clock::now(); + time_diff = chrono::duration_cast<chrono::microseconds>(time_end - time_start); + cout << "Done [" << time_diff.count() << " microseconds]" << endl; + + if (!context->first_context_data()->qualifiers().using_batching) + { + cout << "Given encryption parameters do not support batching." << endl; + return; + } + + cout << "Generating Galois keys: "; + time_start = chrono::high_resolution_clock::now(); + gal_keys = keygen.galois_keys_local(); + time_end = chrono::high_resolution_clock::now(); + time_diff = chrono::duration_cast<chrono::microseconds>(time_end - time_start); + cout << "Done [" << time_diff.count() << " microseconds]" << endl; + } + + Encryptor encryptor(context, public_key); + Decryptor decryptor(context, secret_key); + Evaluator evaluator(context); + CKKSEncoder ckks_encoder(context); + + chrono::microseconds time_encode_sum(0); + chrono::microseconds time_decode_sum(0); + chrono::microseconds time_encrypt_sum(0); + chrono::microseconds time_decrypt_sum(0); + chrono::microseconds time_add_sum(0); + chrono::microseconds time_multiply_sum(0); + chrono::microseconds time_multiply_plain_sum(0); + chrono::microseconds time_square_sum(0); + chrono::microseconds time_relinearize_sum(0); + chrono::microseconds time_rescale_sum(0); + chrono::microseconds time_rotate_one_step_sum(0); + chrono::microseconds time_rotate_random_sum(0); + chrono::microseconds time_conjugate_sum(0); + + /* + How many times to run the test? + */ + long long count = 10; + + /* + Populate a vector of floating-point values to batch. + */ + vector<double> pod_vector; + random_device rd; + for (size_t i = 0; i < ckks_encoder.slot_count(); i++) + { + pod_vector.push_back(1.001 * static_cast<double>(i)); + } + + cout << "Running tests "; + for (long long i = 0; i < count; i++) + { + /* + [Encoding] + For scale we use the square root of the last coeff_modulus prime + from parms. + */ + Plaintext plain(parms.poly_modulus_degree() * parms.coeff_modulus().size(), 0); + /* + + */ + double scale = sqrt(static_cast<double>(parms.coeff_modulus().back().value())); + time_start = chrono::high_resolution_clock::now(); + ckks_encoder.encode(pod_vector, scale, plain); + time_end = chrono::high_resolution_clock::now(); + time_encode_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Decoding] + */ + vector<double> pod_vector2(ckks_encoder.slot_count()); + time_start = chrono::high_resolution_clock::now(); + ckks_encoder.decode(plain, pod_vector2); + time_end = chrono::high_resolution_clock::now(); + time_decode_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Encryption] + */ + Ciphertext encrypted(context); + time_start = chrono::high_resolution_clock::now(); + encryptor.encrypt(plain, encrypted); + time_end = chrono::high_resolution_clock::now(); + time_encrypt_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Decryption] + */ + Plaintext plain2(poly_modulus_degree, 0); + time_start = chrono::high_resolution_clock::now(); + decryptor.decrypt(encrypted, plain2); + time_end = chrono::high_resolution_clock::now(); + time_decrypt_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Add] + */ + Ciphertext encrypted1(context); + ckks_encoder.encode(i + 1, plain); + encryptor.encrypt(plain, encrypted1); + Ciphertext encrypted2(context); + ckks_encoder.encode(i + 1, plain2); + encryptor.encrypt(plain2, encrypted2); + time_start = chrono::high_resolution_clock::now(); + evaluator.add_inplace(encrypted1, encrypted1); + evaluator.add_inplace(encrypted2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_add_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Multiply] + */ + encrypted1.reserve(3); + time_start = chrono::high_resolution_clock::now(); + evaluator.multiply_inplace(encrypted1, encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_multiply_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Multiply Plain] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.multiply_plain_inplace(encrypted2, plain); + time_end = chrono::high_resolution_clock::now(); + time_multiply_plain_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Square] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.square_inplace(encrypted2); + time_end = chrono::high_resolution_clock::now(); + time_square_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + if (context->using_keyswitching()) + { + /* + [Relinearize] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.relinearize_inplace(encrypted1, relin_keys); + time_end = chrono::high_resolution_clock::now(); + time_relinearize_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Rescale] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.rescale_to_next_inplace(encrypted1); + time_end = chrono::high_resolution_clock::now(); + time_rescale_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Rotate Vector] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.rotate_vector_inplace(encrypted, 1, gal_keys); + evaluator.rotate_vector_inplace(encrypted, -1, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_rotate_one_step_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Rotate Vector Random] + */ + int random_rotation = static_cast<int>(rd() % ckks_encoder.slot_count()); + time_start = chrono::high_resolution_clock::now(); + evaluator.rotate_vector_inplace(encrypted, random_rotation, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_rotate_random_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + + /* + [Complex Conjugate] + */ + time_start = chrono::high_resolution_clock::now(); + evaluator.complex_conjugate_inplace(encrypted, gal_keys); + time_end = chrono::high_resolution_clock::now(); + time_conjugate_sum += chrono::duration_cast<chrono::microseconds>(time_end - time_start); + } + + /* + Print a dot to indicate progress. + */ + cout << "."; + cout.flush(); + } + + cout << " Done" << endl << endl; + cout.flush(); + + auto avg_encode = time_encode_sum.count() / count; + auto avg_decode = time_decode_sum.count() / count; + auto avg_encrypt = time_encrypt_sum.count() / count; + auto avg_decrypt = time_decrypt_sum.count() / count; + auto avg_add = time_add_sum.count() / (3 * count); + auto avg_multiply = time_multiply_sum.count() / count; + auto avg_multiply_plain = time_multiply_plain_sum.count() / count; + auto avg_square = time_square_sum.count() / count; + auto avg_relinearize = time_relinearize_sum.count() / count; + auto avg_rescale = time_rescale_sum.count() / count; + auto avg_rotate_one_step = time_rotate_one_step_sum.count() / (2 * count); + auto avg_rotate_random = time_rotate_random_sum.count() / count; + auto avg_conjugate = time_conjugate_sum.count() / count; + + cout << "Average encode: " << avg_encode << " microseconds" << endl; + cout << "Average decode: " << avg_decode << " microseconds" << endl; + cout << "Average encrypt: " << avg_encrypt << " microseconds" << endl; + cout << "Average decrypt: " << avg_decrypt << " microseconds" << endl; + cout << "Average add: " << avg_add << " microseconds" << endl; + cout << "Average multiply: " << avg_multiply << " microseconds" << endl; + cout << "Average multiply plain: " << avg_multiply_plain << " microseconds" << endl; + cout << "Average square: " << avg_square << " microseconds" << endl; + if (context->using_keyswitching()) + { + cout << "Average relinearize: " << avg_relinearize << " microseconds" << endl; + cout << "Average rescale: " << avg_rescale << " microseconds" << endl; + cout << "Average rotate vector one step: " << avg_rotate_one_step << " microseconds" << endl; + cout << "Average rotate vector random: " << avg_rotate_random << " microseconds" << endl; + cout << "Average complex conjugate: " << avg_conjugate << " microseconds" << endl; + } + cout.flush(); +} + +void example_bfv_performance_default() +{ + print_example_banner("BFV Performance Test with Degrees: 4096, 8192, and 16384"); + + EncryptionParameters parms(scheme_type::BFV); + size_t poly_modulus_degree = 4096; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + parms.set_plain_modulus(786433); + bfv_performance_test(SEALContext::Create(parms)); + + cout << endl; + poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + parms.set_plain_modulus(786433); + bfv_performance_test(SEALContext::Create(parms)); + + cout << endl; + poly_modulus_degree = 16384; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + parms.set_plain_modulus(786433); + bfv_performance_test(SEALContext::Create(parms)); + + /* + Comment out the following to run the biggest example. + */ + // cout << endl; + // poly_modulus_degree = 32768; + // parms.set_poly_modulus_degree(poly_modulus_degree); + // parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + // parms.set_plain_modulus(786433); + // bfv_performance_test(SEALContext::Create(parms)); +} + +void example_bfv_performance_custom() +{ + size_t poly_modulus_degree = 0; + cout << endl << "Set poly_modulus_degree (1024, 2048, 4096, 8192, 16384, or 32768): "; + if (!(cin >> poly_modulus_degree)) + { + cout << "Invalid option." << endl; + cin.clear(); + cin.ignore(numeric_limits<streamsize>::max(), '\n'); + return; + } + if (poly_modulus_degree < 1024 || poly_modulus_degree > 32768 || + (poly_modulus_degree & (poly_modulus_degree - 1)) != 0) + { + cout << "Invalid option." << endl; + return; + } + + string banner = "BFV Performance Test with Degree: "; + print_example_banner(banner + to_string(poly_modulus_degree)); + + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + if (poly_modulus_degree == 1024) + { + parms.set_plain_modulus(12289); + } + else + { + parms.set_plain_modulus(786433); + } + bfv_performance_test(SEALContext::Create(parms)); +} + +void example_ckks_performance_default() +{ + print_example_banner("CKKS Performance Test with Degrees: 4096, 8192, and 16384"); + + // It is not recommended to use BFVDefault primes in CKKS. However, for performance + // test, BFVDefault primes are good enough. + EncryptionParameters parms(scheme_type::CKKS); + size_t poly_modulus_degree = 4096; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + ckks_performance_test(SEALContext::Create(parms)); + + cout << endl; + poly_modulus_degree = 8192; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + ckks_performance_test(SEALContext::Create(parms)); + + cout << endl; + poly_modulus_degree = 16384; + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + ckks_performance_test(SEALContext::Create(parms)); + + /* + Comment out the following to run the biggest example. + */ + // cout << endl; + // poly_modulus_degree = 32768; + // parms.set_poly_modulus_degree(poly_modulus_degree); + // parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + // ckks_performance_test(SEALContext::Create(parms)); +} + +void example_ckks_performance_custom() +{ + size_t poly_modulus_degree = 0; + cout << endl << "Set poly_modulus_degree (1024, 2048, 4096, 8192, 16384, or 32768): "; + if (!(cin >> poly_modulus_degree)) + { + cout << "Invalid option." << endl; + cin.clear(); + cin.ignore(numeric_limits<streamsize>::max(), '\n'); + return; + } + if (poly_modulus_degree < 1024 || poly_modulus_degree > 32768 || + (poly_modulus_degree & (poly_modulus_degree - 1)) != 0) + { + cout << "Invalid option." << endl; + return; + } + + string banner = "CKKS Performance Test with Degree: "; + print_example_banner(banner + to_string(poly_modulus_degree)); + + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(poly_modulus_degree); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); + ckks_performance_test(SEALContext::Create(parms)); +} + +/* +Prints a sub-menu to select the performance test. +*/ +void example_performance_test() +{ + print_example_banner("Example: Performance Test"); + + while (true) + { + cout << endl; + cout << "Select a scheme (and optionally poly_modulus_degree):" << endl; + cout << " 1. BFV with default degrees" << endl; + cout << " 2. BFV with a custom degree" << endl; + cout << " 3. CKKS with default degrees" << endl; + cout << " 4. CKKS with a custom degree" << endl; + cout << " 0. Back to main menu" << endl; + + int selection = 0; + cout << endl << "> Run performance test (1 ~ 4) or go back (0): "; + if (!(cin >> selection)) + { + cout << "Invalid option." << endl; + cin.clear(); + cin.ignore(numeric_limits<streamsize>::max(), '\n'); + continue; + } + + switch (selection) + { + case 1: + example_bfv_performance_default(); + break; + + case 2: + example_bfv_performance_custom(); + break; + + case 3: + example_ckks_performance_default(); + break; + + case 4: + example_ckks_performance_custom(); + break; + + case 0: + cout << endl; + return; + + default: + cout << "Invalid option." << endl; + } + } +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_result_v1.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_result_v1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17874a1064c0f0ea23a202df918b5d2ac4ff5c4f --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_result_v1.cpp @@ -0,0 +1,139 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// bool decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +bool decrypt(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + // cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + bool result_str = decrypt(sample_size, dir); + cout << result_str << endl; + + return 0; + } +} + +bool decrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + + bool isContain = false; + if (sample_size <= decr.bcode->slot_count()/2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + // cout << pod_matrix.size() << endl; + + int no_dual_vectors = (decr.bcode->slot_count() / 2) / (sample_size); + + vector<int64_t> v1, v2; + for (size_t i = 0; i < no_dual_vectors * sample_size; i++) + { + v1.push_back(pod_matrix[i]); + v2.push_back(pod_matrix[(pod_matrix.size() / 2) + i]); + } + + int64_t sum = 0; + if (isContain == false) + { + // cout << "1 : "; + for (size_t i = 0; i < v1.size(); i++) + { + // cout << v1[i]; + if ((i + 1) % sample_size == 0) + { + // cout << endl; + if (i < v1.size() - 1) + { + // cout << ((i + 1) / 40) + 1 << " : "; + } + } + else + { + // cout << ", "; + } + + if (v1[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + // cout << endl; + if (isContain == false) + { + sum = 0; + // cout << (v2.size() + 1) / 40 + 1 << " : "; + for (size_t i = 0; i < v2.size(); i++) + { + // cout << v2[i]; + if ((i + 1) % sample_size == 0) + { + // cout << endl; + if (i < v2.size() - 1) + { + // cout << ((v2.size() + i + 1) / 40) + 1 << " : "; + } + } + else + { + // cout << ", "; + } + + if (v2[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + } + else + { + // cout << endl << "Sample size is too large" << endl; + } + + delete_operator_batching(decr); + return isContain; +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_v1.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_v1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..842c00cd8b1d2fb1b577b44d4fcc7367ad42d985 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_decrypt_v1.cpp @@ -0,0 +1,78 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// vector<int64_t> decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +vector<double> decrypt(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + vector<double> result = decrypt(sample_size, dir); + + for (int i = 0; i < result.size(); ++i) + { + std::cout << result[i] << ' '; + } + + std::cout << endl; + + return 0; + } +} + + +vector<double> decrypt(int &sample_size, string &ciphertext_dir) +{ + struct cdecryptor_t decr; + // init_operator_batching(decr, key_dir); + init_operator_ckks(decr, key_dir); + // init_operator_batching(2048, 4294967296, decr, key_dir); + // init_operator_batching(4096, 4294967296, decr, key_dir); + // init_operator_batching(8192, 4294967296, decr, key_dir); + // init_operator_batching(16384, 4294967296, decr, key_dir); + // init_operator_batching(32768, 4294967296, decr, key_dir); + + vector<double> v; + if (sample_size <= decr.ccode->slot_count()/2) + { + Ciphertext cipher_matrix; + + vector<double> pod_matrix; + load_ciphertext_ckks(decr, cipher_matrix, ciphertext_dir); + // pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + // pod_matrix = decrypt_ciphermatrix_ckks(decr, cipher_matrix); + decrypt_ciphertext_ckks(decr, cipher_matrix, pod_matrix); + // void decrypt_ciphertext_ckks(struct cdecryptor_t& op_st, seal::Ciphertext& ct, std::vector<double>& pt_val); + + for (size_t i = 0; i < sample_size; i++) + { + v.push_back(pod_matrix[i]); + } + } + else + { + // cout << endl << "Sample size is too large" << endl; + } + // delete_operator_batching(decr); + delete_operator_ckks(decr); + return v; +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_encrypt_v1.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_encrypt_v1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a35963a4659bebd064c6e539cfd8f727f8db67e6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_encrypt_v1.cpp @@ -0,0 +1,53 @@ +#include "seal_api.h" + +using namespace seal; +using namespace std; + +int main(int argc, char **argv) +{ + if (argc != 6) + { + // cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl; + cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or " + "prefix, ciphertext output file directory, sample size and public key path" + << endl; + return -1; + } + else + { + string plaintext = argv[1]; + string ciphertext_name = argv[2]; + string ciphertext_dir = argv[3]; + int sample_size = atol(argv[4]); + string key_dir = argv[5]; + + struct cencryptor_t encr; + init_operator_ckks(encr, key_dir); + + stringstream ss; + ss << plaintext; + vector<double> pod_matrix; + double x = 0; + + while (ss >> x) + { + pod_matrix.push_back(x); + } + + if (pod_matrix.size() <= encr.ccode->slot_count() && pod_matrix.size() >= sample_size) + { + Ciphertext encrypted_matrix; + init_ciphertext_ckks(encr, pod_matrix, encrypted_matrix); + save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct"); + delete_operator_ckks(encr); + return 0; + } + else + { + delete_operator_ckks(encr); + return -1; + } + delete_operator_ckks(encr); + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1 copy.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1 copy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce61335dda74c3a520899a70fe55285e68e9fd7d --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1 copy.cpp @@ -0,0 +1,515 @@ +#include <iostream> +#include "seal_api.h" +#include "util.h" +// #include <algorithm> +// #include <iterator> +// #include <vector> +// #include <filesystem> + +using namespace seal; +using namespace std; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +bool is_number(const string &s); + +void printStrVector(const vector<string> &v); + +vector<vector<string>> split_ends(const vector<string> &data, const vector<int> &ends); + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out); + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent); + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +int simpleCheck( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval); + +// string relink_key_path; +// string galois_key_path; +// string public_key_path; +string key_dir = ""; + +int main(int argc, char **argv) +{ + // input processing - begin + // string result_name = argv[argc - 6]; + // string result_dir = argv[argc - 5]; + // int sample_size = atoi(argv[argc - 4]); + // relink_key_path = argv[argc - 3]; + // galois_key_path = argv[argc - 2]; + // public_key_path = argv[argc - 1]; + string source = argv[1]; + + string result_name = argv[argc - 4]; + string result_dir = argv[argc - 3]; + int sample_size = atoi(argv[argc - 2]); + key_dir = argv[argc - 1]; + + vector<string> data; + for (int i = 2; i < argc - 4; i++) + { + data.push_back(argv[i]); + } + + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || + // relink_key_path == "" || galois_key_path == "" || public_key_path == "") + if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || key_dir == "") + { + // error handling + cout << "[ERROR] please enter a source path, data paths, output ciphertext file name or prefix, output " + "ciphertext directory, sample size, linking key path, galois key path and public key path" + << endl; + return -1; + } + // input processing - end + + // simple algo + // int result = simpleCheck(source, data, result_name, result_dir, sample_size, key_dir); + // sequence algo + int result = checkSq(source, data, result_name, result_dir, sample_size, key_dir); + + // error handling + if (result == -1) + { + fprintf(stderr, "error!\n"); + } + else + { + cout << "done"; + } + + // checkSq(source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, public_key_path); + + return result; +} + +int simpleCheck( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + struct evaluator_t eval; + init_operator_batching(eval, key_dir); + + struct encryptor_t encr; + init_operator_batching(encr, key_dir); + + // cout << sample_size*data.size() << endl; + // cout << encr.bcode->slot_count() << endl; + if (sample_size * data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count() / 2) + { + // error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // normalize input data if its size is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + int required_range = normalized_data_size * sample_size; + int required_no_row_elements = required_range / 2; + int required_range_row = required_range / 2; + + // create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row; + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[required_no_row_elements + i] = 1; + padding_matrix[encr.bcode->slot_count() - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // add dummy vector for oddy data + temp2 = encrypted_dummy_matrix; + } + + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + // add renmaining padding slots + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + } + + save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + return 0; + } +} + +// int checkSq( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path) +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + struct evaluator_t eval; + // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + init_operator_batching(eval, key_dir); + + struct encryptor_t encr; + // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // init_operator_batching(16384, 4294967296, encr, public_key_path); + // init_operator_batching(32768, 4294967296, encr, public_key_path); + init_operator_batching(encr, key_dir); + + // if (sample_size*data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count()/2) + if (sample_size > encr.bcode->slot_count() / 2) + { + // error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + // struct evaluator_t eval; + // // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + + // struct encryptor_t encr; + // // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // // init_operator_batching(16384, 4294967296, encr, public_key_path); + // // init_operator_batching(32768, 4294967296, encr, public_key_path); + + int capacity = (encr.bcode->slot_count()) / sample_size; + // cout << capacity << endl; + + // vector<string> v_temp; + // vector<string> v_v_temp; + // Ciphertext result; + vector<Ciphertext> v_result; + int nSq = data.size() / capacity; + for (size_t i = 0; i < nSq; i++) + { + Ciphertext result; + // cout << "sq : " << i << endl; + vector<string> v_temp; + for (size_t j = 0; j < capacity; j++) + { + string str = data.back(); + v_temp.push_back(str); + data.pop_back(); + } + if (i == 0) + { + // cout << "sq : init" << endl; + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + else + { + // cout << "sq : other" << endl; + // Ciphertext result2 = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + } + + if (data.size() % capacity != 0) + { + // cout << "oddy!!! " << endl; + // Ciphertext result = check( + // source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + Ciphertext result = check(source, data, result_name, result_dir, sample_size, key_dir, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + v_result.push_back(result); + } + + Ciphertext result; + multiply_ciphertexts(eval, v_result, result); + relinearize_inplace(eval, result); + + save_ciphertext(result, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + return 0; + } +} + +// Ciphertext check( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path, struct encryptor_t &encr, +// struct evaluator_t &eval) +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval) +{ + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0) + // { + // // error handling + // // return -1; + + // } + // else + // { + + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // normalize input data if its size is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + int required_range = normalized_data_size * sample_size; + int required_no_row_elements = required_range / 2; + int required_range_row = required_range / 2; + + // create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row; + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[required_no_row_elements + i] = 1; + padding_matrix[(encr.bcode->slot_count() - 1) - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // add dummy vector for oddy data + temp2 = encrypted_dummy_matrix; + } + + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + // add renmaining padding slots + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + } + + // // save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + // delete_operator_batching(eval); + + return encrypted_result_matrix; + // } +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->sub(ct1, ct2, ct_out); +} + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->sub_inplace(ct1, ct2); +} + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->sub_plain_inplace(ct, plain); +} + +void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->negate_inplace(ct); +} + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->multiply_inplace(ct1, ct2); +} + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->multiply_plain_inplace(ct, plain); +} + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out) +{ + op_st.eval->relinearize(ct, op_st.lk, ct_out); +} + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent) +{ + op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk); +} + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->mod_switch_to_next_inplace(ct); +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff62355bb42f86ac44405836cb107b4406aefd08 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_evaluate_v1.cpp @@ -0,0 +1,568 @@ +#include <iostream> +#include "csv_api.h" +#include "print_api.h" +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext_ckks(struct cevaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext_ckks(struct cevaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +bool is_number(const string &s); + +void printStrVector(const vector<string> &v); + +vector<vector<string>> split_ends(const vector<string> &data, const vector<int> &ends); + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void multiply_ciphertexts_ckks(struct cevaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void relinearize_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct); + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out); + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void add_plain_inplace_ciphertext_ckks(struct cevaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void add_plain_ckks(struct cevaluator_t &op_st, Ciphertext &ct, Plaintext &plain, Ciphertext &ct_out); + +void multiply_plain_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void multiply_plain_ckks(struct cevaluator_t &op_st, Ciphertext &ct, const Plaintext &plain, Ciphertext &out); + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void add_many_ciphertext_ckks(struct cevaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent); + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void mod_switch_to_next_inplace_ciphertext_ckks(struct cevaluator_t &op_st, Plaintext &plain); + +void mod_switch_to_inplace_ckks(struct cevaluator_t &op_st, Plaintext &plain, parms_id_type &parms_id); + +void mod_switch_to_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct, parms_id_type &parms_id); + +int ANNProcess( + vector<string> &wFilePaths, string &xCT, vector<string> &bFilePaths, string &result_name, string &result_dir, + int &sample_size, string &key_dir); + +int main(int argc, char **argv) +{ + string wFilePath = argv[1]; + string wFilePath2 = argv[2]; + string wFilePath3 = argv[3]; + string wFilePath4 = argv[4]; + + string xCT = argv[5]; + + string bFilePath = argv[6]; + string bFilePath2 = argv[7]; + string bFilePath3 = argv[8]; + string bFilePath4 = argv[9]; + + string result_name = argv[argc - 4]; + string result_dir = argv[argc - 3]; + int sample_size = atoi(argv[argc - 2]); + string key_dir = argv[argc - 1]; + + // Midify and improve later + vector<string> wFilePaths; + wFilePaths.push_back(wFilePath); + wFilePaths.push_back(wFilePath2); + wFilePaths.push_back(wFilePath3); + wFilePaths.push_back(wFilePath4); + // Midify and improve later + vector<string> bFilePaths; + bFilePaths.push_back(bFilePath); + bFilePaths.push_back(bFilePath2); + bFilePaths.push_back(bFilePath3); + bFilePaths.push_back(bFilePath4); + + if (xCT == "" || result_name == "" || result_dir == "" || sample_size == 0 || key_dir == "") + { + // error handling + cout << "[ERROR] please enter a source path, data paths, output ciphertext file name or prefix, output " + "ciphertext directory, sample size, linking key path, galois key path and public key path" + << endl; + return -1; + } + + int result = 0; + result = ANNProcess(wFilePaths, xCT, bFilePaths, result_name, result_dir, sample_size, key_dir); + + // error handling + if (result == -1) + { + fprintf(stderr, "error!\n"); + } + else + { + std::cout << "done"; + } + + return result; +} + +void rotate_2d_matrix_clockwise_impl( + vector<vector<double>> const &matrix, vector<vector<double>> &rotated_matrix, int const M, int const N) +{ + for (int x = 0; x < N; ++x) + { + for (int y = 0; y < M; ++y) + { + // cout << "[ANN Engine] ..... " << matrix[x][y] << endl; + // Source : https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations + rotated_matrix[y][-x - 1 + N] = matrix[x][y]; + } + } +} + +auto rotate_2d_matrix_clockwise(vector<vector<double>> const &original_matrix) -> vector<vector<double>> +{ + int const M = original_matrix[0].size(); + int const N = original_matrix.size(); + vector<vector<double>> rotated_matrix; + rotated_matrix.resize(M); + for (auto x = 0; x < M; ++x) + { + rotated_matrix[x].resize(N); + } + rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N); + return rotated_matrix; +} + +vector<vector<double>> load_matrix_and_rotate_clockwise(string &original_matrix, int n) +{ + // cout << "[ANN Engine] loading matrix w " << original_matrix << "..... " << endl; + vector<vector<double>> w; + load_csv_file(original_matrix, w, 0); + // cout << "[ANN Engine] loading matrix w ..... end \n" << endl; + + // cout << "[ANN Engine] rotating matrix w ..... " << endl; + for (int i = 0; i < n; i++) + { + w = rotate_2d_matrix_clockwise(w); + } + // cout << "[ANN Engine] rotating matrix w ..... end \n" << endl; + + // cout << "[ANN Engine] printing rotated matrix w ..... " << endl; + // print_matrix(w); + // cout << "[ANN Engine] printing rotated matrix w ..... end \n" << endl; + + return w; +} + +Ciphertext getIndexVector(cencryptor_t &encr, cevaluator_t &eval, Ciphertext vector_ct, int slot_count, int index) +{ + // std::cout << "[ANN Engine] Error 1 ..... \n" << endl; + vector<double> index_vector(encr.ccode->slot_count(), 0ULL); + index_vector[index - 1] = 1ULL; + + Plaintext index_vector_pt; + init_plaintext_ckks(encr, index_vector, index_vector_pt); + + // std::cout << "[ANN Engine] Error 2 ..... \n" << endl; + + Ciphertext v_ct = vector_ct; + + // std::cout << "[ANN Engine] Error 3 ..... \n" << endl; + + parms_id_type last_parms_id2 = v_ct.parms_id(); + mod_switch_to_inplace_ckks(eval, index_vector_pt, last_parms_id2); + + // std::cout << "[ANN Engine] Computing v_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of v_ct: " << log2(v_ct.scale()) << " bits" << endl; + // cout << " + Modulus chain index for v_ct: " << eval.context->get_context_data(v_ct.parms_id())->chain_index() + // << endl; + + // cout << " + Scale of index_vector_pt: " << log2(index_vector_pt.scale()) << " bits" << endl; + // cout << " + Modulus chain index for index_vector_pt: " + // << eval.context->get_context_data(index_vector_pt.parms_id())->chain_index() << endl; + + multiply_plain_inplace_ckks(eval, v_ct, index_vector_pt); + relinearize_inplace_ckks(eval, v_ct); + rescale_to_next_inplace_ckks(eval, v_ct); + + eval.eval->rotate_vector(v_ct, -(slot_count - index), eval.gk, v_ct); + + Ciphertext result = v_ct; + + // std::cout << "[ANN Engine] Error 4 ..... \n" << endl; + + for (size_t i = 0; i < slot_count; i++) + { + // std::cout << "[ANN Engine] Error 5 ..... \n" << endl; + + eval.eval->rotate_vector_inplace(result, 1, eval.gk); + // eval.eval->rotate_vector(result, 1, eval.gk, result); + + // std::cout << "[ANN Engine] Error 6 ..... \n" << endl; + + // std::cout << "[ANN Engine] Computing v_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of v_ct: " << log2(v_ct.scale()) << " bits" << endl; + // cout << " + Modulus chain index for v_ct: " << + // eval.context->get_context_data(v_ct.parms_id())->chain_index() + // << endl; + + // cout << " + Scale of result: " << log2(result.scale()) << " bits" << endl; + // cout << " + Modulus chain index for result: " + // << eval.context->get_context_data(result.parms_id())->chain_index() << endl; + + add_ciphertext_ckks(eval, v_ct, result, result); + + // std::cout << "[ANN Engine] Error 7 ..... \n" << endl; + } + return result; +} + +Ciphertext action_compute( + cencryptor_t &encr, cevaluator_t &eval, string &wFilePath, Ciphertext &x, string &bFilePath, int sample_size) +{ + vector<vector<double>> cw; + cw = load_matrix_and_rotate_clockwise(wFilePath, 3); + + // Transform into vector<Plaintext> + // std::cout << "[ANN Engine] Transform into vector<Plaintext> cw_pt ..... \n" << endl; + vector<Plaintext> cw_pt; + for (int i = 0; i < cw.size(); i++) + { + Plaintext temp_pt; + init_plaintext_ckks(encr, cw[i], temp_pt); + cw_pt.push_back(temp_pt); + } + // std::cout << "[ANN Engine] Transform into vector<Plaintext> cw_pt ..... end \n" << endl; + + // cout << "[ANN Engine] loading vector b " << bFilePath << "..... " << endl; + vector<vector<double>> b; + load_csv_file(bFilePath, b, 0); + + Plaintext b_pt; + + init_plaintext_ckks(encr, b[0], b_pt); + + // cout << "[ANN Engine] loading vector b ..... end \n" << endl; + + std::cout << "[ANN Engine] Computing wxb_ct ..... " << endl; + vector<Ciphertext> wxb_ct; + + Ciphertext index_vector; + + // std::cout << "[ANN Engine] Computing wxb_ct (multiply_plain_inplace_ckks)..... " << endl; + for (int i = 0; i < cw_pt.size(); i++) + { + Ciphertext x_ct = x; + Plaintext pt; + + // std::cout << "[ANN Engine] Computing wxb_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of x_ct: " << log2(x_ct.scale()) << " bits" << endl; + // cout << " + Modulus chain index for x_ct: " << + // eval.context->get_context_data(x_ct.parms_id())->chain_index() + // << endl; + + // cout << " + Scale of cw_pt[i]: " << log2(cw_pt[i].scale()) << " bits" << endl; + // cout << " + Modulus chain index for cw_pt[i]: " + // << eval.context->get_context_data(cw_pt[i].parms_id())->chain_index() << endl; + + // std::cout << "[ANN Engine] Error 1..... " << endl; + parms_id_type last_parms_id2 = x_ct.parms_id(); + mod_switch_to_inplace_ckks(eval, cw_pt[i], last_parms_id2); + + // index_vector = getIndexVector(encr, eval, x_ct, 3, 1); + index_vector = getIndexVector(encr, eval, x_ct, sample_size, sample_size - i); + + // std::cout << "[ANN Engine] Error 1.1..... " << endl; + + parms_id_type last_parms_id3 = x_ct.parms_id(); + mod_switch_to_inplace_ckks(eval, cw_pt[i], last_parms_id3); + + // Ciphertext b = getIndexVector(encr, eval, a, 3, 1); + // std::cout << "[ANN Engine] Error 2..... " << endl; + + // std::cout << "[ANN Engine] Computing wxb_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of x_ct: " << log2(x_ct.scale()) << " bits" << endl; + // cout << " + Modulus chain index for x_ct: " << + // eval.context->get_context_data(x_ct.parms_id())->chain_index() + // << endl; + + // cout << " + Scale of cw_pt[i]: " << log2(cw_pt[i].scale()) << " bits" << endl; + // cout << " + Modulus chain index for cw_pt[i]: " + // << eval.context->get_context_data(cw_pt[i].parms_id())->chain_index() << endl; + + // x_ct = getIndexVector(encr, eval, x_ct, 3, 1); + + // multiply_plain_inplace_ckks(eval, x_ct, cw_pt[i]); + // std::cout << "[ANN Engine] Error 3..... " << endl; + // std::cout << "[ANN Engine] Error 2..... " << endl; + + // std::cout << "[ANN Engine] Computing wxb_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of index_vector: " << log2(index_vector.scale()) << " bits" << endl; + // cout << " + Modulus chain index for index_vector: " + // << eval.context->get_context_data(index_vector.parms_id())->chain_index() << endl; + + // cout << " + Scale of cw_pt[i]: " << log2(cw_pt[i].scale()) << " bits" << endl; + // cout << " + Modulus chain index for cw_pt[i]: " + // << eval.context->get_context_data(cw_pt[i].parms_id())->chain_index() << endl; + + parms_id_type last_parms_id4 = index_vector.parms_id(); + mod_switch_to_inplace_ckks(eval, cw_pt[i], last_parms_id4); + // cw_pt[i].scale() = pow(2.0, 40); + // index_vector.scale() = pow(2.0, 40); + + multiply_plain_ckks(eval, index_vector, cw_pt[i], x_ct); + + // std::cout << "[ANN Engine] Computing wxb_ct (add_ciphertext_ckks)..... " << endl; + // cout << " + Scale of x_ct: " << log2(x_ct.scale()) << " bits" << endl; + // cout << " + Modulus chain index for x_ct: " << + // eval.context->get_context_data(x_ct.parms_id())->chain_index() + // << endl; + + // cout << " + Scale of b_pt: " << log2(b_pt.scale()) << " bits" << endl; + // cout << " + Modulus chain index for b_pt: " << + // eval.context->get_context_data(b_pt.parms_id())->chain_index() + // << endl; + + relinearize_inplace_ckks(eval, x_ct); + rescale_to_next_inplace_ckks(eval, x_ct); + // rescale b_pt + parms_id_type last_parms_id = x_ct.parms_id(); + mod_switch_to_inplace_ckks(eval, b_pt, last_parms_id); + // more solution + // cout << " + Exact scale 1 in x_ct: " << x_ct.scale() << endl; + // cout << " + Exact scale 1 in b_pt: " << b_pt.scale() << endl; + // cout << " + Exact scale 1 in b_ct: " << b_ct.scale() << endl; + x_ct.scale() = pow(2.0, 40); + b_pt.scale() = pow(2.0, 40); + // cout << " + Exact scale 2 in x_ct: " << x_ct.scale() << endl; + // cout << " + Exact scale 2 in b_pt: " << b_pt.scale() << endl; + + wxb_ct.push_back(x_ct); + } + Ciphertext a; + // std::cout << "[ANN Engine] Computing wxb_ct (add_many_ciphertext_ckks)..... " << endl; + add_many_ciphertext_ckks(eval, wxb_ct, a); + + add_plain_inplace_ciphertext_ckks(eval, a, b_pt); + // add_ciphertext_ckks(eval, ct, b_ct, ct); + // rescale_to_next_inplace_ckks(eval, ct); + + std::cout << "[ANN Engine] Computing wxb_ct ..... end" << endl; + return a; +} + +int ANNProcess( + vector<string> &wFilePaths, string &xCT, vector<string> &bFilePaths, string &result_name, string &result_dir, + int &sample_size, string &key_dir) +{ + // This should be revised and improved! + struct cevaluator_t eval; + init_operator_ckks(eval, key_dir); + struct cencryptor_t encr; + init_operator_ckks(encr, key_dir); + + int slot_count = encr.ccode->slot_count(); + std::cout << slot_count << endl; + + // cout << "[ANN Engine] loading vector x " << xCT << "..... " << endl; + Ciphertext a; // x + load_ciphertext_ckks(eval, a, xCT); + // cout << "[ANN Engine] loading vector x ..... end \n" << endl; + + // for (size_t i = 0; i < wFilePaths.size(); i++) + for (size_t i = 0; i < 3; i++) + { + /* code */ + cout << "[ANN Engine] compute a" << i + 1 << " ....." << endl; + a = action_compute(encr, eval, wFilePaths[i], a, bFilePaths[i], sample_size); + cout << "[ANN Engine] compute a" << i + 1 << " ..... end \n" << endl; + } + + // getIndexVector(encr, eval, a, slot_count, 3); + + // Ciphertext b = getIndexVector(encr, eval, a, 3, 1); + // index_vector = getIndexVector(encr, eval, x_ct, 3, 3); + + save_ciphertext(a, result_dir + "/" + result_name + ".ct"); + delete_operator_ckks(encr); + delete_operator_ckks(eval); + + return 0; +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->sub(ct1, ct2, ct_out); +} + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->sub_inplace(ct1, ct2); +} + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->sub_plain_inplace(ct, plain); +} + +void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->negate_inplace(ct); +} + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_plain_inplace_ciphertext_ckks(struct cevaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_plain_ckks(struct cevaluator_t &op_st, Ciphertext &ct, Plaintext &plain, Ciphertext &ct_out) +{ + op_st.eval->add_plain(ct, plain, ct_out); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_ciphertext_ckks(struct cevaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_many_ciphertext_ckks(struct cevaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +// void add_many_ciphertext_ckks(struct cevaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +// { +// op_st.eval->add_many(cts, ct_out); +// } + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_ciphertext_ckks(struct cevaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->multiply_inplace(ct1, ct2); +} + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_ciphertexts_ckks(struct cevaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_plain_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->multiply_plain_inplace(ct, plain); +} + +void multiply_plain_ckks(struct cevaluator_t &op_st, Ciphertext &ct, const Plaintext &plain, Ciphertext &out) +{ + op_st.eval->multiply_plain(ct, plain, out); +} + +// void multiply_plain_inplace_ckks(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +// { +// op_st.eval->multiply_plain_inplace(ct, plain); +// } + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out) +{ + op_st.eval->relinearize(ct, op_st.lk, ct_out); +} + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + +void rescale_to_next_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent) +{ + op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk); +} + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->mod_switch_to_next_inplace(ct); +} + +void mod_switch_to_inplace_ckks(struct cevaluator_t &op_st, Plaintext &plain, parms_id_type &parms_id) +{ + op_st.eval->mod_switch_to_inplace(plain, parms_id); +} + +void mod_switch_to_inplace_ckks(struct cevaluator_t &op_st, Ciphertext &ct, parms_id_type &parms_id) +{ + op_st.eval->mod_switch_to_inplace(ct, parms_id); +} + +void mod_switch_to_next_inplace_ciphertext_ckks(struct cevaluator_t &op_st, Plaintext &plain) +{ + op_st.eval->mod_switch_to_next_inplace(plain); +} + +// mod_switch_drop_to_next \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ANN_genkey_v1.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_genkey_v1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..662e3f0c5dfd65cc3e693912ce39c5d9a2bb1013 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ANN_genkey_v1.cpp @@ -0,0 +1,34 @@ +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + string key_dir = argv[1]; + + // size_t poly_d = 4096; + // size_t poly_d = 8192; + size_t poly_d = 16384; + + // Params option 1 + // int bit_size = 20; + int bit_size = 0; + + // Params option 2 + // uint64_t plain_modulus = 1032193; + // vector<int> bit_sizes = { 36, 36, 37 }; + + // timeval t0, t1; + // unsigned long dt = 0; + // gettimeofday(&t0, NULL); + + generate_keys_ckks(poly_d, bit_size, key_dir, true); + // batching_generate_keys(poly_d, bit_sizes, plain_modulus, key_dir, true); + + // gettimeofday(&t1, NULL); + // dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + // cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/CMakeLists.txt b/bigpiseal3.5.1/native/examples/ANN/v1/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..97bbaad156cf1816832727dcbc8fee23b78d27da --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/CMakeLists.txt @@ -0,0 +1,171 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME ANN) + +#set(GENKEY_BIN ${TEST_NAME}_genkey) +#set(ENCR_BIN ${TEST_NAME}_encrypt) +#set(DECR_BIN ${TEST_NAME}_decrypt) +#set(EVAL_BIN ${TEST_NAME}_evaluate) +#set(SCR_TEST test.sh) + +set(GENKEY_BIN_2 ${TEST_NAME}_genkey_v1) +set(ENCR_BIN_2 ${TEST_NAME}_encrypt_v1) +set(DECR_BIN_2 ${TEST_NAME}_decrypt_v1) +set(DECR_RESULT_BIN_2 ${TEST_NAME}_decrypt_result_v1) +set(EVAL_BIN_2 ${TEST_NAME}_evaluate_v1) + +set(SCR_ENC encrypt.sh) +set(SCR_DEC decrypt.sh) +set(SCR_DEC_RESULT decrypt_result.sh) +set(SCR_EVAL eval.sh) +set(SCR_GEN genkey.sh) +set(SCR_TEST_v1 test_v1.sh) + + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + + +set(GENKEY_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey_v1.cpp + ) + +set(ENCR_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt_v1.cpp + ) + +set(DECR_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_v1.cpp + ) + +set(DECR_RESULT_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_result_v1.cpp + ) + +set(EVAL_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/csv_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/print_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate_v1.cpp + ) + + +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/util.h + ${CMAKE_CURRENT_LIST_DIR}/csv_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/print_api.cpp + ) + +#add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +#add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +#add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +#add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +add_executable(${GENKEY_BIN_2} ${GENKEY_SRCS_2} ${HEADER_FILES}) +add_executable(${ENCR_BIN_2} ${ENCR_SRCS_2} ${HEADER_FILES}) +add_executable(${DECR_BIN_2} ${DECR_SRCS_2} ${HEADER_FILES}) +add_executable(${DECR_RESULT_BIN_2} ${DECR_RESULT_SRCS_2} ${HEADER_FILES}) +add_executable(${EVAL_BIN_2} ${EVAL_SRCS_2} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +# Link Microsoft SEAL +#target_link_libraries(${GENKEY_BIN} SEAL::seal) +#target_link_libraries(${ENCR_BIN} SEAL::seal) +#target_link_libraries(${DECR_BIN} SEAL::seal) +#target_link_libraries(${EVAL_BIN} SEAL::seal) + +target_link_libraries(${GENKEY_BIN_2} SEAL::seal) +target_link_libraries(${ENCR_BIN_2} SEAL::seal) +target_link_libraries(${DECR_BIN_2} SEAL::seal) +target_link_libraries(${DECR_RESULT_BIN_2} SEAL::seal) +target_link_libraries(${EVAL_BIN_2} SEAL::seal) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + +#set_target_properties(${GENKEY_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${ENCR_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${DECR_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${EVAL_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) + +set_target_properties(${GENKEY_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${ENCR_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${DECR_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${DECR_RESULT_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${EVAL_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) + + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC_RESULT} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_EVAL} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST_v1} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a174025cbba488070dda13c3436d4002265cff2e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.cpp @@ -0,0 +1,497 @@ +/* + */ + +#include "csv_api.h" + +/* namespaces */ +using namespace std; + +int load_csv_line(const string &filename, vector<int64_t> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + string l; + getline(fd, l); + if (l.empty()) + { + cerr << "[csv-error] empty csv file, please provide a valid csv file" << endl; + ret = 0; + } + else + { + string w; + stringstream s(l); + while (getline(s, w, ',')) + { + int64_t val = boost::lexical_cast<int64_t>(w); + in.push_back(val); + } + fd.close(); + + /* print the obtained vector of numbers from a csv line */ + if (print_info) + { + cout << "[csv-info] loading vector from a csv input (line): " << endl; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } + } + } + return ret; +} + +int load_csv_line(const string &filename, vector<double> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + string l; + getline(fd, l); + if (l.empty()) + { + cerr << "[csv-error] empty csv file, please provide a valid csv file" << endl; + ret = 0; + } + else + { + string w; + stringstream s(l); + while (getline(s, w, ',')) + { + double val = boost::lexical_cast<double>(w); + in.push_back(val); + } + fd.close(); + + /* print the obtained vector of numbers from a csv line */ + if (print_info) + { + cout << "[csv-info] loading vector from a csv input (line): " << endl; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } + } + } + return ret; +} + +int load_windows_csv_line(const string &filename, vector<int64_t> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + string l; + getline(fd, l); + if (l.empty()) + { + cerr << "[csv-error] empty csv file, please provide a valid csv file" << endl; + ret = 0; + } + else + { + if (l[l.size() - 1] == '\r') + l.erase(l.size() - 1); + + string w; + stringstream s(l); + while (getline(s, w, ',')) + { + int64_t val = boost::lexical_cast<int64_t>(w); + in.push_back(val); + } + fd.close(); + + /* print the obtained vector of numbers from a csv line */ + if (print_info) + { + cout << "[csv-info] loading vector from a csv input (line): " << endl; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } + } + } + return ret; +} + +int load_windows_csv_line(const string &filename, vector<double> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + string l; + getline(fd, l); + if (l.empty()) + { + cerr << "[csv-error] empty csv file, please provide a valid csv file" << endl; + ret = 0; + } + else + { + if (l[l.size() - 1] == '\r') + l.erase(l.size() - 1); + + string w; + stringstream s(l); + while (getline(s, w, ',')) + { + double val = boost::lexical_cast<double>(w); + in.push_back(val); + } + fd.close(); + + /* print the obtained vector of numbers from a csv line */ + if (print_info) + { + cout << "[csv-info] loading vector from a csv input (line): " << endl; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } + } + } + return ret; +} + +void string_to_number_vector(string &s, vector<int64_t> &in, bool print_info) +{ + if (in.size() > 0) + in.clear(); + + string w; + + stringstream c(s); + while (getline(c, w, ',')) + { + int64_t val = boost::lexical_cast<int64_t>(w); + in.push_back(val); + } + /* print the obtained vectors of numbers from a csv file */ + if (print_info) + { + cout << "[csv-info] converting a csv line to a vector of numbers" << endl; + cout << "[csv-info] input line: " << s << endl; + cout << "[csv-info] output vector: "; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } +} + +void string_to_number_vector(string &s, vector<double> &in, bool print_info) +{ + if (in.size() > 0) + in.clear(); + + string w; + + stringstream c(s); + while (getline(c, w, ',')) + { + double val = boost::lexical_cast<double>(w); + in.push_back(val); + } + /* print the obtained vectors of numbers from a csv file */ + if (print_info) + { + cout << "[csv-info] converting a csv line to a vector of numbers" << endl; + cout << "[csv-info] input line: " << s << endl; + cout << "[csv-info] output vector: "; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << " "; + cout << endl; + } +} + +int load_csv_file(const string &filename, vector<vector<int64_t>> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + while (!fd.eof()) + { + string l; + getline(fd, l); + vector<int64_t> tmp; + string_to_number_vector(l, tmp); + in.push_back(tmp); + } + fd.close(); + /* print the different csv lines */ + if (print_info) + { + cout << "[csv-info] loaded vectors from the lines of a csv file: " << endl; + print_matrix(in); + } + } + return ret; +} + +void remove_carriage_return(std::string &line) +{ + if (*line.rbegin() == '\r') + { + line.erase(line.length() - 1); + } +} + +int load_csv_file(const string &filename, vector<vector<double>> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + int i = 0; + while (!fd.eof()) + { + string l; + getline(fd, l); + remove_carriage_return(l); + vector<double> tmp; + string_to_number_vector(l, tmp); + in.push_back(tmp); + i++; + } + fd.close(); + /* print the different csv lines */ + if (print_info) + { + cout << "[csv-info] loaded vectors from the lines of a csv file: " << endl; + print_matrix(in); + } + } + return ret; +} + +int read_csv_file(const string &filename, vector<string> &in, bool print_info) +{ + int ret = 1; + + if (in.size() > 0) + in.clear(); + + fstream fd; + fd.open(filename, std::fstream::in); + if (!fd.is_open()) + { + cerr << "[csv-error] opening csv file failure" << endl; + ret = 0; + } + else + { + while (!fd.eof()) + { + string l; + getline(fd, l); + in.push_back(l); + } + fd.close(); + /* print the different csv lines */ + if (print_info) + { + cout << "[csv-info] reading csv lines: " << endl; + for (int i = 0; i < (int)(in.size()); ++i) + cout << in[i] << endl; + } + } + return ret; +} + +int write_to_csv_file(const string &filename, vector<int64_t> &in) +{ + int ret = 1; + + ofstream fd(filename); + if (!fd.is_open()) + { + cerr << "[csv-error] could not open the csv output file" << endl; + ret = 0; + } + else + { + for (int i = 0; i < (int)(in.size() - 1); ++i) + { + fd << in[i] << ","; + } + fd << in[in.size() - 1] << endl; + fd.close(); + } + return ret; +} + +int write_to_csv_file(const string &filename, vector<double> &in) +{ + int ret = 1; + + ofstream fd(filename); + if (!fd.is_open()) + { + cerr << "[csv-error] could not open the csv output file" << endl; + ret = 0; + } + else + { + for (int i = 0; i < (int)(in.size() - 1); ++i) + { + fd << in[i] << ","; + } + fd << in[in.size() - 1] << endl; + fd.close(); + } + return ret; +} + +int convert_crlf_to_lf(char *in, char *out) +{ + int ret = 1; + int c; + FILE *ifp, *ofp; + + if ((ifp = fopen(in, "rb")) == NULL) + { + cout << "[csv-error] could not open input file" << endl; + ret = 0; + } + else + { + if ((ofp = fopen(out, "wb")) == NULL) + { + cout << "[csv-error] could not open output file" << endl; + fclose(ifp); + ret = 0; + } + else + { + while ((c = getc(ifp)) != EOF) + { + if (c == '\r') + { + putc('\n', ofp); + c = getc(ifp); + if (c == EOF) + break; + if (c == '\n') + continue; + } + putc(c, ofp); + } + fclose(ifp); + fclose(ofp); + } + } + return ret; +} + +int convert_lf_to_crlf(char *in, char *out) +{ + int ret = 1; + int c; + FILE *ifp, *ofp; + + if ((ifp = fopen(in, "rb")) == NULL) + { + cout << "[csv-error] could not open input file\n" << endl; + ret = 0; + } + else + { + if ((ofp = fopen(out, "wb")) == NULL) + { + cout << "[csv-error] could not open output file\n" << endl; + fclose(ifp); + ret = 0; + } + else + { + while ((c = getc(ifp)) != EOF) + { + if (c == '\n') + { + putc('\r', ofp); + putc('\n', ofp); + c = getc(ifp); + if (c == EOF) + break; + if (c == '\n') + continue; + } + putc(c, ofp); + } + fclose(ifp); + fclose(ofp); + } + } + return ret; +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.h b/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.h new file mode 100644 index 0000000000000000000000000000000000000000..a2f951c6aed3c719f2161fff9c5103e0f449d141 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/csv_api.h @@ -0,0 +1,38 @@ +/* + (C) Copyright 2022 CEA LIST. All Rights Reserved. + */ + +#ifndef _CSV_API_H_ +#define _CSV_API_H_ + +/* includes */ +#include <iostream> +#include <fstream> +#include <string> +#include <cstdio> +#include <boost/lexical_cast.hpp> +#include <boost/algorithm/string.hpp> +#include "print_api.h" + +/* prototypes */ +int load_csv_line(const std::string& filename, std::vector<int64_t>& in, bool print_info = 0); +int load_csv_line(const std::string& filename, std::vector<double>& in, bool print_info = 0); + +int load_windows_csv_line(const std::string& filename, std::vector<int64_t>& in, bool print_info = 0); +int load_windows_csv_line(const std::string& filename, std::vector<double>& in, bool print_info = 0); + +void string_to_number_vector(std::string& s, std::vector<int64_t>& in, bool print_info = 0); +void string_to_number_vector(std::string& s, std::vector<double>& in, bool print_info = 0); + +int load_csv_file(const std::string& filename, std::vector<std::vector<int64_t>>& in, bool print_info = 0); +int load_csv_file(const std::string& filename, std::vector<std::vector<double>>& in, bool print_info = 0); + +int read_csv_file(const std::string& filename, std::vector<std::string>& in, bool print_info = 0); + +int write_to_csv_file(const std::string& filename, std::vector<int64_t> &in); +int write_to_csv_file(const std::string& filename, std::vector<double> &in); + +int convert_crlf_to_lf(char *in, char *out); +int convert_lf_to_crlf(char *in, char *out); + +#endif diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/decrypt.sh b/bigpiseal3.5.1/native/examples/ANN/v1/decrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..e68c4d8bc0f9add8be296f3653dbdcd777f34965 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/decrypt.sh @@ -0,0 +1,12 @@ +#decrypt +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./ANN_decrypt_v1 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/ANN_decrypt_v1 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/decrypt_result.sh b/bigpiseal3.5.1/native/examples/ANN/v1/decrypt_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..2a163a9ed2aa68945524496146bbd4088975977f --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/decrypt_result.sh @@ -0,0 +1,12 @@ +#decrypt result +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./ANN_decrypt_result_v1 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/ANN_decrypt_result_v1 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/encrypt.sh b/bigpiseal3.5.1/native/examples/ANN/v1/encrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..e217d33ace26e21d99e98f03fad3e911267be6b1 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/encrypt.sh @@ -0,0 +1,16 @@ +#encrypt +licenseNo=$1 +# ex: "23 65 78 127 255" (en ASCII) +filename=$2 +# ex: "l" (extension will be .ct) +outputDir=$3 +# ex: lcheck/ +sample=$4 +# ex: 40 +keyDir=$5 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./ANN_encrypt_v1 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" +time ${CURR_DIR}/ANN_encrypt_v1 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/eval.sh b/bigpiseal3.5.1/native/examples/ANN/v1/eval.sh new file mode 100644 index 0000000000000000000000000000000000000000..eff2a83efa0c3e1a17878cf51a189efea9784662 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/eval.sh @@ -0,0 +1,30 @@ +# evaluate +licensePath=$1 +# ex: lcheck/l.ct +licensePathList=${@: 2:$#-5} +# licensePathList="${@:2:102}" +# for var in "${@: 2:$#-7}" +# do +# echo "$var" +# done +# ex: parent/l0/l.ct parent/l1/l.ct parent/l2/l.ct parent/l3/l.ct parent/l4/l.ct parent/l5/l.ct parent/l6/l.ct parent/l7/l.ct parent/l8/l.ct parent/l9/l.ct +filename=${@: -4:1} +# ex: "l" (extension will be .ct) +outputDir=${@: -3:1} +# ex: result/ +sample=${@: -2:1} +# ex: 40 +KeyDir=${@: -1} +# ex: keys/ +# linkingKeyPath=${@: -3:1} +# # ex: ckks.lk +# galoisKeyPath=${@: -2:1} +# # ex: ckks.gk +# publicKeyPath=${@: -1} +# # ex: ckks.pk + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./ANN_evaluate_v1 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$linkingKeyPath" "$galoisKeyPath" "$publicKeyPath" +# time ./ANN_evaluate_v1 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" +time ${CURR_DIR}/ANN_evaluate_v1 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/genkey.sh b/bigpiseal3.5.1/native/examples/ANN/v1/genkey.sh new file mode 100644 index 0000000000000000000000000000000000000000..b9c6ef5fdd5fe557fa4680041bb3356194a5057d --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/genkey.sh @@ -0,0 +1,8 @@ +#gen key +keyDir=$1 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./ANN_genkey_v1 "$keyDir" +time ${CURR_DIR}/ANN_genkey_v1 "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/ls.txt b/bigpiseal3.5.1/native/examples/ANN/v1/ls.txt new file mode 100644 index 0000000000000000000000000000000000000000..897ab0d689bcaa91e45968dfadab860bf8878cba --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/ls.txt @@ -0,0 +1,102 @@ +243 65 191 66 134 2 36 209 39 215 143 95 22 211 213 168 142 178 25 77 88 120 159 33 247 144 244 253 14 39 205 86 123 249 215 166 113 82 205 150 +175 50 195 231 96 99 136 186 176 104 92 99 13 0 110 219 168 146 101 169 70 189 249 6 205 90 118 46 166 136 3 243 158 95 230 38 149 234 81 68 +175 223 168 200 187 205 246 220 192 127 220 10 38 6 241 89 77 25 53 169 12 91 49 133 75 89 118 147 211 16 18 90 159 50 175 114 249 103 145 153 +49 38 145 31 236 196 166 137 78 10 134 2 9 48 43 202 166 45 141 90 71 90 3 252 26 204 222 82 120 151 253 232 223 158 248 92 76 218 17 20 +253 197 52 226 110 61 176 101 59 117 111 242 135 173 213 205 211 108 89 132 49 113 195 86 63 122 64 184 137 144 183 174 195 112 166 50 32 10 55 61 +174 82 23 246 3 4 64 68 96 49 0 64 111 225 149 57 79 42 33 154 9 38 130 10 151 121 104 222 138 228 248 83 145 192 106 30 126 198 248 76 +180 247 84 38 133 245 173 82 166 53 211 109 137 8 48 191 137 233 238 3 6 252 162 232 253 125 29 210 241 208 9 1 160 232 209 215 203 250 19 95 +224 122 90 44 22 59 96 241 96 5 186 23 249 4 201 102 23 99 38 242 38 11 99 253 184 38 146 248 198 74 214 21 114 63 242 42 100 142 50 9 +27 95 228 0 180 66 2 225 77 120 56 85 176 254 198 157 229 112 97 253 181 26 235 172 93 123 154 100 112 157 17 231 249 250 168 61 185 10 23 223 +93 79 52 151 155 73 110 9 111 93 241 249 109 94 46 181 223 180 146 145 180 220 10 88 208 243 229 116 55 68 219 252 230 119 188 235 75 213 186 49 +113 68 160 136 24 127 12 242 95 245 251 193 159 128 167 209 169 141 59 75 148 209 46 147 127 11 96 49 101 36 27 168 159 70 133 223 190 41 62 111 +204 224 117 188 183 127 35 194 202 71 227 252 187 199 93 187 45 6 13 26 160 189 74 4 42 41 220 73 14 149 232 126 38 240 250 32 154 10 86 117 +50 177 30 212 186 247 71 41 17 66 116 129 97 126 206 97 211 146 215 132 166 164 159 196 179 219 118 9 223 202 9 36 165 18 103 127 127 86 141 7 +100 132 232 248 220 67 101 79 90 171 184 246 27 161 186 73 60 207 87 41 90 216 92 128 37 168 132 223 226 77 122 237 189 84 167 2 177 29 190 34 +125 249 230 63 58 47 50 166 229 202 116 158 178 187 13 206 170 66 68 247 225 96 191 118 244 173 231 73 104 151 81 94 129 186 112 2 177 16 25 176 +3 110 136 235 79 87 181 238 1 10 63 76 249 75 138 219 113 139 120 142 22 14 15 10 106 41 20 88 214 10 222 249 64 154 201 65 155 15 64 126 +122 208 157 182 115 121 122 45 23 70 77 10 118 119 196 193 133 76 171 235 237 84 161 69 250 250 87 180 132 227 173 58 224 173 76 127 61 216 180 42 +160 8 76 36 240 227 62 127 191 177 184 122 236 65 168 71 127 41 29 237 240 13 243 13 82 252 189 84 207 17 237 36 148 39 100 79 188 117 226 34 +220 170 19 17 240 120 251 108 73 236 13 222 6 151 158 15 114 111 224 137 96 67 227 226 163 183 75 168 169 142 68 168 43 116 110 2 40 48 246 56 +129 18 215 139 153 101 0 78 41 84 166 43 124 117 38 143 234 111 196 215 224 227 139 168 121 168 243 190 113 206 242 244 106 238 36 228 232 242 116 23 +96 196 168 14 3 243 231 228 157 42 92 68 180 245 158 92 24 220 95 20 242 40 220 203 97 204 117 236 167 197 168 145 194 116 54 83 240 204 224 196 +242 120 49 36 230 129 177 52 253 37 64 122 162 25 33 241 144 30 57 243 96 218 181 34 83 111 47 109 12 222 236 60 106 211 151 240 106 90 222 176 +188 94 62 191 29 58 226 217 156 180 232 75 128 182 96 135 50 43 237 169 239 132 195 85 110 183 221 218 19 132 178 6 56 170 239 25 173 18 2 177 +172 121 70 34 39 58 92 54 221 187 16 209 74 118 106 236 157 67 137 56 63 186 26 77 163 164 49 180 219 71 60 51 6 153 226 123 72 154 108 218 +37 50 1 84 90 216 199 53 10 51 50 112 92 140 146 32 34 216 92 88 2 27 35 110 103 123 14 36 85 250 238 108 175 212 31 253 203 237 252 38 +186 93 22 42 241 233 240 19 6 1 135 63 216 27 244 242 234 225 172 60 202 29 162 209 45 48 50 2 25 114 16 193 49 18 223 6 92 226 247 152 +7 52 3 64 158 201 131 133 244 252 137 177 48 12 212 32 80 155 115 46 69 104 164 229 73 85 47 20 43 109 127 157 74 198 173 230 80 81 77 89 +52 157 7 85 253 86 36 188 136 153 153 217 240 216 10 220 82 128 206 131 3 132 187 146 154 129 173 249 241 223 194 181 34 119 223 47 12 3 120 175 +79 248 87 79 141 253 81 183 218 242 193 142 225 128 43 194 89 249 91 113 156 9 6 225 67 81 62 247 53 240 54 233 203 167 43 45 89 87 38 191 +139 236 151 143 164 112 20 19 46 27 245 112 95 111 228 78 41 202 219 223 46 51 0 87 22 93 206 164 184 244 227 156 65 85 196 12 39 10 38 211 +204 6 40 128 152 29 83 46 202 117 5 182 176 253 39 35 178 54 196 62 92 208 132 41 120 55 154 34 104 253 99 105 140 31 192 187 27 121 250 170 +112 151 190 147 230 92 201 191 166 248 147 40 120 158 197 26 157 180 66 205 96 164 166 202 85 140 163 189 45 57 100 208 8 45 220 97 122 92 187 79 +19 235 223 178 38 129 247 230 75 205 34 201 225 86 107 188 195 222 57 209 209 29 117 39 137 150 179 210 135 220 201 87 59 66 14 230 125 107 69 215 +128 238 197 217 149 64 76 132 85 73 113 194 38 240 118 246 236 157 86 79 68 64 183 85 231 97 77 65 242 215 205 237 149 121 71 10 186 84 138 81 +73 148 48 26 197 191 106 117 210 190 160 17 57 243 43 154 33 229 19 97 121 124 148 187 205 157 31 228 139 110 77 43 227 234 153 106 37 84 195 95 +105 171 209 97 188 215 172 152 250 234 104 67 10 36 190 3 10 28 163 200 182 80 230 38 136 196 67 194 36 234 231 236 208 214 138 112 219 50 161 115 +35 110 94 87 17 149 240 187 223 184 156 48 252 243 43 13 122 214 98 93 13 69 47 71 19 12 20 83 31 32 69 77 95 251 5 50 179 115 22 104 +144 58 242 80 215 234 31 8 220 168 129 223 119 88 142 201 43 128 151 32 164 73 209 241 222 162 16 196 207 5 200 198 155 249 138 206 115 56 176 7 +192 241 134 145 232 209 129 59 165 109 163 35 191 115 10 193 94 52 28 2 156 95 47 234 252 128 169 37 145 175 244 123 31 122 48 90 208 18 199 48 +30 155 143 133 138 228 122 76 0 216 17 161 128 159 70 128 98 233 124 98 111 43 12 110 112 126 185 230 2 254 115 1 184 188 252 154 244 87 24 251 +246 230 251 113 82 63 122 176 177 13 143 199 184 66 180 221 86 138 5 204 70 44 78 205 175 57 231 112 250 16 27 57 0 96 72 15 231 113 220 142 +96 219 38 213 82 125 36 56 146 138 21 184 89 206 248 215 129 133 61 173 68 178 44 242 135 198 95 140 30 73 4 135 133 243 168 75 126 161 230 144 +77 148 87 166 0 213 254 109 133 197 23 176 116 139 183 177 14 247 103 168 2 179 58 189 65 224 241 240 51 117 227 95 151 93 246 82 50 31 36 146 +54 44 18 64 95 15 195 97 161 107 78 170 56 203 219 88 87 205 251 144 95 235 164 90 158 165 154 197 100 124 41 4 190 250 215 247 113 6 118 168 +82 38 87 61 160 228 230 70 1 82 221 201 88 10 251 185 131 73 130 223 85 253 51 53 38 225 197 115 15 24 86 118 142 33 78 1 134 27 7 63 +187 49 168 238 221 95 101 148 142 48 32 216 107 44 178 5 151 239 9 210 27 63 80 213 78 154 185 115 116 154 205 218 151 72 51 0 19 80 47 35 +129 83 198 111 206 165 128 66 93 136 144 1 98 43 191 32 140 108 4 61 96 220 223 208 190 103 181 221 120 177 28 171 118 109 104 16 181 205 89 119 +144 237 152 98 240 33 69 171 190 105 241 216 47 79 100 77 232 102 3 207 45 218 12 252 50 169 172 79 199 8 74 185 102 204 239 68 60 110 180 103 +134 147 162 53 146 7 22 61 179 85 73 136 152 129 215 91 155 20 98 184 167 140 71 220 176 102 0 232 24 230 98 64 238 198 78 121 214 47 49 30 +33 152 125 6 139 198 251 17 102 221 96 44 14 97 132 122 47 148 123 78 242 79 90 68 41 195 234 94 92 88 144 149 151 222 149 222 23 169 128 96 +5 147 175 167 148 160 245 249 149 190 251 144 170 43 6 31 105 179 238 220 78 96 162 100 33 102 222 230 41 20 220 71 197 21 2 230 105 89 186 23 +189 25 11 66 195 114 227 94 239 107 114 60 13 135 173 221 29 106 188 224 2 99 101 16 65 8 59 118 108 101 53 130 218 58 85 241 161 202 95 28 +242 7 36 125 186 134 74 190 201 239 248 17 67 198 17 130 101 233 9 144 50 24 141 186 153 168 116 176 244 46 85 75 185 226 242 187 114 201 46 185 +189 212 128 105 116 216 27 158 103 36 104 182 63 48 134 164 141 221 192 138 64 161 12 226 96 199 15 220 232 232 249 160 199 174 150 213 83 237 67 98 +172 128 175 243 30 178 226 235 6 21 96 79 29 55 68 61 186 133 3 238 238 209 235 225 142 205 245 110 81 201 214 118 121 230 157 75 87 156 171 221 +150 88 231 85 232 232 25 199 105 115 195 242 253 157 187 99 254 189 133 153 204 26 44 247 99 116 201 198 134 144 221 113 37 100 179 225 44 204 112 58 +195 216 121 2 140 125 171 120 57 131 195 38 29 171 168 44 75 216 34 21 205 136 228 148 69 76 224 157 29 177 246 42 193 208 29 15 227 142 249 113 +6 169 58 207 217 235 221 2 55 238 220 201 52 72 150 86 195 201 162 243 28 39 14 36 73 171 61 153 126 79 50 23 157 244 201 32 94 176 3 148 +184 136 252 175 214 160 230 141 6 28 32 31 25 201 120 165 51 201 28 174 47 41 88 137 243 141 3 147 81 144 45 227 1 88 167 242 135 229 96 226 +221 63 43 181 252 208 89 114 28 160 232 107 239 139 37 235 122 161 137 215 4 225 151 69 107 136 192 240 119 72 193 67 248 98 164 222 134 27 217 71 +159 177 248 8 22 8 225 53 34 85 30 59 239 208 75 34 55 10 48 36 186 78 177 130 153 47 204 153 244 14 195 56 42 194 9 16 158 37 179 54 +196 80 154 144 140 106 144 178 227 226 95 98 19 205 74 248 25 212 145 71 103 17 206 163 253 31 219 0 207 78 163 214 162 230 119 242 161 43 242 9 +26 214 71 182 197 167 77 154 90 51 97 152 93 239 253 62 210 6 78 166 134 153 7 28 194 211 96 83 238 97 207 60 125 99 152 91 176 215 43 131 +49 171 224 67 45 8 152 176 154 138 185 111 138 218 209 10 161 147 61 202 2 206 158 133 47 184 69 109 209 120 33 232 150 52 19 220 12 222 145 121 +14 223 234 125 182 85 47 214 2 201 239 31 136 171 239 137 222 109 126 64 185 240 242 15 60 174 204 141 78 201 251 143 147 18 174 242 50 104 212 96 +80 99 123 154 99 103 182 179 200 107 120 89 184 38 133 206 80 117 99 95 134 166 168 87 133 46 113 218 165 148 116 204 176 163 84 97 153 208 247 104 +75 14 63 135 208 245 119 40 181 217 233 28 201 238 140 156 80 1 202 29 233 18 152 65 180 195 39 169 179 18 48 191 226 96 118 68 119 160 34 82 +230 207 122 86 55 40 145 243 126 215 183 187 111 55 55 234 127 170 154 229 227 55 63 146 253 122 192 181 163 140 229 197 33 178 145 40 131 170 244 131 +77 215 49 68 142 109 44 231 248 204 237 147 226 134 103 161 32 229 126 164 4 164 17 54 225 215 166 43 134 152 151 244 1 112 143 54 42 0 145 164 +100 251 82 139 171 82 80 102 203 100 203 167 167 185 30 80 117 175 229 222 221 128 18 172 218 62 57 134 93 174 46 23 155 10 82 182 138 209 5 121 +154 163 46 67 239 144 180 0 114 232 112 119 238 71 119 235 6 38 161 70 37 29 170 205 117 236 128 200 73 186 104 31 160 1 236 14 170 232 80 42 +17 211 4 136 175 119 46 100 228 130 217 224 34 254 36 73 50 35 236 177 243 151 152 121 156 155 159 177 160 173 39 90 43 2 241 223 76 228 87 103 +169 206 87 76 200 243 28 63 172 126 243 19 22 243 9 180 62 155 244 218 211 133 169 59 36 6 200 112 23 237 4 59 143 210 169 242 19 88 164 83 +19 203 87 241 39 235 176 141 68 184 116 111 143 134 252 160 155 51 235 214 69 89 14 81 124 191 99 187 154 142 44 2 123 183 239 22 35 159 237 180 +100 103 196 211 197 44 201 83 240 240 222 237 168 8 79 242 252 119 225 133 27 75 12 91 213 192 108 124 41 183 73 158 228 122 151 61 24 203 4 40 +240 146 118 63 84 208 253 218 31 219 161 245 139 155 215 133 67 97 31 63 70 213 26 136 208 18 148 175 143 106 89 110 109 11 20 140 232 54 54 116 +215 63 197 97 52 142 119 104 12 43 251 248 94 37 20 189 121 237 26 55 180 214 121 227 200 56 181 212 141 231 254 77 145 6 13 52 69 67 87 21 +94 140 175 252 248 213 69 144 114 122 24 93 97 189 221 148 37 34 153 216 50 84 143 42 128 92 244 34 163 170 8 96 53 34 79 141 215 178 251 248 +31 4 33 217 50 106 111 32 68 196 73 66 223 10 61 162 187 4 230 107 238 130 186 94 154 124 188 109 57 171 174 100 141 110 44 233 21 149 46 1 +152 108 19 201 39 178 165 29 169 210 27 14 208 86 23 161 146 39 253 59 211 124 49 231 175 20 212 194 210 182 142 49 46 232 97 113 250 23 89 46 +150 94 60 73 120 117 241 166 229 253 163 220 4 156 89 79 139 185 209 141 35 178 90 243 148 111 132 233 120 19 132 5 227 65 10 61 156 92 30 22 +127 65 65 78 70 235 178 212 111 49 75 249 129 26 181 128 2 159 144 214 62 27 23 23 90 129 187 119 52 88 131 103 137 248 212 143 108 63 217 83 +108 148 116 144 155 94 50 23 216 40 142 27 137 26 171 179 122 53 5 11 104 129 218 212 73 175 160 80 170 228 161 243 179 185 191 7 186 8 42 243 +108 192 115 49 141 130 194 33 150 24 72 230 212 61 228 92 250 253 243 86 163 21 223 67 85 58 227 243 176 44 230 49 174 154 31 230 209 233 142 202 +222 102 86 205 182 235 109 79 237 138 210 168 197 185 206 124 45 25 209 76 19 132 51 13 195 170 125 214 235 205 49 243 51 89 90 179 64 202 195 105 +36 122 78 19 11 191 90 179 49 157 56 195 227 248 207 108 120 85 93 84 227 201 61 223 78 53 221 35 207 127 82 100 227 155 111 89 199 192 98 142 +86 154 170 18 104 19 94 133 7 234 85 143 38 236 120 171 31 181 4 104 98 172 219 246 152 121 162 144 201 251 55 71 55 13 248 197 122 44 75 232 +134 84 38 28 8 252 208 217 203 36 157 114 143 226 223 176 182 165 20 18 156 48 94 136 183 76 165 148 33 72 157 171 172 181 0 195 20 75 2 175 +86 84 249 178 214 96 104 190 18 15 235 239 147 165 182 68 244 89 42 152 252 156 13 96 254 3 204 249 116 87 128 54 136 100 64 24 39 20 159 247 +208 126 15 89 202 90 63 197 48 181 85 57 169 154 18 79 101 94 63 39 94 11 59 137 64 87 55 152 237 161 183 82 253 47 5 245 39 10 176 125 +206 62 169 198 37 59 60 83 153 8 31 221 76 29 237 198 22 0 239 101 20 128 189 218 0 108 250 9 92 221 22 228 197 155 56 245 238 173 44 157 +58 233 22 58 38 241 229 253 55 231 94 137 50 139 112 139 95 193 64 100 114 43 165 235 236 13 47 14 109 145 221 244 45 151 105 187 2 0 19 234 +217 111 78 154 50 197 31 175 85 41 147 217 128 203 183 159 0 55 4 41 36 15 108 184 139 183 55 13 85 113 62 11 234 44 87 204 209 210 120 29 +152 12 157 80 80 148 225 215 145 90 229 157 196 4 174 194 17 127 211 169 84 25 133 97 91 137 203 33 120 216 44 108 11 158 58 214 148 165 90 173 +228 210 184 66 66 145 254 216 116 7 190 96 113 173 236 1 81 225 39 123 188 8 24 15 80 254 77 59 1 142 172 154 139 52 105 40 219 99 81 216 +62 181 17 211 233 249 43 93 6 240 107 20 107 37 123 233 243 131 225 137 17 193 70 74 73 177 180 247 134 139 145 36 97 101 101 125 194 147 136 134 +153 225 152 193 104 116 18 63 151 230 241 230 135 204 10 44 126 48 68 30 251 160 17 140 98 52 151 201 154 17 36 73 17 179 138 215 98 75 235 42 +214 103 74 89 186 178 138 124 197 2 237 205 136 135 246 179 83 136 194 148 152 142 133 56 61 150 56 64 46 164 25 71 178 242 131 196 171 174 93 184 +228 20 26 114 115 154 89 87 229 168 36 186 81 202 99 223 196 218 70 252 30 151 232 18 163 116 251 165 43 189 95 250 44 52 103 244 95 43 217 220 +6 29 54 106 164 42 19 49 142 133 94 82 174 204 18 83 132 184 239 212 26 83 58 223 237 88 237 225 88 4 53 50 79 8 90 224 103 157 174 101 +201 2 143 195 58 94 175 28 0 254 237 152 126 249 240 56 247 138 11 219 155 178 229 199 153 146 136 86 22 59 200 18 124 136 54 241 181 170 183 196 +32 114 115 105 20 163 240 105 135 124 190 106 63 159 1 200 136 118 212 148 179 200 155 113 103 47 37 85 32 55 228 105 244 202 66 24 199 102 20 90 diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/print_api.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/print_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03db8548af85cdf9abc5b38e4e32fa7f1cbfbdb6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/print_api.cpp @@ -0,0 +1,59 @@ +/* + (C) Copyright 2022 CEA LIST. All Rights Reserved. + */ + +#include "print_api.h" + +using namespace std; + +void print_vectors(vector<int64_t> &v) +{ + for (int i = 0; i < (int)(v.size()); ++i) + cout << v[i] << " "; + cout << endl; +} + +void print_vectors(vector<double> &v) +{ + for (int i = 0; i < (int)(v.size()); ++i) + cout << v[i] << " "; + cout << endl; +} + +void print_matrix(vector<vector<int64_t>> &m) +{ + for (int i = 0; i < (int)(m.size()); ++i) + print_vectors(m[i]); +} + +void print_matrix(vector<vector<double>> &m) +{ + for (int i = 0; i < (int)(m.size()); ++i) + print_vectors(m[i]); +} + +/*void rand_vector(int seed, uint64_t v_space, uint32_t v_size, vector<int64_t>& v) +{ + srand(seed); + for (uint32_t i = 0; i < v_size; ++i) + v[i] = rand() % v_space; +} +*/ + +void rand_vector(int seed, uint64_t v_space, uint32_t v_size, vector<int64_t>& v) +{ + std::uniform_real_distribution<double> unif(0, v_space); + std::default_random_engine re; + re.seed(seed); + for (uint32_t i = 0; i < v_size; ++i) + v[i] = (int64_t)unif(re) % v_space; +} + +void rand_vector(int seed, uint64_t v_space, uint32_t v_size, vector<double>& v) +{ + std::uniform_real_distribution<double> unif(0, v_space); + std::default_random_engine re; + re.seed(seed); + for (uint32_t i = 0; i < v_size; ++i) + v[i] = unif(re); +} diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/print_api.h b/bigpiseal3.5.1/native/examples/ANN/v1/print_api.h new file mode 100644 index 0000000000000000000000000000000000000000..715fed15ebba65640ccce5314e3e148a9e4dc1e4 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/print_api.h @@ -0,0 +1,25 @@ +/* + (C) Copyright 2022 CEA LIST. All Rights Reserved. + */ + +#ifndef _PRINT_API_H_ +#define _PRINT_API_H_ + +/* includes */ +#include <iostream> +#include <random> +#include <cstdio> +#include <vector> +#include <time.h> + +/* prototypes */ +void print_vectors(std::vector<int64_t>& v); +void print_vectors(std::vector<double> &v); + +void print_matrix(std::vector<std::vector<int64_t>>& m); +void print_matrix(std::vector<std::vector<double>>& m); + +void rand_vector(int seed, uint64_t v_space, uint32_t v_size, std::vector<int64_t>& v); +void rand_vector(int seed, uint64_t v_space, uint32_t v_size, std::vector<double>& v); + +#endif diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4560d91ab76df00e668336bec7136bfd56bf7f7 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.cpp @@ -0,0 +1,1247 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, ios::binary); + if (!in_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, ios::binary); + if (!out_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + + save_params(params, "bfv_params.conf"); + + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching(size_t poly_d, int bit_size, shared_ptr<SEALContext> &context, const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(PlainModulus::Batching(poly_d, bit_size)); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +// void ckks_init_context_batching( +// size_t poly_d, int bit_size, shared_ptr<SEALContext> &context, const std::string &key_dir) +// { +// EncryptionParameters params(scheme_type::CKKS); +// params.set_poly_modulus_degree(poly_d); +// params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); +// params.set_plain_modulus(PlainModulus::Batching(poly_d, bit_size)); +// save_params(params, key_dir + "bfv_params.conf"); +// context = SEALContext::Create(params); +// print_context(context); +// } + +void init_context_batching( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, + const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 36, 36, 37 })); + params.set_plain_modulus(plain_modulus); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +// void ckks_init_context_batching( +// size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, +// const std::string &key_dir) +// { +// EncryptionParameters params(scheme_type::CKKS); +// params.set_poly_modulus_degree(poly_d); +// params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 36, 36, 37 })); +// params.set_plain_modulus(plain_modulus); +// save_params(params, key_dir + "ckks_params.conf"); +// context = SEALContext::Create(params); +// print_context(context); +// } + +// void init_context_ckks(size_t poly_d, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, +// const std::string &key_dir) +// { +// int ret = 1; + +// EncryptionParameters params(scheme_type::CKKS); +// params.set_poly_modulus_degree(poly_d); +// switch (poly_d) +// { +// case 4096: +// params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 30, 20, 20, 30 })); +// break; +// case 8192: +// params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 60, 40, 40, 60 })); +// break; +// default: +// cout << "[seal-error] enter valid poly degree: 4096 or 8192" << endl; +// break; +// } +// // params.set_plain_modulus(plain_modulus); +// save_params(params, key_dir + "ckks_params.conf"); + +// context = SEALContext::Create(params); +// print_context(context); + +// // context = SEALContext(params); +// // if (context.parameter_error_message() == "valid") +// // { +// // clog << "[seal-ckks] parameter validation: valid" << endl; +// // save_params(params, "ckks_params.conf"); +// // } +// // else +// // { +// // clog << "[seal-error] parameter validation: invalid" << endl; +// // ret = 0; +// // } +// // return ret; +// } + +// int init_context_ckks(uint32_t poly_deg, SEALContext& context) +int init_context_ckks(uint32_t poly_deg, shared_ptr<SEALContext> &context, const std::string &key_dir) +{ + int ret = 1; + + EncryptionParameters params(scheme_type::CKKS); + params.set_poly_modulus_degree(poly_deg); + switch (poly_deg) + { + case 4096: + params.set_coeff_modulus(CoeffModulus::Create(poly_deg, { 30, 20, 20, 30 })); + break; + case 8192: + params.set_coeff_modulus(CoeffModulus::Create(poly_deg, { 60, 40, 40, 60 })); + break; + case 16384: + params.set_coeff_modulus(CoeffModulus::Create(poly_deg, { 60, 40, 40, 40, 40, 40, 40, 40, 60 })); + // params.set_coeff_modulus(CoeffModulus::Create(poly_deg, { 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 })); + // params.set_coeff_modulus(CoeffModulus::Create(poly_deg, { 30, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 30 })); + break; + default: + cout << "[seal-error] enter valid poly degree: 4096 or 8192" << endl; + break; + } + + context = SEALContext::Create(params); + // if (context.parameter_error_message() == "valid") { + // clog << "[seal-ckks] parameter validation: valid" << endl; + save_params(params, key_dir + "ckks_params.conf"); + // } + // else { + // clog << "[seal-error] parameter validation: invalid" << endl; + // ret = 0; + // } + print_context(context); + return ret; +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext> &context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + cout << "[CONTEXT] scheme: " << scheme_name << endl; + cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + // /* Print the size of the true (product) coefficient modulus */ + cout << "[CONTEXT] coeff_modulus size: "; + cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + cout << coeff_modulus[i].bit_count() << " + "; + cout << coeff_modulus.back().bit_count(); + cout << ") bits" << endl; + + cout << "[CONTEXT] coeff_modulus values: ("; + for (int i = 0; i < (coeff_modulus.size() - 1); ++i) + { + cout << coeff_modulus[i].value() << ",\t"; + cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + } + + /* For the BFV scheme print the plain_modulus parameter */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + { + cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; + } +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(GaloisKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<GaloisKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, GaloisKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, bool serializable) +{ + shared_ptr<SEALContext> context; + init_context(poly_d, p_modulus, context); + + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + save_key(pk, "bfv.pk"); + SecretKey sk = keygen.secret_key(); + save_key(sk, "bfv.sk"); + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, "bfv.lk"); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, "bfv.lk"); + } +} + +bool suffix_exist(const std::string &str, const std::string &suffix) +{ + return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +/* +Helper function: Prints the parameters in a SEALContext. +*/ +inline void print_parameters(std::shared_ptr<seal::SEALContext> context) +{ + // Verify parameters + if (!context) + { + throw std::invalid_argument("context is not set"); + } + auto &context_data = *context->key_context_data(); + + /* + Which scheme are we using? + */ + std::string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw std::invalid_argument("unsupported scheme"); + } + // cout << "/" << std::endl; + // cout << "| Encryption parameters :" << std::endl; + // cout << "| scheme: " << scheme_name << std::endl; + // cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << std::endl; + + /* + Print the size of the true (product) coefficient modulus. + */ + // cout << "| coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + std::size_t coeff_modulus_size = coeff_modulus.size(); + // for (std::size_t i = 0; i < coeff_modulus_size - 1; i++) + // { + // cout << coeff_modulus[i].bit_count() << " + "; + // } + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << std::endl; + + /* + For the BFV scheme print the plain_modulus parameter. + */ + // if (context_data.parms().scheme() == seal::scheme_type::BFV) + // { + // cout << "| plain_modulus: " << context_data.parms().plain_modulus().value() << std::endl; + // } + + // cout << "\\" << std::endl; +} + +void batching_generate_keys(size_t poly_d, int bit_size, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_size, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_size, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void generate_keys_ckks(size_t poly_d, int bit_size, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_size, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/ckks.pk"); + string keypath2("/ckks.sk"); + string keypath3("/ckks.lk"); + string keypath4("/ckks.gk"); + string ckks_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "ckks.pk"; + keypath2 = "ckks.sk"; + keypath3 = "ckks.lk"; + keypath4 = "ckks.gk"; + ckks_params_path = key_dir; + } + + // ckks_init_context_batching(poly_d, bit_size, context, ckks_params_path); + + // init_context_ckks(poly_d, bit_size, context, ckks_params_path); + init_context_ckks(poly_d, context, ckks_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + print_parameters(context); +} + +void batching_generate_keys( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_sizes, plain_modulus, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_sizes, plain_modulus, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void init_operator(struct encryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + PublicKey pk; + load_key(op_st.context, "bfv.pk", pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct encryptor_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + PublicKey pk; + string keypath(""); + string keypath1("bfv.pk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +// void init_operator_ckks(struct encryptor_t &op_st, const string &key_dir) +void init_operator_ckks(struct cencryptor_t &op_st, const string &key_dir) +{ + string ckks_params_path(""); + string ckks_params_path1("/ckks_params.conf"); + ckks_params_path = ""; + ckks_params_path.append(key_dir); + ckks_params_path.append(ckks_params_path1); + // cout << "[INFO] ckksparams: " << ckks_params_path << endl; + load_context(op_st.context, ckks_params_path); + PublicKey pk; + string keypath(""); + string keypath1("ckks.pk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + // op_st.icode = new IntegerEncoder(op_st.context); + op_st.ccode = new CKKSEncoder(op_st.context); + // auto &context_data = *(op_st.context.key_context_data()); + auto &context_data = *op_st.context->key_context_data(); + int poly_deg = context_data.parms().poly_modulus_degree(); + switch (poly_deg) + { + case 4096: + op_st.scale = pow(2.0, 20); + case 8192: + op_st.scale = pow(2.0, 40); + case 16384: + op_st.scale = pow(2.0, 40); + // op_st.scale = pow(2.0, 20); + } + // return 1; +} + +void init_operator_ckks(struct cdecryptor_t &op_st, const string &key_dir) +{ + string ckks_params_path(""); + string ckks_params_path1("/ckks_params.conf"); + ckks_params_path = ""; + ckks_params_path.append(key_dir); + ckks_params_path.append(ckks_params_path1); + // cout << "[INFO] ckksparams: " << ckks_params_path << endl; + load_context(op_st.context, ckks_params_path); + // PublicKey pk; + SecretKey sk; + string keypath(""); + string keypath1("ckks.sk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, sk); + op_st.decr = new Decryptor(op_st.context, sk); + // op_st.icode = new IntegerEncoder(op_st.context); + op_st.ccode = new CKKSEncoder(op_st.context); + // auto &context_data = *(op_st.context.key_context_data()); + auto &context_data = *op_st.context->key_context_data(); + int poly_deg = context_data.parms().poly_modulus_degree(); + switch (poly_deg) + { + case 4096: + op_st.scale = pow(2.0, 20); + case 8192: + op_st.scale = pow(2.0, 40); + case 16384: + op_st.scale = pow(2.0, 40); + // op_st.scale = pow(2.0, 20); + } + // return 1; +} + +void init_operator_ckks(struct cevaluator_t &op_st, const string &key_dir) +{ + string ckks_params_path(""); + string ckks_params_path1("/ckks_params.conf"); + ckks_params_path = ""; + ckks_params_path.append(key_dir); + ckks_params_path.append(ckks_params_path1); + // cout << "[INFO] bfvparams: " << ckks_params_path << endl; + load_context(op_st.context, ckks_params_path); + + string keypath(""); + string keypath1("ckks.lk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + + string keypath3(""); + string keypath4("ckks.gk"); + keypath3.append(key_dir); + keypath3.append(keypath4); + // cout << "[INFO] Keypath evaluator: " << keypath3 << endl; + load_key(op_st.context, keypath3, op_st.gk); + + // op_st.eval = new Evaluator(op_st.context, sk); + + // op_st.icode = new IntegerEncoder(op_st.context); + // op_st.ccode = new CKKSEncoder(op_st.context); + op_st.eval = new Evaluator(op_st.context); + // auto &context_data = *(op_st.context.key_context_data()); + auto &context_data = *op_st.context->key_context_data(); + int poly_deg = context_data.parms().poly_modulus_degree(); + switch (poly_deg) + { + case 4096: + op_st.scale = pow(2.0, 20); + case 8192: + op_st.scale = pow(2.0, 40); + case 16384: + op_st.scale = pow(2.0, 40); + // op_st.scale = pow(2.0, 20); + } + // return 1; +} + +// int init_operator_ckks(struct cencryptor_t &op_st, const string &key_dir) +// { +// int ret = 1; + +// // if (!load_context("/ckks_params.conf", op_st.context)) { +// // cerr << "[seal-error] failure for loading ckks context during encryptor setting!" << endl; +// // ret = 0; +// // } +// // else { +// // PublicKey pk; +// // if (!load_key(op_st.context, "ckks.pk", pk)) { +// // cerr << "[seal-error] failure for loading ckks public key during encryptor setting!" << endl; +// // ret = 0; +// // } +// // else { +// op_st.encr = new Encryptor(op_st.context, pk); +// op_st.ccode = new CKKSEncoder(op_st.context); +// auto &context_data = *(op_st.context.key_context_data()); +// int poly_deg = context_data.parms().poly_modulus_degree(); +// switch (poly_deg) +// { +// case 4096: +// op_st.scale = pow(2.0, 20); +// case 8192: +// op_st.scale = pow(2.0, 40); +// } +// // } +// // } +// return ret; +// } + +void init_operator_batching(struct encryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void delete_operator_batching(struct encryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void delete_operator_ckks(struct cencryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.ccode; +} + +void delete_operator_ckks(struct cdecryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.ccode; +} + +void delete_operator_ckks(struct cevaluator_t &op_st) +{ + delete op_st.eval; +} + +void init_operator(struct decryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + SecretKey sk; + load_key(op_st.context, "bfv.sk", sk); + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct decryptor_t &op_st, const std::string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + + load_context(op_st.context, bfv_params_path); + SecretKey sk; + string keypath(""); + string keypath1("bfv.sk"); + + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath decrypt: " << keypath << endl; + + load_key(op_st.context, keypath, sk); + + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct decryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void delete_operator_batching(struct decryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct evaluator_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, "bfv.lk", op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator(struct evaluator_t &op_st, const string &relink_key_path) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, relink_key_path, op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator_batching(struct evaluator_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + + string keypath(""); + string keypath1("bfv.lk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + + string keypath3(""); + string keypath4("bfv.gk"); + keypath3.append(key_dir); + keypath3.append(keypath4); + // cout << "[INFO] Keypath evaluator: " << keypath3 << endl; + load_key(op_st.context, keypath3, op_st.gk); + + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void delete_operator_batching(struct evaluator_t &op_st) +{ + delete_operator(op_st); +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + // cout << "[INFO] encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + // cout << plain << endl; +} + +void init_ciphermatrix(struct encryptor_t &op_st, vector<int64_t> &plain_matrix, Ciphertext &encrypted_matrix) +{ + // cout << "[INFO] encrypting: " << endl; + Plaintext plaintext_matrix; + // BatchEncoder batch_encoder(op_st.context); + // batch_encoder.encode(plain_matrix, plaintext_matrix); + op_st.bcode->encode(plain_matrix, plaintext_matrix); + // op_st.ccode->encode(plain_matrix, plaintext_matrix); + op_st.encr->encrypt(plaintext_matrix, encrypted_matrix); + // cout << plain << endl; +} + +/* ckks plaintext management */ +// void init_plaintext_ckks(CKKSEncoder& encoder, double scale, vector<double>& p_vector, Plaintext& pt, bool +// print_info) void init_plaintext_ckks(CKKSEncoder& encoder, double scale, vector<double>& p_vector, Plaintext& pt) +// { +// try { +// encoder.encode(p_vector, scale, pt); +// } +// catch (std::exception &e) { +// clog << "[seal-error] catched exception: " << e.what() << endl; +// clog << "[seal-error] ckks slots encoding error" << endl; +// } + +// if (print_info) { +// clog << "[seal-ckks] plaintexts: " << endl; +// print_vectors(p_vector); +// } +// } + +/* ckks ciphertext management */ +// void init_ciphertext(CKKSEncoder& encoder, Encryptor& encryptor, double scale, vector<double>& c_vector, Ciphertext& +// ct, bool print_info) +void init_ciphertext_ckks( + CKKSEncoder &encoder, Encryptor &encryptor, double scale, vector<double> &c_vector, Ciphertext &ct) +{ + Plaintext pt; + try + { + encoder.encode(c_vector, scale, pt); + } + catch (std::exception &e) + { + clog << "[seal-error] catched exception: " << e.what() << endl; + clog << "[seal-error] ckks slots encoding error" << endl; + } + encryptor.encrypt(pt, ct); + + // if (print_info) { + // clog << "[seal-ckks] ciphertext inputs: " << endl; + // print_vectors(c_vector); + // } +} + +void init_ciphertext_ckks(cencryptor_t &op_st, double scale, vector<double> &c_vector, Ciphertext &ct) +{ + init_ciphertext_ckks(*(op_st.ccode), *(op_st.encr), scale, c_vector, ct); +} + +void init_ciphertext_ckks(cencryptor_t &op_st, vector<double> &c_vector, Ciphertext &ct) +{ + init_ciphertext_ckks(*(op_st.ccode), *(op_st.encr), op_st.scale, c_vector, ct); +} + + + +/* ckks decryption */ +void decrypt_ciphertext_ckks(cdecryptor_t &op_st, Ciphertext &ct, vector<double> &pt_val) +{ + decrypt_ciphertext_ckks(*(op_st.ccode), *(op_st.decr), ct, pt_val); +} + +void decrypt_ciphertext_ckks(CKKSEncoder &encoder, Decryptor &decryptor, Ciphertext &ct, vector<double> &pt_val) +{ + Plaintext pt; + decryptor.decrypt(ct, pt); + encoder.decode(pt, pt_val); + + // if (print_info) { + // clog << "[seal-ckks] decrypted plaintexts: " << endl; + // print_vectors(pt_val); + // } +} + +// vector<double> decrypt_ciphermatrix_ckks(struct decryptor_t &op_st, Ciphertext &ct) +// { +// Plaintext pt; +// op_st.decr->decrypt(ct, pt); +// vector<double> pod_matrix; +// // BatchEncoder batch_encoder(op_st.context); +// // batch_encoder.decode(pt, pod_matrix); +// encoder.decode(pt, pod_matrix); +// // print_matrix(pod_matrix, 3); +// decrypt_ciphertext_ckks +// return pod_matrix; +// } + +/* saving ciphertexts and plaintexts */ +// plaintexts +int load_plaintext_ckks(struct cencryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext_ckks(struct cdecryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext_ckks(struct cevaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} +// ciphertexts +int load_ciphertext_ckks(struct cevaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext_ckks(struct cencryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext_ckks(struct cdecryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] decrypted result: " << res << endl; +} + +int64_t decrypt_ciphertext_and_return_value(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] Decrypted result: " << res << endl; + return res; +} + +vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + vector<int64_t> pod_matrix; + BatchEncoder batch_encoder(op_st.context); + batch_encoder.decode(pt, pod_matrix); + // print_matrix(pod_matrix, 3); + return pod_matrix; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + pt.save(out_file); + else + ret = 0; + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + ct.save(out_file); + else + ret = 0; + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + pt.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + ct.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +/* ckks plaintext management */ +void init_plaintext_ckks(CKKSEncoder &encoder, double scale, vector<double> &p_vector, Plaintext &pt, bool print_info) +{ + try + { + encoder.encode(p_vector, scale, pt); + } + catch (std::exception &e) + { + clog << "[seal-error] catched exception: " << e.what() << endl; + clog << "[seal-error] ckks slots encoding error" << endl; + } + + // if (print_info) + // { + // clog << "[seal-ckks] plaintexts: " << endl; + // print_vectors(p_vector); + // } +} + +void init_plaintext_ckks(cencryptor_t &op_st, double scale, vector<double> &p_vector, Plaintext &pt, bool print_info) +{ + init_plaintext_ckks(*(op_st.ccode), scale, p_vector, pt, print_info); +} + +void init_plaintext_ckks(cencryptor_t &op_st, vector<double> &p_vector, Plaintext &pt, bool print_info) +{ + init_plaintext_ckks(*(op_st.ccode), op_st.scale, p_vector, pt, print_info); +} + +void init_plaintext_ckks(cdecryptor_t &op_st, double scale, vector<double> &p_vector, Plaintext &pt, bool print_info) +{ + init_plaintext_ckks(*(op_st.ccode), scale, p_vector, pt, print_info); +} + +void init_plaintext_ckks(cdecryptor_t &op_st, vector<double> &p_vector, Plaintext &pt, bool print_info) +{ + init_plaintext_ckks(*(op_st.ccode), op_st.scale, p_vector, pt, print_info); +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.h b/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..19deb3301fa21011cc3d8dbd2454bebab6268ea5 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/seal_api.h @@ -0,0 +1,185 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" +#include "csv_api.h" + +/** BFV definitions **/ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::GaloisKeys gk; + seal::Evaluator *eval; +}; + +/** CKKS definitions **/ +struct cencryptor_t { + // seal::SEALContext context{0}; + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor* encr{nullptr}; + seal::CKKSEncoder* ccode{nullptr}; + double scale{0}; +}; + +struct cdecryptor_t { + // seal::SEALContext context{0}; + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor* decr{nullptr}; + seal::CKKSEncoder* ccode{nullptr}; + double scale{0}; +}; + +struct cevaluator_t { + // seal::SEALContext context{0}; + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk{}; + seal::GaloisKeys gk{}; + seal::Evaluator* eval{nullptr}; + // seal::CKKSEncoder* ccode{nullptr}; + double scale{0}; +}; + +/** prototypes **/ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::GaloisKeys& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); +void generate_keys(size_t poly_d, size_t p_modulus, bool seriablizable = false); +void batching_generate_keys(size_t poly_d, int bit_size, const std::string key_path, bool serializable = false); +void batching_generate_keys(size_t poly_d, std::vector<int> bit_sizes, std::uint64_t plain_modulus, std::string key_dir, bool serializable = false); + +/** for homomorphic operators management **/ +void init_operator(struct encryptor_t& op_st); +void init_operator(struct encryptor_t &op_st, const std::string& public_key_path); +void init_operator_batching(struct encryptor_t &op_st, const std::string& key_dir); +void init_operator(struct decryptor_t& op_st); +void init_operator(struct decryptor_t &op_st, const std::string& secret_key_path); +void init_operator_batching(struct decryptor_t &op_st, const std::string& key_dir); +void init_operator(struct evaluator_t& op_st); +void init_operator(struct evaluator_t& op_st, const std::string& relink_key_path); +void init_operator_batching(struct evaluator_t &op_st, const std::string &key_dir); +void delete_operator(struct encryptor_t& op_st); +void delete_operator_batching(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator_batching(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); +void delete_operator_batching(struct evaluator_t& op_st); + +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void init_ciphermatrix(struct encryptor_t &op_st, std::vector<int64_t> &plain_matrix, seal::Ciphertext &encrypted_matrix); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::int64_t decrypt_ciphertext_and_return_value(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, seal::Ciphertext &ct); + +/*** ckks plaintexts ***/ +void init_plaintext_ckks(seal::CKKSEncoder& encoder, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +void init_plaintext_ckks(struct cencryptor_t& op_st, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +void init_plaintext_ckks(struct cencryptor_t& op_st, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +void init_plaintext_ckks(struct cdecryptor_t& op_st, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +void init_plaintext_ckks(struct cdecryptor_t& op_st, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + +int load_ciphertext_ckks(struct cevaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext_ckks(struct cdecryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + + + + +/** prototypes **/ +/*** ckks opertors ***/ +// int init_operator(struct cencryptor_t& op_st); +// int init_operator_ckks(struct cencryptor_t& op_st); +void init_operator_ckks(struct cencryptor_t &op_st, const std::string& key_dir); +void init_operator_ckks(struct cdecryptor_t &op_st, const std::string& key_dir); +void init_operator_ckks(struct cevaluator_t& op_st, const std::string& key_dir); +// int init_operator(struct cdecryptor_t& op_st); +// int init_operator(struct cevaluator_t& op_st); +void delete_operator_ckks(struct cencryptor_t& op_st); +void delete_operator_ckks(struct cdecryptor_t& op_st); +void delete_operator_ckks(struct cevaluator_t& op_st); +// void delete_operator(struct cevaluator_t& op_st); + +/*** ckks plaintexts ***/ +// void init_plaintext(seal::CKKSEncoder& encoder, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +// void init_plaintext(struct cencryptor_t& op_st, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +// void init_plaintext(struct cencryptor_t& op_st, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +// void init_plaintext(struct cdecryptor_t& op_st, double scale, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); +// void init_plaintext(struct cdecryptor_t& op_st, std::vector<double>& p_vector, seal::Plaintext& pt, bool print_info = 1); + +/*** ckks ciphertexts ***/ +void init_ciphertext_ckks(seal::CKKSEncoder& encoder, seal::Encryptor& encryptor, double scale, std::vector<double>& c_vector, seal::Ciphertext& ct); +void init_ciphertext_ckks(struct cencryptor_t& op_st, double scale, std::vector<double>& c_vector, seal::Ciphertext& ct); +void init_ciphertext_ckks(struct cencryptor_t& op_st, std::vector<double>& c_vector, seal::Ciphertext& ct); + +/*** ckks decryption ***/ +void decrypt_ciphertext_ckks(seal::CKKSEncoder& encoder, seal::Decryptor& decryptor, seal::Ciphertext& ct, std::vector<double>& pt_val); +void decrypt_ciphertext_ckks(struct cdecryptor_t& op_st, seal::Ciphertext& ct, std::vector<double>& pt_val); +// std::vector<double> decrypt_ciphermatrix_ckks(struct cdecryptor_t &op_st, seal::Ciphertext &ct); + +/*** saving plaintexts and ciphertexts ***/ +int load_plaintext_ckks(struct cevaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext_ckks(struct cencryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext_ckks(struct cdecryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); + +int load_ciphertext_ckks(struct cevaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext_ckks(struct cencryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext_ckks(struct cdecryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); +void generate_keys_ckks(size_t poly_d, int bit_size, const std::string key_path, bool serializable = false); + +/*** sum ***/ +// void sum_batch_ciphertext(struct cevaluator_t& op_st, std::vector<seal::Ciphertext>& ct, seal::Ciphertext& ct_out); + +/*** testing ***/ +// void test_ckks_batch_functions(const uint32_t poly_deg); + +#endif diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/test_v1.sh b/bigpiseal3.5.1/native/examples/ANN/v1/test_v1.sh new file mode 100644 index 0000000000000000000000000000000000000000..27ff4cd4118ff03b6be1f65b0b7883345da9ac10 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/test_v1.sh @@ -0,0 +1,115 @@ +mkdir -p keys/ +mkdir -p lcheck/ +mkdir -p parent/ +mkdir -p result/ +# rm ls.txt + + +# bash data_creating.sh 0 99 9 1000 + +# Number of driving licenses, eg: (0..99) +min=0 +max=101 +# max=1631 +# max=101 +# sim: (eval: 0.465s, 0.488s, 0.480s decrypt: 0.028s, 0.080s, 0.077s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=203 +# (eval: 3.635s, 3.510s, 3.628s decrypt: 0.062s, 0.153s. 0.134s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=407 +# (eval: 38.607s, 39.600s, 39.565s decrypt: 0.264s, 0.260s, 0.245s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=815 +# (eval: x decrypt: x ) + +# Number of chars/words of a driving license, eg: 9 +n_char=39 + +# Encrypted number range, eg: 10, 100, 1000 for 1 2 3 4 digits +range=255 +# (8-bit) + +# sampling size +sample=40 + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Note + + + +# gen keys +# ./ANN_genkey_v1 keys/ +${CURR_DIR}/ANN_genkey_v1 keys/ + +line=$((RANDOM %max)) +lcheck="" +# gen data +for i in $(seq $min $max) +do + mkdir -p parent/l"$i"/ + echo "Created folder $i" + + value="" + for j in $(seq 0 $n_char) + do + value+="$((RANDOM %$range)) " + done + + echo $value + echo $value >> ls.txt + # ./ANN_encrypt_v1 "$value" "l" parent/l"$i"/ $sample keys/ + ${CURR_DIR}/ANN_encrypt_v1 "$value" "l" parent/l"$i"/ $sample keys/ + + if [[ "$line" -eq "$i" ]] + then + lcheck="$value" + fi + +done + + + +# get random lc +# lcheck=$(sed -n "$((RANDOM %9){p;q}" ls.txt) +# line=$((RANDOM %max)) +# lcheck="$(sed -n "${line}{p;q}" ls.txt)" +echo "Pick up license to check: $lcheck" +# ./ANN_encrypt_v1 "$lcheck" "l" lcheck/ $sample keys/ +${CURR_DIR}/ANN_encrypt_v1 "$lcheck" "l" lcheck/ $sample keys/ +# ./ANN_encrypt "47 25 76 23 30 21 1 47 88 3" "a" keys/bfv.pk lcheck/ + + + + +# eval +value1="lcheck/l.ct " + + +value2="" +for i in $(seq 0 $max) +do + value2+="parent/l${i}/l.ct " +done + +# value2="${value1} ${value2}" +value3="$value1$value2" +echo "$value3" + +# time ./ANN_evaluate_v1 $value3 "l" result/ $sample keys/ +# ./ANN_evaluate_v1 $value3 "l" result/ $sample keys/ +time ${CURR_DIR}/ANN_evaluate_v1 $value3 "l" result/ $sample keys/ + +echo "" + +# time ./ANN_decrypt_result_v1 result/l.ct $sample keys/ +# ./ANN_decrypt_result_v1 result/l.ct $sample keys/ +${CURR_DIR}/ANN_decrypt_result_v1 result/l.ct $sample keys/ + + +# rm -r keys/* +# rm -r lcheck/* +# rm -r parent/* +# rm -r result/* +# rm ls.txt diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/util.cpp b/bigpiseal3.5.1/native/examples/ANN/v1/util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72367dab3632e64801bf24ead89070859286704e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/util.cpp @@ -0,0 +1,73 @@ +#include "util.h" +// #include <filesystem> +#include "seal_api.h" + +// #include <boost/filesystem.hpp> + +// namespace fs = boost::filesystem; + +bool sub_str_exist(const std::string &str, const std::string &sub_str) +{ + return str.size() >= sub_str.size() && str.compare(str.size() - sub_str.size(), sub_str.size(), sub_str) == 0; +} + +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// auto dirIter = std::filesystem::directory_iterator(path); +// int fileCount = std::count_if( +// begin(dirIter), +// end(dirIter), +// [](auto &entry) { return entry.is_regular_file(); }); +// return fileCount; +// } + +// int findNumberOfFilesInDirectory(std::string &path, std::string &ext) +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// // namespace fs = boost::filesystem; + +// std::string ext = ".ct"; + +// fs::path Path(path); +// int Nb_ext = 0; +// fs::directory_iterator end_iter; // Default constructor for an iterator is the end iterator + +// for (fs::directory_iterator iter(Path); iter != end_iter; ++iter) +// if (iter->path().extension() == ext) +// ++Nb_ext; + +// return Nb_ext; +// } + +// c++ 17 +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> r; +// for(auto& p : std::filesystem::recursive_directory_iterator(s)) +// if (p.is_directory()) +// r.push_back(p.path().string()); +// return r; +// } + +// struct path_leaf_string +// { +// std::string operator()(const boost::filesystem::directory_entry &entry) const +// { +// return entry.path().leaf().string(); +// } +// }; + +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> v; + +// boost::filesystem::path p(s); +// boost::filesystem::directory_iterator start(p); +// boost::filesystem::directory_iterator end; +// std::transform(start, end, std::back_inserter(v), path_leaf_string()); + +// std::copy(v.begin(), v.end(), +// std::ostream_iterator<std::string>(std::cout, "\n")); + +// return v; +// } diff --git a/bigpiseal3.5.1/native/examples/ANN/v1/util.h b/bigpiseal3.5.1/native/examples/ANN/v1/util.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8ffd7ce1534fac8fec3d5a4bfb2a2fdf8f0961 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/ANN/v1/util.h @@ -0,0 +1,15 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <string> +#include <vector> + +// int findNumberOfFilesInDirectory(const std::string &path); + +bool sub_str_exist(const std::string &str, const std::string &sub_str); + +// std::vector<std::string> get_directories(const std::string &s); + +// std::vector<std::string> get_directories_deep(const std::string &s); + +#endif diff --git a/bigpiseal3.5.1/native/examples/CMakeLists.txt b/bigpiseal3.5.1/native/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c3b5d614124c693738e655abe04a387860181ed6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +target_sources(sealexamples + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/examples.cpp + ${CMAKE_CURRENT_LIST_DIR}/1_bfv_basics.cpp + ${CMAKE_CURRENT_LIST_DIR}/2_encoders.cpp + ${CMAKE_CURRENT_LIST_DIR}/3_levels.cpp + ${CMAKE_CURRENT_LIST_DIR}/4_ckks_basics.cpp + ${CMAKE_CURRENT_LIST_DIR}/5_rotation.cpp + ${CMAKE_CURRENT_LIST_DIR}/6_serialization.cpp + ${CMAKE_CURRENT_LIST_DIR}/7_performance.cpp +) \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj b/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..0e101770cd47f900716ff83c728a7bb5f1145262 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{2B57D847-26DC-45FF-B9AF-EE33910B5093}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>SEALExamples</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealexamples</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealexamples</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealexamples</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealexamples</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)native\src</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)native\src</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)native\src</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <ControlFlowGuard>Guard</ControlFlowGuard> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <Profile>true</Profile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)native\src</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <ControlFlowGuard>Guard</ControlFlowGuard> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <Profile>true</Profile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="1_bfv_basics.cpp" /> + <ClCompile Include="2_encoders.cpp" /> + <ClCompile Include="4_ckks_basics.cpp" /> + <ClCompile Include="5_rotation.cpp" /> + <ClCompile Include="3_levels.cpp" /> + <ClCompile Include="6_serialization.cpp" /> + <ClCompile Include="7_performance.cpp" /> + <ClCompile Include="examples.cpp" /> + </ItemGroup> + <ItemGroup> + <Text Include="CMakeLists.txt" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="examples.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets" /> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj.filters b/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..f903eae8c8afb791b9cab833553ef8be8a9e20b6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/SEALExamples.vcxproj.filters @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Other"> + <UniqueIdentifier>{abd2e216-316f-4dad-a2a4-a72ffccfd92b}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="examples.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="3_levels.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="5_rotation.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="1_bfv_basics.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="2_encoders.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="4_ckks_basics.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="7_performance.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="6_serialization.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Text Include="CMakeLists.txt"> + <Filter>Other</Filter> + </Text> + </ItemGroup> + <ItemGroup> + <ClInclude Include="examples.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/examples.cpp b/bigpiseal3.5.1/native/examples/examples.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22e770be4c7c703c2bd676f86666741f77f3cd0b --- /dev/null +++ b/bigpiseal3.5.1/native/examples/examples.cpp @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "examples.h" + +using namespace std; +using namespace seal; + +int main() +{ + cout << "Microsoft SEAL version: " << SEAL_VERSION << endl; + while (true) + { + cout << "+---------------------------------------------------------+" << endl; + cout << "| The following examples should be executed while reading |" << endl; + cout << "| comments in associated files in native/examples/. |" << endl; + cout << "+---------------------------------------------------------+" << endl; + cout << "| Examples | Source Files |" << endl; + cout << "+----------------------------+----------------------------+" << endl; + cout << "| 1. BFV Basics | 1_bfv_basics.cpp |" << endl; + cout << "| 2. Encoders | 2_encoders.cpp |" << endl; + cout << "| 3. Levels | 3_levels.cpp |" << endl; + cout << "| 4. CKKS Basics | 4_ckks_basics.cpp |" << endl; + cout << "| 5. Rotation | 5_rotation.cpp |" << endl; + cout << "| 6. Serialization | 6_serialization.cpp |" << endl; + cout << "| 7. Performance Test | 7_performance.cpp |" << endl; + cout << "+----------------------------+----------------------------+" << endl; + + /* + Print how much memory we have allocated from the current memory pool. + By default the memory pool will be a static global pool and the + MemoryManager class can be used to change it. Most users should have + little or no reason to touch the memory allocation system. + */ + size_t megabytes = MemoryManager::GetPool().alloc_byte_count() >> 20; + cout << "[" << setw(7) << right << megabytes << " MB] " + << "Total allocation from the memory pool" << endl; + + int selection = 0; + bool invalid = true; + do + { + cout << endl << "> Run example (1 ~ 7) or exit (0): "; + if (!(cin >> selection)) + { + invalid = false; + } + else if (selection < 0 || selection > 7) + { + invalid = false; + } + else + { + invalid = true; + } + if (!invalid) + { + cout << " [Beep~~] Invalid option: type 0 ~ 7" << endl; + cin.clear(); + cin.ignore(numeric_limits<streamsize>::max(), '\n'); + } + } while (!invalid); + + switch (selection) + { + case 1: + example_bfv_basics(); + break; + + case 2: + example_encoders(); + break; + + case 3: + example_levels(); + break; + + case 4: + example_ckks_basics(); + break; + + case 5: + example_rotation(); + break; + + case 6: + example_serialization(); + break; + + case 7: + example_performance_test(); + break; + + case 0: + return 0; + } + } + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/examples.h b/bigpiseal3.5.1/native/examples/examples.h new file mode 100644 index 0000000000000000000000000000000000000000..448a87698b432dd933e25c8150545333c3d24d78 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/examples.h @@ -0,0 +1,223 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/seal.h" +#include <algorithm> +#include <chrono> +#include <cstddef> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <limits> +#include <memory> +#include <mutex> +#include <numeric> +#include <random> +#include <sstream> +#include <string> +#include <thread> +#include <vector> + +void example_bfv_basics(); + +void example_encoders(); + +void example_levels(); + +void example_ckks_basics(); + +void example_rotation(); + +void example_serialization(); + +void example_performance_test(); + +/* +Helper function: Prints the name of the example in a fancy banner. +*/ +inline void print_example_banner(std::string title) +{ + if (!title.empty()) + { + std::size_t title_length = title.length(); + std::size_t banner_length = title_length + 2 * 10; + std::string banner_top = "+" + std::string(banner_length - 2, '-') + "+"; + std::string banner_middle = "|" + std::string(9, ' ') + title + std::string(9, ' ') + "|"; + + std::cout << std::endl << banner_top << std::endl << banner_middle << std::endl << banner_top << std::endl; + } +} + +/* +Helper function: Prints the parameters in a SEALContext. +*/ +inline void print_parameters(std::shared_ptr<seal::SEALContext> context) +{ + // Verify parameters + if (!context) + { + throw std::invalid_argument("context is not set"); + } + auto &context_data = *context->key_context_data(); + + /* + Which scheme are we using? + */ + std::string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw std::invalid_argument("unsupported scheme"); + } + std::cout << "/" << std::endl; + std::cout << "| Encryption parameters :" << std::endl; + std::cout << "| scheme: " << scheme_name << std::endl; + std::cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << std::endl; + + /* + Print the size of the true (product) coefficient modulus. + */ + std::cout << "| coeff_modulus size: "; + std::cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + std::size_t coeff_modulus_size = coeff_modulus.size(); + for (std::size_t i = 0; i < coeff_modulus_size - 1; i++) + { + std::cout << coeff_modulus[i].bit_count() << " + "; + } + std::cout << coeff_modulus.back().bit_count(); + std::cout << ") bits" << std::endl; + + /* + For the BFV scheme print the plain_modulus parameter. + */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + { + std::cout << "| plain_modulus: " << context_data.parms().plain_modulus().value() << std::endl; + } + + std::cout << "\\" << std::endl; +} + +/* +Helper function: Prints the `parms_id' to std::ostream. +*/ +inline std::ostream &operator<<(std::ostream &stream, seal::parms_id_type parms_id) +{ + /* + Save the formatting information for std::cout. + */ + std::ios old_fmt(nullptr); + old_fmt.copyfmt(std::cout); + + stream << std::hex << std::setfill('0') << std::setw(16) << parms_id[0] << " " << std::setw(16) << parms_id[1] + << " " << std::setw(16) << parms_id[2] << " " << std::setw(16) << parms_id[3] << " "; + + /* + Restore the old std::cout formatting. + */ + std::cout.copyfmt(old_fmt); + + return stream; +} + +/* +Helper function: Prints a vector of floating-point values. +*/ +template <typename T> +inline void print_vector(std::vector<T> vec, std::size_t print_size = 4, int prec = 3) +{ + /* + Save the formatting information for std::cout. + */ + std::ios old_fmt(nullptr); + old_fmt.copyfmt(std::cout); + + std::size_t slot_count = vec.size(); + + std::cout << std::fixed << std::setprecision(prec); + std::cout << std::endl; + if (slot_count <= 2 * print_size) + { + std::cout << " ["; + for (std::size_t i = 0; i < slot_count; i++) + { + std::cout << " " << vec[i] << ((i != slot_count - 1) ? "," : " ]\n"); + } + } + else + { + vec.resize(std::max(vec.size(), 2 * print_size)); + std::cout << " ["; + for (std::size_t i = 0; i < print_size; i++) + { + std::cout << " " << vec[i] << ","; + } + if (vec.size() > 2 * print_size) + { + std::cout << " ...,"; + } + for (std::size_t i = slot_count - print_size; i < slot_count; i++) + { + std::cout << " " << vec[i] << ((i != slot_count - 1) ? "," : " ]\n"); + } + } + std::cout << std::endl; + + /* + Restore the old std::cout formatting. + */ + std::cout.copyfmt(old_fmt); +} + +/* +Helper function: Prints a matrix of values. +*/ +template <typename T> +inline void print_matrix(std::vector<T> matrix, std::size_t row_size) +{ + /* + We're not going to print every column of the matrix (there are 2048). Instead + print this many slots from beginning and end of the matrix. + */ + std::size_t print_size = 5; + + std::cout << std::endl; + std::cout << " ["; + for (std::size_t i = 0; i < print_size; i++) + { + std::cout << std::setw(3) << std::right << matrix[i] << ","; + } + std::cout << std::setw(3) << " ...,"; + for (std::size_t i = row_size - print_size; i < row_size; i++) + { + std::cout << std::setw(3) << matrix[i] << ((i != row_size - 1) ? "," : " ]\n"); + } + std::cout << " ["; + for (std::size_t i = row_size; i < row_size + print_size; i++) + { + std::cout << std::setw(3) << matrix[i] << ","; + } + std::cout << std::setw(3) << " ...,"; + for (std::size_t i = 2 * row_size - print_size; i < 2 * row_size; i++) + { + std::cout << std::setw(3) << matrix[i] << ((i != 2 * row_size - 1) ? "," : " ]\n"); + } + std::cout << std::endl; +} + +/* +Helper function: Print line number. +*/ +inline void print_line(int line_number) +{ + std::cout << "Line " << std::setw(3) << line_number << " --> "; +} diff --git a/bigpiseal3.5.1/native/examples/generic/CMakeLists.txt b/bigpiseal3.5.1/native/examples/generic/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3ad39fa3ed2b6b138fe8ebdf23b750297bfb5f64 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/CMakeLists.txt @@ -0,0 +1,114 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME generic) +set(GENKEY_BIN ${TEST_NAME}_genkey) +set(ENCR_BIN ${TEST_NAME}_encrypt) +set(DECR_BIN ${TEST_NAME}_decrypt) +set(EVAL_BIN ${TEST_NAME}_evaluate) +set(EVAL_BIN_MUL ${TEST_NAME}_evaluate_multiply) +set(EVAL_BIN_SUB ${TEST_NAME}_evaluate_sub) +set(SCR_ENC encrypt_gen.sh) +set(SCR_DEC decrypt_gen.sh) +set(SCR_GEN genkey_gen.sh) + + + + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/add.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + +set(EVAL_SRCS_SUB + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/sub.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate_sub.cpp + ) + +set(EVAL_SRCS_MUL + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/multiply.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate_multiply.cpp + ) + +set(HEADER_DIR ${CMAKE_SOURCE_DIR}/${TEST_NAME}) +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/add.h + ) + +add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +add_executable(${EVAL_BIN_SUB} ${EVAL_SRCS_SUB} ${HEADER_FILES}) +add_executable(${EVAL_BIN_MUL} ${EVAL_SRCS_MUL} ${HEADER_FILES}) + +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +# Link Microsoft SEAL +target_link_libraries(${GENKEY_BIN} SEAL::seal) +target_link_libraries(${ENCR_BIN} SEAL::seal) +target_link_libraries(${DECR_BIN} SEAL::seal) +target_link_libraries(${EVAL_BIN} SEAL::seal) +target_link_libraries(${EVAL_BIN_SUB} SEAL::seal) +target_link_libraries(${EVAL_BIN_MUL} SEAL::seal) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +set_target_properties(${GENKEY_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${ENCR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${DECR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${EVAL_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) + +set_target_properties(${EVAL_BIN_SUB} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) + + +set_target_properties(${EVAL_BIN_MUL} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}) + diff --git a/bigpiseal3.5.1/native/examples/generic/add.cpp b/bigpiseal3.5.1/native/examples/generic/add.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cce13421c37dff3a4f5efeec7198c93629c7351f --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/add.cpp @@ -0,0 +1,30 @@ +#include "add.h" + +using namespace std; +using namespace seal; + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, Plaintext &pt, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->add_plain(ct, pt, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic addition (pt+ct) time in (us): " << dt << endl; +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->add(ct1, ct2, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic addition (ct+ct) time in (us): " << dt << endl; +} diff --git a/bigpiseal3.5.1/native/examples/generic/add.h b/bigpiseal3.5.1/native/examples/generic/add.h new file mode 100644 index 0000000000000000000000000000000000000000..7730c057c6502b48c825d09c5af5d918ead71d4a --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/add.h @@ -0,0 +1,13 @@ +#ifndef _ADD_H_ +#define _ADD_H_ + +#include <sys/time.h> +#include <iostream> +#include <string> +#include "seal/seal.h" +#include "seal_api.h" + +void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct, seal::Plaintext &pt, seal::Ciphertext &ct_out); +void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct1, seal::Ciphertext &ct2, seal::Ciphertext &ct_out); + +#endif diff --git a/bigpiseal3.5.1/native/examples/generic/decrypt_gen.sh b/bigpiseal3.5.1/native/examples/generic/decrypt_gen.sh new file mode 100644 index 0000000000000000000000000000000000000000..5eb4db8c1f2aad426cacaf296346d49481f87079 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/decrypt_gen.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# +# 2020 CEA LIST. + +declare -r ERROR_NUMBER_PARAM=1 +declare -r ERROR_VALUE_PARAM=2 +declare -r ERROR_KEY_NOT_FOUND=3 +declare -r ERRROR_ENCRYPT_DECRYPT_NOT_PERFORMED=4 +declare -r ERROR_FILE_ZIP_NOT FOUND=5 +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# /opt/seal/native/bin +# /opt/pki/seal/ +# /opt/pki/seal/natives/examples/generic +# seal preparation executable seal_generic_decrypt +# code genéré pour 63bits signés. +# params +# 1 size_bit 1 63 +# 2 signed 0 unsigned 1 signed +# 3 path_to_key .pk +# 4 path_to_storage +# 5 prefix + +if [ "$#" -ne 5 ]; then + echo "You must enter exactly 5 command line arguments" + echo "size bit <1..63>, signed <0,1> , path to sk , path to storage, prefix " + exit 1 +fi + +# size bit 1 63 +case $1 in + ''|*[!0-9]*) echo only numeric size 1..63;; + *) echo numeric + if [ "$1" -ge 1 -a "$1" -le 63 ]; then echo "size input Ok" + else + echo echo "ERROR_SIZING VALUE " $1 ",size bit is 1..63" + exit 2 + fi + ;; +esac +size_bit=$1 +# signed 0 or 1 +case $2 in + ''|*[!0-1]*) echo bad only 0 or 1 for signed value; exit 2;; + *) echo Signed value OK;; +esac +signed=$2 + +# path to sk an key existence +# if not found error +path_to_key=$3 +# si $3 contient .sk à la fin, alors c'est correct sinon +# si cest directory alors ajouter bfv.sk a la fin +# si c'est un fichier, verifier l'existence + +if [[ "$path_to_key" == */ ]] +then + file="$path_to_key"bfv.sk +else + file="$path_to_key"/bfv.sk +fi + +if test -f "$file"; then + echo "$file exist" +else + echo " ERROR_KEY_NOT_FOUND " $3/bfv.sk " not found" $file + exit 3 +fi + + + + +# path to result +path_to_storage=$4 +if [[ "$path_to_storage" == */ ]] +then + file="$path_to_storage" +else + file="$path_to_storage"/ +fi + +prefix=$5 +if [ -d "$path_to_storage" ] +then + echo 1 +else + echo 3 + #~ extract_zip +fi + +${CURR_DIR}/generic_decrypt $prefix $path_to_key $path_to_storage +# ./generic_decrypt ct2 /home/bigpi/ storage/ +# recuperate result +if [ "$?" == "0" ]; then + echo ok done +else + echo DECRYPTION_NOT_PERFORMED + exit 4 +fi diff --git a/bigpiseal3.5.1/native/examples/generic/encrypt_gen.sh b/bigpiseal3.5.1/native/examples/generic/encrypt_gen.sh new file mode 100644 index 0000000000000000000000000000000000000000..f741c83519992fce3c5780fc95c0bd0916ff6333 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/encrypt_gen.sh @@ -0,0 +1,126 @@ +#!/bin/bash +# +# 2020 CEA LIST. +declare -r ERROR_NUMBER_PARAM=1 +declare -r ERROR_VALUE_PARAM=2 +declare -r ERROR_KEY_NOT_FOUND=3 +declare -r ERRROR_ENCRYPT_DECRYPT_NOT_PERFORMED=4 +declare -r ERROR_FILE_ZIP_NOTFOUND=5 +#/opt/seal/native/bin +# /opt/pki/seal/ +# /opt/pki/seal/natives/examples/generic +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +# params executable seal_generic_encrypt +# value +# size_bit 1 63 , limited to 63 bits Seal -ou 2-**63signed max=x value to test +# signed 0 unsigned 1 signed +# path_to_key existing key pk encrypt +# path_storage + + +if [ "$#" -ne 6 ]; then + echo "You must enter exactly 6 command line arguments" + # display help if empty + echo "value , size bit <1..63>, signed <0,1> , path to sk , path to storage, prefix " + exit $ERROR_NUMBER_PARAM +fi + +[ -n "$1" ] && [ "$1" -eq "$1" ] 2>/dev/null +if [ $? -ne 0 ]; then + echo $1 is not number + exit 2 +fi +[ -n "$2" ] && [ "$2" -eq "$2" ] 2>/dev/null +if [ $? -ne 0 ]; + then + echo $2 is not number + exit 2 + else + if [ "$2" -ge 1 -a "$2" -le 63 ]; + then echo "size input Ok" + else + echo "ERROR_SIZING VALUE " $2 ",size bit is 1..63" + exit 2 + fi +fi + + +value=$1 +size_bit=$2 + +case $3 in + ''|*[!0-1]*) echo bad signed value $3 , only 0 or 1; exit 2;; + *) echo Signed value OK;; +esac +Signed=$3 + + + + +path_to_key=$4 +if [[ "$path_to_key" == */ ]] +then + file="$path_to_key"bfv.pk +else + file="$path_to_key"/bfv.pk +fi + +if test -f "$file"; then + echo "$file exist" +else + echo "ERROR_KEY_NOT_FOUND " $4/bfv.pk" not found" + exit 3 +fi + + + +directory=$5 +if [ -d "$directory" ] +then + echo "OK" +else + echo " Path to storage directory " $5 " not found" + mkdir $directory + # + echo " path to storage created" + +fi + + +path_storage=$5 +prefix=$6 + +defaut_coherence_test_value_sizebit_seal() +{ + # define max value equal 2*2 ..*2 size_bit time + ((X=(2**$size_bit)-1)); echo "max value" $X + ((Y=(2**63)-1)); echo "max value 2**63 -1" $Y +# let "maxvalue=1" +# for i in $(seq $1 $size_bit) +# do +# let "maxvalue=maxvalue*2" +# done + if [ "$value" -gt "$Y" ]; then + echo " value to high or equal", $value, " to max value" $Y + exit 2 + fi +} + + + +defaut_coherence_test_value_sizebit_seal + +# encryption +echo "encryption" +${CURR_DIR}/generic_encrypt $value $prefix $path_to_key $path_storage +# recuperate result +if [ "$?" == "0" ]; then + echo ok done +else + echo ENCRYPTION_NOT_PERFORMED + exit 4 +fi + + + +exit diff --git a/bigpiseal3.5.1/native/examples/generic/generic_decrypt.cpp b/bigpiseal3.5.1/native/examples/generic/generic_decrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..529bbd711ee92c3acb4e529822d4325d6d96be64 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_decrypt.cpp @@ -0,0 +1,71 @@ +#include <sys/time.h> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + if(argc != 4) + cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; +// ./_decrypt prefix_name ct3 /home/bigpi/ storage/ + else { + timeval t0, t1; + unsigned long dt = 0; + struct decryptor_t decr; + string pathK = argv[2]; + string Ctfile = argv[1]; + string prefix(""); + if (suffix_exist(pathK, "/")) + { + prefix.append(pathK); + } + else + { + prefix.append(pathK); + prefix.append("/"); + } + + //cout << "[INFO] Keypathname sk: " << prefix << endl; + init_operator(8192, 4294967296, decr,prefix); + + + // path to storage argv[3] + string pathStorage = argv[3]; + prefix=""; + if (suffix_exist(pathStorage, "/")) + { + prefix.append(pathStorage); + } + else + { + prefix.append(pathStorage); + prefix.append("/"); + } + + //cout << "[INFO] Ctx de " << prefix << endl; + + + Ciphertext ct; + + if (Ctfile.at(0) == '/') + load_ciphertext(decr, ct, Ctfile); + else { + prefix.append(Ctfile); + load_ciphertext(decr, ct, prefix); + } + gettimeofday(&t0, NULL); + load_ciphertext(decr, ct, prefix); + + + gettimeofday(&t0, NULL); + decrypt_ciphertext(decr, ct); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] ciphertext decryption time in seconds: " << ((float)dt)/1000000 << endl; + + delete_operator(decr); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/generic/generic_encrypt.cpp b/bigpiseal3.5.1/native/examples/generic/generic_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7787305d267122233438899c3c6be04c9c3fd0ea --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_encrypt.cpp @@ -0,0 +1,68 @@ +#include <cstdint> +#include <sys/time.h> +#include <boost/lexical_cast.hpp> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + if(argc != 5) + cerr << "[ERROR] please enter 1 plaintext values, prefix , pathstorage(exists) " << endl; +// ./generic_encrypt 21 ct1 /home/bigpi/ storage/ + + else { + timeval t0, t1; + unsigned long dt = 0; + struct encryptor_t encr; + string pathK = argv[3]; + string Prefix = argv[2]; + string pathStorage = argv[4]; + //cout << "[INFO] Prefix . : " << Prefix << endl; + string prefix(""); + //string postfix1(".ct"); + prefix=""; + if (suffix_exist(pathK, "/")) + { + prefix.append(pathK); + } + else + { + prefix.append(pathK); + prefix.append("/"); + } + init_operator(8192, 4294967296, encr,prefix); + + Ciphertext ct; + + int64_t plain = boost::lexical_cast<int64_t>(argv[1]); + gettimeofday(&t0, NULL); + init_ciphertext(encr, plain, ct); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] plaintext encryption time in seconds: " << ((float)dt)/1000000 << endl; + prefix=""; + if (suffix_exist(pathStorage, "/")) + { + prefix.append(pathStorage); + } + else + { + prefix.append(pathStorage); + prefix.append("/"); + } + prefix.append(Prefix); + prefix.append(".ct"); + //cout << "[INFO] suffix .ct : " << prefix << endl; + save_ciphertext(ct, prefix); + + //~ plain = boost::lexical_cast<int64_t>(argv[2]); + //~ init_ciphertext(encr, plain, ct); + //~ save_ciphertext(ct, "ct2.ct"); + + delete_operator(encr); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/generic/generic_evaluate.cpp b/bigpiseal3.5.1/native/examples/generic/generic_evaluate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..937560d5dc8335cbaa86910359e55338a874c113 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_evaluate.cpp @@ -0,0 +1,63 @@ +#include <sys/stat.h> +#include "add.h" + +using namespace std; +using namespace seal; + +inline bool exists_file (const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +int main(int argc, char **argv) +{ + if(argc != 5) { + cout << "[ERROR] please enter 3 ciphertext /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct full/path/to/publickey" << endl; + // ../generic_evaluate /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct /home/bigpi/path/to/pubKey + return EXIT_FAILURE; + } + else { + struct evaluator_t eval; + string Ct1 = argv[1]; + string Ct2 = argv[2]; + string Ct3 = argv[3]; + string pathK1 = argv[4]; + string pathK =""; + + if (exists_file(Ct1) == false || exists_file(Ct2) == false) + { + cout << "[ERROR] please enter 2 first ciphertext input /path/to/ct1.ct /path/to/ct2.ct" << endl; + return EXIT_FAILURE; + } + +/* if (suffix_exist(Ct3, "/") == false) { + cout << "[ERROR] please enter 3rd parameter /path/to/result/name.ct/you/wish" << endl; + return EXIT_FAILURE; + } */ + + + if (suffix_exist(pathK1, "/")) + { + pathK =pathK1; + } + else + { + pathK .append(pathK1); + pathK .append("/"); + } + + init_operator(2048, 256, eval,pathK); + + Ciphertext ct1, ct2, ct3; + string prefix(""); + load_ciphertext(eval, ct1, Ct1); + load_ciphertext(eval, ct2, Ct2); + add_ciphertext(eval, ct1, ct2, ct3); + + save_ciphertext(ct3, Ct3); + + delete_operator(eval); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/generic/generic_evaluate_multiply.cpp b/bigpiseal3.5.1/native/examples/generic/generic_evaluate_multiply.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f6d3d64db73a2b41bc71f1805ea53c88841f653 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_evaluate_multiply.cpp @@ -0,0 +1,65 @@ +#include <sys/stat.h> +#include "multiply.h" + +using namespace std; +using namespace seal; + +inline bool exists_file (const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +int main(int argc, char **argv) +{ + if(argc != 5) { + cout << "ct1.ct x ct2.ct = ct3.ct" << endl; + cout << "[ERROR] please enter 3 ciphertext /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct full/path/to/publickey" << endl; + // ../generic_evaluate /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct /home/bigpi/path/to/pubKey + return EXIT_FAILURE; + } + + struct evaluator_t eval; + string Ct1 = argv[1]; + string Ct2 = argv[2]; + string Ct3 = argv[3]; + string pathK1 = argv[4]; + string pathK =""; + + if (exists_file(Ct1) == false || exists_file(Ct2) == false) + { + cout << "[ERROR] please enter 2 first ciphertext input /path/to/ct1.ct /path/to/ct2.ct" << endl; + return EXIT_FAILURE; + } + +/* if (suffix_exist(Ct3, "/") == false) { +cout << "[ERROR] please enter 3rd parameter /path/to/result/name.ct/you/wish" << endl; + return EXIT_FAILURE; + } */ + + + if (suffix_exist(pathK1, "/")) + { + pathK =pathK1; + } + else + { + pathK .append(pathK1); + pathK .append("/"); + } + + init_operator(2048, 256, eval,pathK); + + Ciphertext ct1, ct2, ct3; + string prefix(""); + load_ciphertext(eval, ct1, Ct1); + load_ciphertext(eval, ct2, Ct2); + multiply_ciphertext(eval, ct1, ct2, ct3); + + save_ciphertext(ct3, Ct3); + + delete_operator(eval); + return 0; +} + + + diff --git a/bigpiseal3.5.1/native/examples/generic/generic_evaluate_sub.cpp b/bigpiseal3.5.1/native/examples/generic/generic_evaluate_sub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..085aed3ed9a3c77a72280924ccf506e0e2a665a3 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_evaluate_sub.cpp @@ -0,0 +1,63 @@ +#include <sys/stat.h> +#include "sub.h" + +using namespace std; +using namespace seal; + +inline bool exists_file (const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +int main(int argc, char **argv) +{ + if(argc != 5) { + cout << "ct1.ct - ct2.ct = ct3.ct" << endl; + cout << "[ERROR] please enter 3 ciphertext /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct full/path/to/publickey" << endl; + // ../generic_evaluate /path/to/ct1.ct /path/to/ct2.ct /path/to/result.ct /home/bigpi/path/to/pubKey + return EXIT_FAILURE; + } + + struct evaluator_t eval; + string Ct1 = argv[1]; + string Ct2 = argv[2]; + string Ct3 = argv[3]; + string pathK1 = argv[4]; + string pathK =""; + + if (exists_file(Ct1) == false || exists_file(Ct2) == false) + { + cout << "[ERROR] please enter 2 first ciphertext input /path/to/ct1.ct /path/to/ct2.ct" << endl; + return EXIT_FAILURE; + } + +/* if (suffix_exist(Ct3, "/") == false) { +cout << "[ERROR] please enter 3rd parameter /path/to/result/name.ct/you/wish" << endl; + return EXIT_FAILURE; + } */ + + + if (suffix_exist(pathK1, "/")) + { + pathK =pathK1; + } + else + { + pathK .append(pathK1); + pathK .append("/"); + } + + init_operator(2048, 256, eval,pathK); + + Ciphertext ct1, ct2, ct3; + string prefix(""); + load_ciphertext(eval, ct1, Ct1); + load_ciphertext(eval, ct2, Ct2); + sub_ciphertext(eval, ct1, ct2, ct3); + + save_ciphertext(ct3, Ct3); + + delete_operator(eval); + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/generic/generic_genkey.cpp b/bigpiseal3.5.1/native/examples/generic/generic_genkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..239813293e92f02e2c400e155c0b902bceb16978 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/generic_genkey.cpp @@ -0,0 +1,23 @@ +#include <sys/time.h> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + timeval t0, t1; + unsigned long dt = 0; + // gen keys § path to sk + string pathSk = argv[1]; + + gettimeofday(&t0, NULL); + generate_keys(8192, 4294967296,pathSk, true); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/generic/genkey_gen.sh b/bigpiseal3.5.1/native/examples/generic/genkey_gen.sh new file mode 100644 index 0000000000000000000000000000000000000000..0f579888082797c30bf1db7293adf34135daf7ae --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/genkey_gen.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# 2020 CEA LIST. +declare -r ERROR_NUMBER_PARAM=1 +declare -r ERROR_KEY_NOT_FOUND=3 +declare -r KEYGEN_NOT_PERFORMED=4 +#/opt/seal/native/bin +# /opt/pki/seal/ +# /opt/pki/seal/natives/examples/generic +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +# params executable seal_generic_encrypt +# value +# path_to_key existing key pk encrypt + +if [ "$#" -ne 1 ]; then + echo "You must enter exactly 1 command line arguments" + # display help if empty + echo " path to sk , " + exit $ERROR_NUMBER_PARAM +fi + + +path_to_key=$1 + +# encryption +echo "key generation" +${CURR_DIR}/generic_genkey $path_to_key +# recuperate result +if [ "$?" == "0" ]; then + echo ok done +else + echo KEYGEN_NOT_PERFORMED + exit 4 +fi + +exit diff --git a/bigpiseal3.5.1/native/examples/generic/multiply.cpp b/bigpiseal3.5.1/native/examples/generic/multiply.cpp new file mode 100644 index 0000000000000000000000000000000000000000..884dd65539943dbb845373dc2113ce3097b8665c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/multiply.cpp @@ -0,0 +1,30 @@ +#include "multiply.h" + +using namespace std; +using namespace seal; + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, Plaintext &pt, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->multiply_plain(ct, pt, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic multiplication (pt*ct) time in (us): " << dt << endl; +} + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->multiply(ct1, ct2, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic multiplication (ct*ct) time in (us): " << dt << endl; +} diff --git a/bigpiseal3.5.1/native/examples/generic/multiply.h b/bigpiseal3.5.1/native/examples/generic/multiply.h new file mode 100644 index 0000000000000000000000000000000000000000..35d1fe5b0106aa4644b2274cb9c9cfb8506fe928 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/multiply.h @@ -0,0 +1,13 @@ +#ifndef _MULT_H_ +#define _MULT_H_ + +#include <sys/time.h> +#include <iostream> +#include <string> +#include "seal/seal.h" +#include "seal_api.h" + +void multiply_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct, seal::Plaintext &pt, seal::Ciphertext &ct_out); +void multiply_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct1, seal::Ciphertext &ct2, seal::Ciphertext &ct_out); + +#endif diff --git a/bigpiseal3.5.1/native/examples/generic/seal_api.cpp b/bigpiseal3.5.1/native/examples/generic/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c73afaed79cf8123b085ed9f44624375cda44692 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/seal_api.cpp @@ -0,0 +1,453 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR06] file opening failure" << filename << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR07] file opening failure" << filename << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context,const std::string& pathname) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + //ruf + //cout << "[INFO] save bfvparams: " << pathname<< endl; + + save_params(params, pathname); + + context = SEALContext::Create(params); + print_context(context); +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext>& context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + cout << "[CONTEXT] scheme: " << scheme_name << endl; + cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + /* Print the size of the true (product) coefficient modulus */ + cout << "[CONTEXT] coeff_modulus size: "; + cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + cout << coeff_modulus[i].bit_count() << " + "; + cout << coeff_modulus.back().bit_count(); + cout << ") bits" << endl; + + std::cout << "[CONTEXT] coeff_modulus values: (" ; + for(int i = 0; i < (coeff_modulus.size() - 1); ++i) + cout << coeff_modulus[i].value() << ",\t"; + cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + + /* For the BFV scheme print the plain_modulus parameter */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR 00] File opening failure " << filename << endl; + exit(1) ; + ret = 0; + } + else + k.save(out_file); + + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR 01] File opening failure " << filename << endl; + exit(1) ; + ret = 0; + } + else + k.save(out_file); + + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR 02] File opening failure " << filename << endl; + exit(1) ; + ret = 0; + } + else + k.save(out_file); +} + + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 0; + ifstream in_file(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR 03] File opening failure " << filename << endl; + exit(1) ; + ret = 0; + } + else + k.load(context, in_file); + + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR 04] File opening failure " << filename << endl; + ret = 0; + } + else + k.load(context, in_file); + + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR 05] File opening failure"<< filename << endl; + ret = 0; + } + else + k.load(context, in_file); + + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, const std::string& pathname, bool serializable ) +//void generate_keys(size_t poly_d, size_t p_modulus, bool serializable ,const std::string& pathname) +{ + shared_ptr<SEALContext> context; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + + if (suffix_exist(pathname, "/")) + { + keypath1="bfv.pk"; + keypath2="bfv.sk"; + keypath3="bfv.lk"; + bfv_params_path1="bfv_params.conf"; + } + bfv_params_path=""; + bfv_params_path.append(pathname); + bfv_params_path.append(bfv_params_path1); + + init_context(poly_d, p_modulus, context,bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(pathname); + keypath.append(keypath1); + + //cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath ); + + keypath=""; + keypath.append(pathname); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + //cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath=""; + keypath.append(pathname); + keypath.append(keypath3); + //cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } +} + +void init_operator(size_t poly_d, size_t p_modulus, struct encryptor_t &op_st,const std::string& pathname) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path=""; + bfv_params_path.append(pathname); + bfv_params_path.append(bfv_params_path1); + //cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + PublicKey pk; + string keypath(""); + string keypath1("bfv.pk"); + keypath.append(pathname); + keypath.append(keypath1); + //cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void init_operator(size_t poly_d, size_t p_modulus, struct decryptor_t &op_st,const std::string& pathname) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path=""; + bfv_params_path.append(pathname); + bfv_params_path.append(bfv_params_path1); + cout << "[INFO] bfvparams: " << bfv_params_path << endl; + + load_context(op_st.context, bfv_params_path); + SecretKey sk; + string keypath(""); + string keypath1("bfv.sk"); + + keypath.append(pathname); + keypath.append(keypath1); + cout << "[INFO] Keypath decrypt: " << keypath << endl; + + load_key(op_st.context, keypath, sk); + + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void init_operator(size_t poly_d, size_t p_modulus, struct evaluator_t &op_st,const std::string& pathname) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path=""; + bfv_params_path.append(pathname); + bfv_params_path.append(bfv_params_path1); + cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + string keypath(""); + string keypath1("bfv.lk"); + keypath.append(pathname); + keypath.append(keypath1); + cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + cout << "[INFO] Encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + cout << plain << endl; +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + cout << "[INFO] Decrypted result: " << res << endl; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR1 File opening failure " << filename<< endl; + ret = 0; + } + else + pt.save(out_file); + + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR2] File opening failure " << filename << endl; + ret = 0; + } + else + ct.save(out_file); + + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR3] File opening failure " << filename << endl; + ret = 0; + } + else + pt.load(context, in_file); + + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR4] File opening failure " << filename << endl; + exit(1); + ret = 0; + } + else + ct.load(context, in_file); + ret=0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + + + +bool suffix_exist(const std::string &str, const std::string &suffix) +{ + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} diff --git a/bigpiseal3.5.1/native/examples/generic/seal_api.h b/bigpiseal3.5.1/native/examples/generic/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..22920cd140348026cd2c6aaf6fe25955a0509a99 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/seal_api.h @@ -0,0 +1,79 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" + +/* definitions */ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::Evaluator *eval; +}; + +/* prototypes */ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context,const std::string& pathname); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename,const std::string& pathname); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::Serializable<seal::RelinKeys>& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); + +void init_operator(size_t poly_d, size_t p_modulus, struct encryptor_t& op_st,const std::string& pathname); +void init_operator(size_t poly_d, size_t p_modulus, struct decryptor_t& op_st,const std::string& pathname); +void init_operator(size_t poly_d, size_t p_modulus, struct evaluator_t& op_st,const std::string& pathname); +void delete_operator(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); +//void generate_keys(size_t poly_d, size_t p_modulus, bool serializable = false ,const std::string& pathname); +void generate_keys(size_t poly_d, size_t p_modulus,const std::string& pathname, bool seriablizable = false); +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); +bool suffix_exist(const std::string &str, const std::string &suffix) ; +#endif diff --git a/bigpiseal3.5.1/native/examples/generic/sub.cpp b/bigpiseal3.5.1/native/examples/generic/sub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d030b7c1a21edfa29dc675b64530a5f8efd701f9 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/sub.cpp @@ -0,0 +1,30 @@ +#include "sub.h" + +using namespace std; +using namespace seal; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, Plaintext &pt, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->sub_plain(ct, pt, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic subtraction (pt+ct) time in (us): " << dt << endl; +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + op_st.eval->sub(ct1, ct2, ct_out); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] Homomorphic subtraction (ct+ct) time in (us): " << dt << endl; +} diff --git a/bigpiseal3.5.1/native/examples/generic/sub.h b/bigpiseal3.5.1/native/examples/generic/sub.h new file mode 100644 index 0000000000000000000000000000000000000000..a462532d5135bc1b9ac145cf2ec9c86f97aa8768 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/generic/sub.h @@ -0,0 +1,13 @@ +#ifndef _SUB_H_ +#define _SUB_H_ + +#include <sys/time.h> +#include <iostream> +#include <string> +#include "seal/seal.h" +#include "seal_api.h" + +void sub_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct, seal::Plaintext &pt, seal::Ciphertext &ct_out); +void sub_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct1, seal::Ciphertext &ct2, seal::Ciphertext &ct_out); + +#endif diff --git a/bigpiseal3.5.1/native/examples/hello/CMakeLists.txt b/bigpiseal3.5.1/native/examples/hello/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..50bc363859105b43d1a8d7ee406939edc4dd9575 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME hello) +set(GENKEY_BIN ${TEST_NAME}_genkey) +set(ENCR_BIN ${TEST_NAME}_encrypt) +set(DECR_BIN ${TEST_NAME}_decrypt) +set(EVAL_BIN ${TEST_NAME}_evaluate) + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/add.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/add.h + ) + +add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +# Link Microsoft SEAL +target_link_libraries(${GENKEY_BIN} SEAL::seal) +target_link_libraries(${ENCR_BIN} SEAL::seal) +target_link_libraries(${DECR_BIN} SEAL::seal) +target_link_libraries(${EVAL_BIN} SEAL::seal) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +set_target_properties(${GENKEY_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${ENCR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${DECR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) +set_target_properties(${EVAL_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" + ) diff --git a/bigpiseal3.5.1/native/examples/hello/add.cpp b/bigpiseal3.5.1/native/examples/hello/add.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08746987105ed286fff228d02f5ab3aeaec3f1d5 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/add.cpp @@ -0,0 +1,14 @@ +#include "add.h" + +using namespace std; +using namespace seal; + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, Plaintext &pt, Ciphertext &ct_out) +{ + op_st.eval->add_plain(ct, pt, ct_out); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} diff --git a/bigpiseal3.5.1/native/examples/hello/add.h b/bigpiseal3.5.1/native/examples/hello/add.h new file mode 100644 index 0000000000000000000000000000000000000000..6641afabdb6d05ba0d9496a6b1e55d39531d9ed2 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/add.h @@ -0,0 +1,12 @@ +#ifndef _ADD_H_ +#define _ADD_H_ + +#include <iostream> +#include <string> +#include "seal/seal.h" +#include "seal_api.h" + +void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct, seal::Plaintext &pt, seal::Ciphertext &ct_out); +void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct1, seal::Ciphertext &ct2, seal::Ciphertext &ct_out); + +#endif diff --git a/bigpiseal3.5.1/native/examples/hello/hello_decrypt.cpp b/bigpiseal3.5.1/native/examples/hello/hello_decrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f301b14d8915f9ff0238b71984403cdd7a95906 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/hello_decrypt.cpp @@ -0,0 +1,36 @@ +#include <sys/time.h> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + if(argc != 2) + cout << "[ERROR] please enter a ciphertext file" << endl; + else { + timeval t0, t1; + unsigned long dt = 0; + struct decryptor_t decr; + + init_operator(8192, 4294967296, decr); + + Ciphertext ct; + + gettimeofday(&t0, NULL); + load_ciphertext(decr, ct, argv[1]); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] ciphertext loading time in seconds: " << ((float)dt)/1000000 << endl; + + gettimeofday(&t0, NULL); + decrypt_ciphertext(decr, ct); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] ciphertext decryption time in seconds: " << ((float)dt)/1000000 << endl; + + delete_operator(decr); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/hello/hello_encrypt.cpp b/bigpiseal3.5.1/native/examples/hello/hello_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..691aa3a3c9665a73c6f22d5d8cf8490c61193ea5 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/hello_encrypt.cpp @@ -0,0 +1,38 @@ +#include <cstdint> +#include <sys/time.h> +#include <boost/lexical_cast.hpp> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + if(argc != 3) + cout << "[ERROR] please enter 2 plaintext values" << endl; + else { + timeval t0, t1; + unsigned long dt = 0; + struct encryptor_t encr; + + init_operator(8192, 4294967296, encr); + + Ciphertext ct; + + int64_t plain = boost::lexical_cast<int64_t>(argv[1]); + gettimeofday(&t0, NULL); + init_ciphertext(encr, plain, ct); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] plaintext encryption time in seconds: " << ((float)dt)/1000000 << endl; + save_ciphertext(ct, "ct1.ct"); + + plain = boost::lexical_cast<int64_t>(argv[2]); + init_ciphertext(encr, plain, ct); + save_ciphertext(ct, "ct2.ct"); + + delete_operator(encr); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/hello/hello_evaluate.cpp b/bigpiseal3.5.1/native/examples/hello/hello_evaluate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2739e2b9a63138dea0c2991027d28390aa2fcfef --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/hello_evaluate.cpp @@ -0,0 +1,39 @@ +#include <sys/time.h> +#include "add.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + if(argc != 3) + cout << "[ERROR] please enter 2 ciphertext files" << endl; + else { + timeval t0, t1; + unsigned long dt = 0; + struct evaluator_t eval; + + init_operator(8192, 4294967296, eval); + + Ciphertext ct1, ct2, ct3; + cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, "ct1.ct"); + + cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, "ct2.ct"); + + cout << "[INFO] adding ciphertext 1 to ciphertext 2" << endl; + gettimeofday(&t0, NULL); + add_ciphertext(eval, ct1, ct2, ct3); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + cout << "[INFO] homomorphic addition time in seconds: " << ((float)dt)/1000000 << endl; + + cout << "[INFO] saving ciphertext addition to a new ciphertext file" << endl; + save_ciphertext(ct3, "ct3.ct"); + + delete_operator(eval); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/hello/hello_genkey.cpp b/bigpiseal3.5.1/native/examples/hello/hello_genkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c383b11fb7cebe8a2c7f4847bdc79c4d2ee89b2 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/hello_genkey.cpp @@ -0,0 +1,20 @@ +#include <sys/time.h> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + timeval t0, t1; + unsigned long dt = 0; + + gettimeofday(&t0, NULL); + generate_keys(8192, 4294967296, true); + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/hello/seal_api.cpp b/bigpiseal3.5.1/native/examples/hello/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13f862737cf653dde4dc2910d308a0c67d85224b --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/seal_api.cpp @@ -0,0 +1,339 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, std::ios::binary); + if(!in_file) { + cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, std::ios::binary); + if(!out_file) { + cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + + save_params(params, "bfv_params.conf"); + + context = SEALContext::Create(params); + print_context(context); +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext>& context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + cout << "[CONTEXT] scheme: " << scheme_name << endl; + cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + /* Print the size of the true (product) coefficient modulus */ + cout << "[CONTEXT] coeff_modulus size: "; + cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + cout << coeff_modulus[i].bit_count() << " + "; + cout << coeff_modulus.back().bit_count(); + cout << ") bits" << endl; + + std::cout << "[CONTEXT] coeff_modulus values: (" ; + for(int i = 0; i < (coeff_modulus.size() - 1); ++i) + cout << coeff_modulus[i].value() << ",\t"; + cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + + /* For the BFV scheme print the plain_modulus parameter */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, bool serializable) +{ + shared_ptr<SEALContext> context; + init_context(poly_d, p_modulus, context); + + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + save_key(pk, "bfv.pk"); + SecretKey sk = keygen.secret_key(); + save_key(sk, "bfv.sk"); + if (serializable) { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, "bfv.lk"); + } + else { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, "bfv.lk"); + } +} + +void init_operator(size_t poly_d, size_t p_modulus, struct encryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + PublicKey pk; + load_key(op_st.context, "bfv.pk", pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void init_operator(size_t poly_d, size_t p_modulus, struct decryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + SecretKey sk; + load_key(op_st.context, "bfv.sk", sk); + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void init_operator(size_t poly_d, size_t p_modulus, struct evaluator_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, "bfv.lk", op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + cout << "[INFO] encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + cout << plain << endl; +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + cout << "[INFO] decrypted result: " << res << endl; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + pt.save(out_file); + else + ret = 0; + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file; + if(open_binary_file(out_file, filename)) + ct.save(out_file); + else + ret = 0; + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + pt.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file; + if(open_binary_file(in_file, filename)) + ct.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} diff --git a/bigpiseal3.5.1/native/examples/hello/seal_api.h b/bigpiseal3.5.1/native/examples/hello/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..79acf89fbcc99c2c302d8c12c5b6f777bd80c982 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/hello/seal_api.h @@ -0,0 +1,80 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" + +/* definitions */ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::Evaluator *eval; +}; + +/* prototypes */ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::Serializable<seal::RelinKeys>& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); +void generate_keys(size_t poly_d, size_t p_modulus, bool seriablizable = false); + +/** for homomorphic operators management **/ +void init_operator(size_t poly_d, size_t p_modulus, struct encryptor_t& op_st); +void init_operator(size_t poly_d, size_t p_modulus, struct decryptor_t& op_st); +void init_operator(size_t poly_d, size_t p_modulus, struct evaluator_t& op_st); +void delete_operator(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); + +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + +#endif diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/CMakeLists.txt b/bigpiseal3.5.1/native/examples/patternSearch/v1/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef0995da8f93efe05f0f5b79ce68d8aab2cf5570 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/CMakeLists.txt @@ -0,0 +1,97 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME patternSearch) +set(GENKEY_BIN ${TEST_NAME}_genkey) +set(ENCR_BIN ${TEST_NAME}_encrypt) +set(DECR_BIN ${TEST_NAME}_decrypt) +set(EVAL_BIN ${TEST_NAME}_evaluate) +set(SCR_TEST test.sh) + +set(SCR_ENC encrypt.sh) +set(SCR_DEC decrypt.sh) +set(SCR_DEC_RESULT decrypt_result.sh) +set(SCR_EVAL eval.sh) +set(SCR_GEN genkey.sh) + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + + + +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/util.h + ) + +add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +# Link Microsoft SEAL +target_link_libraries(${GENKEY_BIN} SEAL::seal) +target_link_libraries(${ENCR_BIN} SEAL::seal) +target_link_libraries(${DECR_BIN} SEAL::seal) +target_link_libraries(${EVAL_BIN} SEAL::seal) + + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +set_target_properties(${GENKEY_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${ENCR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${DECR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${EVAL_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) + + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC_RESULT} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_EVAL} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST_V2} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..ba531fda676f69823f0f735a5a7fea4a146c73da --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt.sh @@ -0,0 +1,12 @@ +#decrypt +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt_result.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..cb087cd12eb2612b8f5621260ef74d744962e6cf --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/decrypt_result.sh @@ -0,0 +1,12 @@ +#decrypt result +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/encrypt.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/encrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..5ab0992d0767facfa1a00d579622289675a47fd3 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/encrypt.sh @@ -0,0 +1,16 @@ +#encrypt +licenseNo=$1 +# ex: "23 65 78 127 255" (en ASCII) +filename=$2 +# ex: "l" (extension will be .ct) +outputDir=$3 +# ex: lcheck/ +sample=$4 +# ex: 40 +keyDir=$5 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/eval.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/eval.sh new file mode 100644 index 0000000000000000000000000000000000000000..72138f16eff3fb911a7b5a9eaeb9a6462c9d0f0c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/eval.sh @@ -0,0 +1,30 @@ +# evaluate +licensePath=$1 +# ex: lcheck/l.ct +licensePathList=${@: 2:$#-5} +# licensePathList="${@:2:102}" +# for var in "${@: 2:$#-7}" +# do +# echo "$var" +# done +# ex: parent/l0/l.ct parent/l1/l.ct parent/l2/l.ct parent/l3/l.ct parent/l4/l.ct parent/l5/l.ct parent/l6/l.ct parent/l7/l.ct parent/l8/l.ct parent/l9/l.ct +filename=${@: -4:1} +# ex: "l" (extension will be .ct) +outputDir=${@: -3:1} +# ex: result/ +sample=${@: -2:1} +# ex: 40 +KeyDir=${@: -1} +# ex: keys/ +# linkingKeyPath=${@: -3:1} +# # ex: bfv.lk +# galoisKeyPath=${@: -2:1} +# # ex: bfv.gk +# publicKeyPath=${@: -1} +# # ex: bfv.pk + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$linkingKeyPath" "$galoisKeyPath" "$publicKeyPath" +# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" +time ${CURR_DIR}/patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/genkey.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/genkey.sh new file mode 100644 index 0000000000000000000000000000000000000000..1691c61844aa7935f256b4d49495131983128a6c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/genkey.sh @@ -0,0 +1,8 @@ +#gen key +keyDir=$1 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_genkey_v2 "$keyDir" +time ${CURR_DIR}/patternSearch_genkey_v2 "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_decrypt.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_decrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36de6dc73b9eec4f08c54a9ea9add04461d7b8ef --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_decrypt.cpp @@ -0,0 +1,133 @@ +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string secret_key_path; + +string decrypt(string &ciphertext_dir); +bool decrypt_vector(string &ciphertext_dir); +string decrypt_vectors(string &parent_dir); +bool decrypt_isContain(string &result); + +int main(int argc, char **argv) +{ + if (argc != 3) + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + // cout << "[ERROR] please enter a ciphertext name, ciphertext directory and secret key path" << endl; + cout << "[ERROR] please enter a ciphertext file path and secret key path" << endl; + else + { + string dir = argv[1]; + secret_key_path = argv[2]; + + string result_str = decrypt(dir); + // cout << result_str << endl; + bool result = decrypt_isContain(result_str); + cout << result << endl; + + return 0; + } +} + +bool decrypt_isContain(string &result) +{ + long result_l = atol(result.c_str()); + if (result_l == 0) + { + // cout << "true"; + return true; + } + else + { + // cout << "false"; + return false; + } +} + +string decrypt(string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator(decr, secret_key_path); + Ciphertext ct; + string str; + load_ciphertext(decr, ct, ciphertext_dir); + str = to_string(decrypt_ciphertext_and_return_value(decr, ct)); + // decrypt_ciphertext(decr, ct); + delete_operator(decr); + return str; +} + +// Used for dynamic search +// string decrypt_vectors(string &parent_dir) +// { +// vector<string> directories = get_directories(parent_dir); +// string path_result = ""; +// bool result; +// for (const auto &entry : directories) +// { +// string ciphertext_dir = entry + "/"; +// cout << ciphertext_dir << endl; +// result = decrypt_vector(ciphertext_dir); +// if (result == true) +// { +// path_result = ciphertext_dir; +// break; +// } +// } +// return path_result; +// } + +// Used for dynamic search +// bool decrypt_vector(string &ciphertext_dir) +// { +// int nFiles = findNumberOfFilesInDirectory(ciphertext_dir); + +// struct decryptor_t decr; +// init_operator(2048, 256, decr, secret_key_path); + +// Ciphertext ct; +// string plaintext; +// stringstream ss; +// for (int index = 0; index <= nFiles - 1; index++) +// { +// load_ciphertext(decr, ct, ciphertext_dir + "/" + ciphertext_name + "_" + to_string(index) + ".ct"); +// plaintext = decrypt_ciphertext_and_return_string(decr, ct); + +// if (index == nFiles - 1) +// { +// ss << plaintext; +// } +// else +// { +// ss << plaintext << " "; +// } +// } +// // cout << to_string(ss.str().size()); +// // cout << ss.str() << endl; +// int x; +// int index = 0; +// bool result = false; +// while (ss >> x) +// { +// if (x == 0) +// { +// result = true; +// } +// else +// { +// result = false; +// break; +// } +// index++; +// } +// // if (index > 0 && result == true) +// // { +// // cout << "true" << endl; +// // } +// delete_operator(decr); +// return result; +// } diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea64476057c15609e587319e251a9388a351748d --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt.cpp @@ -0,0 +1,43 @@ +#include "seal_api.h" + +using namespace seal; +using namespace std; + +int main(int argc, char **argv) +{ + if(argc != 5) + // cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl; + // cout << "[ERROR] please enter plaintext value (eg. 75 67 8 23 076 2 23), public key path, ciphertext output directory and ciphertext output file name" << endl; + cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or prefix, public key path and ciphertext output file directory" << endl; + else { + string plaintext = argv[1]; + string ciphertext_name = argv[2]; + + string public_key_path = argv[3]; + string ciphertext_dir = argv[4]; + + // cout << plaintext << endl; + + struct encryptor_t encr; + // init_operator(2048, 256, encr, public_key_path); + init_operator(encr, public_key_path); + + stringstream ss; + ss << plaintext; + + int64_t x = 0; + int index = 0; + Ciphertext ct; + while (ss >> x) + { + /* Encrypt */ + init_ciphertext(encr, x, ct); + save_ciphertext(ct, ciphertext_dir + "/" + ciphertext_name + "_" + to_string(index) + ".ct"); + index++; + } + + delete_operator(encr); + + return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt_dev.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt_dev.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d996b84c6b3003990db9de7d0c337881b52ac88 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_encrypt_dev.cpp @@ -0,0 +1,58 @@ +#include "seal_api.h" + +using namespace seal; +using namespace std; + + +int main(int argc, char **argv) +{ + if (argc != 6) + { + // cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl; + cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or " + "prefix, ciphertext output file directory, sample size and public key path" + << endl; + return -1; + } + else + { + string plaintext = argv[1]; + string ciphertext_name = argv[2]; + string ciphertext_dir = argv[3]; + int sample_size = atol(argv[4]); + string key_dir = argv[5]; + + struct encryptor_t encr; + // init_operator_batching(2048, 4294967296, encr, public_key_path); + // init_operator_batching(4096, 4294967296, encr, public_key_path); + init_operator_batching(4096, 4294967296, encr, key_dir); + // init_operator_batching(16384, 4294967296, encr, public_key_path); + // init_operator_batching(32768, 4294967296, encr, public_key_path); + + stringstream ss; + ss << plaintext; + vector<int64_t> pod_matrix; + int64_t x = 0; + + while (ss >> x) + { + pod_matrix.push_back(x); + } + + if (pod_matrix.size() <= encr.bcode->slot_count() / 2 && pod_matrix.size() <= sample_size) + { + Ciphertext encrypted_matrix; + init_ciphermatrix(encr, pod_matrix, encrypted_matrix); + save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct"); + delete_operator_batching(encr); + return 0; + } + else + { + delete_operator_batching(encr); + return -1; + } + // delete_operator_batching(encr); + // return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_evaluate.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_evaluate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16839195134d9a5ae225394dc7a01c03e95967f9 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_evaluate.cpp @@ -0,0 +1,456 @@ +#include "seal_api.h" +#include "util.h" + +#include <iostream> +// #include <algorithm> +// #include <iterator> +// #include <vector> +// #include <filesystem> + + +using namespace seal; + +std::string relink_key_path; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void isContain(std::vector<std::vector<std::string>> &v_v, std::string &result_name, std::string &result_dir, std::string &relink_key_path); + +bool is_number(const std::string &s); + +void printStrVector(const std::vector<std::string> &v); + +std::vector<std::vector<std::string>> split_ends(const std::vector<std::string> &source, const std::vector<int> &ends); + +void multiply_ciphertexts(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out); + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out); + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void add_many_ciphertext(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out); + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent); + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +// void sub_vector(std::string &ciphertext_name2, std::string &ciphertext_dir2, std::string &result_name, std::string &result_dir); + +// void sub_vectors(std::string &parent_dir, std::string &result_name, std::string &result_dir); + +int main(int argc, char **argv) +{ + // if (argc != 7) + // std::cout << "[ERROR] please enter prefix_file_to_decrypt_1 /full/path/to/storage_1 " + // "/full/path/to/parent prefix_result_file /full/path/to/result_storage full/path/to/relink/key" + // << std::endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt_1 /full/path/to/storage_1 prefix_file_to_decrypt_2 " + // "/full/path/to/storage_2 prefix_result_file /full/path/to/result_storage full/path/to/relink/key" + // << endl; + // cout << "[ERROR] please enter name and directory of 1st ciphertexts, name and directory of 2nd ciphertexts, name + // and directory of result ciphertexts, and relink key path" << endl; + // else + + std::string ciphertext_name1 = argv[1]; + // ciphertext_dir1 = argv[2]; + + std::string result_name = argv[argc - 3]; + std::string result_dir = argv[argc - 2]; + + relink_key_path = argv[argc - 1]; + + std::vector<std::string> source; + // std::vector<int> ends; + std::vector<std::vector<std::string>> v_v; + + for (int i = 2; i < argc - 3; i++) + { + if (is_number(argv[i])) + { + // ends.push_back(std::stoi( argv[i]) ); + int len = std::stoi( argv[i]); + std::vector<std::string> source; + for (int i2 = 1; i2 <= len; i2++) + { + source.push_back(argv[i + i2]); + } + + v_v.push_back(source); + + } + // else + // { + // source.push_back(argv[i]); + // std::cout << "[ERROR]" << argv[i] << std::endl; + // } + } + + + // auto splitted = split_ends(source, ends); + // for (const auto& v: v_v) { + // printStrVector(v); + // // std::cout << '\n'; + // } + + + isContain(v_v, result_name, result_dir, relink_key_path); + + std::cout << "done" << std::endl; + + return 1; +} + +void isContain(std::vector<std::vector<std::string>> &v_v, std::string &result_name, std::string &result_dir, std::string &relink_key_path) +{ + + struct evaluator_t eval; + // init_operator(8192, 4294967296, eval, relink_key_path); + init_operator(eval, relink_key_path); + + Ciphertext result; + + std::vector<Ciphertext> cts; + + // std::cout << v_v.size() -1 << std::endl; + + for (int index = 1; index < v_v.size(); index++) + { + Ciphertext ct3; + int noFiles1 = v_v.at(0).size(); + int noFiles2 = v_v.at(index).size(); + // std::cout << noFiles1 -1 << std::endl; + if (noFiles1 == noFiles2) + { + std::vector<Ciphertext> cts2; + for (int index2 = 0; index2 < noFiles1; index2++) + { + Ciphertext ct1, ct2; + Ciphertext temp; + // std::cout << "[INFO] loading ciphertext 1" << std::endl; + load_ciphertext(eval, ct1, v_v.at(0).at(index2)); + // std::cout << "[INFO] loading ciphertext 2" << std::endl; + load_ciphertext(eval, ct2, v_v.at(index).at(index2)); + // std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl; + sub_ciphertext(eval, ct1, ct2, temp); + + // u_int64_t x = 2; + // exponentiate_inplace_ciphertext(eval, temp, x); + + cts2.push_back(temp); + + + } + + add_many_ciphertext(eval, cts2, ct3); + relinearize_inplace(eval, ct3); + + } + else + { + // number of files is different in 2 directories + } + + cts.push_back(ct3); + + // if(index == 1) + // { + // result = ct3; + // } + // else + // { + // multiply_inplace_ciphertext(eval, result, ct3); + // relinearize_inplace(eval, result); + // mod_switch_to_next_inplace_ciphertext(eval, result); + // } + } + + multiply_ciphertexts(eval, cts, result); + // mod_switch_to_next_inplace_ciphertext(eval, result); + + + save_ciphertext(result, result_dir + "/" + result_name + ".ct"); + delete_operator(eval); +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->sub(ct1, ct2, ct_out); +} + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->sub_inplace(ct1, ct2); +} + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->sub_plain_inplace(ct, plain); +} + +void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->negate_inplace(ct); +} + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_many_ciphertext(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->multiply_inplace(ct1, ct2); +} + +void multiply_ciphertexts(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->multiply_plain_inplace(ct, plain); +} + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out) +{ + op_st.eval->relinearize(ct, op_st.lk, ct_out); +} + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent) +{ + op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk); +} + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->mod_switch_to_next_inplace(ct); +} + + + + +// // void isContain(std::string &parent_dir, std::string &result_name, std::string &result_dir) +// void isContain(std::string *dirs, int &len, std::string &result_name, std::string &result_dir) +// { +// struct evaluator_t eval; + +// // init_operator(2048, 256, eval, relink_key_path); +// init_operator(8192, 4294967296, eval, relink_key_path); + +// Ciphertext ct1, ct2, ct3, result; + +// // std::cout << "[ERROR]" << std::endl; +// for (int index = 0; index < len; index++) +// { +// // std::cout << "[ERROR]" << dirs[index] << std::endl; + +// std::string ciphertext_dir2 = dirs[index]; + +// // std::cout << ciphertext_dir2 << std::endl; + +// int noFiles1 = findNumberOfFilesInDirectory(ciphertext_dir1); +// int noFiles2 = findNumberOfFilesInDirectory(ciphertext_dir2); + +// if (noFiles1 == noFiles2) +// { +// for (int index2 = 0; index2 < noFiles1; index2++) +// { +// // std::cout << "[INFO] loading ciphertext 1" << std::endl; +// // load_ciphertext(eval, ct1, ciphertext_dir1 + "/" + ciphertext_name1 + "_" + std::to_string(index) + +// // ".ct"); +// load_ciphertext(eval, ct1, ciphertext_dir1 + ciphertext_name1 + "_" + std::to_string(index2) + ".ct"); +// // std::cout << "[INFO] loading ciphertext 2" << std::endl; +// // load_ciphertext(eval, ct2, ciphertext_dir2 + "/" + ciphertext_name1 + "_" + std::to_string(index) + +// // ".ct"); +// load_ciphertext(eval, ct2, ciphertext_dir2 + ciphertext_name1 + "_" + std::to_string(index2) + ".ct"); +// // std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl; +// sub_ciphertext(eval, ct1, ct2, ct1); + +// if (index2 == 0) +// { +// ct3 = ct1; +// } +// else +// { +// add_ciphertext(eval, ct3, ct1, ct3); +// } +// } +// } +// else +// { +// // number of files is different in 2 directories +// } + +// if (index == 0) +// { +// result = ct3; +// } +// else +// { +// multiply_ciphertext(eval, result, ct3, ct3); +// } +// } + +// save_ciphertext(ct3, result_dir + "/" + result_name + ".ct"); + +// delete_operator(eval); +// } + +// // Used for dynamic search +// void sub_vectors(std::string &ciphertext_name1, std::string &ciphertext_dir1, std::string &parent_dir, std::string &result_name, std::string &result_dir, std::string &relink_key_path) +// { +// std::vector<std::string> directories = get_directories(parent_dir); + +// // for (const auto &entry : std::filesystem::directory_iterator(path)) +// for (const auto &entry : directories) +// { +// // std::cout << entry << std::endl; + +// std::string ciphertext_dir2 = entry + "/"; + +// std::string result_dir2 = result_dir + ciphertext_dir2; + +// // std::cout << result_dir2 << std::endl; + +// // std::cout << ciphertext_dir2 << std::endl; + +// std::filesystem::create_directories(result_dir2); + +// sub_vector(ciphertext_name1, ciphertext_dir2, result_name, result_dir2); + +// // file reduction +// // std::cout << "[INFO] file reduction!!!" << std::endl; +// struct evaluator_t eval; +// init_operator(2048, 256, eval, relink_key_path); +// Ciphertext ct1, ct2, ct3; +// int noFiles = findNumberOfFilesInDirectory(result_dir2); +// for (int index = 1; index < noFiles; index++) +// { +// // std::cout << "[INFO] loading ciphertext 1" << std::endl; +// load_ciphertext(eval, ct1, result_dir2 + result_name + "_" + "0" + ".ct"); +// // std::cout << "[INFO] loading ciphertext 2" << std::endl; +// load_ciphertext(eval, ct2, result_dir2 + result_name + "_" + std::to_string(index) + ".ct"); +// // std::cout << "[INFO] addition ciphertext 1 with ciphertext 2" << std::endl; +// add_ciphertext(eval, ct1, ct2, ct1); +// // std::cout << "[INFO] saving ciphertext addition to a new ciphertext file" << std::endl; +// save_ciphertext(ct1, result_dir2 + result_name + "_" + "0" + ".ct"); +// std::filesystem::remove(result_dir2 + result_name + "_" + std::to_string(index) + ".ct"); +// } +// } +// } + +// // Used for dynamic search +// void sub_vector(std::string &ciphertext_name1, std::string &ciphertext_dir1, std::string &ciphertext_name2, std::string &ciphertext_dir2, std::string &result_name, std::string &result_dir, std::string &relink_key_path) +// { +// struct evaluator_t eval; + +// int noFiles1 = findNumberOfFilesInDirectory(ciphertext_dir1); +// int noFiles2 = findNumberOfFilesInDirectory(ciphertext_dir2); + +// // init_operator(2048, 256, eval); +// init_operator(2048, 256, eval, relink_key_path); + +// Ciphertext ct1, ct2, ct3; + +// if (noFiles1 == noFiles2) +// { +// for (int index = 0; index < noFiles1; index++) +// { +// // std::cout << "[INFO] loading ciphertext 1" << std::endl; +// load_ciphertext(eval, ct1, ciphertext_dir1 + "/" + ciphertext_name1 + "_" + std::to_string(index) + ".ct"); +// // std::cout << "[INFO] loading ciphertext 2" << std::endl; +// load_ciphertext(eval, ct2, ciphertext_dir2 + "/" + ciphertext_name2 + "_" + std::to_string(index) + ".ct"); +// // std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl; +// sub_ciphertext(eval, ct1, ct2, ct3); +// // std::cout << "[INFO] saving ciphertext subtraction to a new ciphertext file" << std::endl; +// save_ciphertext(ct3, result_dir + "/" + result_name + "_" + std::to_string(index) + ".ct"); +// } +// } +// else +// {} +// delete_operator(eval); +// } + + +// Input processing + +bool is_number(const std::string &s) +{ + std::string::const_iterator it = s.begin(); + while (it != s.end() && std::isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +// C++11 +// bool is_number(const std::string& s) +// { +// return !s.empty() && std::find_if(s.begin(), +// s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); +// } + +// std::vector<std::vector<std::string>> split_ends(const std::vector<std::string> &source, const std::vector<int> &ends) +// { +// std::vector<std::vector<std::string>> result; +// result.reserve(ends.size()); +// auto anchor_front = source.begin(); +// for (auto one_end: ends) +// { +// auto anchor_end = std::next(source.begin(), one_end + 1); +// result.emplace_back(anchor_front, anchor_end); +// anchor_front = anchor_end; +// } +// return result; +// } + +// void printStrVector(const std::vector<std::string>& v) +// { +// for (auto x: v) +// { +// std::cout << x << ' '; +// } +// } \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_genkey.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_genkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15bcda7d39ec8202b4f2dbda6a52c9dacb5642ee --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/patternSearch_genkey.cpp @@ -0,0 +1,21 @@ +#include <sys/time.h> +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + timeval t0, t1; + unsigned long dt = 0; + gettimeofday(&t0, NULL); + + generate_keys(8192, 4294967296, true); + + gettimeofday(&t1, NULL); + dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + + cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5c447d47b5f403e408b5f661151e1b48059ccc0 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.cpp @@ -0,0 +1,748 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, ios::binary); + if (!in_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, ios::binary); + if (!out_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + + save_params(params, "bfv_params.conf"); + + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching(size_t poly_d, int bit_size, shared_ptr<SEALContext> &context, const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(PlainModulus::Batching(poly_d, bit_size)); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, + const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 36, 36, 37 })); + params.set_plain_modulus(plain_modulus); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext> &context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + // cout << "[CONTEXT] scheme: " << scheme_name << endl; + // cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + /* Print the size of the true (product) coefficient modulus */ + // cout << "[CONTEXT] coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + // cout << coeff_modulus[i].bit_count() << " + "; + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << endl; + + // cout << "[CONTEXT] coeff_modulus values: (" ; + for (int i = 0; i < (coeff_modulus.size() - 1); ++i) + { + // cout << coeff_modulus[i].value() << ",\t"; + // cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + } + + /* For the BFV scheme print the plain_modulus parameter */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + { + // cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; + } +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(GaloisKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<GaloisKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, GaloisKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, bool serializable) +{ + shared_ptr<SEALContext> context; + init_context(poly_d, p_modulus, context); + + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + save_key(pk, "bfv.pk"); + SecretKey sk = keygen.secret_key(); + save_key(sk, "bfv.sk"); + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, "bfv.lk"); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, "bfv.lk"); + } +} + +bool suffix_exist(const std::string &str, const std::string &suffix) +{ + return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +/* +Helper function: Prints the parameters in a SEALContext. +*/ +inline void print_parameters(std::shared_ptr<seal::SEALContext> context) +{ + // Verify parameters + if (!context) + { + throw std::invalid_argument("context is not set"); + } + auto &context_data = *context->key_context_data(); + + /* + Which scheme are we using? + */ + std::string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw std::invalid_argument("unsupported scheme"); + } + cout << "/" << std::endl; + cout << "| Encryption parameters :" << std::endl; + cout << "| scheme: " << scheme_name << std::endl; + cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << std::endl; + + /* + Print the size of the true (product) coefficient modulus. + */ + cout << "| coeff_modulus size: "; + cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + std::size_t coeff_modulus_size = coeff_modulus.size(); + for (std::size_t i = 0; i < coeff_modulus_size - 1; i++) + { + cout << coeff_modulus[i].bit_count() << " + "; + } + cout << coeff_modulus.back().bit_count(); + cout << ") bits" << std::endl; + + /* + For the BFV scheme print the plain_modulus parameter. + */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + { + cout << "| plain_modulus: " << context_data.parms().plain_modulus().value() << std::endl; + } + + cout << "\\" << std::endl; +} + +void batching_generate_keys(size_t poly_d, int bit_size, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_size, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_size, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void batching_generate_keys( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_sizes, plain_modulus, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_sizes, plain_modulus, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void init_operator(struct encryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + PublicKey pk; + load_key(op_st.context, "bfv.pk", pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct encryptor_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + PublicKey pk; + string keypath(""); + string keypath1("bfv.pk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct encryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void delete_operator_batching(struct encryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct decryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + SecretKey sk; + load_key(op_st.context, "bfv.sk", sk); + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct decryptor_t &op_st, const std::string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + + load_context(op_st.context, bfv_params_path); + SecretKey sk; + string keypath(""); + string keypath1("bfv.sk"); + + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath decrypt: " << keypath << endl; + + load_key(op_st.context, keypath, sk); + + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct decryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void delete_operator_batching(struct decryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct evaluator_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, "bfv.lk", op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator(struct evaluator_t &op_st, const string &relink_key_path) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, relink_key_path, op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator_batching(struct evaluator_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + + string keypath(""); + string keypath1("bfv.lk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + + string keypath3(""); + string keypath4("bfv.gk"); + keypath3.append(key_dir); + keypath3.append(keypath4); + // cout << "[INFO] Keypath evaluator: " << keypath3 << endl; + load_key(op_st.context, keypath3, op_st.gk); + + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void delete_operator_batching(struct evaluator_t &op_st) +{ + delete_operator(op_st); +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + // cout << "[INFO] encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + // cout << plain << endl; +} + +void init_ciphermatrix(struct encryptor_t &op_st, vector<int64_t> &plain_matrix, Ciphertext &encrypted_matrix) +{ + // cout << "[INFO] encrypting: " << endl; + Plaintext plaintext_matrix; + // BatchEncoder batch_encoder(op_st.context); + // batch_encoder.encode(plain_matrix, plaintext_matrix); + op_st.bcode->encode(plain_matrix, plaintext_matrix); + op_st.encr->encrypt(plaintext_matrix, encrypted_matrix); + // cout << plain << endl; +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] decrypted result: " << res << endl; +} + +int64_t decrypt_ciphertext_and_return_value(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] Decrypted result: " << res << endl; + return res; +} + +vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + vector<int64_t> pod_matrix; + BatchEncoder batch_encoder(op_st.context); + batch_encoder.decode(pt, pod_matrix); + // print_matrix(pod_matrix, 3); + return pod_matrix; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + pt.save(out_file); + else + ret = 0; + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + ct.save(out_file); + else + ret = 0; + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + pt.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + ct.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.h b/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..f248144bd2fde614f882f9a69ca3dd7a9fc0c363 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/seal_api.h @@ -0,0 +1,97 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" + +/* definitions */ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::GaloisKeys gk; + seal::Evaluator *eval; +}; + +/* prototypes */ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::GaloisKeys& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); +void generate_keys(size_t poly_d, size_t p_modulus, bool seriablizable = false); +void batching_generate_keys(size_t poly_d, int bit_size, const std::string key_path, bool serializable = false); +void batching_generate_keys(size_t poly_d, std::vector<int> bit_sizes, std::uint64_t plain_modulus, std::string key_dir, bool serializable = false); + +/** for homomorphic operators management **/ +void init_operator(struct encryptor_t& op_st); +void init_operator(struct encryptor_t &op_st, const std::string& public_key_path); +void init_operator_batching(struct encryptor_t &op_st, const std::string& key_dir); +void init_operator(struct decryptor_t& op_st); +void init_operator(struct decryptor_t &op_st, const std::string& secret_key_path); +void init_operator_batching(struct decryptor_t &op_st, const std::string& key_dir); +void init_operator(struct evaluator_t& op_st); +void init_operator(struct evaluator_t& op_st, const std::string& relink_key_path); +void init_operator_batching(struct evaluator_t &op_st, const std::string &key_dir); +void delete_operator(struct encryptor_t& op_st); +void delete_operator_batching(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator_batching(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); +void delete_operator_batching(struct evaluator_t& op_st); + +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void init_ciphermatrix(struct encryptor_t &op_st, std::vector<int64_t> &plain_matrix, seal::Ciphertext &encrypted_matrix); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::int64_t decrypt_ciphertext_and_return_value(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, seal::Ciphertext &ct); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + +#endif diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/test.sh b/bigpiseal3.5.1/native/examples/patternSearch/v1/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..1c26ba7ac62de28956b6f8ccd1fe2583747604e7 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/test.sh @@ -0,0 +1,142 @@ +# mkdir -p lcheck/ +# mkdir -p parent/ +# mkdir -p result/ +# # rm ls.txt + + +# # bash data_creating.sh 0 99 9 1000 + +# # Number of driving licenses, eg: (0..99) +# min=0 +# max=5 + +# # Number of chars/words of a driving license, eg: 9 +# n_char=7 + +# # Encrypted number range, eg: 10, 100, 1000 for 1 2 3 4 digits +# range=128 +# # (8-bit) + + + + + +# # gen keys +# ./patternSearch_genkey + +# line=$((RANDOM %max)) +# lcheck="" +# # gen data +# for i in $(seq $min $max) +# do +# mkdir -p parent/l"$i"/ +# echo "Created folder $i" + +# value="" +# for j in $(seq 0 $n_char) +# do +# value+="$((RANDOM %$range)) " +# done + +# echo $value +# echo $value >> ls.txt +# ./patternSearch_encrypt "$value" "a" bfv.pk parent/l"$i"/ + +# if [[ "$line" -eq "$i" ]] +# then +# lcheck="$value" +# fi + +# done + + + +# # get random lc +# # lcheck=$(sed -n "$((RANDOM %9){p;q}" ls.txt) +# # line=$((RANDOM %max)) +# # lcheck="$(sed -n "${line}{p;q}" ls.txt)" +# echo "Pick up license to check: $lcheck" +# ./patternSearch_encrypt "$lcheck" "a" bfv.pk lcheck/ +# # ./patternSearch_encrypt "47 25 76 23 30 21 1 47 88 3" "a" bfv.pk lcheck/ + + + + +# # eval +# value1="" +# for i in $(seq 0 $n_char) +# do +# value1+="lcheck/a_${i}.ct " +# done + +# value1="$(($n_char+1)) ${value1}" + +# # v=$(($n_char+1)) +# # echo $v + +# value2="" +# for i in $(seq 0 $max) +# do +# value2="${value2} $(($n_char+1)) " +# for j in $(seq 0 $n_char) +# do +# value2+="parent/l${i}/a_${j}.ct " +# done + +# # value2="${value2} $(($n_char+1))" +# done + +# # value2="${value1} ${value2}" +# value3="$value1$value2" +# echo "$value3" + +# ./patternSearch_evaluate "a" $value3 "a" result/ bfv.lk + + +# ./patternSearch_decrypt result/a.ct bfv.sk + + + +# rm -r lcheck/* +# rm -r parent/* +# rm -r result/* + + + + + + + + +# # ./patternSearch_evaluate "a" 10 lcheck/a_0.ct lcheck/a_1.ct lcheck/a_2.ct lcheck/a_3.ct lcheck/a_4.ct lcheck/a_5.ct lcheck/a_6.ct lcheck/a_7.ct lcheck/a_8.ct lcheck/a_9.ct 10 parent/l0/a_0.ct parent/l0/a_1.ct parent/l0/a_2.ct parent/l0/a_3.ct parent/l0/a_4.ct parent/l0/a_5.ct parent/l0/a_6.ct parent/l0/a_7.ct parent/l0/a_8.ct parent/l0/a_9.ct 10 parent/l1/a_0.ct parent/l1/a_1.ct parent/l1/a_2.ct parent/l1/a_3.ct parent/l1/a_4.ct parent/l1/a_5.ct parent/l1/a_6.ct parent/l1/a_7.ct parent/l1/a_8.ct parent/l1/a_9.ct 10 parent/l2/a_0.ct parent/l2/a_1.ct parent/l2/a_2.ct parent/l2/a_3.ct parent/l2/a_4.ct parent/l2/a_5.ct parent/l2/a_6.ct parent/l2/a_7.ct parent/l2/a_8.ct parent/l2/a_9.ct 10 parent/l3/a_0.ct parent/l3/a_1.ct parent/l3/a_2.ct parent/l3/a_3.ct parent/l3/a_4.ct parent/l3/a_5.ct parent/l3/a_6.ct parent/l3/a_7.ct parent/l3/a_8.ct parent/l3/a_9.ct 10 parent/l4/a_0.ct parent/l4/a_1.ct parent/l4/a_2.ct parent/l4/a_3.ct parent/l4/a_4.ct parent/l4/a_5.ct parent/l4/a_6.ct parent/l4/a_7.ct parent/l4/a_8.ct parent/l4/a_9.ct 10 parent/l5/a_0.ct parent/l5/a_1.ct parent/l5/a_2.ct parent/l5/a_3.ct parent/l5/a_4.ct parent/l5/a_5.ct parent/l5/a_6.ct parent/l5/a_7.ct parent/l5/a_8.ct parent/l5/a_9.ct 10 parent/l6/a_0.ct parent/l6/a_1.ct parent/l6/a_2.ct parent/l6/a_3.ct parent/l6/a_4.ct parent/l6/a_5.ct parent/l6/a_6.ct parent/l6/a_7.ct parent/l6/a_8.ct parent/l6/a_9.ct 10 parent/l7/a_0.ct parent/l7/a_1.ct parent/l7/a_2.ct parent/l7/a_3.ct parent/l7/a_4.ct parent/l7/a_5.ct parent/l7/a_6.ct parent/l7/a_7.ct parent/l7/a_8.ct parent/l7/a_9.ct 10 parent/l8/a_0.ct parent/l8/a_1.ct parent/l8/a_2.ct parent/l8/a_3.ct parent/l8/a_4.ct parent/l8/a_5.ct parent/l8/a_6.ct parent/l8/a_7.ct parent/l8/a_8.ct parent/l8/a_9.ct 10 parent/l9/a_0.ct parent/l9/a_1.ct parent/l9/a_2.ct parent/l9/a_3.ct parent/l9/a_4.ct parent/l9/a_5.ct parent/l9/a_6.ct parent/l9/a_7.ct parent/l9/a_8.ct parent/l9/a_9.ct "a" result/ key/bfv.lk + + + +# # ./patternSearch_encrypt "$lc1" "a" bfv.pk lcheck/ + +# #eval +# # ./patternSearch_evaluate "a" lcheck/ parent/ "a" result/ bfv.lk + +# #decrypt +# # ./patternSearch_decrypt "a" bfv.sk result/parent/ + + + +# #example + +# # lc1=$1; +# # lc2=$2; + +# # mkdir -p l1/; +# # mkdir -p l2/; +# # mkdir -p result/; + +# # ./patternSearch_genkey +# # ./patternSearch_encrypt "$lc1" "a" bfv.pk l1/ +# # ./patternSearch_encrypt "$lc2" "a" bfv.pk l2/ +# # ./patternSearch_evaluate "a" l1/ "a" l2/ "a" result/ bfv.lk +# # ./patternSearch_decrypt "a" bfv.sk result/ + +# # rm l1/*; +# # rm l2/*; +# # rm result/*; \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/util.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v1/util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72367dab3632e64801bf24ead89070859286704e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/util.cpp @@ -0,0 +1,73 @@ +#include "util.h" +// #include <filesystem> +#include "seal_api.h" + +// #include <boost/filesystem.hpp> + +// namespace fs = boost::filesystem; + +bool sub_str_exist(const std::string &str, const std::string &sub_str) +{ + return str.size() >= sub_str.size() && str.compare(str.size() - sub_str.size(), sub_str.size(), sub_str) == 0; +} + +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// auto dirIter = std::filesystem::directory_iterator(path); +// int fileCount = std::count_if( +// begin(dirIter), +// end(dirIter), +// [](auto &entry) { return entry.is_regular_file(); }); +// return fileCount; +// } + +// int findNumberOfFilesInDirectory(std::string &path, std::string &ext) +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// // namespace fs = boost::filesystem; + +// std::string ext = ".ct"; + +// fs::path Path(path); +// int Nb_ext = 0; +// fs::directory_iterator end_iter; // Default constructor for an iterator is the end iterator + +// for (fs::directory_iterator iter(Path); iter != end_iter; ++iter) +// if (iter->path().extension() == ext) +// ++Nb_ext; + +// return Nb_ext; +// } + +// c++ 17 +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> r; +// for(auto& p : std::filesystem::recursive_directory_iterator(s)) +// if (p.is_directory()) +// r.push_back(p.path().string()); +// return r; +// } + +// struct path_leaf_string +// { +// std::string operator()(const boost::filesystem::directory_entry &entry) const +// { +// return entry.path().leaf().string(); +// } +// }; + +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> v; + +// boost::filesystem::path p(s); +// boost::filesystem::directory_iterator start(p); +// boost::filesystem::directory_iterator end; +// std::transform(start, end, std::back_inserter(v), path_leaf_string()); + +// std::copy(v.begin(), v.end(), +// std::ostream_iterator<std::string>(std::cout, "\n")); + +// return v; +// } diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v1/util.h b/bigpiseal3.5.1/native/examples/patternSearch/v1/util.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8ffd7ce1534fac8fec3d5a4bfb2a2fdf8f0961 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v1/util.h @@ -0,0 +1,15 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <string> +#include <vector> + +// int findNumberOfFilesInDirectory(const std::string &path); + +bool sub_str_exist(const std::string &str, const std::string &sub_str); + +// std::vector<std::string> get_directories(const std::string &s); + +// std::vector<std::string> get_directories_deep(const std::string &s); + +#endif diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/CMakeLists.txt b/bigpiseal3.5.1/native/examples/patternSearch/v2/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ea70f9fda824203588365be48ee172a0fc19e4e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/CMakeLists.txt @@ -0,0 +1,167 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME patternSearch) + +#set(GENKEY_BIN ${TEST_NAME}_genkey) +#set(ENCR_BIN ${TEST_NAME}_encrypt) +#set(DECR_BIN ${TEST_NAME}_decrypt) +#set(EVAL_BIN ${TEST_NAME}_evaluate) +#set(SCR_TEST test.sh) + +set(GENKEY_BIN_2 ${TEST_NAME}_genkey_v2) +set(ENCR_BIN_2 ${TEST_NAME}_encrypt_v2) +set(DECR_BIN_2 ${TEST_NAME}_decrypt_v2) +set(DECR_RESULT_BIN_2 ${TEST_NAME}_decrypt_result_v2) +set(EVAL_BIN_2 ${TEST_NAME}_evaluate_v2) + +set(SCR_ENC encrypt.sh) +set(SCR_DEC decrypt.sh) +set(SCR_DEC_RESULT decrypt_result.sh) +set(SCR_EVAL eval.sh) +set(SCR_GEN genkey.sh) +set(SCR_TEST_V2 test_v2.sh) + + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + + +set(GENKEY_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey_v2.cpp + ) + +set(ENCR_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt_v2.cpp + ) + +set(DECR_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_v2.cpp + ) + +set(DECR_RESULT_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_result_v2.cpp + ) + +set(EVAL_SRCS_2 + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate_v2.cpp + ) + + +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/util.h + ) + +#add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +#add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +#add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +#add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +add_executable(${GENKEY_BIN_2} ${GENKEY_SRCS_2} ${HEADER_FILES}) +add_executable(${ENCR_BIN_2} ${ENCR_SRCS_2} ${HEADER_FILES}) +add_executable(${DECR_BIN_2} ${DECR_SRCS_2} ${HEADER_FILES}) +add_executable(${DECR_RESULT_BIN_2} ${DECR_RESULT_SRCS_2} ${HEADER_FILES}) +add_executable(${EVAL_BIN_2} ${EVAL_SRCS_2} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +# Link Microsoft SEAL +#target_link_libraries(${GENKEY_BIN} SEAL::seal) +#target_link_libraries(${ENCR_BIN} SEAL::seal) +#target_link_libraries(${DECR_BIN} SEAL::seal) +#target_link_libraries(${EVAL_BIN} SEAL::seal) + +target_link_libraries(${GENKEY_BIN_2} SEAL::seal) +target_link_libraries(${ENCR_BIN_2} SEAL::seal) +target_link_libraries(${DECR_BIN_2} SEAL::seal) +target_link_libraries(${DECR_RESULT_BIN_2} SEAL::seal) +target_link_libraries(${EVAL_BIN_2} SEAL::seal) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + +#set_target_properties(${GENKEY_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${ENCR_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${DECR_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) +#set_target_properties(${EVAL_BIN} +# PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}" +# ) + +set_target_properties(${GENKEY_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2" + ) +set_target_properties(${ENCR_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2" + ) +set_target_properties(${DECR_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2" + ) +set_target_properties(${DECR_RESULT_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2" + ) +set_target_properties(${EVAL_BIN_2} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2" + ) + + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC_RESULT} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_EVAL} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST_V2} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v2) \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..ba531fda676f69823f0f735a5a7fea4a146c73da --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt.sh @@ -0,0 +1,12 @@ +#decrypt +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt_result.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..cb087cd12eb2612b8f5621260ef74d744962e6cf --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/decrypt_result.sh @@ -0,0 +1,12 @@ +#decrypt result +resultPath=$1 +# ex: result/l.ct +sample=$2 +# ex: 40 +keyDir=$3 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/encrypt.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/encrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..5ab0992d0767facfa1a00d579622289675a47fd3 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/encrypt.sh @@ -0,0 +1,16 @@ +#encrypt +licenseNo=$1 +# ex: "23 65 78 127 255" (en ASCII) +filename=$2 +# ex: "l" (extension will be .ct) +outputDir=$3 +# ex: lcheck/ +sample=$4 +# ex: 40 +keyDir=$5 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" +time ${CURR_DIR}/patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/eval.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/eval.sh new file mode 100644 index 0000000000000000000000000000000000000000..72138f16eff3fb911a7b5a9eaeb9a6462c9d0f0c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/eval.sh @@ -0,0 +1,30 @@ +# evaluate +licensePath=$1 +# ex: lcheck/l.ct +licensePathList=${@: 2:$#-5} +# licensePathList="${@:2:102}" +# for var in "${@: 2:$#-7}" +# do +# echo "$var" +# done +# ex: parent/l0/l.ct parent/l1/l.ct parent/l2/l.ct parent/l3/l.ct parent/l4/l.ct parent/l5/l.ct parent/l6/l.ct parent/l7/l.ct parent/l8/l.ct parent/l9/l.ct +filename=${@: -4:1} +# ex: "l" (extension will be .ct) +outputDir=${@: -3:1} +# ex: result/ +sample=${@: -2:1} +# ex: 40 +KeyDir=${@: -1} +# ex: keys/ +# linkingKeyPath=${@: -3:1} +# # ex: bfv.lk +# galoisKeyPath=${@: -2:1} +# # ex: bfv.gk +# publicKeyPath=${@: -1} +# # ex: bfv.pk + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$linkingKeyPath" "$galoisKeyPath" "$publicKeyPath" +# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" +time ${CURR_DIR}/patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/genkey.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/genkey.sh new file mode 100644 index 0000000000000000000000000000000000000000..1691c61844aa7935f256b4d49495131983128a6c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/genkey.sh @@ -0,0 +1,8 @@ +#gen key +keyDir=$1 +# ex: keys/ + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# time ./patternSearch_genkey_v2 "$keyDir" +time ${CURR_DIR}/patternSearch_genkey_v2 "$keyDir" \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_result_v2.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_result_v2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17874a1064c0f0ea23a202df918b5d2ac4ff5c4f --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_result_v2.cpp @@ -0,0 +1,139 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// bool decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +bool decrypt(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + // cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + bool result_str = decrypt(sample_size, dir); + cout << result_str << endl; + + return 0; + } +} + +bool decrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + + bool isContain = false; + if (sample_size <= decr.bcode->slot_count()/2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + // cout << pod_matrix.size() << endl; + + int no_dual_vectors = (decr.bcode->slot_count() / 2) / (sample_size); + + vector<int64_t> v1, v2; + for (size_t i = 0; i < no_dual_vectors * sample_size; i++) + { + v1.push_back(pod_matrix[i]); + v2.push_back(pod_matrix[(pod_matrix.size() / 2) + i]); + } + + int64_t sum = 0; + if (isContain == false) + { + // cout << "1 : "; + for (size_t i = 0; i < v1.size(); i++) + { + // cout << v1[i]; + if ((i + 1) % sample_size == 0) + { + // cout << endl; + if (i < v1.size() - 1) + { + // cout << ((i + 1) / 40) + 1 << " : "; + } + } + else + { + // cout << ", "; + } + + if (v1[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + // cout << endl; + if (isContain == false) + { + sum = 0; + // cout << (v2.size() + 1) / 40 + 1 << " : "; + for (size_t i = 0; i < v2.size(); i++) + { + // cout << v2[i]; + if ((i + 1) % sample_size == 0) + { + // cout << endl; + if (i < v2.size() - 1) + { + // cout << ((v2.size() + i + 1) / 40) + 1 << " : "; + } + } + else + { + // cout << ", "; + } + + if (v2[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + } + else + { + // cout << endl << "Sample size is too large" << endl; + } + + delete_operator_batching(decr); + return isContain; +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_v2.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_v2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f8391afffac961f6aae830b1a9df6417c1e5d56 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_decrypt_v2.cpp @@ -0,0 +1,73 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// vector<int64_t> decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + vector<int64_t> result = decrypt(sample_size, dir); + + for (int i = 0; i < result.size(); ++i) + { + std::cout << result[i] << ' '; + } + + std::cout << endl; + + return 0; + } +} + + +vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + // init_operator_batching(2048, 4294967296, decr, key_dir); + // init_operator_batching(4096, 4294967296, decr, key_dir); + // init_operator_batching(8192, 4294967296, decr, key_dir); + // init_operator_batching(16384, 4294967296, decr, key_dir); + // init_operator_batching(32768, 4294967296, decr, key_dir); + + vector<int64_t> v; + if (sample_size <= decr.bcode->slot_count()/2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + for (size_t i = 0; i < sample_size; i++) + { + v.push_back(pod_matrix[i]); + } + } + else + { + // cout << endl << "Sample size is too large" << endl; + } + delete_operator_batching(decr); + return v; +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_encrypt_v2.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_encrypt_v2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..644961e6285a349e96f4f37211f5c474b869576c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_encrypt_v2.cpp @@ -0,0 +1,54 @@ +#include "seal_api.h" + +using namespace seal; +using namespace std; + + +int main(int argc, char **argv) +{ + if (argc != 6) + { + // cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl; + cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or " + "prefix, ciphertext output file directory, sample size and public key path" + << endl; + return -1; + } + else + { + string plaintext = argv[1]; + string ciphertext_name = argv[2]; + string ciphertext_dir = argv[3]; + int sample_size = atol(argv[4]); + string key_dir = argv[5]; + + struct encryptor_t encr; + init_operator_batching(encr, key_dir); + + stringstream ss; + ss << plaintext; + vector<int64_t> pod_matrix; + int64_t x = 0; + + while (ss >> x) + { + pod_matrix.push_back(x); + } + + if (pod_matrix.size() <= encr.bcode->slot_count() / 2 && pod_matrix.size() <= sample_size) + { + Ciphertext encrypted_matrix; + init_ciphermatrix(encr, pod_matrix, encrypted_matrix); + save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct"); + delete_operator_batching(encr); + return 0; + } + else + { + delete_operator_batching(encr); + return -1; + } + // delete_operator_batching(encr); + // return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_evaluate_v2.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_evaluate_v2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce61335dda74c3a520899a70fe55285e68e9fd7d --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_evaluate_v2.cpp @@ -0,0 +1,515 @@ +#include <iostream> +#include "seal_api.h" +#include "util.h" +// #include <algorithm> +// #include <iterator> +// #include <vector> +// #include <filesystem> + +using namespace seal; +using namespace std; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +bool is_number(const string &s); + +void printStrVector(const vector<string> &v); + +vector<vector<string>> split_ends(const vector<string> &data, const vector<int> &ends); + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out); + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent); + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +int simpleCheck( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval); + +// string relink_key_path; +// string galois_key_path; +// string public_key_path; +string key_dir = ""; + +int main(int argc, char **argv) +{ + // input processing - begin + // string result_name = argv[argc - 6]; + // string result_dir = argv[argc - 5]; + // int sample_size = atoi(argv[argc - 4]); + // relink_key_path = argv[argc - 3]; + // galois_key_path = argv[argc - 2]; + // public_key_path = argv[argc - 1]; + string source = argv[1]; + + string result_name = argv[argc - 4]; + string result_dir = argv[argc - 3]; + int sample_size = atoi(argv[argc - 2]); + key_dir = argv[argc - 1]; + + vector<string> data; + for (int i = 2; i < argc - 4; i++) + { + data.push_back(argv[i]); + } + + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || + // relink_key_path == "" || galois_key_path == "" || public_key_path == "") + if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || key_dir == "") + { + // error handling + cout << "[ERROR] please enter a source path, data paths, output ciphertext file name or prefix, output " + "ciphertext directory, sample size, linking key path, galois key path and public key path" + << endl; + return -1; + } + // input processing - end + + // simple algo + // int result = simpleCheck(source, data, result_name, result_dir, sample_size, key_dir); + // sequence algo + int result = checkSq(source, data, result_name, result_dir, sample_size, key_dir); + + // error handling + if (result == -1) + { + fprintf(stderr, "error!\n"); + } + else + { + cout << "done"; + } + + // checkSq(source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, public_key_path); + + return result; +} + +int simpleCheck( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + struct evaluator_t eval; + init_operator_batching(eval, key_dir); + + struct encryptor_t encr; + init_operator_batching(encr, key_dir); + + // cout << sample_size*data.size() << endl; + // cout << encr.bcode->slot_count() << endl; + if (sample_size * data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count() / 2) + { + // error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // normalize input data if its size is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + int required_range = normalized_data_size * sample_size; + int required_no_row_elements = required_range / 2; + int required_range_row = required_range / 2; + + // create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row; + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[required_no_row_elements + i] = 1; + padding_matrix[encr.bcode->slot_count() - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // add dummy vector for oddy data + temp2 = encrypted_dummy_matrix; + } + + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + // add renmaining padding slots + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + } + + save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + return 0; + } +} + +// int checkSq( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path) +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + struct evaluator_t eval; + // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + init_operator_batching(eval, key_dir); + + struct encryptor_t encr; + // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // init_operator_batching(16384, 4294967296, encr, public_key_path); + // init_operator_batching(32768, 4294967296, encr, public_key_path); + init_operator_batching(encr, key_dir); + + // if (sample_size*data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count()/2) + if (sample_size > encr.bcode->slot_count() / 2) + { + // error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + // struct evaluator_t eval; + // // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + + // struct encryptor_t encr; + // // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // // init_operator_batching(16384, 4294967296, encr, public_key_path); + // // init_operator_batching(32768, 4294967296, encr, public_key_path); + + int capacity = (encr.bcode->slot_count()) / sample_size; + // cout << capacity << endl; + + // vector<string> v_temp; + // vector<string> v_v_temp; + // Ciphertext result; + vector<Ciphertext> v_result; + int nSq = data.size() / capacity; + for (size_t i = 0; i < nSq; i++) + { + Ciphertext result; + // cout << "sq : " << i << endl; + vector<string> v_temp; + for (size_t j = 0; j < capacity; j++) + { + string str = data.back(); + v_temp.push_back(str); + data.pop_back(); + } + if (i == 0) + { + // cout << "sq : init" << endl; + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + else + { + // cout << "sq : other" << endl; + // Ciphertext result2 = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + } + + if (data.size() % capacity != 0) + { + // cout << "oddy!!! " << endl; + // Ciphertext result = check( + // source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + Ciphertext result = check(source, data, result_name, result_dir, sample_size, key_dir, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + v_result.push_back(result); + } + + Ciphertext result; + multiply_ciphertexts(eval, v_result, result); + relinearize_inplace(eval, result); + + save_ciphertext(result, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + return 0; + } +} + +// Ciphertext check( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path, struct encryptor_t &encr, +// struct evaluator_t &eval) +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval) +{ + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0) + // { + // // error handling + // // return -1; + + // } + // else + // { + + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // normalize input data if its size is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + int required_range = normalized_data_size * sample_size; + int required_no_row_elements = required_range / 2; + int required_range_row = required_range / 2; + + // create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row; + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[required_no_row_elements + i] = 1; + padding_matrix[(encr.bcode->slot_count() - 1) - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // add dummy vector for oddy data + temp2 = encrypted_dummy_matrix; + } + + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + // add renmaining padding slots + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + } + + // // save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + // delete_operator_batching(eval); + + return encrypted_result_matrix; + // } +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->sub(ct1, ct2, ct_out); +} + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->sub_inplace(ct1, ct2); +} + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->sub_plain_inplace(ct, plain); +} + +void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->negate_inplace(ct); +} + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->multiply_inplace(ct1, ct2); +} + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->multiply_plain_inplace(ct, plain); +} + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out) +{ + op_st.eval->relinearize(ct, op_st.lk, ct_out); +} + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent) +{ + op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk); +} + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->mod_switch_to_next_inplace(ct); +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_genkey_v2.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_genkey_v2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af3a074e0143790087372822879c86eb4810f5df --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/patternSearch_genkey_v2.cpp @@ -0,0 +1,31 @@ +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + string key_dir = argv[1]; + + size_t poly_d = 4096; + + // Params option 1 + int bit_size = 20; + + // Params option 2 + // uint64_t plain_modulus = 1032193; + // vector<int> bit_sizes = { 36, 36, 37 }; + + // timeval t0, t1; + // unsigned long dt = 0; + // gettimeofday(&t0, NULL); + + batching_generate_keys(poly_d, bit_size, key_dir, true); + // batching_generate_keys(poly_d, bit_sizes, plain_modulus, key_dir, true); + + // gettimeofday(&t1, NULL); + // dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + // cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bad358280f951ca380970e86e6b0cc919068161e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.cpp @@ -0,0 +1,748 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, ios::binary); + if (!in_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, ios::binary); + if (!out_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + + save_params(params, "bfv_params.conf"); + + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching(size_t poly_d, int bit_size, shared_ptr<SEALContext> &context, const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(PlainModulus::Batching(poly_d, bit_size)); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, + const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 36, 36, 37 })); + params.set_plain_modulus(plain_modulus); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext> &context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + // cout << "[CONTEXT] scheme: " << scheme_name << endl; + // cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + /* Print the size of the true (product) coefficient modulus */ + // cout << "[CONTEXT] coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + // cout << coeff_modulus[i].bit_count() << " + "; + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << endl; + + // cout << "[CONTEXT] coeff_modulus values: (" ; + for (int i = 0; i < (coeff_modulus.size() - 1); ++i) + { + // cout << coeff_modulus[i].value() << ",\t"; + // cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + } + + /* For the BFV scheme print the plain_modulus parameter */ + if (context_data.parms().scheme() == seal::scheme_type::BFV) + { + // cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; + } +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(GaloisKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<GaloisKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, GaloisKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, bool serializable) +{ + shared_ptr<SEALContext> context; + init_context(poly_d, p_modulus, context); + + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + save_key(pk, "bfv.pk"); + SecretKey sk = keygen.secret_key(); + save_key(sk, "bfv.sk"); + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, "bfv.lk"); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, "bfv.lk"); + } +} + +bool suffix_exist(const std::string &str, const std::string &suffix) +{ + return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +/* +Helper function: Prints the parameters in a SEALContext. +*/ +inline void print_parameters(std::shared_ptr<seal::SEALContext> context) +{ + // Verify parameters + if (!context) + { + throw std::invalid_argument("context is not set"); + } + auto &context_data = *context->key_context_data(); + + /* + Which scheme are we using? + */ + std::string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw std::invalid_argument("unsupported scheme"); + } + // cout << "/" << std::endl; + // cout << "| Encryption parameters :" << std::endl; + // cout << "| scheme: " << scheme_name << std::endl; + // cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << std::endl; + + /* + Print the size of the true (product) coefficient modulus. + */ + // cout << "| coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + auto coeff_modulus = context_data.parms().coeff_modulus(); + std::size_t coeff_modulus_size = coeff_modulus.size(); + // for (std::size_t i = 0; i < coeff_modulus_size - 1; i++) + // { + // cout << coeff_modulus[i].bit_count() << " + "; + // } + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << std::endl; + + /* + For the BFV scheme print the plain_modulus parameter. + */ + // if (context_data.parms().scheme() == seal::scheme_type::BFV) + // { + // cout << "| plain_modulus: " << context_data.parms().plain_modulus().value() << std::endl; + // } + + // cout << "\\" << std::endl; +} + +void batching_generate_keys(size_t poly_d, int bit_size, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_size, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_size, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void batching_generate_keys( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_sizes, plain_modulus, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_sizes, plain_modulus, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void init_operator(struct encryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + PublicKey pk; + load_key(op_st.context, "bfv.pk", pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct encryptor_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + PublicKey pk; + string keypath(""); + string keypath1("bfv.pk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct encryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void delete_operator_batching(struct encryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct decryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + SecretKey sk; + load_key(op_st.context, "bfv.sk", sk); + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct decryptor_t &op_st, const std::string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + + load_context(op_st.context, bfv_params_path); + SecretKey sk; + string keypath(""); + string keypath1("bfv.sk"); + + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath decrypt: " << keypath << endl; + + load_key(op_st.context, keypath, sk); + + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct decryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void delete_operator_batching(struct decryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct evaluator_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, "bfv.lk", op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator(struct evaluator_t &op_st, const string &relink_key_path) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, relink_key_path, op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator_batching(struct evaluator_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + + string keypath(""); + string keypath1("bfv.lk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + + string keypath3(""); + string keypath4("bfv.gk"); + keypath3.append(key_dir); + keypath3.append(keypath4); + // cout << "[INFO] Keypath evaluator: " << keypath3 << endl; + load_key(op_st.context, keypath3, op_st.gk); + + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void delete_operator_batching(struct evaluator_t &op_st) +{ + delete_operator(op_st); +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + // cout << "[INFO] encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + // cout << plain << endl; +} + +void init_ciphermatrix(struct encryptor_t &op_st, vector<int64_t> &plain_matrix, Ciphertext &encrypted_matrix) +{ + // cout << "[INFO] encrypting: " << endl; + Plaintext plaintext_matrix; + // BatchEncoder batch_encoder(op_st.context); + // batch_encoder.encode(plain_matrix, plaintext_matrix); + op_st.bcode->encode(plain_matrix, plaintext_matrix); + op_st.encr->encrypt(plaintext_matrix, encrypted_matrix); + // cout << plain << endl; +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] decrypted result: " << res << endl; +} + +int64_t decrypt_ciphertext_and_return_value(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] Decrypted result: " << res << endl; + return res; +} + +vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + vector<int64_t> pod_matrix; + BatchEncoder batch_encoder(op_st.context); + batch_encoder.decode(pt, pod_matrix); + // print_matrix(pod_matrix, 3); + return pod_matrix; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + pt.save(out_file); + else + ret = 0; + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + ct.save(out_file); + else + ret = 0; + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + pt.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + ct.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.h b/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..f248144bd2fde614f882f9a69ca3dd7a9fc0c363 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/seal_api.h @@ -0,0 +1,97 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" + +/* definitions */ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::GaloisKeys gk; + seal::Evaluator *eval; +}; + +/* prototypes */ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::GaloisKeys& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); +void generate_keys(size_t poly_d, size_t p_modulus, bool seriablizable = false); +void batching_generate_keys(size_t poly_d, int bit_size, const std::string key_path, bool serializable = false); +void batching_generate_keys(size_t poly_d, std::vector<int> bit_sizes, std::uint64_t plain_modulus, std::string key_dir, bool serializable = false); + +/** for homomorphic operators management **/ +void init_operator(struct encryptor_t& op_st); +void init_operator(struct encryptor_t &op_st, const std::string& public_key_path); +void init_operator_batching(struct encryptor_t &op_st, const std::string& key_dir); +void init_operator(struct decryptor_t& op_st); +void init_operator(struct decryptor_t &op_st, const std::string& secret_key_path); +void init_operator_batching(struct decryptor_t &op_st, const std::string& key_dir); +void init_operator(struct evaluator_t& op_st); +void init_operator(struct evaluator_t& op_st, const std::string& relink_key_path); +void init_operator_batching(struct evaluator_t &op_st, const std::string &key_dir); +void delete_operator(struct encryptor_t& op_st); +void delete_operator_batching(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator_batching(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); +void delete_operator_batching(struct evaluator_t& op_st); + +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void init_ciphermatrix(struct encryptor_t &op_st, std::vector<int64_t> &plain_matrix, seal::Ciphertext &encrypted_matrix); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::int64_t decrypt_ciphertext_and_return_value(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, seal::Ciphertext &ct); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + +#endif diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/test_v2.sh b/bigpiseal3.5.1/native/examples/patternSearch/v2/test_v2.sh new file mode 100644 index 0000000000000000000000000000000000000000..2c1e81fa3d74fd34d9a70f9214c0b5c4ec7da46b --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/test_v2.sh @@ -0,0 +1,115 @@ +mkdir -p keys/ +mkdir -p lcheck/ +mkdir -p parent/ +mkdir -p result/ +# rm ls.txt + + +# bash data_creating.sh 0 99 9 1000 + +# Number of driving licenses, eg: (0..99) +min=0 +max=101 +# max=1631 +# max=101 +# sim: (eval: 0.465s, 0.488s, 0.480s decrypt: 0.028s, 0.080s, 0.077s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=203 +# (eval: 3.635s, 3.510s, 3.628s decrypt: 0.062s, 0.153s. 0.134s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=407 +# (eval: 38.607s, 39.600s, 39.565s decrypt: 0.264s, 0.260s, 0.245s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=815 +# (eval: x decrypt: x ) + +# Number of chars/words of a driving license, eg: 9 +n_char=39 + +# Encrypted number range, eg: 10, 100, 1000 for 1 2 3 4 digits +range=255 +# (8-bit) + +# sampling size +sample=40 + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Note + + + +# gen keys +# ./patternSearch_genkey_v2 keys/ +${CURR_DIR}/patternSearch_genkey_v2 keys/ + +line=$((RANDOM %max)) +lcheck="" +# gen data +for i in $(seq $min $max) +do + mkdir -p parent/l"$i"/ + echo "Created folder $i" + + value="" + for j in $(seq 0 $n_char) + do + value+="$((RANDOM %$range)) " + done + + echo $value + echo $value >> ls.txt + # ./patternSearch_encrypt_v2 "$value" "l" parent/l"$i"/ $sample keys/ + ${CURR_DIR}/patternSearch_encrypt_v2 "$value" "l" parent/l"$i"/ $sample keys/ + + if [[ "$line" -eq "$i" ]] + then + lcheck="$value" + fi + +done + + + +# get random lc +# lcheck=$(sed -n "$((RANDOM %9){p;q}" ls.txt) +# line=$((RANDOM %max)) +# lcheck="$(sed -n "${line}{p;q}" ls.txt)" +echo "Pick up license to check: $lcheck" +# ./patternSearch_encrypt_v2 "$lcheck" "l" lcheck/ $sample keys/ +${CURR_DIR}/patternSearch_encrypt_v2 "$lcheck" "l" lcheck/ $sample keys/ +# ./patternSearch_encrypt "47 25 76 23 30 21 1 47 88 3" "a" keys/bfv.pk lcheck/ + + + + +# eval +value1="lcheck/l.ct " + + +value2="" +for i in $(seq 0 $max) +do + value2+="parent/l${i}/l.ct " +done + +# value2="${value1} ${value2}" +value3="$value1$value2" +echo "$value3" + +# time ./patternSearch_evaluate_v2 $value3 "l" result/ $sample keys/ +# ./patternSearch_evaluate_v2 $value3 "l" result/ $sample keys/ +time ${CURR_DIR}/patternSearch_evaluate_v2 $value3 "l" result/ $sample keys/ + +echo "" + +# time ./patternSearch_decrypt_result_v2 result/l.ct $sample keys/ +# ./patternSearch_decrypt_result_v2 result/l.ct $sample keys/ +${CURR_DIR}/patternSearch_decrypt_result_v2 result/l.ct $sample keys/ + + +# rm -r keys/* +# rm -r lcheck/* +# rm -r parent/* +# rm -r result/* +# rm ls.txt diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/util.cpp b/bigpiseal3.5.1/native/examples/patternSearch/v2/util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72367dab3632e64801bf24ead89070859286704e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/util.cpp @@ -0,0 +1,73 @@ +#include "util.h" +// #include <filesystem> +#include "seal_api.h" + +// #include <boost/filesystem.hpp> + +// namespace fs = boost::filesystem; + +bool sub_str_exist(const std::string &str, const std::string &sub_str) +{ + return str.size() >= sub_str.size() && str.compare(str.size() - sub_str.size(), sub_str.size(), sub_str) == 0; +} + +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// auto dirIter = std::filesystem::directory_iterator(path); +// int fileCount = std::count_if( +// begin(dirIter), +// end(dirIter), +// [](auto &entry) { return entry.is_regular_file(); }); +// return fileCount; +// } + +// int findNumberOfFilesInDirectory(std::string &path, std::string &ext) +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// // namespace fs = boost::filesystem; + +// std::string ext = ".ct"; + +// fs::path Path(path); +// int Nb_ext = 0; +// fs::directory_iterator end_iter; // Default constructor for an iterator is the end iterator + +// for (fs::directory_iterator iter(Path); iter != end_iter; ++iter) +// if (iter->path().extension() == ext) +// ++Nb_ext; + +// return Nb_ext; +// } + +// c++ 17 +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> r; +// for(auto& p : std::filesystem::recursive_directory_iterator(s)) +// if (p.is_directory()) +// r.push_back(p.path().string()); +// return r; +// } + +// struct path_leaf_string +// { +// std::string operator()(const boost::filesystem::directory_entry &entry) const +// { +// return entry.path().leaf().string(); +// } +// }; + +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> v; + +// boost::filesystem::path p(s); +// boost::filesystem::directory_iterator start(p); +// boost::filesystem::directory_iterator end; +// std::transform(start, end, std::back_inserter(v), path_leaf_string()); + +// std::copy(v.begin(), v.end(), +// std::ostream_iterator<std::string>(std::cout, "\n")); + +// return v; +// } diff --git a/bigpiseal3.5.1/native/examples/patternSearch/v2/util.h b/bigpiseal3.5.1/native/examples/patternSearch/v2/util.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8ffd7ce1534fac8fec3d5a4bfb2a2fdf8f0961 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/patternSearch/v2/util.h @@ -0,0 +1,15 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <string> +#include <vector> + +// int findNumberOfFilesInDirectory(const std::string &path); + +bool sub_str_exist(const std::string &str, const std::string &sub_str); + +// std::vector<std::string> get_directories(const std::string &s); + +// std::vector<std::string> get_directories_deep(const std::string &s); + +#endif diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/CMakeLists.txt b/bigpiseal3.5.1/native/examples/similarityMatch/v1/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9695b71711599dbbcf60497f7a766af181e44313 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/CMakeLists.txt @@ -0,0 +1,143 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.10) + +set(TEST_NAME similarityMatch) + +set(GENKEY_BIN ${TEST_NAME}_genkey) +set(ENCR_BIN ${TEST_NAME}_encrypt) +set(DECR_BIN ${TEST_NAME}_decrypt) +set(DECR_RESULT_BIN ${TEST_NAME}_decrypt_result) +set(DECR_RESULT_BIN ${TEST_NAME}_decrypt_1st_result) +set(EVAL_BIN ${TEST_NAME}_evaluate) + +#set(SCR_TEST test.sh) + +set(SCR_ENC encrypt.sh) +set(SCR_DEC decrypt.sh) +set(SCR_DEC_RESULT decrypt_1st_result.sh) +set(SCR_DEC_RESULT decrypt_result.sh) +set(SCR_EVAL eval.sh) +set(SCR_GEN genkey.sh) +set(SCR_TEST test.sh) + + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + + +set(GENKEY_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp + ) + +set(ENCR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp + ) + +set(DECR_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp + ) + +set(DECR_RESULT_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_result.cpp + ) + +set(DECR_RESULT_SRCS + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_1st_result.cpp + ) + +set(EVAL_SRCS + ${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp + ) + + +set(HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/seal_api.h + ${CMAKE_CURRENT_LIST_DIR}/util.h + ) + +add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES}) +add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES}) +add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES}) +add_executable(${DECR_RESULT_BIN} ${DECR_RESULT_SRCS} ${HEADER_FILES}) +add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES}) +#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR}) + +# Import Microsoft SEAL +find_package(SEAL 3.5 REQUIRED) + +target_link_libraries(${GENKEY_BIN} SEAL::seal) +target_link_libraries(${ENCR_BIN} SEAL::seal) +target_link_libraries(${DECR_BIN} SEAL::seal) +target_link_libraries(${DECR_RESULT_BIN} SEAL::seal) +target_link_libraries(${EVAL_BIN} SEAL::seal) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + + +set_target_properties(${GENKEY_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${ENCR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${DECR_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${DECR_RESULT_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) +set_target_properties(${EVAL_BIN} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1" + ) + + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC_RESULT} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_EVAL} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST_V2} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}/v1) \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..4afeb0e131adf8c7fd4baccdab859ee426febe06 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt.sh @@ -0,0 +1,11 @@ +# Decrypt Data + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +resultPath=$1 # ex: result/l.ct +sample=$2 # ex: 40 +keyDir=$3 # ex: keys/ + +time ${CURR_DIR}/similarityMatch_decrypt "$resultPath" "$sample" "$keyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_1st_result.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_1st_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..ac522c90bc5e3b1107528fa73531d4e9d705f78f --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_1st_result.sh @@ -0,0 +1,11 @@ +# Decrypt Result + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +resultPath=$1 # ex: result/l.ct +sample=$2 # ex: 40 +keyDir=$3 # ex: keys/ + +time ${CURR_DIR}/similarityMatch_decrypt_1st_result "$resultPath" "$sample" "$keyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_result.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..1887b1ffe3403c7fb29cd442cac96ac810917295 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/decrypt_result.sh @@ -0,0 +1,11 @@ +# Decrypt Result + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +resultPath=$1 # ex: result/l.ct +sample=$2 # ex: 40 +keyDir=$3 # ex: keys/ + +time ${CURR_DIR}/similarityMatch_decrypt_result "$resultPath" "$sample" "$keyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/encrypt.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/encrypt.sh new file mode 100644 index 0000000000000000000000000000000000000000..ba91f5130e5d69ff48e3f8934c82627d204ffceb --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/encrypt.sh @@ -0,0 +1,13 @@ +# Encrypt Data + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +licenseNo=$1 # ex: "23 65 78 127 255" (en ASCII) +outputFileName=$2 # ex: "l" (extension will be .ct) +outputDir=$3 # ex: lcheck/ +sample=$4 # ex: 40 +keyDir=$5 # ex: keys/ + +time ${CURR_DIR}/similarityMatch_encrypt "$licenseNo" "$outputFileName" "$outputDir" "$sample" "$keyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/eval.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/eval.sh new file mode 100644 index 0000000000000000000000000000000000000000..367cd69b4bbba7f26e7d4804ff8fdf7f7f2a7455 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/eval.sh @@ -0,0 +1,14 @@ +# Evaluate + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +licensePath=$1 # ex: lcheck/l.ct +licensePathList=${@: 2:$#-5} # ex: parent/l0/l.ct parent/l1/l.ct parent/l2/l.ct parent/l3/l.ct parent/l4/l.ct parent/l5/l.ct parent/l6/l.ct parent/l7/l.ct parent/l8/l.ct parent/l9/l.ct +outputFileName=${@: -4:1} # ex: "l" (extension will be .ct) +outputDir=${@: -3:1} # ex: result/ +sample=${@: -2:1} # ex: 40 +KeyDir=${@: -1} # ex: keys/ + +time ${CURR_DIR}/similarityMatch_evaluate "$licensePath" $licensePathList "$outputFileName" "$outputDir" "$sample" "$KeyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/genkey.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/genkey.sh new file mode 100644 index 0000000000000000000000000000000000000000..1333f412a38211932c88587ec661a6e926dc6fea --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/genkey.sh @@ -0,0 +1,9 @@ +# Generate Keys + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +###################### General - Begin ###################### +keyDir=$1 # ex: keys/ + +time ${CURR_DIR}/similarityMatch_genkey "$keyDir" +###################### General - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e98da78cceb85c11846c15dfb5b069679b6d3c95 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.cpp @@ -0,0 +1,750 @@ +#include "seal_api.h" + +/* namespaces */ +using namespace std; +using namespace seal; + +/* functions */ +int open_binary_file(ifstream &in_file, const string &filename) +{ + int ret = 1; + in_file = ifstream(filename, ios::binary); + if (!in_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int open_binary_file(ofstream &out_file, const string &filename) +{ + int ret = 1; + out_file = ofstream(filename, ios::binary); + if (!out_file) + { + // cerr << "[ERRROR] file opening failure" << endl; + ret = 0; + } + + return ret; +} + +int save_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + params.save(out_file); + else + ret = 0; + return ret; +} + +int load_params(EncryptionParameters &params, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + params.load(in_file); + else + ret = 0; + return ret; +} + +void init_context(size_t poly_d, size_t p_modulus, shared_ptr<SEALContext> &context) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(p_modulus); + + save_params(params, "bfv_params.conf"); + + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching(size_t poly_d, int bit_size, shared_ptr<SEALContext> &context, const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_d)); + params.set_plain_modulus(PlainModulus::Batching(poly_d, bit_size)); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void init_context_batching( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, shared_ptr<SEALContext> &context, + const std::string &key_dir) +{ + EncryptionParameters params(scheme_type::BFV); + params.set_poly_modulus_degree(poly_d); + params.set_coeff_modulus(CoeffModulus::Create(poly_d, { 36, 36, 37 })); + params.set_plain_modulus(plain_modulus); + save_params(params, key_dir + "bfv_params.conf"); + context = SEALContext::Create(params); + print_context(context); +} + +void load_context(shared_ptr<SEALContext> &context, const string &filename) +{ + EncryptionParameters params; + load_params(params, filename); + context = SEALContext::Create(params); + print_context(context); +} + +/* print paramaeters function from examples.h */ +void print_context(shared_ptr<SEALContext> &context) +{ + if (!context) + throw invalid_argument("[ERROR] context is not set"); + + auto &context_data = *context->key_context_data(); + /* which scheme is used */ + string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw invalid_argument("[ERROR] unsupported scheme"); + } + + // cout << "[CONTEXT] scheme: " << scheme_name << endl; + // cout << "[CONTEXT] poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl; + + /* Print the size of the true (product) coefficient modulus */ + // cout << "[CONTEXT] coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + + // auto coeff_modulus = context_data.parms().coeff_modulus(); + // size_t coeff_modulus_size = coeff_modulus.size(); + // for (size_t i = 0; i < coeff_modulus_size - 1; i++) + + // cout << coeff_modulus[i].bit_count() << " + "; + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << endl; + // cout << "[CONTEXT] coeff_modulus values: (" ; + + // for (int i = 0; i < (coeff_modulus.size() - 1); ++i) + // { + // cout << coeff_modulus[i].value() << ",\t"; + // cout << coeff_modulus[coeff_modulus.size() - 1].value() << ")" << endl; + // } + + /* For the BFV scheme print the plain_modulus parameter */ + // if (context_data.parms().scheme() == seal::scheme_type::BFV) + // { + // cout << "[CONTEXT] plain_modulus: " << context_data.parms().plain_modulus().value() << endl; + // } +} + +int save_key(PublicKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(SecretKey &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(RelinKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<RelinKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(GaloisKeys &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int save_key(Serializable<GaloisKeys> &k, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + k.save(out_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, PublicKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, SecretKey &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, RelinKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_key(shared_ptr<SEALContext> &context, const string &filename, GaloisKeys &k) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + k.load(context, in_file); + else + ret = 0; + return ret; +} + +void generate_keys(size_t poly_d, size_t p_modulus, bool serializable) +{ + shared_ptr<SEALContext> context; + init_context(poly_d, p_modulus, context); + + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + save_key(pk, "bfv.pk"); + SecretKey sk = keygen.secret_key(); + save_key(sk, "bfv.sk"); + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, "bfv.lk"); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, "bfv.lk"); + } +} + +bool suffix_exist(const std::string &str, const std::string &suffix) +{ + return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +/* +Helper function: Prints the parameters in a SEALContext. +*/ +inline void print_parameters(std::shared_ptr<seal::SEALContext> context) +{ + // Verify parameters + if (!context) + { + throw std::invalid_argument("context is not set"); + } + auto &context_data = *context->key_context_data(); + + /* + Which scheme are we using? + */ + std::string scheme_name; + switch (context_data.parms().scheme()) + { + case seal::scheme_type::BFV: + scheme_name = "BFV"; + break; + case seal::scheme_type::CKKS: + scheme_name = "CKKS"; + break; + default: + throw std::invalid_argument("unsupported scheme"); + } + // cout << "/" << std::endl; + // cout << "| Encryption parameters :" << std::endl; + // cout << "| scheme: " << scheme_name << std::endl; + // cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << std::endl; + + /* + Print the size of the true (product) coefficient modulus. + */ + // cout << "| coeff_modulus size: "; + // cout << context_data.total_coeff_modulus_bit_count() << " ("; + // auto coeff_modulus = context_data.parms().coeff_modulus(); + // std::size_t coeff_modulus_size = coeff_modulus.size(); + // for (std::size_t i = 0; i < coeff_modulus_size - 1; i++) + // { + // cout << coeff_modulus[i].bit_count() << " + "; + // } + // cout << coeff_modulus.back().bit_count(); + // cout << ") bits" << std::endl; + + /* + For the BFV scheme print the plain_modulus parameter. + */ + // if (context_data.parms().scheme() == seal::scheme_type::BFV) + // { + // cout << "| plain_modulus: " << context_data.parms().plain_modulus().value() << std::endl; + // } + + // cout << "\\" << std::endl; +} + +void batching_generate_keys(size_t poly_d, int bit_size, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_size, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_size, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void batching_generate_keys( + size_t poly_d, vector<int> bit_sizes, std::uint64_t plain_modulus, string key_dir, bool serializable) +{ + shared_ptr<SEALContext> context; + // init_context_batching(poly_d, bit_sizes, plain_modulus, context, key_dir); + // auto qualifiers = context->first_context_data()->qualifiers(); + // cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl; + + string keypath(""); + string keypath1("/bfv.pk"); + string keypath2("/bfv.sk"); + string keypath3("/bfv.lk"); + string keypath4("/bfv.gk"); + string bfv_params_path(key_dir + "/"); + + if (suffix_exist(key_dir, "/")) + { + keypath1 = "bfv.pk"; + keypath2 = "bfv.sk"; + keypath3 = "bfv.lk"; + keypath4 = "bfv.gk"; + bfv_params_path = key_dir; + } + + init_context_batching(poly_d, bit_sizes, plain_modulus, context, bfv_params_path); + KeyGenerator keygen(context); + PublicKey pk = keygen.public_key(); + keypath.append(key_dir); + keypath.append(keypath1); + + // cout << "[INFO] Keypathname pk: " << keypath << endl; + save_key(pk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath2); + SecretKey sk = keygen.secret_key(); + // cout << "[INFO] Keypathname sk: " << keypath << endl; + save_key(sk, keypath); + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath3); + // cout << "[INFO] Keypathname lk: " << keypath << endl; + if (serializable) + { + Serializable<RelinKeys> lk = keygen.relin_keys(); + save_key(lk, keypath); + } + else + { + RelinKeys lk = keygen.relin_keys_local(); + save_key(lk, keypath); + } + + keypath = ""; + keypath.append(key_dir); + keypath.append(keypath4); + // cout << "[INFO] Keypathname gk: " << keypath << endl; + if (serializable) + { + Serializable<GaloisKeys> gk = keygen.galois_keys(); + save_key(gk, keypath); + } + else + { + GaloisKeys gk = keygen.galois_keys_local(); + save_key(gk, keypath); + } + // print_parameters(context); +} + +void init_operator(struct encryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + PublicKey pk; + load_key(op_st.context, "bfv.pk", pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct encryptor_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + PublicKey pk; + string keypath(""); + string keypath1("bfv.pk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath encrypt: " << keypath << endl; + load_key(op_st.context, keypath, pk); + op_st.encr = new Encryptor(op_st.context, pk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct encryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct encryptor_t &op_st) +{ + delete op_st.encr; + delete op_st.icode; +} + +void delete_operator_batching(struct encryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct decryptor_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + SecretKey sk; + load_key(op_st.context, "bfv.sk", sk); + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator(struct decryptor_t &op_st, const std::string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + + load_context(op_st.context, bfv_params_path); + SecretKey sk; + string keypath(""); + string keypath1("bfv.sk"); + + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath decrypt: " << keypath << endl; + + load_key(op_st.context, keypath, sk); + + op_st.decr = new Decryptor(op_st.context, sk); + op_st.icode = new IntegerEncoder(op_st.context); +} + +void init_operator_batching(struct decryptor_t &op_st, const string &key_dir) +{ + init_operator(op_st, key_dir); + op_st.bcode = new BatchEncoder(op_st.context); +} + +void delete_operator(struct decryptor_t &op_st) +{ + delete op_st.decr; + delete op_st.icode; +} + +void delete_operator_batching(struct decryptor_t &op_st) +{ + delete_operator(op_st); + delete op_st.bcode; +} + +void init_operator(struct evaluator_t &op_st) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, "bfv.lk", op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator(struct evaluator_t &op_st, const string &relink_key_path) +{ + load_context(op_st.context, "bfv_params.conf"); + load_key(op_st.context, relink_key_path, op_st.lk); + op_st.eval = new Evaluator(op_st.context); +} + +void init_operator_batching(struct evaluator_t &op_st, const string &key_dir) +{ + string bfv_params_path(""); + string bfv_params_path1("/bfv_params.conf"); + bfv_params_path = ""; + bfv_params_path.append(key_dir); + bfv_params_path.append(bfv_params_path1); + // cout << "[INFO] bfvparams: " << bfv_params_path << endl; + load_context(op_st.context, bfv_params_path); + + string keypath(""); + string keypath1("bfv.lk"); + keypath.append(key_dir); + keypath.append(keypath1); + // cout << "[INFO] Keypath evaluator: " << keypath << endl; + load_key(op_st.context, keypath, op_st.lk); + + string keypath3(""); + string keypath4("bfv.gk"); + keypath3.append(key_dir); + keypath3.append(keypath4); + // cout << "[INFO] Keypath evaluator: " << keypath3 << endl; + load_key(op_st.context, keypath3, op_st.gk); + + op_st.eval = new Evaluator(op_st.context); +} + +void delete_operator(struct evaluator_t &op_st) +{ + delete op_st.eval; +} + +void delete_operator_batching(struct evaluator_t &op_st) +{ + delete_operator(op_st); +} + +void init_plaintext(struct encryptor_t &op_st, int64_t plain, Plaintext &pt) +{ + pt = Plaintext(op_st.icode->encode(plain)); +} + +void init_ciphertext(struct encryptor_t &op_st, int64_t plain, Ciphertext &ct) +{ + // cout << "[INFO] encrypting: " << endl; + op_st.encr->encrypt(Plaintext(op_st.icode->encode(plain)), ct); + // cout << plain << endl; +} + +void init_ciphermatrix(struct encryptor_t &op_st, vector<int64_t> &plain_matrix, Ciphertext &encrypted_matrix) +{ + // cout << "[INFO] encrypting: " << endl; + Plaintext plaintext_matrix; + // BatchEncoder batch_encoder(op_st.context); + // batch_encoder.encode(plain_matrix, plaintext_matrix); + op_st.bcode->encode(plain_matrix, plaintext_matrix); + op_st.encr->encrypt(plaintext_matrix, encrypted_matrix); + // cout << plain << endl; +} + +void decrypt_ciphertext(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] decrypted result: " << res << endl; +} + +int64_t decrypt_ciphertext_and_return_value(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + int64_t res = op_st.icode->decode_int64(pt); + // cout << "[INFO] Decrypted result: " << res << endl; + return res; +} + +vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, Ciphertext &ct) +{ + Plaintext pt; + op_st.decr->decrypt(ct, pt); + vector<int64_t> pod_matrix; + BatchEncoder batch_encoder(op_st.context); + batch_encoder.decode(pt, pod_matrix); + // print_matrix(pod_matrix, 3); + return pod_matrix; +} + +int save_plaintext(Plaintext &pt, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + pt.save(out_file); + else + ret = 0; + return ret; +} + +int save_ciphertext(Ciphertext &ct, const string &filename) +{ + int ret = 1; + ofstream out_file; + if (open_binary_file(out_file, filename)) + ct.save(out_file); + else + ret = 0; + return ret; +} + +int load_plaintext(shared_ptr<SEALContext> &context, Plaintext &pt, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + pt.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_plaintext(struct evaluator_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_plaintext(struct decryptor_t &op_st, Plaintext &pt, const string &filename) +{ + return load_plaintext(op_st.context, pt, filename); +} + +int load_ciphertext(shared_ptr<SEALContext> &context, Ciphertext &ct, const string &filename) +{ + int ret = 1; + ifstream in_file; + if (open_binary_file(in_file, filename)) + ct.load(context, in_file); + else + ret = 0; + return ret; +} + +int load_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} + +int load_ciphertext(struct decryptor_t &op_st, Ciphertext &ct, const string &filename) +{ + return load_ciphertext(op_st.context, ct, filename); +} diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.h b/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.h new file mode 100644 index 0000000000000000000000000000000000000000..f248144bd2fde614f882f9a69ca3dd7a9fc0c363 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/seal_api.h @@ -0,0 +1,97 @@ +#ifndef _SEAL_API_H_ +#define _SEAL_API_H_ + +/* includes */ +#include <sys/time.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <cstdio> +#include <cassert> +#include <cstdint> +#include <boost/lexical_cast.hpp> +#include "seal/seal.h" + +/* definitions */ +struct encryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Encryptor *encr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct decryptor_t { + std::shared_ptr<seal::SEALContext> context; + seal::Decryptor *decr; + seal::BatchEncoder *bcode; + seal::IntegerEncoder *icode; +}; + +struct evaluator_t { + std::shared_ptr<seal::SEALContext> context; + seal::RelinKeys lk; + seal::GaloisKeys gk; + seal::Evaluator *eval; +}; + +/* prototypes */ +/** for binary files management **/ +int open_binary_file(std::ifstream& in_file, const std::string& filename); +int open_binary_file(std::ofstream& out_file, const std::string& filename); + +/** for context management **/ +int save_params(seal::EncryptionParameters &params, const std::string &filename); +int load_params(seal::EncryptionParameters &params, const std::string &filename); + +void init_context(size_t poly_d, size_t p_modulus, std::shared_ptr<seal::SEALContext>& context); +void load_context(std::shared_ptr<seal::SEALContext>& context, const std::string& filename); +void print_context(std::shared_ptr<seal::SEALContext>& context); + +/** for key management **/ +int save_key(seal::PublicKey& k, const std::string& filename); +int save_key(seal::SecretKey& k, const std::string& filename); +int save_key(seal::RelinKeys& k, const std::string& filename); +int save_key(seal::GaloisKeys& k, const std::string& filename); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::PublicKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::SecretKey& k); +int load_key(std::shared_ptr<seal::SEALContext>& context, const std::string& filename, seal::RelinKeys& k); +void generate_keys(size_t poly_d, size_t p_modulus, bool seriablizable = false); +void batching_generate_keys(size_t poly_d, int bit_size, const std::string key_path, bool serializable = false); +void batching_generate_keys(size_t poly_d, std::vector<int> bit_sizes, std::uint64_t plain_modulus, std::string key_dir, bool serializable = false); + +/** for homomorphic operators management **/ +void init_operator(struct encryptor_t& op_st); +void init_operator(struct encryptor_t &op_st, const std::string& public_key_path); +void init_operator_batching(struct encryptor_t &op_st, const std::string& key_dir); +void init_operator(struct decryptor_t& op_st); +void init_operator(struct decryptor_t &op_st, const std::string& secret_key_path); +void init_operator_batching(struct decryptor_t &op_st, const std::string& key_dir); +void init_operator(struct evaluator_t& op_st); +void init_operator(struct evaluator_t& op_st, const std::string& relink_key_path); +void init_operator_batching(struct evaluator_t &op_st, const std::string &key_dir); +void delete_operator(struct encryptor_t& op_st); +void delete_operator_batching(struct encryptor_t& op_st); +void delete_operator(struct decryptor_t& op_st); +void delete_operator_batching(struct decryptor_t& op_st); +void delete_operator(struct evaluator_t& op_st); +void delete_operator_batching(struct evaluator_t& op_st); + +/** for plaintexts and ciphertexts management **/ +void init_plaintext(struct encryptor_t& op_st, int64_t plain, seal::Plaintext& pt); +void init_ciphertext(struct encryptor_t& op_st, int64_t plain, seal::Ciphertext& ct); +void init_ciphermatrix(struct encryptor_t &op_st, std::vector<int64_t> &plain_matrix, seal::Ciphertext &encrypted_matrix); +void decrypt_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::int64_t decrypt_ciphertext_and_return_value(struct decryptor_t& op_st, seal::Ciphertext& ct); +std::vector<int64_t> decrypt_ciphermatrix(struct decryptor_t &op_st, seal::Ciphertext &ct); + +int save_plaintext(seal::Plaintext& pt, const std::string& filename); +int save_ciphertext(seal::Ciphertext& ct, const std::string& filename); +int load_plaintext(std::shared_ptr<seal::SEALContext>& context, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct evaluator_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_plaintext(struct decryptor_t& op_st, seal::Plaintext& pt, const std::string& filename); +int load_ciphertext(std::shared_ptr<seal::SEALContext>& context, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct evaluator_t& op_st, seal::Ciphertext& ct, const std::string& filename); +int load_ciphertext(struct decryptor_t& op_st, seal::Ciphertext& ct, const std::string& filename); + +#endif diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f8391afffac961f6aae830b1a9df6417c1e5d56 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt.cpp @@ -0,0 +1,73 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// vector<int64_t> decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + vector<int64_t> result = decrypt(sample_size, dir); + + for (int i = 0; i < result.size(); ++i) + { + std::cout << result[i] << ' '; + } + + std::cout << endl; + + return 0; + } +} + + +vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + // init_operator_batching(2048, 4294967296, decr, key_dir); + // init_operator_batching(4096, 4294967296, decr, key_dir); + // init_operator_batching(8192, 4294967296, decr, key_dir); + // init_operator_batching(16384, 4294967296, decr, key_dir); + // init_operator_batching(32768, 4294967296, decr, key_dir); + + vector<int64_t> v; + if (sample_size <= decr.bcode->slot_count()/2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + for (size_t i = 0; i < sample_size; i++) + { + v.push_back(pod_matrix[i]); + } + } + else + { + // cout << endl << "Sample size is too large" << endl; + } + delete_operator_batching(decr); + return v; +} diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_1st_result.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_1st_result.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c21c8ea1019c1bea34f8daaff373e1141ce1a62 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_1st_result.cpp @@ -0,0 +1,77 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +void binarySimilarityCalculateDecrypt1st(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + // cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + binarySimilarityCalculateDecrypt1st(sample_size, dir); + + return 0; + } +} + +void binarySimilarityCalculateDecrypt1st(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + if (sample_size <= decr.bcode->slot_count() / 2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + vector<int64_t> v1; + for (size_t i = 0; i < sample_size; i++) + { + v1.push_back(pod_matrix[i]); + } + + float sum = 0; + for (size_t i = 0; i < v1.size(); i++) + { + if (v1[i] == 0) + { + sum = sum + 1; + } + + if ((i + 1) % sample_size == 0) + { + // cout << ((i + 1) / 40) << " : "; + cout << ((sum / sample_size) * 100); + sum = 0; + cout << endl; + } + } + } + else + { + cout << endl << "Sample size is too large" << endl; + } + + delete_operator_batching(decr); + // return isContain; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_result.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_result.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2d6c1f7055bc47b18d997e7e57777480d0cc26c --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_decrypt_result.cpp @@ -0,0 +1,267 @@ +#include <iomanip> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +string ciphertext_name; +string key_dir; + +// bool decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir); +bool decrypt(int &sample_size, string &ciphertext_dir); +void binarySimilarityCalculateDecrypt(int &sample_size, string &ciphertext_dir); +void binarySimilarityCalculateDecrypt1st(int &sample_size, string &ciphertext_dir); + +int main(int argc, char **argv) +{ + if (argc != 4) + { + // cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl; + // cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl; + // cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl; + return -1; + } + else + { + string dir = argv[1]; + int sample_size = atol(argv[2]); + key_dir = argv[3]; + + binarySimilarityCalculateDecrypt(sample_size, dir); + // binarySimilarityCalculateDecrypt1st(sample_size, dir); + // bool result_str = decrypt(sample_size, dir); + // cout << result_str << endl; + + return 0; + } +} + +bool decrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + bool isContain = false; + if (sample_size <= decr.bcode->slot_count() / 2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + // cout << pod_matrix.size() << endl; + + int no_dual_vectors = (decr.bcode->slot_count() / 2) / (sample_size); + + for (size_t i = 0; i < decr.bcode->slot_count(); i++) + { + cout << (pod_matrix[i]); + } + + vector<int64_t> v1, v2; + for (size_t i = 0; i < no_dual_vectors * sample_size; i++) + { + v1.push_back(pod_matrix[i]); + v2.push_back(pod_matrix[(pod_matrix.size() / 2) + i]); + } + + int64_t sum = 0; + if (isContain == false) + { + cout << "1 : "; + for (size_t i = 0; i < v1.size(); i++) + { + cout << v1[i]; + if ((i + 1) % sample_size == 0) + { + cout << endl; + if (i < v1.size() - 1) + { + cout << ((i + 1) / 40) + 1 << " : "; + } + } + else + { + cout << ", "; + } + + if (v1[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + cout << endl; + + if (isContain == false) + { + sum = 0; + cout << (v2.size() + 1) / 40 + 1 << " : "; + for (size_t i = 0; i < v2.size(); i++) + { + cout << v2[i]; + if ((i + 1) % sample_size == 0) + { + cout << endl; + if (i < v2.size() - 1) + { + cout << ((v2.size() + i + 1) / 40) + 1 << " : "; + } + } + else + { + cout << ", "; + } + + if (v2[i] == 0) + { + sum = sum + 1; + } + else + { + sum = 0; + } + if (sum == sample_size) + { + isContain = true; + } + } + } + + cout << sample_size; + } + else + { + cout << endl << "Sample size is too large" << endl; + } + + delete_operator_batching(decr); + return isContain; +} + +void binarySimilarityCalculateDecrypt(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + if (sample_size <= decr.bcode->slot_count() / 2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + // cout << pod_matrix.size() << endl; + + int no_dual_vectors = (decr.bcode->slot_count() / 2) / (sample_size); + + vector<int64_t> v1, v2; + for (size_t i = 0; i < no_dual_vectors * sample_size; i++) + { + v1.push_back(pod_matrix[i]); + v2.push_back(pod_matrix[(pod_matrix.size() / 2) + i]); + } + + float sum = 0; + for (size_t i = 0; i < v1.size(); i++) + { + if (v1[i] == 0) + { + sum = sum + 1; + } + + if ((i + 1) % sample_size == 0) + { + // cout << ((i + 1) / 40) << " : "; + cout << ((sum / sample_size) * 100); + sum = 0; + cout << endl; + } + } + + float sum2 = 0; + for (size_t i = 0; i < v2.size(); i++) + { + if (v2[i] == 0) + { + sum2 = sum2 + 1; + } + + if ((i + 1) % sample_size == 0) + { + // cout << ((v2.size() + i + 1) / 40) << " : "; + cout << ((sum2 / sample_size) * 100); + sum2 = 0; + cout << endl; + } + } + } + else + { + cout << endl << "Sample size is too large" << endl; + } + delete_operator_batching(decr); +} + +void binarySimilarityCalculateDecrypt1st(int &sample_size, string &ciphertext_dir) +{ + struct decryptor_t decr; + init_operator_batching(decr, key_dir); + + if (sample_size <= decr.bcode->slot_count() / 2) + { + Ciphertext cipher_matrix; + + vector<int64_t> pod_matrix; + load_ciphertext(decr, cipher_matrix, ciphertext_dir); + pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix); + + vector<int64_t> v1; + for (size_t i = 0; i < sample_size; i++) + { + v1.push_back(pod_matrix[i]); + } + + int unMatched = 0; + int other = 0; + float sum = 0; + for (size_t i = 0; i < v1.size(); i++) + { + if (v1[i] == 0) + { + sum = sum + 1; + } else if (v1[i] == 1 || v1[i] == -1) + { + unMatched = unMatched + 1; + } else { + other = other + 1; + } + + if ((i + 1) % sample_size == 0) + { + // cout << ((i + 1) / 40) << " : "; + cout << (sum / (sample_size - other) * 100); + sum = 0; + cout << endl; + } + } + } + else + { + cout << endl << "Sample size is too large" << endl; + } + + delete_operator_batching(decr); + // return isContain; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_encrypt.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09d7f8052cab5518915e7421be1eedd6f5b1aff6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_encrypt.cpp @@ -0,0 +1,55 @@ +#include "seal_api.h" + +using namespace seal; +using namespace std; + + +int main(int argc, char **argv) +{ + if (argc != 6) + { + // cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl; + cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or " + "prefix, ciphertext output file directory, sample size and public key path" + << endl; + // cout << "patternSearchN_encrypt \"1 2 3 ... 99\" filename directory/subdirectory/ 40 keys/" << endl; + return -1; + } + else + { + string plaintext = argv[1]; + string ciphertext_name = argv[2]; + string ciphertext_dir = argv[3]; + int sample_size = atol(argv[4]); + string key_dir = argv[5]; + + struct encryptor_t encr; + init_operator_batching(encr, key_dir); + + stringstream ss; + ss << plaintext; + vector<int64_t> pod_matrix; + int64_t x = 0; + + while (ss >> x) + { + pod_matrix.push_back(x); + } + + if (pod_matrix.size() <= encr.bcode->slot_count() / 2 && pod_matrix.size() <= sample_size) + { + Ciphertext encrypted_matrix; + init_ciphermatrix(encr, pod_matrix, encrypted_matrix); + save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct"); + delete_operator_batching(encr); + return 0; + } + else + { + delete_operator_batching(encr); + return -1; + } + // delete_operator_batching(encr); + // return 0; + } +} diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_evaluate.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_evaluate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..024a60ba6c431931db7068f980074852804630e6 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_evaluate.cpp @@ -0,0 +1,543 @@ +// #include <algorithm> +// #include <iterator> +// #include <vector> +// #include <filesystem> +#include <iostream> +#include "seal_api.h" +#include "util.h" + +using namespace seal; +using namespace std; + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out); + +bool is_number(const string &s); + +void printStrVector(const vector<string> &v); + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct); + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out); + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2); + +void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain); + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out); + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent); + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain); + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct); + +int computeSimilarity( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir); + +// string relink_key_path; +// string galois_key_path; +// string public_key_path; +string key_dir = ""; + +vector<vector<string>> split_ends(const vector<string> &data, const vector<int> &ends); + +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval); + +int main(int argc, char **argv) +{ + // input processing - begin + // string result_name = argv[argc - 6]; + // string result_dir = argv[argc - 5]; + // int sample_size = atoi(argv[argc - 4]); + // relink_key_path = argv[argc - 3]; + // galois_key_path = argv[argc - 2]; + // public_key_path = argv[argc - 1]; + string source = argv[1]; + + string result_name = argv[argc - 4]; + string result_dir = argv[argc - 3]; + int sample_size = atoi(argv[argc - 2]); + key_dir = argv[argc - 1]; + + vector<string> data; + for (int i = 2; i < argc - 4; i++) + { + data.push_back(argv[i]); + } + + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || + // relink_key_path == "" || galois_key_path == "" || public_key_path == "") + if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || key_dir == "") + { + // error handling + cout << "[ERROR] please enter a source path, data paths, output ciphertext file name or prefix, output " + "ciphertext directory, sample size, linking key path, galois key path and public key path" + << endl; + return -1; + } + // input processing - end + + int result = computeSimilarity(source, data, result_name, result_dir, sample_size, key_dir); + // int result = checkSq(source, data, result_name, result_dir, sample_size, key_dir); + // checkSq(source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, public_key_path); + + // error handling + if (result == -1) + { + fprintf(stderr, "error!\n"); + } + else + { + cout << "done"; + } + + return result; +} + +int computeSimilarity( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + // cout << "\n[INFO] Start Similarity Search Algorithm!" << endl; + + // cout << "\n[INFO] Start Initializing Evaluator!" << endl; + struct evaluator_t eval; + init_operator_batching(eval, key_dir); + // cout << "[INFO] End Initializing Evaluator!" << endl; + + // cout << "\n[INFO] Start Initializing Encryptor!" << endl; + struct encryptor_t encr; + init_operator_batching(encr, key_dir); + // cout << "[INFO] End Initializing Encryptor!" << endl; + + // cout << "\n[INFO] Input Parameters:" << endl; + // cout << " Sample Size: " << sample_size << endl; + // cout << " Required Slots (Sample Size x Data Size): " << sample_size * data.size() << endl; + // cout << " Provided Slots: " << encr.bcode->slot_count() << endl; + + if (sample_size * data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count() / 2) + { + // Error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // Normalizing data input if the number ciphertext is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + // cout << "[INFO] normalized_data_size: " << normalized_data_size << endl; + + int normalized_required_slots = normalized_data_size * sample_size; + int half_normalized_required_slots = normalized_required_slots / 2; + // int required_range_row = normalized_required_slots / 2; + + // Create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - half_normalized_required_slots; + + // cout << "[INFO] padding_slots: " << padding_slots << endl; + + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[half_normalized_required_slots + i] = 1; + padding_matrix[encr.bcode->slot_count() - 1 - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (half_normalized_required_slots > 0 && half_normalized_required_slots <= encr.bcode->slot_count()) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // Add dummy vector for oddy data + + temp2 = encrypted_dummy_matrix; + } + // Switching column + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + // Shifting slots + // cout << "[INFO] index: " << index << endl; + // eval.eval->rotate_rows_inplace(encrypted_result_matrix, +sample_size, eval.gk); + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + // Shifting the remaining slots + // eval.eval->rotate_rows_inplace(encrypted_result_matrix, +((encr.bcode->slot_count() - sample_size * + // data.size()) / 2), eval.gk); eval.eval->rotate_rows_inplace(encrypted_result_matrix, + // +((encr.bcode->slot_count()%sample_size))/2, eval.gk); + } + + save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + // cout << "\n[INFO] End Similarity Search Algorithm!" << endl; + + return 0; + } +} + + + + + + +// This is advance algorithm - Testing +// int checkSq( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path) +int checkSq( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir) +{ + struct evaluator_t eval; + // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + init_operator_batching(eval, key_dir); + + struct encryptor_t encr; + // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // init_operator_batching(16384, 4294967296, encr, public_key_path); + // init_operator_batching(32768, 4294967296, encr, public_key_path); + init_operator_batching(encr, key_dir); + + // if (sample_size*data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count()/2) + if (sample_size > encr.bcode->slot_count() / 2) + { + // error handling + delete_operator_batching(encr); + delete_operator_batching(eval); + return -1; + } + else + { + // struct evaluator_t eval; + // // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path); + // init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path); + // // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path); + + // struct encryptor_t encr; + // // init_operator_batching(4096, 4294967296, encr, public_key_path); + // init_operator_batching(8192, 4294967296, encr, public_key_path); + // // init_operator_batching(16384, 4294967296, encr, public_key_path); + // // init_operator_batching(32768, 4294967296, encr, public_key_path); + + int capacity = (encr.bcode->slot_count()) / sample_size; + // cout << capacity << endl; + + // vector<string> v_temp; + // vector<string> v_v_temp; + // Ciphertext result; + vector<Ciphertext> v_result; + int nSq = data.size() / capacity; + for (size_t i = 0; i < nSq; i++) + { + Ciphertext result; + // cout << "sq : " << i << endl; + vector<string> v_temp; + for (size_t j = 0; j < capacity; j++) + { + string str = data.back(); + v_temp.push_back(str); + data.pop_back(); + } + if (i == 0) + { + // cout << "sq : init" << endl; + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + else + { + // cout << "sq : other" << endl; + // Ciphertext result2 = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + // result = check( + // source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval); + v_result.push_back(result); + } + } + + if (data.size() % capacity != 0) + { + // cout << "oddy!!! " << endl; + // Ciphertext result = check( + // source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, + // public_key_path, encr, eval); + Ciphertext result = check(source, data, result_name, result_dir, sample_size, key_dir, encr, eval); + // multiply_ciphertext(eval, result2, result, result); + // relinearize_inplace(eval, result); + v_result.push_back(result); + } + + Ciphertext result; + multiply_ciphertexts(eval, v_result, result); + relinearize_inplace(eval, result); + + save_ciphertext(result, result_dir + "/" + result_name + ".ct"); + delete_operator_batching(encr); + delete_operator_batching(eval); + + return 0; + } +} + +// Ciphertext check( +// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, +// string &relink_key_path, string &galois_key_path, string &public_key_path, struct encryptor_t &encr, +// struct evaluator_t &eval) +Ciphertext check( + string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir, + struct encryptor_t &encr, struct evaluator_t &eval) +{ + // if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0) + // { + // // error handling + // // return -1; + + // } + // else + // { + + Ciphertext encrypted_result_matrix; + vector<int64_t> result_matrix; + init_ciphermatrix(encr, result_matrix, encrypted_result_matrix); + + vector<int64_t> dummy_matrix; + for (size_t i = 0; i < sample_size; i++) + { + dummy_matrix.push_back(1); + } + Ciphertext encrypted_dummy_matrix; + init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix); + + // normalize input data if its size is odd + int normalized_data_size; + if (data.size() % 2 == 0) + { + normalized_data_size = data.size(); + } + else + { + normalized_data_size = data.size() + 1; + } + + int required_range = normalized_data_size * sample_size; + int required_no_row_elements = required_range / 2; + int required_range_row = required_range / 2; + + // create padding matrix + int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row; + vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL); + for (size_t i = 0; i < padding_slots; i++) + { + padding_matrix[required_no_row_elements + i] = 1; + padding_matrix[encr.bcode->slot_count() - i] = 1; + } + Ciphertext encrypted_padding_matrix; + init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix); + + if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0) + { + for (int index = 0; index < normalized_data_size / 2; index++) + { + Ciphertext ct1, ct2, ct3; + Ciphertext temp1, temp2; + // cout << "[INFO] loading ciphertext 1" << endl; + load_ciphertext(eval, ct1, source); + // cout << "[INFO] loading ciphertext 2" << endl; + load_ciphertext(eval, ct2, data.at(index)); + sub_ciphertext(eval, ct1, ct2, temp1); + + if ((normalized_data_size / 2) + index < data.size()) + { + // cout << "[INFO] loading ciphertext 3" << endl; + load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index)); + sub_ciphertext(eval, ct1, ct3, temp2); + } + else + { + // add dummy vector for oddy data + temp2 = encrypted_dummy_matrix; + } + + eval.eval->rotate_columns_inplace(temp2, eval.gk); + add_ciphertext(eval, temp1, temp2, temp1); + + add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix); + + // avoid the last shift + if (index + 1 != (normalized_data_size / 2)) + { + eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk); + } + } + // add renmaining padding slots + add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix); + } + + // // save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct"); + // delete_operator_batching(eval); + + return encrypted_result_matrix; + // } +} + +void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->sub(ct1, ct2, ct_out); +} + +void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->sub_inplace(ct1, ct2); +} + +void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->sub_plain_inplace(ct, plain); +} + +void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->negate_inplace(ct); +} + +void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->add_plain_inplace(ct, plain); +} + +void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->add(ct1, ct2, ct_out); +} + +void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->add_many(cts, ct_out); +} + +void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out) +{ + op_st.eval->multiply(ct1, ct2, ct_out); +} + +void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2) +{ + op_st.eval->multiply_inplace(ct1, ct2); +} + +void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out) +{ + op_st.eval->multiply_many(cts, op_st.lk, ct_out); +} + +void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain) +{ + op_st.eval->multiply_plain_inplace(ct, plain); +} + +void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->relinearize_inplace(ct, op_st.lk); +} + +void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out) +{ + op_st.eval->relinearize(ct, op_st.lk, ct_out); +} + +void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->rescale_to_next_inplace(ct); +} + +void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent) +{ + op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk); +} + +void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct) +{ + op_st.eval->mod_switch_to_next_inplace(ct); +} diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_genkey.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_genkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af3a074e0143790087372822879c86eb4810f5df --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/similarityMatch_genkey.cpp @@ -0,0 +1,31 @@ +#include "seal_api.h" + +using namespace std; +using namespace seal; + +int main(int argc, char **argv) +{ + string key_dir = argv[1]; + + size_t poly_d = 4096; + + // Params option 1 + int bit_size = 20; + + // Params option 2 + // uint64_t plain_modulus = 1032193; + // vector<int> bit_sizes = { 36, 36, 37 }; + + // timeval t0, t1; + // unsigned long dt = 0; + // gettimeofday(&t0, NULL); + + batching_generate_keys(poly_d, bit_size, key_dir, true); + // batching_generate_keys(poly_d, bit_sizes, plain_modulus, key_dir, true); + + // gettimeofday(&t1, NULL); + // dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec); + // cout << "[INFO] keys generation time in seconds: " << ((float)dt)/1000000 << endl; + + return 0; +} diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/test.sh b/bigpiseal3.5.1/native/examples/similarityMatch/v1/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..eb6bd335eda6a47cf4605e0936c4b677d6275e7e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/test.sh @@ -0,0 +1,99 @@ +# Testing Script + +CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + + +###################### Test 1 - Begin ###################### +mkdir -p keys/ +mkdir -p lcheck/ +mkdir -p parent/ +mkdir -p result/ +# rm ls.txt + +# Number of ciphertext data, eg: (0..99) +min=0 +max=0 # max=101 or 1631 + +n_char=39 # Number of chars/words of a ciphertext, eg: 9 + +# Encrypted number range, eg: 2(1-bit), 10, 100, 255(8-bit), 1000 +# range=255 +range=2 + +sample=40 # sampling size + +# Generate keys +${CURR_DIR}/similarityMatch_genkey keys/ # gen keys + +# Get random data line +if [[ "$max" -ne 0 ]] +then + line=$((RANDOM %max)) +else + line=0 +fi + +lcheck="" +# Generate data randomly +for i in $(seq $min $max) +do + mkdir -p parent/l"$i"/ + echo "Created folder $i" + value="" + for j in $(seq 0 $n_char) + do + value+="$((RANDOM %$range)) " + done + echo $value + echo $value >> ls.txt + # ./similarityMatch_encrypt "$value" "l" parent/l"$i"/ $sample keys/ + ${CURR_DIR}/similarityMatch_encrypt "$value" "l" parent/l"$i"/ $sample keys/ + if [[ "$line" -eq "$i" ]] + then + lcheck="$value" + fi +done + +echo "Pick up data to check: $lcheck" + +${CURR_DIR}/similarityMatch_encrypt "$lcheck" "l" lcheck/ $sample keys/ + +# Evaluate +value1="lcheck/l.ct " +value2="" +for i in $(seq 0 $max) +do + value2+="parent/l${i}/l.ct " +done +value3="$value1$value2" +echo "$value3" + +time ${CURR_DIR}/similarityMatch_evaluate $value3 "l" result/ $sample keys/ + +echo "" + +${CURR_DIR}/similarityMatch_decrypt_1st_result result/l.ct $sample keys/ + +# rm -r keys/* +# rm -r lcheck/* +# rm -r parent/* +# rm -r result/* +# rm ls.txt +###################### Test 1 - End ######################## + + + + + +###################### Report - Begin ###################### +# sim: (eval: 0.465s, 0.488s, 0.480s decrypt: 0.028s, 0.080s, 0.077s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=203 +# (eval: 3.635s, 3.510s, 3.628s decrypt: 0.062s, 0.153s. 0.134s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=407 +# (eval: 38.607s, 39.600s, 39.565s decrypt: 0.264s, 0.260s, 0.245s) +# seq: (eval: 0.xxx, 0.xxx, 0.xxx decrypt: 0.xxx, 0.xxx, 0.xxx) +# max=815 +# (eval: x decrypt: x ) +###################### Report - End ######################## \ No newline at end of file diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.cpp b/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72367dab3632e64801bf24ead89070859286704e --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.cpp @@ -0,0 +1,73 @@ +#include "util.h" +// #include <filesystem> +#include "seal_api.h" + +// #include <boost/filesystem.hpp> + +// namespace fs = boost::filesystem; + +bool sub_str_exist(const std::string &str, const std::string &sub_str) +{ + return str.size() >= sub_str.size() && str.compare(str.size() - sub_str.size(), sub_str.size(), sub_str) == 0; +} + +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// auto dirIter = std::filesystem::directory_iterator(path); +// int fileCount = std::count_if( +// begin(dirIter), +// end(dirIter), +// [](auto &entry) { return entry.is_regular_file(); }); +// return fileCount; +// } + +// int findNumberOfFilesInDirectory(std::string &path, std::string &ext) +// int findNumberOfFilesInDirectory(const std::string &path) +// { +// // namespace fs = boost::filesystem; + +// std::string ext = ".ct"; + +// fs::path Path(path); +// int Nb_ext = 0; +// fs::directory_iterator end_iter; // Default constructor for an iterator is the end iterator + +// for (fs::directory_iterator iter(Path); iter != end_iter; ++iter) +// if (iter->path().extension() == ext) +// ++Nb_ext; + +// return Nb_ext; +// } + +// c++ 17 +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> r; +// for(auto& p : std::filesystem::recursive_directory_iterator(s)) +// if (p.is_directory()) +// r.push_back(p.path().string()); +// return r; +// } + +// struct path_leaf_string +// { +// std::string operator()(const boost::filesystem::directory_entry &entry) const +// { +// return entry.path().leaf().string(); +// } +// }; + +// std::vector<std::string> get_directories(const std::string &s) +// { +// std::vector<std::string> v; + +// boost::filesystem::path p(s); +// boost::filesystem::directory_iterator start(p); +// boost::filesystem::directory_iterator end; +// std::transform(start, end, std::back_inserter(v), path_leaf_string()); + +// std::copy(v.begin(), v.end(), +// std::ostream_iterator<std::string>(std::cout, "\n")); + +// return v; +// } diff --git a/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.h b/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8ffd7ce1534fac8fec3d5a4bfb2a2fdf8f0961 --- /dev/null +++ b/bigpiseal3.5.1/native/examples/similarityMatch/v1/util.h @@ -0,0 +1,15 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <string> +#include <vector> + +// int findNumberOfFilesInDirectory(const std::string &path); + +bool sub_str_exist(const std::string &str, const std::string &sub_str); + +// std::vector<std::string> get_directories(const std::string &s); + +// std::vector<std::string> get_directories_deep(const std::string &s); + +#endif diff --git a/bigpiseal3.5.1/native/src/CMakeConfig.cmd b/bigpiseal3.5.1/native/src/CMakeConfig.cmd new file mode 100644 index 0000000000000000000000000000000000000000..52691451665cb3a4bb06a1b754ed97576a5bc7d2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/CMakeConfig.cmd @@ -0,0 +1,97 @@ +@echo off + +rem Copyright (c) Microsoft Corporation. All rights reserved. +rem Licensed under the MIT license. + +setlocal + +rem The purpose of this script is to have CMake generate config.h for use by Microsoft SEAL. +rem We assume that CMake was installed with Visual Studio, which should be the default +rem when the user installs the "Desktop Development with C++" workload. + +set VSVERSION=%~1 +set PROJECTCONFIGURATION=%~2 +set PROJECTPLATFORM=%~3 +set VSDEVENVDIR=%~4 +set INCLUDEPATH=%~5 +set LIBRARYPATH=%~6 + +echo Configuring Microsoft SEAL through CMake + +if not exist "%VSDEVENVDIR%" ( + rem We may be running in the CI server. Try a standard VS path. + echo Did not find VS at provided location: "%VSDEVENVDIR%". + echo Trying standard location. + set VSDEVENVDIR="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE" +) + +set VSDEVENVDIR=%VSDEVENVDIR:"=% +set CMAKEPATH=%VSDEVENVDIR%\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe + +if not exist "%CMAKEPATH%" ( + echo ****************************************************************************************************************** + echo ** Did not find CMake at "%CMAKEPATH%" + echo ** Please make sure "Visual C++ Tools for CMake" are enabled in the "Desktop development with C++" workload. + echo ****************************************************************************************************************** + exit 1 +) + +echo Found CMake at %CMAKEPATH% + +rem Identify Visual Studio version and set CMake generator accordingly. +set CMAKEGEN="" +if "%VSVERSION%"=="15.0" ( + set CMAKEGEN="Visual Studio 15 2017" +) else if "%VSVERSION%"=="16.0" ( + set CMAKEGEN="Visual Studio 16 2019" +) else ( + echo *************************************************** + echo ** Unsupported Visual Studio version "%VSVERSION%" + echo *************************************************** + exit 1 +) + +rem Download Microsoft GSL +set MSGSLCONFIGDIR="..\..\thirdparty\msgsl\.config\%VSVERSION%\%PROJECTPLATFORM%" +cd %~dp0 +if not exist %MSGSLCONFIGDIR% ( + mkdir %MSGSLCONFIGDIR% +) +cd %MSGSLCONFIGDIR% +"%CMAKEPATH%" ..\..\.. -G %CMAKEGEN% -A %PROJECTPLATFORM% +"%CMAKEPATH%" --build . --config "%PROJECTCONFIGURATION%" + +rem Copy Microsoft GSL header files into the local source directory +robocopy ..\..\..\src\include %~dp0 /s + +rem Download and build ZLIB +set ZLIBCONFIGDIR="..\..\thirdparty\zlib\.config\%VSVERSION%\%PROJECTPLATFORM%" +cd %~dp0 +if not exist %ZLIBCONFIGDIR% ( + mkdir %ZLIBCONFIGDIR% +) +cd %ZLIBCONFIGDIR% +"%CMAKEPATH%" ..\..\.. -G %CMAKEGEN% -A %PROJECTPLATFORM% ^ + -DZLIB_PLATFORM="%PROJECTPLATFORM%" + +"%CMAKEPATH%" --build . --config "%PROJECTCONFIGURATION%" + +rem Configure Microsoft SEAL +set CONFIGDIR="..\..\.config\%VSVERSION%\%PROJECTPLATFORM%" +cd %~dp0 +if not exist %CONFIGDIR% ( + mkdir %CONFIGDIR% +) +cd %CONFIGDIR% +echo Running CMake configuration in %cd% + +"%CMAKEPATH%" ..\..\.. -G %CMAKEGEN% -A %PROJECTPLATFORM% ^ + -DALLOW_COMMAND_LINE_BUILD=1 ^ + -DCMAKE_BUILD_TYPE="%PROJECTCONFIGURATION%" ^ + -DBUILD_SHARED_LIBS=OFF ^ + -DSEAL_USE_MSGSL=ON ^ + -DSEAL_USE_ZLIB=ON ^ + -DSEAL_BUILD_TESTS=OFF ^ + -DSEAL_BUILD_EXAMPLES=OFF ^ + -DSEAL_BUILD_SEAL_C=OFF ^ + --no-warn-unused-cli diff --git a/bigpiseal3.5.1/native/src/SEAL.vcxproj b/bigpiseal3.5.1/native/src/SEAL.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..09c2a7c426aa203633a6d25ebde5f5060eb1b4a5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/SEAL.vcxproj @@ -0,0 +1,356 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <ClInclude Include="seal\batchencoder.h" /> + <ClInclude Include="seal\biguint.h" /> + <ClInclude Include="seal\ciphertext.h" /> + <ClInclude Include="seal\ckks.h" /> + <ClInclude Include="seal\modulus.h" /> + <ClInclude Include="seal\context.h" /> + <ClInclude Include="seal\decryptor.h" /> + <ClInclude Include="seal\encryptionparams.h" /> + <ClInclude Include="seal\encryptor.h" /> + <ClInclude Include="seal\evaluator.h" /> + <ClInclude Include="seal\galoiskeys.h" /> + <ClInclude Include="seal\intarray.h" /> + <ClInclude Include="seal\intencoder.h" /> + <ClInclude Include="seal\keygenerator.h" /> + <ClInclude Include="seal\kswitchkeys.h" /> + <ClInclude Include="seal\memorymanager.h" /> + <ClInclude Include="seal\plaintext.h" /> + <ClInclude Include="seal\publickey.h" /> + <ClInclude Include="seal\randomgen.h" /> + <ClInclude Include="seal\randomtostd.h" /> + <ClInclude Include="seal\relinkeys.h" /> + <ClInclude Include="seal\seal.h" /> + <ClInclude Include="seal\secretkey.h" /> + <ClInclude Include="seal\serializable.h" /> + <ClInclude Include="seal\serialization.h" /> + <ClInclude Include="seal\util\blake2.h" /> + <ClInclude Include="seal\util\blake2-impl.h" /> + <ClInclude Include="seal\util\clang.h" /> + <ClInclude Include="seal\util\clipnormal.h" /> + <ClInclude Include="seal\util\common.h" /> + <ClInclude Include="seal\util\croots.h" /> + <ClInclude Include="seal\util\defines.h" /> + <ClInclude Include="seal\util\galois.h" /> + <ClInclude Include="seal\util\gcc.h" /> + <ClInclude Include="seal\util\globals.h" /> + <ClInclude Include="seal\util\hash.h" /> + <ClInclude Include="seal\util\hestdparms.h" /> + <ClInclude Include="seal\util\iterator.h" /> + <ClInclude Include="seal\util\locks.h" /> + <ClInclude Include="seal\util\mempool.h" /> + <ClInclude Include="seal\util\msvc.h" /> + <ClInclude Include="seal\util\numth.h" /> + <ClInclude Include="seal\util\pointer.h" /> + <ClInclude Include="seal\util\polyarith.h" /> + <ClInclude Include="seal\util\polyarithmod.h" /> + <ClInclude Include="seal\util\polyarithsmallmod.h" /> + <ClInclude Include="seal\util\polycore.h" /> + <ClInclude Include="seal\util\rlwe.h" /> + <ClInclude Include="seal\util\rns.h" /> + <ClInclude Include="seal\util\scalingvariant.h" /> + <ClInclude Include="seal\util\ntt.h" /> + <ClInclude Include="seal\util\streambuf.h" /> + <ClInclude Include="seal\util\uintarith.h" /> + <ClInclude Include="seal\util\uintarithmod.h" /> + <ClInclude Include="seal\util\uintarithsmallmod.h" /> + <ClInclude Include="seal\util\uintcore.h" /> + <ClInclude Include="seal\util\ztools.h" /> + <ClInclude Include="seal\valcheck.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="seal\batchencoder.cpp" /> + <ClCompile Include="seal\biguint.cpp" /> + <ClCompile Include="seal\ciphertext.cpp" /> + <ClCompile Include="seal\ckks.cpp" /> + <ClCompile Include="seal\modulus.cpp" /> + <ClCompile Include="seal\context.cpp" /> + <ClCompile Include="seal\decryptor.cpp" /> + <ClCompile Include="seal\encryptionparams.cpp" /> + <ClCompile Include="seal\encryptor.cpp" /> + <ClCompile Include="seal\evaluator.cpp" /> + <ClCompile Include="seal\intencoder.cpp" /> + <ClCompile Include="seal\keygenerator.cpp" /> + <ClCompile Include="seal\kswitchkeys.cpp" /> + <ClCompile Include="seal\memorymanager.cpp" /> + <ClCompile Include="seal\plaintext.cpp" /> + <ClCompile Include="seal\randomgen.cpp" /> + <ClCompile Include="seal\serialization.cpp" /> + <ClCompile Include="seal\util\rns.cpp" /> + <ClCompile Include="seal\util\ztools.cpp" /> + <ClCompile Include="seal\valcheck.cpp" /> + <ClCompile Include="seal\util\blake2b.c" /> + <ClCompile Include="seal\util\blake2xb.c" /> + <ClCompile Include="seal\util\clipnormal.cpp" /> + <ClCompile Include="seal\util\croots.cpp" /> + <ClCompile Include="seal\util\galois.cpp" /> + <ClCompile Include="seal\util\globals.cpp" /> + <ClCompile Include="seal\util\hash.cpp" /> + <ClCompile Include="seal\util\mempool.cpp" /> + <ClCompile Include="seal\util\numth.cpp" /> + <ClCompile Include="seal\util\polyarith.cpp" /> + <ClCompile Include="seal\util\polyarithmod.cpp" /> + <ClCompile Include="seal\util\polyarithsmallmod.cpp" /> + <ClCompile Include="seal\util\rlwe.cpp" /> + <ClCompile Include="seal\util\scalingvariant.cpp" /> + <ClCompile Include="seal\util\ntt.cpp" /> + <ClCompile Include="seal\util\streambuf.cpp" /> + <ClCompile Include="seal\util\uintarith.cpp" /> + <ClCompile Include="seal\util\uintarithmod.cpp" /> + <ClCompile Include="seal\util\uintarithsmallmod.cpp" /> + <ClCompile Include="seal\util\uintcore.cpp" /> + </ItemGroup> + <ItemGroup> + <Text Include="seal\CMakeLists.txt" /> + <Text Include="seal\util\CMakeLists.txt" /> + </ItemGroup> + <ItemGroup> + <None Include="cmake\FindMSGSL.cmake" /> + <None Include="cmake\SEALConfig.cmake.in" /> + <None Include="seal\util\config.h.in" /> + <None Include="CMakeConfig.cmd" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{7EA96C25-FC0D-485A-BB71-32B6DA55652A}</ProjectGuid> + <RootNamespace>SEAL</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <CLRSupport>false</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <CLRSupport>false</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <CLRSupport>false</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <CLRSupport>false</CLRSupport> + </PropertyGroup> + <PropertyGroup> + <ZlibName Condition="'$(ZLIB_ROOT)'!=''">zlibstatic.lib</ZlibName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\</IntDir> + <TargetExt>.lib</TargetExt> + <TargetName>seal</TargetName> + <ExtensionsToDeleteOnClean> + </ExtensionsToDeleteOnClean> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\</IntDir> + <TargetExt>.lib</TargetExt> + <TargetName>seal</TargetName> + <ExtensionsToDeleteOnClean> + </ExtensionsToDeleteOnClean> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\</IntDir> + <TargetExt>.lib</TargetExt> + <TargetName>seal</TargetName> + <ExtensionsToDeleteOnClean> + </ExtensionsToDeleteOnClean> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\</IntDir> + <TargetExt>.lib</TargetExt> + <TargetName>seal</TargetName> + <ExtensionsToDeleteOnClean> + </ExtensionsToDeleteOnClean> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)\thirdparty\zlib\build\$(Platform);$(SolutionDir)/thirdparty/zlib/src;$(ProjectDir)</AdditionalIncludeDirectories> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Neither</FavorSizeOrSpeed> + <LanguageStandard>stdcpp17</LanguageStandard> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <OmitFramePointers>false</OmitFramePointers> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + <PreBuildEvent> + <Command>"$(ProjectDir)CMakeConfig.cmd" "$(VisualStudioVersion)" "$(Configuration)" "$(Platform)" "$(DevEnvDir)" "$(IncludePath)" "$(LibraryPath)"</Command> + </PreBuildEvent> + <PreBuildEvent> + <Message>Configure Microsoft SEAL through CMake</Message> + </PreBuildEvent> + <Lib> + <AdditionalDependencies>Bcrypt.lib;zlibstaticd.lib</AdditionalDependencies> + <AdditionalLibraryDirectories>$(SolutionDir)\thirdparty\zlib\build\$(Platform)\$(Configuration)</AdditionalLibraryDirectories> + <AdditionalOptions>/IGNORE:4006 %(AdditionalOptions)</AdditionalOptions> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)/thirdparty/zlib/src;$(SolutionDir)/thirdparty/zlib/build/$(Platform);$(ProjectDir)</AdditionalIncludeDirectories> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Neither</FavorSizeOrSpeed> + <LanguageStandard>stdcpp17</LanguageStandard> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + <PreBuildEvent> + <Command>"$(ProjectDir)CMakeConfig.cmd" "$(VisualStudioVersion)" "$(Configuration)" "$(Platform)" "$(DevEnvDir)" "$(IncludePath)" "$(LibraryPath)"</Command> + </PreBuildEvent> + <PreBuildEvent> + <Message>Configure Microsoft SEAL through CMake</Message> + </PreBuildEvent> + <Lib> + <AdditionalDependencies>Bcrypt.lib;zlibstaticd.lib</AdditionalDependencies> + <AdditionalLibraryDirectories>$(SolutionDir)\thirdparty\zlib\build\$(Platform)\$(Configuration)</AdditionalLibraryDirectories> + <AdditionalOptions>/IGNORE:4006 %(AdditionalOptions)</AdditionalOptions> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)/thirdparty/zlib/src;$(SolutionDir)/thirdparty/zlib/build/$(Platform);$(ProjectDir)</AdditionalIncludeDirectories> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <InlineFunctionExpansion>Default</InlineFunctionExpansion> + <LanguageStandard>stdcpp17</LanguageStandard> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + <ControlFlowGuard>Guard</ControlFlowGuard> + <OmitFramePointers>true</OmitFramePointers> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + <PreBuildEvent> + <Command>"$(ProjectDir)CMakeConfig.cmd" "$(VisualStudioVersion)" "$(Configuration)" "$(Platform)" "$(DevEnvDir)" "$(IncludePath)" "$(LibraryPath)"</Command> + </PreBuildEvent> + <PreBuildEvent> + <Message>Configure Microsoft SEAL through CMake</Message> + </PreBuildEvent> + <Lib> + <AdditionalDependencies>Bcrypt.lib;zlibstatic.lib</AdditionalDependencies> + <AdditionalLibraryDirectories>$(SolutionDir)\thirdparty\zlib\build\$(Platform)\$(Configuration)</AdditionalLibraryDirectories> + <AdditionalOptions>/IGNORE:4006 %(AdditionalOptions)</AdditionalOptions> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <AdditionalIncludeDirectories>$(SolutionDir)/thirdparty/zlib/src;$(SolutionDir)/thirdparty/zlib/build/$(Platform);$(ProjectDir)</AdditionalIncludeDirectories> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <InlineFunctionExpansion>Default</InlineFunctionExpansion> + <LanguageStandard>stdcpp17</LanguageStandard> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + <ControlFlowGuard>Guard</ControlFlowGuard> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + <PreBuildEvent> + <Command>"$(ProjectDir)CMakeConfig.cmd" "$(VisualStudioVersion)" "$(Configuration)" "$(Platform)" "$(DevEnvDir)" "$(IncludePath)" "$(LibraryPath)"</Command> + </PreBuildEvent> + <PreBuildEvent> + <Message>Configure Microsoft SEAL through CMake</Message> + </PreBuildEvent> + <Lib> + <AdditionalDependencies>Bcrypt.lib;zlibstatic.lib</AdditionalDependencies> + <AdditionalLibraryDirectories>$(SolutionDir)\thirdparty\zlib\build\$(Platform)\$(Configuration)</AdditionalLibraryDirectories> + <AdditionalOptions>/IGNORE:4006 %(AdditionalOptions)</AdditionalOptions> + </Lib> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets" /> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/SEAL.vcxproj.filters b/bigpiseal3.5.1/native/src/SEAL.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..4777f42f96298c610824c61da0b5e3bf8e90a579 --- /dev/null +++ b/bigpiseal3.5.1/native/src/SEAL.vcxproj.filters @@ -0,0 +1,351 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Source Files\util"> + <UniqueIdentifier>{a119ce23-aae9-4b06-be2c-1c8aada4ab20}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\util"> + <UniqueIdentifier>{8740bd83-253c-49f3-8f9a-3b9c526f67c2}</UniqueIdentifier> + </Filter> + <Filter Include="Other"> + <UniqueIdentifier>{8585bc5e-eaa9-481a-a6ee-c38be1319a32}</UniqueIdentifier> + </Filter> + <Filter Include="Other\cmake"> + <UniqueIdentifier>{aaf838b1-cab2-4ccc-a016-a81c7edf506e}</UniqueIdentifier> + </Filter> + <Filter Include="Other\seal"> + <UniqueIdentifier>{31fb1149-1a6f-438b-a86a-744384986d21}</UniqueIdentifier> + </Filter> + <Filter Include="Other\seal\util"> + <UniqueIdentifier>{497d5f96-98a3-44e9-8b38-a2ea4bbea366}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="seal\batchencoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\biguint.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\ciphertext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\ckks.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\context.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\decryptor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\encryptionparams.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\encryptor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\evaluator.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\galoiskeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\intarray.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\intencoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\keygenerator.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\kswitchkeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\memorymanager.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\plaintext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\publickey.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\randomgen.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\randomtostd.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\relinkeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\seal.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\secretkey.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\modulus.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\valcheck.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\util\blake2.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\blake2-impl.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\clang.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\clipnormal.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\common.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\croots.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\defines.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\gcc.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\galois.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\globals.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\hash.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\hestdparms.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\locks.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\mempool.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\msvc.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\numth.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\pointer.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\polyarith.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\polyarithmod.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\polyarithsmallmod.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\polycore.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\rlwe.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\scalingvariant.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\ntt.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\streambuf.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\util\uintarith.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\uintarithmod.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\uintarithsmallmod.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\uintcore.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\serializable.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\serialization.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\util\ztools.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\rns.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + <ClInclude Include="seal\util\iterator.h"> + <Filter>Header Files\util</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="seal\batchencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\biguint.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\ciphertext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\ckks.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\context.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\decryptor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\encryptionparams.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\encryptor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\evaluator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\intencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\keygenerator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\kswitchkeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\memorymanager.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\modulus.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\plaintext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\randomgen.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\serialization.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\valcheck.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\util\blake2xb.c"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\blake2b.c"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\clipnormal.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\croots.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\galois.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\globals.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\hash.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\mempool.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\numth.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarith.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarithmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarithsmallmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\rlwe.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\rns.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\scalingvariant.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\ntt.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\streambuf.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarith.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarithmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarithsmallmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintcore.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\ztools.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Text Include="seal\CMakeLists.txt"> + <Filter>Other\seal</Filter> + </Text> + <Text Include="seal\util\CMakeLists.txt"> + <Filter>Other\seal\util</Filter> + </Text> + </ItemGroup> + <ItemGroup> + <None Include="cmake\SEALConfig.cmake.in"> + <Filter>Other\cmake</Filter> + </None> + <None Include="seal\util\config.h.in"> + <Filter>Other\seal\util</Filter> + </None> + <None Include="cmake\FindMSGSL.cmake"> + <Filter>Other\cmake</Filter> + </None> + <None Include="CMakeConfig.cmd"> + <Filter>Other</Filter> + </None> + </ItemGroup> +</Project> diff --git a/bigpiseal3.5.1/native/src/SEAL_C.vcxproj b/bigpiseal3.5.1/native/src/SEAL_C.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..9d6ce5634f5af71357da2ac3abdfcc079712a6df --- /dev/null +++ b/bigpiseal3.5.1/native/src/SEAL_C.vcxproj @@ -0,0 +1,268 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>SEAL_C</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + <ProjectName>SEAL_C</ProjectName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <TargetName>sealc</TargetName> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\c\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <TargetName>sealc</TargetName> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\c\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <TargetName>sealc</TargetName> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\c\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration)\</OutDir> + <TargetName>sealc</TargetName> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\seal\c\</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>SEAL_C_EXPORTS;NOMINMAX;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SCL_SECURE_NO_WARNING;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <PrecompiledHeaderFile>seal\c/stdafx.h</PrecompiledHeaderFile> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <ControlFlowGuard>Guard</ControlFlowGuard> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>SEAL_C_EXPORTS;NOMINMAX;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SCL_SECURE_NO_WARNING;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <PrecompiledHeaderFile>seal\c\stdafx.h</PrecompiledHeaderFile> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <ControlFlowGuard>Guard</ControlFlowGuard> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>SEAL_C_EXPORTS;NOMINMAX;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SCL_SECURE_NO_WARNING;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <PrecompiledHeaderFile>seal\c\stdafx.h</PrecompiledHeaderFile> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>SEAL_C_EXPORTS;NOMINMAX;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SCL_SECURE_NO_WARNING;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + <PrecompiledHeaderFile>seal\c\stdafx.h</PrecompiledHeaderFile> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <ControlFlowGuard>Guard</ControlFlowGuard> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>seal.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="seal\c\modulus.h" /> + <ClInclude Include="seal\c\contextdata.h" /> + <ClInclude Include="seal\c\batchencoder.h" /> + <ClInclude Include="seal\c\biguint.h" /> + <ClInclude Include="seal\c\ciphertext.h" /> + <ClInclude Include="seal\c\ckksencoder.h" /> + <ClInclude Include="seal\c\decryptor.h" /> + <ClInclude Include="seal\c\defines.h" /> + <ClInclude Include="seal\c\intencoder.h" /> + <ClInclude Include="seal\c\encryptionparameterqualifiers.h" /> + <ClInclude Include="seal\c\encryptionparameters.h" /> + <ClInclude Include="seal\c\encryptor.h" /> + <ClInclude Include="seal\c\evaluator.h" /> + <ClInclude Include="seal\c\galoiskeys.h" /> + <ClInclude Include="seal\c\keygenerator.h" /> + <ClInclude Include="seal\c\kswitchkeys.h" /> + <ClInclude Include="seal\c\memorymanager.h" /> + <ClInclude Include="seal\c\memorypoolhandle.h" /> + <ClInclude Include="seal\c\plaintext.h" /> + <ClInclude Include="seal\c\publickey.h" /> + <ClInclude Include="seal\c\relinkeys.h" /> + <ClInclude Include="seal\c\sealcontext.h" /> + <ClInclude Include="seal\c\secretkey.h" /> + <ClInclude Include="seal\c\serialization.h" /> + <ClInclude Include="seal\c\stdafx.h" /> + <ClInclude Include="seal\c\targetver.h" /> + <ClInclude Include="seal\c\utilities.h" /> + <ClInclude Include="seal\c\valcheck.h" /> + <ClInclude Include="seal\c\version.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="seal\c\modulus.cpp" /> + <ClCompile Include="seal\c\contextdata.cpp" /> + <ClCompile Include="seal\c\batchencoder.cpp" /> + <ClCompile Include="seal\c\ciphertext.cpp" /> + <ClCompile Include="seal\c\ckksencoder.cpp" /> + <ClCompile Include="seal\c\decryptor.cpp" /> + <ClCompile Include="seal\c\dllmain.cpp" /> + <ClCompile Include="seal\c\biguint.cpp" /> + <ClCompile Include="seal\c\intencoder.cpp" /> + <ClCompile Include="seal\c\encryptionparameterqualifiers.cpp" /> + <ClCompile Include="seal\c\encryptor.cpp" /> + <ClCompile Include="seal\c\evaluator.cpp" /> + <ClCompile Include="seal\c\galoiskeys.cpp" /> + <ClCompile Include="seal\c\keygenerator.cpp" /> + <ClCompile Include="seal\c\kswitchkeys.cpp" /> + <ClCompile Include="seal\c\memorymanager.cpp" /> + <ClCompile Include="seal\c\memorypoolhandle.cpp" /> + <ClCompile Include="seal\c\plaintext.cpp" /> + <ClCompile Include="seal\c\publickey.cpp" /> + <ClCompile Include="seal\c\relinkeys.cpp" /> + <ClCompile Include="seal\c\sealcontext.cpp" /> + <ClCompile Include="seal\c\secretkey.cpp" /> + <ClCompile Include="seal\c\serialization.cpp" /> + <ClCompile Include="seal\c\encryptionparameters.cpp" /> + <ClCompile Include="seal\c\utilities.cpp" /> + <ClCompile Include="seal\c\stdafx.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="seal\c\valcheck.cpp" /> + <ClCompile Include="seal\c\version.cpp" /> + </ItemGroup> + <ItemGroup> + <Text Include="seal\c\CMakeLists.txt" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/SEAL_C.vcxproj.filters b/bigpiseal3.5.1/native/src/SEAL_C.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..967cb45f3f42f0ef8076f74324ff2fb0763c73d1 --- /dev/null +++ b/bigpiseal3.5.1/native/src/SEAL_C.vcxproj.filters @@ -0,0 +1,196 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Other"> + <UniqueIdentifier>{1027e253-e357-4456-b08e-f29b7cceb334}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="seal\c\defines.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\stdafx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\targetver.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\utilities.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\batchencoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\biguint.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\ciphertext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\ckksencoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\contextdata.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\decryptor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\encryptionparameterqualifiers.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\encryptionparameters.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\encryptor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\evaluator.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\galoiskeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\intencoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\keygenerator.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\kswitchkeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\memorymanager.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\memorypoolhandle.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\modulus.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\plaintext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\publickey.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\relinkeys.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\sealcontext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\secretkey.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\serialization.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\valcheck.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="seal\c\version.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="seal\c\dllmain.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\utilities.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\stdafx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\batchencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\biguint.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\ciphertext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\ckksencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\contextdata.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\decryptor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\encryptionparameterqualifiers.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\encryptionparameters.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\encryptor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\evaluator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\galoiskeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\intencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\keygenerator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\kswitchkeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\memorymanager.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\memorypoolhandle.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\modulus.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\plaintext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\publickey.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\relinkeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\sealcontext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\secretkey.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\serialization.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\valcheck.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\c\version.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Text Include="seal\c\CMakeLists.txt"> + <Filter>Other</Filter> + </Text> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/CMakeLists.txt b/bigpiseal3.5.1/native/src/seal/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..12e19e715cd65aab724ae71934a4e694c773b0b3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Source files in this directory +target_sources(seal_obj PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/batchencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/biguint.cpp + ${CMAKE_CURRENT_LIST_DIR}/ciphertext.cpp + ${CMAKE_CURRENT_LIST_DIR}/ckks.cpp + ${CMAKE_CURRENT_LIST_DIR}/context.cpp + ${CMAKE_CURRENT_LIST_DIR}/decryptor.cpp + ${CMAKE_CURRENT_LIST_DIR}/intencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptionparams.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptor.cpp + ${CMAKE_CURRENT_LIST_DIR}/evaluator.cpp + ${CMAKE_CURRENT_LIST_DIR}/keygenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/memorymanager.cpp + ${CMAKE_CURRENT_LIST_DIR}/modulus.cpp + ${CMAKE_CURRENT_LIST_DIR}/plaintext.cpp + ${CMAKE_CURRENT_LIST_DIR}/randomgen.cpp + ${CMAKE_CURRENT_LIST_DIR}/serialization.cpp + ${CMAKE_CURRENT_LIST_DIR}/valcheck.cpp +) + +# Add header files for installation +install( + FILES + ${CMAKE_CURRENT_LIST_DIR}/batchencoder.h + ${CMAKE_CURRENT_LIST_DIR}/biguint.h + ${CMAKE_CURRENT_LIST_DIR}/ciphertext.h + ${CMAKE_CURRENT_LIST_DIR}/ckks.h + ${CMAKE_CURRENT_LIST_DIR}/modulus.h + ${CMAKE_CURRENT_LIST_DIR}/context.h + ${CMAKE_CURRENT_LIST_DIR}/decryptor.h + ${CMAKE_CURRENT_LIST_DIR}/intencoder.h + ${CMAKE_CURRENT_LIST_DIR}/encryptionparams.h + ${CMAKE_CURRENT_LIST_DIR}/encryptor.h + ${CMAKE_CURRENT_LIST_DIR}/evaluator.h + ${CMAKE_CURRENT_LIST_DIR}/galoiskeys.h + ${CMAKE_CURRENT_LIST_DIR}/intarray.h + ${CMAKE_CURRENT_LIST_DIR}/keygenerator.h + ${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.h + ${CMAKE_CURRENT_LIST_DIR}/memorymanager.h + ${CMAKE_CURRENT_LIST_DIR}/plaintext.h + ${CMAKE_CURRENT_LIST_DIR}/publickey.h + ${CMAKE_CURRENT_LIST_DIR}/randomgen.h + ${CMAKE_CURRENT_LIST_DIR}/randomtostd.h + ${CMAKE_CURRENT_LIST_DIR}/relinkeys.h + ${CMAKE_CURRENT_LIST_DIR}/seal.h + ${CMAKE_CURRENT_LIST_DIR}/secretkey.h + ${CMAKE_CURRENT_LIST_DIR}/serializable.h + ${CMAKE_CURRENT_LIST_DIR}/serialization.h + ${CMAKE_CURRENT_LIST_DIR}/valcheck.h + DESTINATION + ${SEAL_INCLUDES_INSTALL_DIR}/seal +) + +add_subdirectory(util) diff --git a/bigpiseal3.5.1/native/src/seal/batchencoder.cpp b/bigpiseal3.5.1/native/src/seal/batchencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc88963b7c82752ab6529113427aa25a521560ab --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/batchencoder.cpp @@ -0,0 +1,552 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/batchencoder.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/polycore.h" +#include <cstdlib> +#include <limits> +#include <random> +#include <stdexcept> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + BatchEncoder::BatchEncoder(shared_ptr<SEALContext> context) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + auto &context_data = *context_->first_context_data(); + if (context_data.parms().scheme() != scheme_type::BFV) + { + throw invalid_argument("unsupported scheme"); + } + if (!context_data.qualifiers().using_batching) + { + throw invalid_argument("encryption parameters are not valid for batching"); + } + + // Set the slot count + slots_ = context_data.parms().poly_modulus_degree(); + + // Reserve space for all of the primitive roots + roots_of_unity_ = allocate_uint(slots_, pool_); + + // Fill the vector of roots of unity with all distinct odd powers of generator. + // These are all the primitive (2*slots_)-th roots of unity in integers modulo + // parms.plain_modulus(). + populate_roots_of_unity_vector(context_data); + + // Populate matrix representation index map + populate_matrix_reps_index_map(); + } + + void BatchEncoder::populate_roots_of_unity_vector(const SEALContext::ContextData &context_data) + { + uint64_t root = context_data.plain_ntt_tables()->get_root(); + auto &modulus = context_data.parms().plain_modulus(); + + uint64_t generator_sq = multiply_uint_uint_mod(root, root, modulus); + roots_of_unity_[0] = root; + + for (size_t i = 1; i < slots_; i++) + { + roots_of_unity_[i] = multiply_uint_uint_mod(roots_of_unity_[i - 1], generator_sq, modulus); + } + } + + void BatchEncoder::populate_matrix_reps_index_map() + { + int logn = get_power_of_two(slots_); + matrix_reps_index_map_ = allocate<size_t>(slots_, pool_); + + // Copy from the matrix to the value vectors + size_t row_size = slots_ >> 1; + size_t m = slots_ << 1; + uint64_t gen = 3; + uint64_t pos = 1; + for (size_t i = 0; i < row_size; i++) + { + // Position in normal bit order + uint64_t index1 = (pos - 1) >> 1; + uint64_t index2 = (m - pos - 1) >> 1; + + // Set the bit-reversed locations + matrix_reps_index_map_[i] = safe_cast<size_t>(util::reverse_bits(index1, logn)); + matrix_reps_index_map_[row_size | i] = safe_cast<size_t>(util::reverse_bits(index2, logn)); + + // Next primitive root + pos *= gen; + pos &= (m - 1); + } + } + + void BatchEncoder::reverse_bits(uint64_t *input) + { +#ifdef SEAL_DEBUG + if (input == nullptr) + { + throw invalid_argument("input cannot be null"); + } +#endif + size_t coeff_count = context_->first_context_data()->parms().poly_modulus_degree(); + int logn = get_power_of_two(coeff_count); + for (size_t i = 0; i < coeff_count; i++) + { + uint64_t reversed_i = util::reverse_bits(i, logn); + if (i < reversed_i) + { + swap(input[i], input[reversed_i]); + } + } + } + + void BatchEncoder::encode(const vector<uint64_t> &values_matrix, Plaintext &destination) + { + auto &context_data = *context_->first_context_data(); + + // Validate input parameters + size_t values_matrix_size = values_matrix.size(); + if (values_matrix_size > slots_) + { + throw logic_error("values_matrix size is too large"); + } +#ifdef SEAL_DEBUG + uint64_t modulus = context_data.parms().plain_modulus().value(); + for (auto v : values_matrix) + { + // Validate the i-th input + if (v >= modulus) + { + throw invalid_argument("input value is larger than plain_modulus"); + } + } +#endif + // Set destination to full size + destination.resize(slots_); + destination.parms_id() = parms_id_zero; + + // First write the values to destination coefficients. + // Read in top row, then bottom row. + for (size_t i = 0; i < values_matrix_size; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = values_matrix[i]; + } + for (size_t i = values_matrix_size; i < slots_; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = 0; + } + + // Transform destination using inverse of negacyclic NTT + // Note: We already performed bit-reversal when reading in the matrix + inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables()); + } + + void BatchEncoder::encode(const vector<int64_t> &values_matrix, Plaintext &destination) + { + auto &context_data = *context_->first_context_data(); + uint64_t modulus = context_data.parms().plain_modulus().value(); + + // Validate input parameters + size_t values_matrix_size = values_matrix.size(); + if (values_matrix_size > slots_) + { + throw logic_error("values_matrix size is too large"); + } +#ifdef SEAL_DEBUG + uint64_t plain_modulus_div_two = modulus >> 1; + for (auto v : values_matrix) + { + // Validate the i-th input + if (unsigned_gt(llabs(v), plain_modulus_div_two)) + { + throw invalid_argument("input value is larger than plain_modulus"); + } + } +#endif + // Set destination to full size + destination.resize(slots_); + destination.parms_id() = parms_id_zero; + + // First write the values to destination coefficients. + // Read in top row, then bottom row. + for (size_t i = 0; i < values_matrix_size; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = + (values_matrix[i] < 0) ? (modulus + static_cast<uint64_t>(values_matrix[i])) + : static_cast<uint64_t>(values_matrix[i]); + } + for (size_t i = values_matrix_size; i < slots_; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = 0; + } + + // Transform destination using inverse of negacyclic NTT + // Note: We already performed bit-reversal when reading in the matrix + inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables()); + } +#ifdef SEAL_USE_MSGSL + void BatchEncoder::encode(gsl::span<const uint64_t> values_matrix, Plaintext &destination) + { + auto &context_data = *context_->first_context_data(); + + // Validate input parameters + size_t values_matrix_size = static_cast<size_t>(values_matrix.size()); + if (values_matrix_size > slots_) + { + throw logic_error("values_matrix size is too large"); + } +#ifdef SEAL_DEBUG + uint64_t modulus = context_data.parms().plain_modulus().value(); + for (auto v : values_matrix) + { + // Validate the i-th input + if (v >= modulus) + { + throw invalid_argument("input value is larger than plain_modulus"); + } + } +#endif + // Set destination to full size + destination.resize(slots_); + destination.parms_id() = parms_id_zero; + + // First write the values to destination coefficients. Read + // in top row, then bottom row. + using index_type = decltype(values_matrix)::size_type; + for (size_t i = 0; i < values_matrix_size; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = values_matrix[static_cast<index_type>(i)]; + } + for (size_t i = values_matrix_size; i < slots_; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = 0; + } + + // Transform destination using inverse of negacyclic NTT + // Note: We already performed bit-reversal when reading in the matrix + inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables()); + } + + void BatchEncoder::encode(gsl::span<const int64_t> values_matrix, Plaintext &destination) + { + auto &context_data = *context_->first_context_data(); + uint64_t modulus = context_data.parms().plain_modulus().value(); + + // Validate input parameters + size_t values_matrix_size = static_cast<size_t>(values_matrix.size()); + if (values_matrix_size > slots_) + { + throw logic_error("values_matrix size is too large"); + } +#ifdef SEAL_DEBUG + uint64_t plain_modulus_div_two = modulus >> 1; + for (auto v : values_matrix) + { + // Validate the i-th input + if (unsigned_gt(llabs(v), plain_modulus_div_two)) + { + throw invalid_argument("input value is larger than plain_modulus"); + } + } +#endif + // Set destination to full size + destination.resize(slots_); + destination.parms_id() = parms_id_zero; + + // First write the values to destination coefficients. Read + // in top row, then bottom row. + using index_type = decltype(values_matrix)::size_type; + for (size_t i = 0; i < values_matrix_size; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = + (values_matrix[static_cast<index_type>(i)] < 0) + ? (modulus + static_cast<uint64_t>(values_matrix[static_cast<index_type>(i)])) + : static_cast<uint64_t>(values_matrix[static_cast<index_type>(i)]); + } + for (size_t i = values_matrix_size; i < slots_; i++) + { + *(destination.data() + matrix_reps_index_map_[i]) = 0; + } + + // Transform destination using inverse of negacyclic NTT + // Note: We already performed bit-reversal when reading in the matrix + inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables()); + } +#endif + void BatchEncoder::encode(Plaintext &plain, MemoryPoolHandle pool) + { + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + + // Validate input parameters + if (plain.coeff_count() > context_data.parms().poly_modulus_degree()) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } +#ifdef SEAL_DEBUG + if (!are_poly_coefficients_less_than( + plain.data(), plain.coeff_count(), context_data.parms().plain_modulus().value())) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } +#endif + // We need to permute the coefficients of plain. To do this, we allocate + // temporary space. + size_t input_plain_coeff_count = min(plain.coeff_count(), slots_); + auto temp(allocate_uint(input_plain_coeff_count, pool)); + set_uint_uint(plain.data(), input_plain_coeff_count, temp.get()); + + // Set plain to full slot count size. + plain.resize(slots_); + plain.parms_id() = parms_id_zero; + + // First write the values to destination coefficients. Read + // in top row, then bottom row. + for (size_t i = 0; i < input_plain_coeff_count; i++) + { + *(plain.data() + matrix_reps_index_map_[i]) = temp[i]; + } + for (size_t i = input_plain_coeff_count; i < slots_; i++) + { + *(plain.data() + matrix_reps_index_map_[i]) = 0; + } + + // Transform destination using inverse of negacyclic NTT + // Note: We already performed bit-reversal when reading in the matrix + inverse_ntt_negacyclic_harvey(plain.data(), *context_data.plain_ntt_tables()); + } + + void BatchEncoder::decode(const Plaintext &plain, vector<uint64_t> &destination, MemoryPoolHandle pool) + { + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + + // Set destination size + destination.resize(slots_); + + // Never include the leading zero coefficient (if present) + size_t plain_coeff_count = min(plain.coeff_count(), slots_); + + auto temp_dest(allocate_uint(slots_, pool)); + + // Make a copy of poly + set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get()); + set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count); + + // Transform destination using negacyclic NTT. + ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables()); + + // Read top row + for (size_t i = 0; i < slots_; i++) + { + destination[i] = temp_dest[matrix_reps_index_map_[i]]; + } + } + + void BatchEncoder::decode(const Plaintext &plain, vector<int64_t> &destination, MemoryPoolHandle pool) + { + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + uint64_t modulus = context_data.parms().plain_modulus().value(); + + // Set destination size + destination.resize(slots_); + + // Never include the leading zero coefficient (if present) + size_t plain_coeff_count = min(plain.coeff_count(), slots_); + + auto temp_dest(allocate_uint(slots_, pool)); + + // Make a copy of poly + set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get()); + set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count); + + // Transform destination using negacyclic NTT. + ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables()); + + // Read top row, then bottom row + uint64_t plain_modulus_div_two = modulus >> 1; + for (size_t i = 0; i < slots_; i++) + { + uint64_t curr_value = temp_dest[matrix_reps_index_map_[i]]; + destination[i] = (curr_value > plain_modulus_div_two) + ? (static_cast<int64_t>(curr_value) - static_cast<int64_t>(modulus)) + : static_cast<int64_t>(curr_value); + } + } +#ifdef SEAL_USE_MSGSL + void BatchEncoder::decode(const Plaintext &plain, gsl::span<uint64_t> destination, MemoryPoolHandle pool) + { + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + + using index_type = decltype(destination)::size_type; + if (unsigned_gt(destination.size(), numeric_limits<int>::max()) || unsigned_neq(destination.size(), slots_)) + { + throw invalid_argument("destination has incorrect size"); + } + + // Never include the leading zero coefficient (if present) + size_t plain_coeff_count = min(plain.coeff_count(), slots_); + + auto temp_dest(allocate_uint(slots_, pool)); + + // Make a copy of poly + set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get()); + set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count); + + // Transform destination using negacyclic NTT. + ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables()); + + // Read top row + for (size_t i = 0; i < slots_; i++) + { + destination[static_cast<index_type>(i)] = temp_dest[matrix_reps_index_map_[i]]; + } + } + + void BatchEncoder::decode(const Plaintext &plain, gsl::span<int64_t> destination, MemoryPoolHandle pool) + { + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + uint64_t modulus = context_data.parms().plain_modulus().value(); + + using index_type = decltype(destination)::size_type; + if (unsigned_gt(destination.size(), numeric_limits<int>::max()) || unsigned_neq(destination.size(), slots_)) + { + throw invalid_argument("destination has incorrect size"); + } + + // Never include the leading zero coefficient (if present) + size_t plain_coeff_count = min(plain.coeff_count(), slots_); + + auto temp_dest(allocate_uint(slots_, pool)); + + // Make a copy of poly + set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get()); + set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count); + + // Transform destination using negacyclic NTT. + ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables()); + + // Read top row, then bottom row + uint64_t plain_modulus_div_two = modulus >> 1; + for (size_t i = 0; i < slots_; i++) + { + uint64_t curr_value = temp_dest[matrix_reps_index_map_[i]]; + destination[static_cast<index_type>(i)] = + (curr_value > plain_modulus_div_two) + ? (static_cast<int64_t>(curr_value) - static_cast<int64_t>(modulus)) + : static_cast<int64_t>(curr_value); + } + } +#endif + void BatchEncoder::decode(Plaintext &plain, MemoryPoolHandle pool) + { + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->first_context_data(); + + // Never include the leading zero coefficient (if present) + size_t plain_coeff_count = min(plain.coeff_count(), slots_); + + // Allocate temporary space to store a wide copy of plain + auto temp(allocate_uint(slots_, pool)); + + // Make a copy of poly + set_uint_uint(plain.data(), plain_coeff_count, temp.get()); + set_zero_uint(slots_ - plain_coeff_count, temp.get() + plain_coeff_count); + + // Transform destination using negacyclic NTT. + ntt_negacyclic_harvey(temp.get(), *context_data.plain_ntt_tables()); + + // Set plain to full slot count size (note that all new coefficients are + // set to zero). + plain.resize(slots_); + + // Read top row, then bottom row + for (size_t i = 0; i < slots_; i++) + { + *(plain.data() + i) = temp[matrix_reps_index_map_[i]]; + } + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/batchencoder.h b/bigpiseal3.5.1/native/src/seal/batchencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..6d2e023deee23b2ae6a5c5060b6853700fee48c1 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/batchencoder.h @@ -0,0 +1,287 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/plaintext.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <limits> +#include <vector> +#ifdef SEAL_USE_MSGSL +#include <gsl/span> +#endif + +namespace seal +{ + /** + Provides functionality for CRT batching. If the polynomial modulus degree is N, and + the plaintext modulus is a prime number T such that T is congruent to 1 modulo 2N, + then BatchEncoder allows the plaintext elements to be viewed as 2-by-(N/2) + matrices of integers modulo T. Homomorphic operations performed on such encrypted + matrices are applied coefficient (slot) wise, enabling powerful SIMD functionality + for computations that are vectorizable. This functionality is often called "batching" + in the homomorphic encryption literature. + + @par Mathematical Background + Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, and + plain_modulus is a prime number T such that 2N divides T-1, then integers modulo T + contain a primitive 2N-th root of unity and the polynomial X^N+1 splits into n distinct + linear factors as X^N+1 = (X-a_1)*...*(X-a_N) mod T, where the constants a_1, ..., a_n + are all the distinct primitive 2N-th roots of unity in integers modulo T. The Chinese + Remainder Theorem (CRT) states that the plaintext space Z_T[X]/(X^N+1) in this case is + isomorphic (as an algebra) to the N-fold direct product of fields Z_T. The isomorphism + is easy to compute explicitly in both directions, which is what this class does. + Furthermore, the Galois group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose + action on the primitive roots of unity is easy to describe. Since the batching slots + correspond 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the + plaintext act by permuting the slots. By applying generators of the two cyclic + subgroups of the Galois group, we can effectively view the plaintext as a 2-by-(N/2) + matrix, and enable cyclic row rotations, and column rotations (row swaps). + + @par Valid Parameters + Whether batching can be used depends on whether the plaintext modulus has been chosen + appropriately. Thus, to construct a BatchEncoder the user must provide an instance + of SEALContext such that its associated EncryptionParameterQualifiers object has the + flags parameters_set and enable_batching set to true. + + @see EncryptionParameters for more information about encryption parameters. + @see EncryptionParameterQualifiers for more information about parameter qualifiers. + @see Evaluator for rotating rows and columns of encrypted matrices. + */ + class BatchEncoder + { + public: + /** + Creates a BatchEncoder. It is necessary that the encryption parameters + given through the SEALContext object support batching. + + @param[in] context The SEALContext + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid for batching + @throws std::invalid_argument if scheme is not scheme_type::BFV + */ + BatchEncoder(std::shared_ptr<SEALContext> context); + + /** + Creates a plaintext from a given matrix. This function "batches" a given matrix + of integers modulo the plaintext modulus into a plaintext element, and stores + the result in the destination parameter. The input vector must have size at most equal + to the degree of the polynomial modulus. The first half of the elements represent the + first row of the matrix, and the second half represent the second row. The numbers + in the matrix can be at most equal to the plaintext modulus for it to represent + a valid plaintext. + + If the destination plaintext overlaps the input values in memory, the behavior of + this function is undefined. + + @param[in] values The matrix of integers modulo plaintext modulus to batch + @param[out] destination The plaintext polynomial to overwrite with the result + @throws std::invalid_argument if values is too large + */ + void encode(const std::vector<std::uint64_t> &values, Plaintext &destination); + + /** + Creates a plaintext from a given matrix. This function "batches" a given matrix + of integers modulo the plaintext modulus into a plaintext element, and stores + the result in the destination parameter. The input vector must have size at most equal + to the degree of the polynomial modulus. The first half of the elements represent the + first row of the matrix, and the second half represent the second row. The numbers + in the matrix can be at most equal to the plaintext modulus for it to represent + a valid plaintext. + + If the destination plaintext overlaps the input values in memory, the behavior of + this function is undefined. + + @param[in] values The matrix of integers modulo plaintext modulus to batch + @param[out] destination The plaintext polynomial to overwrite with the result + @throws std::invalid_argument if values is too large + */ + void encode(const std::vector<std::int64_t> &values, Plaintext &destination); +#ifdef SEAL_USE_MSGSL + /** + Creates a plaintext from a given matrix. This function "batches" a given matrix + of integers modulo the plaintext modulus into a plaintext element, and stores + the result in the destination parameter. The input must have size at most equal + to the degree of the polynomial modulus. The first half of the elements represent the + first row of the matrix, and the second half represent the second row. The numbers + in the matrix can be at most equal to the plaintext modulus for it to represent + a valid plaintext. + + If the destination plaintext overlaps the input values in memory, the behavior of + this function is undefined. + + @param[in] values The matrix of integers modulo plaintext modulus to batch + @param[out] destination The plaintext polynomial to overwrite with the result + @throws std::invalid_argument if values is too large + */ + void encode(gsl::span<const std::uint64_t> values, Plaintext &destination); + + /** + Creates a plaintext from a given matrix. This function "batches" a given matrix + of integers modulo the plaintext modulus into a plaintext element, and stores + the result in the destination parameter. The input must have size at most equal + to the degree of the polynomial modulus. The first half of the elements represent the + first row of the matrix, and the second half represent the second row. The numbers + in the matrix can be at most equal to the plaintext modulus for it to represent + a valid plaintext. + + If the destination plaintext overlaps the input values in memory, the behavior of + this function is undefined. + + @param[in] values The matrix of integers modulo plaintext modulus to batch + @param[out] destination The plaintext polynomial to overwrite with the result + @throws std::invalid_argument if values is too large + */ + void encode(gsl::span<const std::int64_t> values, Plaintext &destination); +#endif + /** + Creates a plaintext from a given matrix. This function "batches" a given matrix + of integers modulo the plaintext modulus in-place into a plaintext ready to be + encrypted. The matrix is given as a plaintext element whose first N/2 coefficients + represent the first row of the matrix, and the second N/2 coefficients represent the + second row, where N denotes the degree of the polynomial modulus. The input plaintext + must have degress less than the polynomial modulus, and coefficients less than the + plaintext modulus, i.e. it must be a valid plaintext for the encryption parameters. + Dynamic memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] plain The matrix of integers modulo plaintext modulus to batch + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if pool is uninitialized + */ + void encode(Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Inverse of encode. This function "unbatches" a given plaintext into a matrix + of integers modulo the plaintext modulus, and stores the result in the destination + parameter. The input plaintext must have degress less than the polynomial modulus, + and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + for the encryption parameters. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext polynomial to unbatch + @param[out] destination The matrix to be overwritten with the values in the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if pool is uninitialized + */ + void decode( + const Plaintext &plain, std::vector<std::uint64_t> &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Inverse of encode. This function "unbatches" a given plaintext into a matrix + of integers modulo the plaintext modulus, and stores the result in the destination + parameter. The input plaintext must have degress less than the polynomial modulus, + and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + for the encryption parameters. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext polynomial to unbatch + @param[out] destination The matrix to be overwritten with the values in the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if pool is uninitialized + */ + void decode( + const Plaintext &plain, std::vector<std::int64_t> &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()); +#ifdef SEAL_USE_MSGSL + /** + Inverse of encode. This function "unbatches" a given plaintext into a matrix + of integers modulo the plaintext modulus, and stores the result in the destination + parameter. The input plaintext must have degress less than the polynomial modulus, + and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + for the encryption parameters. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext polynomial to unbatch + @param[out] destination The matrix to be overwritten with the values in the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if destination has incorrect size + @throws std::invalid_argument if pool is uninitialized + */ + void decode( + const Plaintext &plain, gsl::span<std::uint64_t> destination, + MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Inverse of encode. This function "unbatches" a given plaintext into a matrix + of integers modulo the plaintext modulus, and stores the result in the destination + parameter. The input plaintext must have degress less than the polynomial modulus, + and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext + for the encryption parameters. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext polynomial to unbatch + @param[out] destination The matrix to be overwritten with the values in the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if destination has incorrect size + @throws std::invalid_argument if pool is uninitialized + */ + void decode( + const Plaintext &plain, gsl::span<std::int64_t> destination, + MemoryPoolHandle pool = MemoryManager::GetPool()); +#endif + /** + Inverse of encode. This function "unbatches" a given plaintext in-place into + a matrix of integers modulo the plaintext modulus. The input plaintext must have + degress less than the polynomial modulus, and coefficients less than the plaintext + modulus, i.e. it must be a valid plaintext for the encryption parameters. Dynamic + memory allocations in the process are allocated from the memory pool pointed to by + the given MemoryPoolHandle. + + @param[in] plain The plaintext polynomial to unbatch + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is in NTT form + @throws std::invalid_argument if pool is uninitialized + */ + void decode(Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Returns the number of slots. + */ + SEAL_NODISCARD inline auto slot_count() const noexcept + { + return slots_; + } + + private: + BatchEncoder(const BatchEncoder &copy) = delete; + + BatchEncoder(BatchEncoder &&source) = delete; + + BatchEncoder &operator=(const BatchEncoder &assign) = delete; + + BatchEncoder &operator=(BatchEncoder &&assign) = delete; + + void populate_roots_of_unity_vector(const SEALContext::ContextData &context_data); + + void populate_matrix_reps_index_map(); + + void reverse_bits(std::uint64_t *input); + + MemoryPoolHandle pool_ = MemoryManager::GetPool(); + + std::shared_ptr<SEALContext> context_{ nullptr }; + + std::size_t slots_; + + util::Pointer<std::uint64_t> roots_of_unity_; + + util::Pointer<std::size_t> matrix_reps_index_map_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/biguint.cpp b/bigpiseal3.5.1/native/src/seal/biguint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27e8dc5d4e77d917db22be021b5b67731ff1c05a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/biguint.cpp @@ -0,0 +1,317 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/biguint.h" +#include "seal/util/common.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" +#include <algorithm> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + BigUInt::BigUInt(int bit_count) + { + resize(bit_count); + } + + BigUInt::BigUInt(const string &hex_value) + { + operator=(hex_value); + } + + BigUInt::BigUInt(int bit_count, const string &hex_value) + { + resize(bit_count); + operator=(hex_value); + if (bit_count != bit_count_) + { + resize(bit_count); + } + } + + BigUInt::BigUInt(int bit_count, uint64_t *value) : value_(decltype(value_)::Aliasing(value)), bit_count_(bit_count) + { + if (bit_count < 0) + { + throw invalid_argument("bit_count must be non-negative"); + } + if (value == nullptr && bit_count > 0) + { + throw invalid_argument("value must be non-null for non-zero bit count"); + } + } +#ifdef SEAL_USE_MSGSL + BigUInt::BigUInt(gsl::span<uint64_t> value) + { + if (unsigned_gt(value.size(), numeric_limits<int>::max() / bits_per_uint64)) + { + throw std::invalid_argument("value has too large size"); + } + value_ = decltype(value_)::Aliasing(value.data()); + bit_count_ = static_cast<int>(value.size()) * bits_per_uint64; + } +#endif + BigUInt::BigUInt(int bit_count, uint64_t value) + { + resize(bit_count); + operator=(value); + if (bit_count != bit_count_) + { + resize(bit_count); + } + } + + BigUInt::BigUInt(const BigUInt &copy) + { + resize(copy.bit_count()); + operator=(copy); + } + + BigUInt::BigUInt(BigUInt &&source) noexcept + : pool_(move(source.pool_)), value_(move(source.value_)), bit_count_(source.bit_count_) + { + // Pointer in source has been taken over so set it to nullptr + source.bit_count_ = 0; + } + + BigUInt::~BigUInt() noexcept + { + reset(); + } + + string BigUInt::to_string() const + { + return uint_to_hex_string(value_.get(), uint64_count()); + } + + string BigUInt::to_dec_string() const + { + return uint_to_dec_string(value_.get(), uint64_count(), pool_); + } + + void BigUInt::resize(int bit_count) + { + if (bit_count < 0) + { + throw invalid_argument("bit_count must be non-negative"); + } + if (value_.is_alias()) + { + throw logic_error("Cannot resize an aliased BigUInt"); + } + if (bit_count == bit_count_) + { + return; + } + + // Lazy initialization of MemoryPoolHandle + if (!pool_) + { + pool_ = MemoryManager::GetPool(); + } + + // Fast path if allocation size doesn't change. + size_t old_uint64_count = uint64_count(); + size_t new_uint64_count = safe_cast<size_t>(divide_round_up(bit_count, bits_per_uint64)); + if (old_uint64_count == new_uint64_count) + { + bit_count_ = bit_count; + return; + } + + // Allocate new space. + decltype(value_) new_value; + if (new_uint64_count > 0) + { + new_value = allocate_uint(new_uint64_count, pool_); + } + + // Copy over old value. + if (new_uint64_count > 0) + { + set_uint_uint(value_.get(), old_uint64_count, new_uint64_count, new_value.get()); + filter_highbits_uint(new_value.get(), new_uint64_count, bit_count); + } + + // Deallocate any owned pointers. + reset(); + + // Update class. + swap(value_, new_value); + bit_count_ = bit_count; + } + + BigUInt &BigUInt::operator=(const BigUInt &assign) + { + // Do nothing if same thing. + if (&assign == this) + { + return *this; + } + + // Verify assigned value will fit within bit count. + int assign_sig_bit_count = assign.significant_bit_count(); + if (assign_sig_bit_count > bit_count_) + { + // Size is too large to currently fit, so resize. + resize(assign_sig_bit_count); + } + + // Copy over value. + size_t assign_uint64_count = safe_cast<size_t>(divide_round_up(assign_sig_bit_count, bits_per_uint64)); + if (uint64_count() > 0) + { + set_uint_uint(assign.value_.get(), assign_uint64_count, uint64_count(), value_.get()); + } + return *this; + } + + BigUInt &BigUInt::operator=(const string &hex_value) + { + int hex_value_length = safe_cast<int>(hex_value.size()); + + int assign_bit_count = get_hex_string_bit_count(hex_value.data(), hex_value_length); + if (assign_bit_count > bit_count_) + { + // Size is too large to currently fit, so resize. + resize(assign_bit_count); + } + if (bit_count_ > 0) + { + // Copy over value. + hex_string_to_uint(hex_value.data(), hex_value_length, uint64_count(), value_.get()); + } + return *this; + } + + BigUInt BigUInt::operator/(const BigUInt &operand2) const + { + int result_bits = significant_bit_count(); + int operand2_bits = operand2.significant_bit_count(); + if (operand2_bits == 0) + { + throw invalid_argument("operand2 must be positive"); + } + if (operand2_bits > result_bits) + { + BigUInt zero(result_bits); + return zero; + } + BigUInt result(result_bits); + BigUInt remainder(result_bits); + size_t result_uint64_count = result.uint64_count(); + if (result_uint64_count > operand2.uint64_count()) + { + BigUInt operand2resized(result_bits); + operand2resized = operand2; + divide_uint_uint( + value_.get(), operand2resized.data(), result_uint64_count, result.data(), remainder.data(), pool_); + } + else + { + divide_uint_uint( + value_.get(), operand2.data(), result_uint64_count, result.data(), remainder.data(), pool_); + } + return result; + } + + BigUInt BigUInt::divrem(const BigUInt &operand2, BigUInt &remainder) const + { + int result_bits = significant_bit_count(); + remainder = *this; + int operand2_bits = operand2.significant_bit_count(); + if (operand2_bits > result_bits) + { + BigUInt zero; + return zero; + } + BigUInt quotient(result_bits); + size_t uint64_count = remainder.uint64_count(); + if (uint64_count > operand2.uint64_count()) + { + BigUInt operand2resized(result_bits); + operand2resized = operand2; + divide_uint_uint_inplace(remainder.data(), operand2resized.data(), uint64_count, quotient.data(), pool_); + } + else + { + divide_uint_uint_inplace(remainder.data(), operand2.data(), uint64_count, quotient.data(), pool_); + } + return quotient; + } + + void BigUInt::save_members(ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + int32_t bit_count32 = safe_cast<int32_t>(bit_count_); + streamsize data_size = safe_cast<streamsize>(mul_safe(uint64_count(), sizeof(uint64_t))); + stream.write(reinterpret_cast<const char *>(&bit_count32), sizeof(int32_t)); + if (data_size) + { + stream.write(reinterpret_cast<const char *>(value_.get()), data_size); + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void BigUInt::load_members(istream &stream) + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + int32_t read_bit_count = 0; + stream.read(reinterpret_cast<char *>(&read_bit_count), sizeof(int32_t)); + if (read_bit_count > bit_count_) + { + // Size is too large to currently fit, so resize. + resize(read_bit_count); + } + + size_t read_uint64_count = safe_cast<size_t>(divide_round_up(read_bit_count, bits_per_uint64)); + streamsize data_size = safe_cast<streamsize>(mul_safe(read_uint64_count, sizeof(uint64_t))); + if (data_size) + { + stream.read(reinterpret_cast<char *>(value_.get()), data_size); + } + + // Zero any extra space. + if (uint64_count() > read_uint64_count) + { + set_zero_uint(uint64_count() - read_uint64_count, value_.get() + read_uint64_count); + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/biguint.h b/bigpiseal3.5.1/native/src/seal/biguint.h new file mode 100644 index 0000000000000000000000000000000000000000..2d1add0fd0e6f240d77a849999b0e97e6ef54701 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/biguint.h @@ -0,0 +1,1728 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/serialization.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" +#include "seal/util/ztools.h" +#include <cstdint> +#include <iostream> +#include <string> +#ifdef SEAL_USE_MSGSL +#include <gsl/span> +#endif + +namespace seal +{ + /** + Represents an unsigned integer with a specified bit width. Non-const + BigUInts are mutable and able to be resized. The bit count for a BigUInt + (which can be read with bit_count()) is set initially by the constructor + and can be resized either explicitly with the resize() function or + implicitly with an assignment operation (e.g., operator=(), operator+=(), + etc.). A rich set of unsigned integer operations are provided by the + BigUInt class, including comparison, traditional arithmetic (addition, + subtraction, multiplication, division), and modular arithmetic functions. + + @par Backing Array + The backing array for a BigUInt stores its unsigned integer value as + a contiguous std::uint64_t array. Each std::uint64_t in the array + sequentially represents 64-bits of the integer value, with the least + significant quad-word storing the lower 64-bits and the order of the bits + for each quad word dependent on the architecture's std::uint64_t + representation. The size of the array equals the bit count of the BigUInt + (which can be read with bit_count()) rounded up to the next std::uint64_t + boundary (i.e., rounded up to the next 64-bit boundary). The uint64_count() + function returns the number of std::uint64_t in the backing array. The + data() function returns a pointer to the first std::uint64_t in the array. + Additionally, the operator [] function allows accessing the individual + bytes of the integer value in a platform-independent way - for example, + reading the third byte will always return bits 16-24 of the BigUInt value + regardless of the platform being little-endian or big-endian. + + @par Implicit Resizing + Both the copy constructor and operator=() allocate more memory for the + backing array when needed, i.e. when the source BigUInt has a larger + backing array than the destination. Conversely, when the destination + backing array is already large enough, the data is only copied and the + unnecessary higher order bits are set to zero. When new memory has to be + allocated, only the significant bits of the source BigUInt are taken + into account. This is is important, because it avoids unnecessary zero + bits to be included in the destination, which in some cases could + accumulate and result in very large unnecessary allocations. However, + sometimes it is necessary to preserve the original size, even if some + of the leading bits are zero. For this purpose BigUInt contains functions + duplicate_from and duplicate_to, which create an exact copy of the source + BigUInt. + + @par Alias BigUInts + An aliased BigUInt (which can be determined with is_alias()) is a special + type of BigUInt that does not manage its underlying std::uint64_t pointer + used to store the value. An aliased BigUInt supports most of the same + operations as a non-aliased BigUInt, including reading and writing the + value, however an aliased BigUInt does not internally allocate or + deallocate its backing array and, therefore, does not support resizing. + Any attempt, either explicitly or implicitly, to resize the BigUInt will + result in an exception being thrown. An aliased BigUInt can be created + with the BigUInt(int, std::uint64_t*) constructor or the alias() function. + Note that the pointer specified to be aliased must be deallocated + externally after the BigUInt is no longer in use. Aliasing is useful in + cases where it is desirable to not have each BigUInt manage its own memory + allocation and/or to prevent unnecessary copying. + + @par Thread Safety + In general, reading a BigUInt is thread-safe while mutating is not. + Specifically, the backing array may be freed whenever a resize occurs, + the BigUInt is destroyed, or alias() is called, which would invalidate + the address returned by data() and the byte references returned by + operator []. When it is known that a resize will not occur, concurrent + reading and mutating will not inherently fail but it is possible for + a read to see a partially updated value from a concurrent write. + A non-aliased BigUInt allocates its backing array from the global + (thread-safe) memory pool. Consequently, creating or resizing a large + number of BigUInt can result in a performance loss due to thread + contention. + */ + class BigUInt + { + public: + /** + Creates an empty BigUInt with zero bit width. No memory is allocated + by this constructor. + */ + BigUInt() = default; + + /** + Creates a zero-initialized BigUInt of the specified bit width. + + @param[in] bit_count The bit width + @throws std::invalid_argument if bit_count is negative + */ + BigUInt(int bit_count); + + /** + Creates a BigUInt initialized and minimally sized to fit the unsigned + hexadecimal integer specified by the string. The string matches the format + returned by to_string() and must consist of only the characters 0-9, A-F, + or a-f, most-significant nibble first. + + @param[in] hex_value The hexadecimal integer string specifying the initial + value + @throws std::invalid_argument if hex_value does not adhere to the expected + format + */ + BigUInt(const std::string &hex_value); + + /** + Creates a BigUInt of the specified bit width and initializes it with the + unsigned hexadecimal integer specified by the string. The string must match + the format returned by to_string() and must consist of only the characters + 0-9, A-F, or a-f, most-significant nibble first. + + @param[in] bit_count The bit width + @param[in] hex_value The hexadecimal integer string specifying the initial + value + @throws std::invalid_argument if bit_count is negative + @throws std::invalid_argument if hex_value does not adhere to the expected + format + */ + BigUInt(int bit_count, const std::string &hex_value); + + /** + Creates an aliased BigUInt with the specified bit width and backing array. + An aliased BigUInt does not internally allocate or deallocate the backing + array, and instead uses the specified backing array for all read/write + operations. Note that resizing is not supported by an aliased BigUInt and + any required deallocation of the specified backing array must occur + externally after the aliased BigUInt is no longer in use. + + @param[in] bit_count The bit width + @param[in] value The backing array to use + @throws std::invalid_argument if bit_count is negative or value is null + and bit_count is positive + */ + BigUInt(int bit_count, std::uint64_t *value); +#ifdef SEAL_USE_MSGSL + /** + Creates an aliased BigUInt with given backing array and bit width set to + the size of the backing array. An aliased BigUInt does not internally + allocate or deallocate the backing array, and instead uses the specified + backing array for all read/write operations. Note that resizing is not + supported by an aliased BigUInt and any required deallocation of the + specified backing array must occur externally after the aliased BigUInt + is no longer in use. + + @param[in] value The backing array to use + @throws std::invalid_argument if value has too large size + */ + BigUInt(gsl::span<std::uint64_t> value); +#endif + /** + Creates a BigUInt of the specified bit width and initializes it to the + specified unsigned integer value. + + @param[in] bit_count The bit width + @param[in] value The initial value to set the BigUInt + @throws std::invalid_argument if bit_count is negative + */ + BigUInt(int bit_count, std::uint64_t value); + + /** + Creates a deep copy of a BigUInt. The created BigUInt will have the same + bit count and value as the original. + + @param[in] copy The BigUInt to copy from + */ + BigUInt(const BigUInt &copy); + + /** + Creates a new BigUInt by moving an old one. + + @param[in] source The BigUInt to move from + */ + BigUInt(BigUInt &&source) noexcept; + + /** + Destroys the BigUInt and deallocates the backing array if it is not + an aliased BigUInt. + */ + ~BigUInt() noexcept; + + /** + Returns whether or not the BigUInt is an alias. + */ + SEAL_NODISCARD inline bool is_alias() const noexcept + { + return value_.is_alias(); + } + + /** + Returns the bit count for the BigUInt. + */ + SEAL_NODISCARD inline int bit_count() const noexcept + { + return bit_count_; + } + + /** + Returns a pointer to the backing array storing the BigUInt value. + The pointer points to the beginning of the backing array at the + least-significant quad word. + + @warning The pointer is valid only until the backing array is freed, + which occurs when the BigUInt is resized, destroyed, or the alias() + function is called. + */ + SEAL_NODISCARD inline std::uint64_t *data() + { + return value_.get(); + } + + /** + Returns a const pointer to the backing array storing the BigUInt value. + The pointer points to the beginning of the backing array at the + least-significant quad word. + + @warning The pointer is valid only until the backing array is freed, which + occurs when the BigUInt is resized, destroyed, or the alias() function is + called. + */ + SEAL_NODISCARD inline const std::uint64_t *data() const noexcept + { + return value_.get(); + } +#ifdef SEAL_USE_MSGSL + /** + Returns the backing array storing the BigUInt value. + + @warning The span is valid only until the backing array is freed, which + occurs when the BigUInt is resized, destroyed, or the alias() function is + called. + */ + SEAL_NODISCARD inline gsl::span<std::uint64_t> data_span() + { + return gsl::span<std::uint64_t>(value_.get(), uint64_count()); + } + + /** + Returns the backing array storing the BigUInt value. + + @warning The span is valid only until the backing array is freed, which + occurs when the BigUInt is resized, destroyed, or the alias() function is + called. + */ + SEAL_NODISCARD inline gsl::span<const std::uint64_t> data_span() const + { + return gsl::span<const std::uint64_t>(value_.get(), uint64_count()); + } +#endif + /** + Returns the number of bytes in the backing array used to store the BigUInt + value. + */ + SEAL_NODISCARD inline std::size_t byte_count() const + { + return static_cast<std::size_t>(util::divide_round_up(bit_count_, util::bits_per_byte)); + } + + /** + Returns the number of std::uint64_t in the backing array used to store + the BigUInt value. + */ + SEAL_NODISCARD inline std::size_t uint64_count() const + { + return static_cast<std::size_t>(util::divide_round_up(bit_count_, util::bits_per_uint64)); + } + + /** + Returns the number of significant bits for the BigUInt. + */ + SEAL_NODISCARD inline int significant_bit_count() const + { + if (bit_count_ == 0) + { + return 0; + } + return util::get_significant_bit_count_uint(value_.get(), uint64_count()); + } + + /** + Returns the BigUInt value as a double. Note that precision may be lost during + the conversion. + */ + SEAL_NODISCARD double to_double() const noexcept + { + const double TwoToThe64 = 18446744073709551616.0; + double result = 0; + for (std::size_t i = uint64_count(); i--;) + { + result *= TwoToThe64; + result += static_cast<double>(value_[i]); + } + return result; + } + + /** + Returns the BigUInt value as a hexadecimal string. + */ + SEAL_NODISCARD std::string to_string() const; + + /** + Returns the BigUInt value as a decimal string. + */ + SEAL_NODISCARD std::string to_dec_string() const; + + /** + Returns whether or not the BigUInt has the value zero. + */ + SEAL_NODISCARD inline bool is_zero() const + { + if (bit_count_ == 0) + { + return true; + } + return util::is_zero_uint(value_.get(), uint64_count()); + } + + /** + Returns the byte at the corresponding byte index of the BigUInt's integer + value. The bytes of the BigUInt are indexed least-significant byte first. + + @param[in] index The index of the byte to read + @throws std::out_of_range if index is not within [0, byte_count()) + */ + SEAL_NODISCARD inline const SEAL_BYTE &operator[](std::size_t index) const + { + if (index >= byte_count()) + { + throw std::out_of_range("index must be within [0, byte count)"); + } + return *util::get_uint64_byte(value_.get(), index); + } + + /** + Returns an byte reference that can read/write the byte at the corresponding + byte index of the BigUInt's integer value. The bytes of the BigUInt are + indexed least-significant byte first. + + @warning The returned byte is an reference backed by the BigUInt's backing + array. As such, it is only valid until the BigUInt is resized, destroyed, + or alias() is called. + + @param[in] index The index of the byte to read + @throws std::out_of_range if index is not within [0, byte_count()) + */ + SEAL_NODISCARD inline SEAL_BYTE &operator[](std::size_t index) + { + if (index >= byte_count()) + { + throw std::out_of_range("index must be within [0, byte count)"); + } + return *util::get_uint64_byte(value_.get(), index); + } + + /** + Sets the BigUInt value to zero. This does not resize the BigUInt. + */ + inline void set_zero() + { + if (bit_count_) + { + return util::set_zero_uint(uint64_count(), value_.get()); + } + } + + /** + Resizes the BigUInt to the specified bit width, copying over the old value + as much as will fit. + + @param[in] bit_count The bit width + @throws std::invalid_argument if bit_count is negative + @throws std::logic_error if the BigUInt is an alias + */ + void resize(int bit_count); + + /** + Makes the BigUInt an aliased BigUInt with the specified bit width and + backing array. An aliased BigUInt does not internally allocate or + deallocate the backing array, and instead uses the specified backing array + for all read/write operations. Note that resizing is not supported by + an aliased BigUInt and any required deallocation of the specified backing + array must occur externally after the aliased BigUInt is no longer in use. + + @param[in] bit_count The bit width + @param[in] value The backing array to use + @throws std::invalid_argument if bit_count is negative or value is null + */ + inline void alias(int bit_count, std::uint64_t *value) + { + if (bit_count < 0) + { + throw std::invalid_argument("bit_count must be non-negative"); + } + if (value == nullptr && bit_count > 0) + { + throw std::invalid_argument("value must be non-null for non-zero bit count"); + } + + // Deallocate any owned pointers. + reset(); + + // Update class. + value_ = util::Pointer<std::uint64_t>::Aliasing(value); + bit_count_ = bit_count; + } +#ifdef SEAL_USE_MSGSL + /** + Makes the BigUInt an aliased BigUInt with the given backing array + and bit width set equal to the size of the backing array. An aliased + BigUInt does not internally allocate or deallocate the backing array, + and instead uses the specified backing array for all read/write + operations. Note that resizing is not supported by an aliased BigUInt + and any required deallocation of the specified backing array must + occur externally after the aliased BigUInt is no longer in use. + + @param[in] value The backing array to use + @throws std::invalid_argument if value has too large size + */ + inline void alias(gsl::span<std::uint64_t> value) + { + if (util::unsigned_gt(value.size(), std::numeric_limits<int>::max())) + { + throw std::invalid_argument("value has too large size"); + } + + // Deallocate any owned pointers. + reset(); + + // Update class. + value_ = util::Pointer<std::uint64_t>::Aliasing(value.data()); + bit_count_ = static_cast<int>(value.size()); + ; + } +#endif + /** + Resets an aliased BigUInt into an empty non-alias BigUInt with bit count + of zero. + + @throws std::logic_error if BigUInt is not an alias + */ + inline void unalias() + { + if (!value_.is_alias()) + { + throw std::logic_error("BigUInt is not an alias"); + } + + // Reset class. + reset(); + } + + /** + Overwrites the BigUInt with the value of the specified BigUInt, enlarging + if needed to fit the assigned value. Only significant bits are used to + size the BigUInt. + + @param[in] assign The BigUInt whose value should be assigned to the + current BigUInt + @throws std::logic_error if BigUInt is an alias and the assigned BigUInt is + too large to fit the current bit width + */ + BigUInt &operator=(const BigUInt &assign); + + /** + Overwrites the BigUInt with the unsigned hexadecimal value specified by + the string, enlarging if needed to fit the assigned value. The string must + match the format returned by to_string() and must consist of only the + characters 0-9, A-F, or a-f, most-significant nibble first. + + @param[in] hex_value The hexadecimal integer string specifying the value + to assign + @throws std::invalid_argument if hex_value does not adhere to the + expected format + @throws std::logic_error if BigUInt is an alias and the assigned value + is too large to fit the current bit width + */ + BigUInt &operator=(const std::string &hex_value); + + /** + Overwrites the BigUInt with the specified integer value, enlarging if + needed to fit the value. + + @param[in] value The value to assign + @throws std::logic_error if BigUInt is an alias and the significant bit + count of value is too large to fit the + current bit width + */ + inline BigUInt &operator=(std::uint64_t value) + { + int assign_bit_count = util::get_significant_bit_count(value); + if (assign_bit_count > bit_count_) + { + // Size is too large to currently fit, so resize. + resize(assign_bit_count); + } + if (bit_count_ > 0) + { + util::set_uint(value, uint64_count(), value_.get()); + } + return *this; + } + + /** + Returns a copy of the BigUInt value resized to the significant bit count. + */ + SEAL_NODISCARD inline BigUInt operator+() const + { + BigUInt result; + result = *this; + return result; + } + + /** + Returns a negated copy of the BigUInt value. The bit count does not change. + */ + SEAL_NODISCARD inline BigUInt operator-() const + { + BigUInt result(bit_count_); + util::negate_uint(value_.get(), result.uint64_count(), result.data()); + util::filter_highbits_uint(result.data(), result.uint64_count(), result.bit_count()); + return result; + } + + /** + Returns an inverted copy of the BigUInt value. The bit count does not change. + */ + SEAL_NODISCARD inline BigUInt operator~() const + { + BigUInt result(bit_count_); + util::not_uint(value_.get(), result.uint64_count(), result.data()); + util::filter_highbits_uint(result.data(), result.uint64_count(), result.bit_count()); + return result; + } + + /** + Increments the BigUInt and returns the incremented value. The BigUInt will + increment the bit count if needed to fit the carry. + + @throws std::logic_error if BigUInt is an alias and a carry occurs requiring + the BigUInt to be resized + */ + inline BigUInt &operator++() + { + if (util::increment_uint(value_.get(), uint64_count(), value_.get())) + { + resize(util::add_safe(bit_count_, 1)); + util::set_bit_uint(value_.get(), uint64_count(), bit_count_); + } + bit_count_ = std::max(bit_count_, significant_bit_count()); + return *this; + } + + /** + Decrements the BigUInt and returns the decremented value. The bit count + does not change. + */ + inline BigUInt &operator--() + { + util::decrement_uint(value_.get(), uint64_count(), value_.get()); + util::filter_highbits_uint(value_.get(), uint64_count(), bit_count_); + return *this; + } +#ifndef SEAL_USE_MAYBE_UNUSED +#if (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif +#endif + /** + Increments the BigUInt but returns its old value. The BigUInt will increment + the bit count if needed to fit the carry. + */ + inline BigUInt operator++(int postfix SEAL_MAYBE_UNUSED) + { + BigUInt result; + result = *this; + if (util::increment_uint(value_.get(), uint64_count(), value_.get())) + { + resize(util::add_safe(bit_count_, 1)); + util::set_bit_uint(value_.get(), uint64_count(), bit_count_); + } + bit_count_ = std::max(bit_count_, significant_bit_count()); + return result; + } + + /** + Decrements the BigUInt but returns its old value. The bit count does not change. + */ + inline BigUInt operator--(int postfix SEAL_MAYBE_UNUSED) + { + BigUInt result; + result = *this; + util::decrement_uint(value_.get(), uint64_count(), value_.get()); + util::filter_highbits_uint(value_.get(), uint64_count(), bit_count_); + return result; + } +#ifndef SEAL_USE_MAYBE_UNUSED +#if (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic pop +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic pop +#endif +#endif + /** + Adds two BigUInts and returns the sum. The input operands are not modified. + The bit count of the sum is set to be one greater than the significant bit + count of the larger of the two input operands. + + @param[in] operand2 The second operand to add + */ + SEAL_NODISCARD inline BigUInt operator+(const BigUInt &operand2) const + { + int result_bits = util::add_safe(std::max(significant_bit_count(), operand2.significant_bit_count()), 1); + BigUInt result(result_bits); + util::add_uint_uint( + value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, result.uint64_count(), + result.data()); + return result; + } + + /** + Adds a BigUInt and an unsigned integer and returns the sum. The input + operands are not modified. The bit count of the sum is set to be one greater + than the significant bit count of the larger of the two operands. + + @param[in] operand2 The second operand to add + */ + SEAL_NODISCARD inline BigUInt operator+(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this + operand2uint; + } + + /** + Subtracts two BigUInts and returns the difference. The input operands are + not modified. The bit count of the difference is set to be the significant + bit count of the larger of the two input operands. + + @param[in] operand2 The second operand to subtract + */ + SEAL_NODISCARD inline BigUInt operator-(const BigUInt &operand2) const + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + BigUInt result(result_bits); + util::sub_uint_uint( + value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, result.uint64_count(), + result.data()); + util::filter_highbits_uint(result.data(), result.uint64_count(), result_bits); + return result; + } + + /** + Subtracts a BigUInt and an unsigned integer and returns the difference. + The input operands are not modified. The bit count of the difference is set + to be the significant bit count of the larger of the two operands. + + @param[in] operand2 The second operand to subtract + */ + SEAL_NODISCARD inline BigUInt operator-(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this - operand2uint; + } + + /** + Multiplies two BigUInts and returns the product. The input operands are + not modified. The bit count of the product is set to be the sum of the + significant bit counts of the two input operands. + + @param[in] operand2 The second operand to multiply + */ + SEAL_NODISCARD inline BigUInt operator*(const BigUInt &operand2) const + { + int result_bits = util::add_safe(significant_bit_count(), operand2.significant_bit_count()); + BigUInt result(result_bits); + util::multiply_uint_uint( + value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), result.uint64_count(), + result.data()); + return result; + } + + /** + Multiplies a BigUInt and an unsigned integer and returns the product. + The input operands are not modified. The bit count of the product is set + to be the sum of the significant bit counts of the two input operands. + + @param[in] operand2 The second operand to multiply + */ + SEAL_NODISCARD inline BigUInt operator*(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this * operand2uint; + } + + /** + Divides two BigUInts and returns the quotient. The input operands are + not modified. The bit count of the quotient is set to be the significant + bit count of the first input operand. + + @param[in] operand2 The second operand to divide + @throws std::invalid_argument if operand2 is zero + */ + SEAL_NODISCARD BigUInt operator/(const BigUInt &operand2) const; + + /** + Divides a BigUInt and an unsigned integer and returns the quotient. The + input operands are not modified. The bit count of the quotient is set + to be the significant bit count of the first input operand. + + @param[in] operand2 The second operand to divide + @throws std::invalid_argument if operand2 is zero + */ + SEAL_NODISCARD inline BigUInt operator/(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this / operand2uint; + } + + /** + Performs a bit-wise XOR operation between two BigUInts and returns the + result. The input operands are not modified. The bit count of the result + is set to the maximum of the two input operand bit counts. + + @param[in] operand2 The second operand to XOR + */ + SEAL_NODISCARD inline BigUInt operator^(const BigUInt &operand2) const + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + BigUInt result(result_bits); + std::size_t uint64_count = result.uint64_count(); + if (uint64_count != this->uint64_count()) + { + result = *this; + util::xor_uint_uint(result.data(), operand2.data(), uint64_count, result.data()); + } + else if (uint64_count != operand2.uint64_count()) + { + result = operand2; + util::xor_uint_uint(result.data(), value_.get(), uint64_count, result.data()); + } + else + { + util::xor_uint_uint(value_.get(), operand2.data(), uint64_count, result.data()); + } + return result; + } + + /** + Performs a bit-wise XOR operation between a BigUInt and an unsigned + integer and returns the result. The input operands are not modified. + The bit count of the result is set to the maximum of the two input + operand bit counts. + + @param[in] operand2 The second operand to XOR + */ + SEAL_NODISCARD inline BigUInt operator^(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this ^ operand2uint; + } + + /** + Performs a bit-wise AND operation between two BigUInts and returns the + result. The input operands are not modified. The bit count of the result + is set to the maximum of the two input operand bit counts. + + @param[in] operand2 The second operand to AND + */ + SEAL_NODISCARD inline BigUInt operator&(const BigUInt &operand2) const + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + BigUInt result(result_bits); + std::size_t uint64_count = result.uint64_count(); + if (uint64_count != this->uint64_count()) + { + result = *this; + util::and_uint_uint(result.data(), operand2.data(), uint64_count, result.data()); + } + else if (uint64_count != operand2.uint64_count()) + { + result = operand2; + util::and_uint_uint(result.data(), value_.get(), uint64_count, result.data()); + } + else + { + util::and_uint_uint(value_.get(), operand2.data(), uint64_count, result.data()); + } + return result; + } + + /** + Performs a bit-wise AND operation between a BigUInt and an unsigned + integer and returns the result. The input operands are not modified. + The bit count of the result is set to the maximum of the two input + operand bit counts. + + @param[in] operand2 The second operand to AND + */ + SEAL_NODISCARD inline BigUInt operator&(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this & operand2uint; + } + + /** + Performs a bit-wise OR operation between two BigUInts and returns the + result. The input operands are not modified. The bit count of the result + is set to the maximum of the two input operand bit counts. + + @param[in] operand2 The second operand to OR + */ + SEAL_NODISCARD inline BigUInt operator|(const BigUInt &operand2) const + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + BigUInt result(result_bits); + std::size_t uint64_count = result.uint64_count(); + if (uint64_count != this->uint64_count()) + { + result = *this; + util::or_uint_uint(result.data(), operand2.data(), uint64_count, result.data()); + } + else if (uint64_count != operand2.uint64_count()) + { + result = operand2; + util::or_uint_uint(result.data(), value_.get(), uint64_count, result.data()); + } + else + { + util::or_uint_uint(value_.get(), operand2.data(), uint64_count, result.data()); + } + return result; + } + + /** + Performs a bit-wise OR operation between a BigUInt and an unsigned + integer and returns the result. The input operands are not modified. + The bit count of the result is set to the maximum of the two input + operand bit counts. + + @param[in] operand2 The second operand to OR + */ + SEAL_NODISCARD inline BigUInt operator|(std::uint64_t operand2) const + { + BigUInt operand2uint; + operand2uint = operand2; + return *this | operand2uint; + } + + /** + Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is + less-than, equal-to, or greater-than the second operand respectively. + The input operands are not modified. + + @param[in] compare The value to compare against + */ + SEAL_NODISCARD inline int compareto(const BigUInt &compare) const + { + return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()); + } + + /** + Compares a BigUInt and an unsigned integer and returns -1, 0, or 1 if + the BigUInt is less-than, equal-to, or greater-than the second operand + respectively. The input operands are not modified. + + @param[in] compare The value to compare against + */ + SEAL_NODISCARD inline int compareto(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return compareto(compareuint); + } + + /** + Returns whether or not a BigUInt is less-than a second BigUInt. The + input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator<(const BigUInt &compare) const + { + return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) < + 0; + } + + /** + Returns whether or not a BigUInt is less-than an unsigned integer. + The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator<(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this < compareuint; + } + + /** + Returns whether or not a BigUInt is greater-than a second BigUInt. + The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator>(const BigUInt &compare) const + { + return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) > + 0; + } + + /** + Returns whether or not a BigUInt is greater-than an unsigned integer. + The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator>(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this > compareuint; + } + + /** + Returns whether or not a BigUInt is less-than or equal to a second + BigUInt. The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator<=(const BigUInt &compare) const + { + return util::compare_uint_uint( + value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) <= 0; + } + + /** + Returns whether or not a BigUInt is less-than or equal to an unsigned + integer. The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator<=(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this <= compareuint; + } + + /** + Returns whether or not a BigUInt is greater-than or equal to a second + BigUInt. The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator>=(const BigUInt &compare) const + { + return util::compare_uint_uint( + value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) >= 0; + } + + /** + Returns whether or not a BigUInt is greater-than or equal to an unsigned + integer. The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator>=(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this >= compareuint; + } + + /** + Returns whether or not a BigUInt is equal to a second BigUInt. + The input operands are not modified. + + @param[in] compare The value to compare against + */ + SEAL_NODISCARD inline bool operator==(const BigUInt &compare) const + { + return util::compare_uint_uint( + value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) == 0; + } + + /** + Returns whether or not a BigUInt is equal to an unsigned integer. + The input operands are not modified. + + @param[in] compare The value to compare against + */ + SEAL_NODISCARD inline bool operator==(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this == compareuint; + } + + /** + Returns whether or not a BigUInt is not equal to a second BigUInt. + The input operands are not modified. + + @param[in] compare The value to compare against + */ + SEAL_NODISCARD inline bool operator!=(const BigUInt &compare) const + { + return !(operator==(compare)); + } + + /** + Returns whether or not a BigUInt is not equal to an unsigned integer. + The input operands are not modified. + + @param[in] operand2 The value to compare against + */ + SEAL_NODISCARD inline bool operator!=(std::uint64_t compare) const + { + BigUInt compareuint; + compareuint = compare; + return *this != compareuint; + } + + /** + Returns a left-shifted copy of the BigUInt. The bit count of the + returned value is the sum of the original significant bit count and + the shift amount. + + @param[in] shift The number of bits to shift by + @throws std::invalid_argument if shift is negative + */ + SEAL_NODISCARD inline BigUInt operator<<(int shift) const + { + if (shift < 0) + { + throw std::invalid_argument("shift must be non-negative"); + } + int result_bits = util::add_safe(significant_bit_count(), shift); + BigUInt result(result_bits); + result = *this; + util::left_shift_uint(result.data(), shift, result.uint64_count(), result.data()); + return result; + } + + /** + Returns a right-shifted copy of the BigUInt. The bit count of the + returned value is the original significant bit count subtracted by + the shift amount (clipped to zero if negative). + + @param[in] shift The number of bits to shift by + @throws std::invalid_argument if shift is negative + */ + SEAL_NODISCARD inline BigUInt operator>>(int shift) const + { + if (shift < 0) + { + throw std::invalid_argument("shift must be non-negative"); + } + int result_bits = util::sub_safe(significant_bit_count(), shift); + if (result_bits <= 0) + { + BigUInt zero; + return zero; + } + BigUInt result(result_bits); + result = *this; + util::right_shift_uint(result.data(), shift, result.uint64_count(), result.data()); + return result; + } + + /** + Adds two BigUInts saving the sum to the first operand, returning + a reference of the first operand. The second input operand is not + modified. The first operand is resized if and only if its bit count + is smaller than one greater than the significant bit count of the + larger of the two input operands. + + @param[in] operand2 The second operand to add + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator+=(const BigUInt &operand2) + { + int result_bits = util::add_safe(std::max(significant_bit_count(), operand2.significant_bit_count()), 1); + if (bit_count_ < result_bits) + { + resize(result_bits); + } + util::add_uint_uint( + value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, uint64_count(), + value_.get()); + return *this; + } + + /** + Adds a BigUInt and an unsigned integer saving the sum to the first operand, + returning a reference of the first operand. The second input operand is not + modified. The first operand is resized if and only if its bit count is + smaller than one greater than the significant bit count of the larger of + the two input operands. + + @param[in] operand2 The second operand to add + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator+=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator+=(operand2uint); + } + + /** + Subtracts two BigUInts saving the difference to the first operand, + returning a reference of the first operand. The second input operand is + not modified. The first operand is resized if and only if its bit count + is smaller than the significant bit count of the second operand. + + @param[in] operand2 The second operand to subtract + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator-=(const BigUInt &operand2) + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + if (bit_count_ < result_bits) + { + resize(result_bits); + } + util::sub_uint_uint( + value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, uint64_count(), + value_.get()); + util::filter_highbits_uint(value_.get(), uint64_count(), result_bits); + return *this; + } + + /** + Subtracts a BigUInt and an unsigned integer saving the difference to + the first operand, returning a reference of the first operand. The second + input operand is not modified. The first operand is resized if and only + if its bit count is smaller than the significant bit count of the second + operand. + + @param[in] operand2 The second operand to subtract + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator-=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator-=(operand2uint); + } + + /** + Multiplies two BigUInts saving the product to the first operand, + returning a reference of the first operand. The second input operand + is not modified. The first operand is resized if and only if its bit + count is smaller than the sum of the significant bit counts of the two + input operands. + + @param[in] operand2 The second operand to multiply + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator*=(const BigUInt &operand2) + { + *this = *this * operand2; + return *this; + } + + /** + Multiplies a BigUInt and an unsigned integer saving the product to + the first operand, returning a reference of the first operand. The + second input operand is not modified. The first operand is resized if + and only if its bit count is smaller than the sum of the significant + bit counts of the two input operands. + + @param[in] operand2 The second operand to multiply + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator*=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator*=(operand2uint); + } + + /** + Divides two BigUInts saving the quotient to the first operand, + returning a reference of the first operand. The second input operand + is not modified. The first operand is never resized. + + @param[in] operand2 The second operand to divide + @throws std::invalid_argument if operand2 is zero + */ + inline BigUInt &operator/=(const BigUInt &operand2) + { + *this = *this / operand2; + return *this; + } + + /** + Divides a BigUInt and an unsigned integer saving the quotient to + the first operand, returning a reference of the first operand. The + second input operand is not modified. The first operand is never resized. + + @param[in] operand2 The second operand to divide + @throws std::invalid_argument if operand2 is zero + */ + inline BigUInt &operator/=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator/=(operand2uint); + } + + /** + Performs a bit-wise XOR operation between two BigUInts saving the result + to the first operand, returning a reference of the first operand. The + second input operand is not modified. The first operand is resized if + and only if its bit count is smaller than the significant bit count of + the second operand. + + @param[in] operand2 The second operand to XOR + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator^=(const BigUInt &operand2) + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + if (bit_count_ != result_bits) + { + resize(result_bits); + } + util::xor_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get()); + return *this; + } + + /** + Performs a bit-wise XOR operation between a BigUInt and an unsigned integer + saving the result to the first operand, returning a reference of the first + operand. The second input operand is not modified. The first operand is + resized if and only if its bit count is smaller than the significant bit + count of the second operand. + + @param[in] operand2 The second operand to XOR + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator^=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator^=(operand2uint); + } + + /** + Performs a bit-wise AND operation between two BigUInts saving the result + to the first operand, returning a reference of the first operand. The + second input operand is not modified. The first operand is resized if + and only if its bit count is smaller than the significant bit count of + the second operand. + + @param[in] operand2 The second operand to AND + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator&=(const BigUInt &operand2) + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + if (bit_count_ != result_bits) + { + resize(result_bits); + } + util::and_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get()); + return *this; + } + + /** + Performs a bit-wise AND operation between a BigUInt and an unsigned integer + saving the result to the first operand, returning a reference of the first + operand. The second input operand is not modified. The first operand is + resized if and only if its bit count is smaller than the significant bit + count of the second operand. + + @param[in] operand2 The second operand to AND + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator&=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator&=(operand2uint); + } + + /** + Performs a bit-wise OR operation between two BigUInts saving the result to + the first operand, returning a reference of the first operand. The second + input operand is not modified. The first operand is resized if and only if + its bit count is smaller than the significant bit count of the second + operand. + + @param[in] operand2 The second operand to OR + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator|=(const BigUInt &operand2) + { + int result_bits = std::max(bit_count_, operand2.bit_count()); + if (bit_count_ != result_bits) + { + resize(result_bits); + } + util::or_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get()); + return *this; + } + + /** + Performs a bit-wise OR operation between a BigUInt and an unsigned integer + saving the result to the first operand, returning a reference of the first + operand. The second input operand is not modified. The first operand is + resized if and only if its bit count is smaller than the significant bit + count of the second operand. + + @param[in] operand2 The second operand to OR + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator|=(std::uint64_t operand2) + { + BigUInt operand2uint; + operand2uint = operand2; + return operator|=(operand2uint); + } + + /** + Left-shifts a BigUInt by the specified amount. The BigUInt is resized if + and only if its bit count is smaller than the sum of its significant bit + count and the shift amount. + + @param[in] shift The number of bits to shift by + @throws std::invalid_argument if shift is negative + @throws std::logic_error if the BigUInt is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + inline BigUInt &operator<<=(int shift) + { + if (shift < 0) + { + throw std::invalid_argument("shift must be non-negative"); + } + int result_bits = util::add_safe(significant_bit_count(), shift); + if (bit_count_ < result_bits) + { + resize(result_bits); + } + util::left_shift_uint(value_.get(), shift, uint64_count(), value_.get()); + return *this; + } + + /** + Right-shifts a BigUInt by the specified amount. The BigUInt is never + resized. + + @param[in] shift The number of bits to shift by + @throws std::invalid_argument if shift is negative + */ + inline BigUInt &operator>>=(int shift) + { + if (shift < 0) + { + throw std::invalid_argument("shift must be non-negative"); + } + if (shift > bit_count_) + { + set_zero(); + return *this; + } + util::right_shift_uint(value_.get(), shift, uint64_count(), value_.get()); + return *this; + } + + /** + Divides two BigUInts and returns the quotient and sets the remainder + parameter to the remainder. The bit count of the quotient is set to be + the significant bit count of the BigUInt. The remainder is resized if + and only if it is smaller than the bit count of the BigUInt. + + @param[in] operand2 The second operand to divide + @param[out] remainder The BigUInt to store the remainder + @throws std::invalid_argument if operand2 is zero + @throws std::logic_error if the remainder is an alias and the operator + attempts to enlarge the BigUInt to fit the result + */ + BigUInt divrem(const BigUInt &operand2, BigUInt &remainder) const; + + /** + Divides a BigUInt and an unsigned integer and returns the quotient and + sets the remainder parameter to the remainder. The bit count of the + quotient is set to be the significant bit count of the BigUInt. The + remainder is resized if and only if it is smaller than the bit count + of the BigUInt. + + @param[in] operand2 The second operand to divide + @param[out] remainder The BigUInt to store the remainder + @throws std::invalid_argument if operand2 is zero + @throws std::logic_error if the remainder is an alias which the + function attempts to enlarge to fit the result + */ + inline BigUInt divrem(std::uint64_t operand2, BigUInt &remainder) const + { + BigUInt operand2uint; + operand2uint = operand2; + return divrem(operand2uint, remainder); + } + + /** + Returns the inverse of a BigUInt with respect to the specified modulus. + The original BigUInt is not modified. The bit count of the inverse is + set to be the significant bit count of the modulus. + + @param[in] modulus The modulus to calculate the inverse with respect to + @throws std::invalid_argument if modulus is zero + @throws std::invalid_argument if modulus is not greater than the BigUInt value + @throws std::invalid_argument if the BigUInt value and modulus are not co-prime + @throws std::logic_error if the BigUInt value is zero + */ + SEAL_NODISCARD inline BigUInt modinv(const BigUInt &modulus) const + { + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus must be positive"); + } + if (is_zero()) + { + throw std::logic_error("BigUInt value cannot be zero"); + } + int result_bits = modulus.significant_bit_count(); + if (*this >= modulus) + { + throw std::invalid_argument("modulus must be greater than BigUInt"); + } + BigUInt result(result_bits); + result = *this; + if (!util::try_invert_uint_mod(result.data(), modulus.data(), result.uint64_count(), result.data(), pool_)) + { + throw std::invalid_argument("BigUInt and modulus are not co-prime"); + } + return result; + } + + /** + Returns the inverse of a BigUInt with respect to the specified modulus. + The original BigUInt is not modified. The bit count of the inverse is set + to be the significant bit count of the modulus. + + @param[in] modulus The modulus to calculate the inverse with respect to + @throws std::invalid_argument if modulus is zero + @throws std::invalid_argument if modulus is not greater than the BigUInt value + @throws std::invalid_argument if the BigUInt value and modulus are not co-prime + @throws std::logic_error if the BigUInt value is zero + */ + SEAL_NODISCARD inline BigUInt modinv(std::uint64_t modulus) const + { + BigUInt modulusuint; + modulusuint = modulus; + return modinv(modulusuint); + } + + /** + Attempts to calculate the inverse of a BigUInt with respect to the + specified modulus, returning whether or not the inverse was successful + and setting the inverse parameter to the inverse. The original BigUInt + is not modified. The inverse parameter is resized if and only if its bit + count is smaller than the significant bit count of the modulus. + + @param[in] modulus The modulus to calculate the inverse with respect to + @param[out] inverse Stores the inverse if the inverse operation was + successful + @throws std::invalid_argument if modulus is zero + @throws std::invalid_argument if modulus is not greater than the BigUInt + value + @throws std::logic_error if the inverse is an alias which the function + attempts to enlarge to fit the result + */ + inline bool trymodinv(const BigUInt &modulus, BigUInt &inverse) const + { + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus must be positive"); + } + if (is_zero()) + { + return false; + } + int result_bits = modulus.significant_bit_count(); + if (*this >= modulus) + { + throw std::invalid_argument("modulus must be greater than BigUInt"); + } + if (inverse.bit_count() < result_bits) + { + inverse.resize(result_bits); + } + inverse = *this; + return util::try_invert_uint_mod( + inverse.data(), modulus.data(), inverse.uint64_count(), inverse.data(), pool_); + } + + /** + Attempts to calculate the inverse of a BigUInt with respect to the + specified modulus, returning whether or not the inverse was successful + and setting the inverse parameter to the inverse. The original BigUInt + is not modified. The inverse parameter is resized if and only if its + bit count is smaller than the significant bit count of the modulus. + + @param[in] modulus The modulus to calculate the inverse with respect to + @param[out] inverse Stores the inverse if the inverse operation was + successful + @throws std::invalid_argument if modulus is zero + @throws std::invalid_argument if modulus is not greater than the BigUInt + value + @throws std::logic_error if the inverse is an alias which the function + attempts to enlarge to fit the result + */ + inline bool trymodinv(std::uint64_t modulus, BigUInt &inverse) const + { + BigUInt modulusuint; + modulusuint = modulus; + return trymodinv(modulusuint, inverse); + } + + /** + Returns an upper bound on the size of the BigUInt, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t members_size = Serialization::ComprSizeEstimate( + util::add_safe( + util::mul_safe(uint64_count(), sizeof(std::uint64_t)), // value_ + sizeof(std::int32_t)), // bit_count_ + compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves the BigUInt to an output stream. The full state of the BigUInt is + serialized, including insignificant bits. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the BigUInt to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&BigUInt::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a BigUInt from an input stream overwriting the current BigUInt. + + @param[in] stream The stream to load the BigUInt from + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded BigUInt is too large for an aliased BigUInt + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::istream &stream) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&BigUInt::load_members, this, _1), stream); + } + + /** + Saves the BigUInt to a given memory location. The full state of the + BigUInt is serialized, including insignificant bits. The output is in + binary format and not human-readable. + + @param[out] out The memory location to write the BigUInt to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&BigUInt::save_members, this, _1), save_size(compr_mode_type::none), out, size, compr_mode); + } + + /** + Loads a BigUInt from a memory location overwriting the current BigUInt. + + @param[in] in The memory location to load the BigUInt from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded BigUInt is too large for an aliased BigUInt + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&BigUInt::load_members, this, _1), in, size); + } + + /** + Creates a minimally sized BigUInt initialized to the specified unsigned + integer value. + + @param[in] value The value to initialized the BigUInt to + */ + SEAL_NODISCARD inline static BigUInt of(std::uint64_t value) + { + BigUInt result; + result = value; + return result; + } + + /** + Duplicates the current BigUInt. The bit count and the value of the + given BigUInt are set to be exactly the same as in the current one. + + @param[out] destination The BigUInt to overwrite with the duplicate + @throws std::logic_error if the destination BigUInt is an alias + */ + inline void duplicate_to(BigUInt &destination) const + { + destination.resize(this->bit_count_); + destination = *this; + } + + /** + Duplicates a given BigUInt. The bit count and the value of the current + BigUInt are set to be exactly the same as in the given one. + + @param[in] value The BigUInt to duplicate + @throws std::logic_error if the current BigUInt is an alias + */ + inline void duplicate_from(const BigUInt &value) + { + this->resize(value.bit_count_); + *this = value; + } + + private: + MemoryPoolHandle pool_; + + /** + Resets the entire state of the BigUInt to an empty, zero-sized state, + freeing any memory it internally allocated. If the BigUInt was an alias, + the backing array is not freed but the alias is no longer referenced. + */ + inline void reset() noexcept + { + value_.release(); + bit_count_ = 0; + } + + void save_members(std::ostream &stream) const; + + void load_members(std::istream &stream); + + /** + Points to the backing array for the BigUInt. This pointer will be set + to nullptr if and only if the bit count is zero. This pointer is + automatically allocated and freed by the BigUInt if and only if + the BigUInt is not an alias. If the BigUInt is an alias, then the + pointer was passed-in to a constructor or alias() call, and will not be + deallocated by the BigUInt. + */ + util::Pointer<std::uint64_t> value_; + + /** + The bit count for the BigUInt. + */ + int bit_count_ = 0; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/c/CMakeLists.txt b/bigpiseal3.5.1/native/src/seal/c/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..953ee9ab4d868b37bbb00910ca0cb38ff56087de --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Source files in this directory +target_sources(sealc PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/batchencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/biguint.cpp + ${CMAKE_CURRENT_LIST_DIR}/ciphertext.cpp + ${CMAKE_CURRENT_LIST_DIR}/ckksencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/contextdata.cpp + ${CMAKE_CURRENT_LIST_DIR}/decryptor.cpp + # ${CMAKE_CURRENT_LIST_DIR}/dllmain.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptionparameterqualifiers.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptionparameters.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptor.cpp + ${CMAKE_CURRENT_LIST_DIR}/evaluator.cpp + ${CMAKE_CURRENT_LIST_DIR}/galoiskeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/intencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/keygenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/memorymanager.cpp + ${CMAKE_CURRENT_LIST_DIR}/memorypoolhandle.cpp + ${CMAKE_CURRENT_LIST_DIR}/modulus.cpp + ${CMAKE_CURRENT_LIST_DIR}/plaintext.cpp + ${CMAKE_CURRENT_LIST_DIR}/publickey.cpp + ${CMAKE_CURRENT_LIST_DIR}/relinkeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/sealcontext.cpp + ${CMAKE_CURRENT_LIST_DIR}/secretkey.cpp + ${CMAKE_CURRENT_LIST_DIR}/serialization.cpp + ${CMAKE_CURRENT_LIST_DIR}/utilities.cpp + ${CMAKE_CURRENT_LIST_DIR}/valcheck.cpp + ${CMAKE_CURRENT_LIST_DIR}/version.cpp +) + +# Add header files for installation +install( + FILES + ${CMAKE_CURRENT_LIST_DIR}/batchencoder.h + ${CMAKE_CURRENT_LIST_DIR}/biguint.h + ${CMAKE_CURRENT_LIST_DIR}/ciphertext.h + ${CMAKE_CURRENT_LIST_DIR}/ckksencoder.h + ${CMAKE_CURRENT_LIST_DIR}/contextdata.h + ${CMAKE_CURRENT_LIST_DIR}/decryptor.h + ${CMAKE_CURRENT_LIST_DIR}/defines.h + ${CMAKE_CURRENT_LIST_DIR}/encryptionparameterqualifiers.h + ${CMAKE_CURRENT_LIST_DIR}/encryptionparameters.h + ${CMAKE_CURRENT_LIST_DIR}/encryptor.h + ${CMAKE_CURRENT_LIST_DIR}/evaluator.h + ${CMAKE_CURRENT_LIST_DIR}/galoiskeys.h + ${CMAKE_CURRENT_LIST_DIR}/intencoder.h + ${CMAKE_CURRENT_LIST_DIR}/keygenerator.h + ${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.h + ${CMAKE_CURRENT_LIST_DIR}/memorymanager.h + ${CMAKE_CURRENT_LIST_DIR}/memorypoolhandle.h + ${CMAKE_CURRENT_LIST_DIR}/modulus.h + ${CMAKE_CURRENT_LIST_DIR}/plaintext.h + ${CMAKE_CURRENT_LIST_DIR}/publickey.h + ${CMAKE_CURRENT_LIST_DIR}/relinkeys.h + ${CMAKE_CURRENT_LIST_DIR}/sealcontext.h + ${CMAKE_CURRENT_LIST_DIR}/secretkey.h + ${CMAKE_CURRENT_LIST_DIR}/serialization.h + ${CMAKE_CURRENT_LIST_DIR}/stdafx.h + ${CMAKE_CURRENT_LIST_DIR}/targetver.h + ${CMAKE_CURRENT_LIST_DIR}/utilities.h + ${CMAKE_CURRENT_LIST_DIR}/valcheck.h + ${CMAKE_CURRENT_LIST_DIR}/version.h + DESTINATION + ${SEAL_INCLUDES_INSTALL_DIR}/seal/c +) diff --git a/bigpiseal3.5.1/native/src/seal/c/batchencoder.cpp b/bigpiseal3.5.1/native/src/seal/c/batchencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26a1d180f646a34575665db06c2002e36cb83191 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/batchencoder.cpp @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <vector> + +// SEALNet +#include "seal/c/batchencoder.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/batchencoder.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC BatchEncoder_Create(void *context, void **batch_encoder) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx, E_POINTER); + IfNullRet(batch_encoder, E_POINTER); + + try + { + BatchEncoder *encoder = new BatchEncoder(sharedctx); + *batch_encoder = encoder; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BatchEncoder_Destroy(void *thisptr) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + + delete encoder; + return S_OK; +} + +SEAL_C_FUNC BatchEncoder_Encode1(void *thisptr, uint64_t count, uint64_t *values, void *destination) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(values, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(destination); + IfNullRet(plain, E_POINTER); + + vector<uint64_t> valvec(count); + for (uint64_t i = 0; i < count; i++) + { + valvec[i] = values[i]; + } + + try + { + encoder->encode(valvec, *plain); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BatchEncoder_Encode2(void *thisptr, uint64_t count, int64_t *values, void *destination) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(values, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(destination); + IfNullRet(plain, E_POINTER); + + vector<int64_t> valvec(count); + for (uint64_t i = 0; i < count; i++) + { + valvec[i] = values[i]; + } + + try + { + encoder->encode(valvec, *plain); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BatchEncoder_Encode3(void *thisptr, void *plain, void *pool) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + try + { + encoder->encode(*plainptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BatchEncoder_Decode1(void *thisptr, void *plain, uint64_t *count, uint64_t *destination, void *pool) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(count, E_POINTER); + IfNullRet(destination, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + vector<uint64_t> result; + try + { + encoder->decode(*plainptr, result, *handle); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + // Copy to actual destination + *count = result.size(); + + for (uint64_t i = 0; i < *count; i++) + { + destination[i] = result[i]; + } + + return S_OK; +} + +SEAL_C_FUNC BatchEncoder_Decode2(void *thisptr, void *plain, uint64_t *count, int64_t *destination, void *pool) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(count, E_POINTER); + IfNullRet(destination, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + vector<int64_t> result; + try + { + encoder->decode(*plainptr, result, *handle); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + *count = result.size(); + + // Copy to actual destination + for (uint64_t i = 0; i < *count; i++) + { + destination[i] = result[i]; + } + + return S_OK; +} + +SEAL_C_FUNC BatchEncoder_Decode3(void *thisptr, void *plain, void *pool) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + try + { + encoder->decode(*plainptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BatchEncoder_GetSlotCount(void *thisptr, uint64_t *slot_count) +{ + BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(slot_count, E_POINTER); + + *slot_count = encoder->slot_count(); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/batchencoder.h b/bigpiseal3.5.1/native/src/seal/c/batchencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..be7d48984289cd1821a7673d7fb9b57acf3afcec --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/batchencoder.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC BatchEncoder_Create(void *context, void **batch_encoder); + +SEAL_C_FUNC BatchEncoder_Destroy(void *thisptr); + +SEAL_C_FUNC BatchEncoder_Encode1(void *thisptr, uint64_t count, uint64_t *values, void *destination); + +SEAL_C_FUNC BatchEncoder_Encode2(void *thisptr, uint64_t count, int64_t *values, void *destination); + +SEAL_C_FUNC BatchEncoder_Encode3(void *thisptr, void *plain, void *pool); + +SEAL_C_FUNC BatchEncoder_Decode1(void *thisptr, void *plain, uint64_t *count, uint64_t *destination, void *pool); + +SEAL_C_FUNC BatchEncoder_Decode2(void *thisptr, void *plain, uint64_t *count, int64_t *destination, void *pool); + +SEAL_C_FUNC BatchEncoder_Decode3(void *thisptr, void *plain, void *pool); + +SEAL_C_FUNC BatchEncoder_GetSlotCount(void *thisptr, uint64_t *slot_count); diff --git a/bigpiseal3.5.1/native/src/seal/c/biguint.cpp b/bigpiseal3.5.1/native/src/seal/c/biguint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d84224834860d23cd7aa31fdad89931af851f96d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/biguint.cpp @@ -0,0 +1,777 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <string> + +// SEALNet +#include "seal/c/biguint.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/biguint.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC BigUInt_Create1(void **bui) +{ + IfNullRet(bui, E_POINTER); + + BigUInt *biguint = new BigUInt(); + *bui = biguint; + return S_OK; +} + +SEAL_C_FUNC BigUInt_Create2(int bitCount, void **bui) +{ + IfNullRet(bui, E_POINTER); + + try + { + BigUInt *biguint = new BigUInt(bitCount, /* value */ static_cast<uint64_t>(0)); + *bui = biguint; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_Create3(int bitCount, char *hex_string, void **bui) +{ + IfNullRet(hex_string, E_POINTER); + IfNullRet(bui, E_POINTER); + + string hexstring(hex_string); + BigUInt *biguint = nullptr; + + try + { + biguint = new BigUInt(bitCount, hexstring); + *bui = biguint; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_Create4(int bitCount, uint64_t value, void **bui) +{ + IfNullRet(bui, E_POINTER); + + try + { + BigUInt *biguint = new BigUInt(bitCount, value); + *bui = biguint; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_Create5(char *hex_string, void **bui) +{ + IfNullRet(hex_string, E_POINTER); + IfNullRet(bui, E_POINTER); + + string hexstring(hex_string); + BigUInt *biguint = nullptr; + + try + { + biguint = new BigUInt(hexstring); + *bui = biguint; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_Create6(void *copy, void **bui) +{ + BigUInt *other = FromVoid<BigUInt>(copy); + IfNullRet(other, E_POINTER); + IfNullRet(bui, E_POINTER); + + BigUInt *biguint = new BigUInt(*other); + *bui = biguint; + return S_OK; +} + +SEAL_C_FUNC BigUInt_Destroy(void *thisptr) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(thisptr, E_POINTER); + + delete biguint; + return S_OK; +} + +SEAL_C_FUNC BigUInt_IsAlias(void *thisptr, bool *is_alias) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(is_alias, E_POINTER); + + *is_alias = biguint->is_alias(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_BitCount(void *thisptr, int *bit_count) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(bit_count, E_POINTER); + + *bit_count = biguint->bit_count(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_ByteCount(void *thisptr, uint64_t *byte_count) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(byte_count, E_POINTER); + + *byte_count = biguint->byte_count(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_UInt64Count(void *thisptr, uint64_t *uint64_count) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(uint64_count, E_POINTER); + + *uint64_count = biguint->uint64_count(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_IsZero(void *thisptr, bool *is_zero) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(is_zero, E_POINTER); + + *is_zero = biguint->is_zero(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_Get(void *thisptr, uint64_t index, uint8_t *value) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(value, E_POINTER) + + if (index >= biguint->byte_count()) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } + + auto result = (*biguint)[index]; + *value = static_cast<uint8_t>(result); + return S_OK; +} + +SEAL_C_FUNC BigUInt_GetU64(void *thisptr, uint64_t index, uint64_t *value) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(value, E_POINTER); + + if (index >= biguint->uint64_count()) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } + + *value = biguint->data()[index]; + return S_OK; +} + +SEAL_C_FUNC BigUInt_Set1(void *thisptr, uint64_t index, uint8_t value) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + + if (index >= biguint->byte_count()) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } + + (*biguint)[index] = static_cast<SEAL_BYTE>(value); + return S_OK; +} + +SEAL_C_FUNC BigUInt_GetSignificantBitCount(void *thisptr, int *significant_bit_count) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(significant_bit_count, E_POINTER); + + *significant_bit_count = biguint->significant_bit_count(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_Set2(void *thisptr, void *assign) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *other = FromVoid<BigUInt>(assign); + IfNullRet(other, E_POINTER); + + *biguint = *other; + return S_OK; +} + +SEAL_C_FUNC BigUInt_Set3(void *thisptr, uint64_t value) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + + try + { + *biguint = value; + return S_OK; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC BigUInt_Set4(void *thisptr, char *assign) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(assign, E_POINTER); + + string assign_str(assign); + + try + { + *biguint = assign_str; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC BigUInt_SetZero(void *thisptr) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + + biguint->set_zero(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_Resize(void *thisptr, int bitCount) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + + biguint->resize(bitCount); + return S_OK; +} + +SEAL_C_FUNC BigUInt_Equals(void *thisptr, void *compare, bool *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *other = FromVoid<BigUInt>(compare); + IfNullRet(other, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*biguint) == (*other); + return S_OK; +} + +SEAL_C_FUNC BigUInt_CompareTo1(void *thisptr, void *compare, int *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *other = FromVoid<BigUInt>(compare); + IfNullRet(other, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = biguint->compareto(*other); + return S_OK; +} + +SEAL_C_FUNC BigUInt_CompareTo2(void *thisptr, uint64_t compare, int *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + + *result = biguint->compareto(compare); + return S_OK; +} + +SEAL_C_FUNC BigUInt_DivideRemainder1(void *thisptr, void *operand2, void *remainder, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operand2bui = FromVoid<BigUInt>(operand2); + IfNullRet(operand2bui, E_POINTER); + BigUInt *remainderbui = FromVoid<BigUInt>(remainder); + IfNullRet(remainderbui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(biguint->divrem(*operand2bui, *remainderbui)); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_DivideRemainder2(void *thisptr, uint64_t operand2, void *remainder, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *remainderbui = FromVoid<BigUInt>(remainder); + IfNullRet(remainderbui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(biguint->divrem(operand2, *remainderbui)); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_ToString(void *thisptr, char *outstr, uint64_t *length) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(length, E_POINTER); + + return ToStringHelper(biguint->to_string(), outstr, length); +} + +SEAL_C_FUNC BigUInt_ToDecimalString(void *thisptr, char *outstr, uint64_t *length) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(length, E_POINTER); + + return ToStringHelper(biguint->to_dec_string(), outstr, length); +} + +SEAL_C_FUNC BigUInt_DuplicateTo(void *thisptr, void *destination) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *destbui = FromVoid<BigUInt>(destination); + IfNullRet(destbui, E_POINTER); + + biguint->duplicate_to(*destbui); + return S_OK; +} + +SEAL_C_FUNC BigUInt_DuplicateFrom(void *thisptr, void *value) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *valuebui = FromVoid<BigUInt>(value); + IfNullRet(valuebui, E_POINTER); + + biguint->duplicate_from(*valuebui); + return S_OK; +} + +SEAL_C_FUNC BigUInt_ModuloInvert1(void *thisptr, void *modulus, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *modulusui = FromVoid<BigUInt>(modulus); + IfNullRet(modulusui, E_POINTER); + IfNullRet(result, E_POINTER); + BigUInt *resultbui = nullptr; + + try + { + resultbui = new BigUInt(biguint->modinv(*modulusui)); + *result = resultbui; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC BigUInt_ModuloInvert2(void *thisptr, uint64_t modulus, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *resultbui = nullptr; + + try + { + resultbui = new BigUInt(biguint->modinv(modulus)); + *result = resultbui; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC BigUInt_TryModuloInvert1(void *thisptr, void *modulus, void *inverse, bool *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *modulusui = FromVoid<BigUInt>(modulus); + IfNullRet(modulusui, E_POINTER); + BigUInt *inverseui = FromVoid<BigUInt>(inverse); + IfNullRet(inverseui, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = biguint->trymodinv(*modulusui, *inverseui); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_TryModuloInvert2(void *thisptr, uint64_t modulus, void *inverse, bool *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *inverseui = FromVoid<BigUInt>(inverse); + IfNullRet(inverseui, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = biguint->trymodinv(modulus, *inverseui); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC BigUInt_OperatorNeg(void *thisptr, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(biguint->operator-()); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorTilde(void *thisptr, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(biguint->operator~()); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorPlus1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint + *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorPlus2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint + operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorMinus1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint - *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorMinus2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint - operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorMult1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint * *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorMult2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint * operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorDiv1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint / *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorDiv2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint / operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorXor1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint ^ *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorXor2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint ^ operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorAnd1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint & *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorAnd2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint & operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorOr1(void *thisptr, void *operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + BigUInt *operandui = FromVoid<BigUInt>(operand); + IfNullRet(operandui, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint | *operandui); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorOr2(void *thisptr, uint64_t operand, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint | operand); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorShiftLeft(void *thisptr, int shift, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint << shift); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_OperatorShiftRight(void *thisptr, int shift, void **result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + BigUInt *resultbui = new BigUInt(*biguint >> shift); + *result = resultbui; + return S_OK; +} + +SEAL_C_FUNC BigUInt_ToDouble(void *thisptr, double *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = biguint->to_double(); + return S_OK; +} + +SEAL_C_FUNC BigUInt_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(biguint->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC BigUInt_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(biguint->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC BigUInt_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + BigUInt *biguint = FromVoid<BigUInt>(thisptr); + IfNullRet(biguint, E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + biguint->load(reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/biguint.h b/bigpiseal3.5.1/native/src/seal/c/biguint.h new file mode 100644 index 0000000000000000000000000000000000000000..4fcbba4d7ff254f9886c43a9a5e19957137c3030 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/biguint.h @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC BigUInt_Create1(void **bui); + +SEAL_C_FUNC BigUInt_Create2(int bitCount, void **bui); + +SEAL_C_FUNC BigUInt_Create3(int bitCount, char *hex_string, void **bui); + +SEAL_C_FUNC BigUInt_Create4(int bitCount, uint64_t value, void **bui); + +SEAL_C_FUNC BigUInt_Create5(char *hex_string, void **bui); + +SEAL_C_FUNC BigUInt_Create6(void *copy, void **bui); + +SEAL_C_FUNC BigUInt_Destroy(void *thispt); + +SEAL_C_FUNC BigUInt_IsAlias(void *thisptr, bool *is_alias); + +SEAL_C_FUNC BigUInt_BitCount(void *thisptr, int *bit_count); + +SEAL_C_FUNC BigUInt_ByteCount(void *thisptr, uint64_t *byte_count); + +SEAL_C_FUNC BigUInt_UInt64Count(void *thisptr, uint64_t *uint64_count); + +SEAL_C_FUNC BigUInt_IsZero(void *thisptr, bool *is_zero); + +SEAL_C_FUNC BigUInt_Get(void *thisptr, uint64_t index, uint8_t *value); + +SEAL_C_FUNC BigUInt_GetU64(void *thisptr, uint64_t index, uint64_t *value); + +SEAL_C_FUNC BigUInt_Set1(void *thisptr, uint64_t index, uint8_t value); + +SEAL_C_FUNC BigUInt_GetSignificantBitCount(void *thisptr, int *significant_bit_count); + +SEAL_C_FUNC BigUInt_Set2(void *thisptr, void *assign); + +SEAL_C_FUNC BigUInt_Set3(void *thisptr, uint64_t value); + +SEAL_C_FUNC BigUInt_Set4(void *thisptr, char *assign); + +SEAL_C_FUNC BigUInt_SetZero(void *thispt); + +SEAL_C_FUNC BigUInt_Resize(void *thisptr, int bitCount); + +SEAL_C_FUNC BigUInt_Equals(void *thisptr, void *compare, bool *result); + +SEAL_C_FUNC BigUInt_CompareTo1(void *thisptr, void *compare, int *result); + +SEAL_C_FUNC BigUInt_CompareTo2(void *thisptr, uint64_t compare, int *result); + +SEAL_C_FUNC BigUInt_DivideRemainder1(void *thisptr, void *operand2, void *remainder, void **result); + +SEAL_C_FUNC BigUInt_DivideRemainder2(void *thisptr, uint64_t operand2, void *remainder, void **result); + +SEAL_C_FUNC BigUInt_ToString(void *thisptr, char *outstr, uint64_t *length); + +SEAL_C_FUNC BigUInt_ToDecimalString(void *thisptr, char *outstr, uint64_t *length); + +SEAL_C_FUNC BigUInt_DuplicateTo(void *thisptr, void *destination); + +SEAL_C_FUNC BigUInt_DuplicateFrom(void *thisptr, void *value); + +SEAL_C_FUNC BigUInt_ModuloInvert1(void *thisptr, void *modulus, void **result); + +SEAL_C_FUNC BigUInt_ModuloInvert2(void *thisptr, uint64_t modulus, void **result); + +SEAL_C_FUNC BigUInt_TryModuloInvert1(void *thisptr, void *modulus, void *inverse, bool *result); + +SEAL_C_FUNC BigUInt_TryModuloInvert2(void *thisptr, uint64_t modulus, void *inverse, bool *result); + +SEAL_C_FUNC BigUInt_OperatorNeg(void *thisptr, void **result); + +SEAL_C_FUNC BigUInt_OperatorTilde(void *thisptr, void **result); + +SEAL_C_FUNC BigUInt_OperatorPlus1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorPlus2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorMinus1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorMinus2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorMult1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorMult2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorDiv1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorDiv2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorXor1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorXor2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorAnd1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorAnd2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorOr1(void *thisptr, void *operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorOr2(void *thisptr, uint64_t operand, void **result); + +SEAL_C_FUNC BigUInt_OperatorShiftLeft(void *thisptr, int shift, void **result); + +SEAL_C_FUNC BigUInt_OperatorShiftRight(void *thisptr, int shift, void **result); + +SEAL_C_FUNC BigUInt_ToDouble(void *thisptr, double *result); + +SEAL_C_FUNC BigUInt_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC BigUInt_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC BigUInt_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/ciphertext.cpp b/bigpiseal3.5.1/native/src/seal/c/ciphertext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d910b501bb9e746238eb799d593fdeb609262721 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/ciphertext.cpp @@ -0,0 +1,566 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/ciphertext.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/ciphertext.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +namespace seal +{ + /** + Enables access to private members of seal::Ciphertext. + */ + struct Ciphertext::CiphertextPrivateHelper + { + static void resize(Ciphertext *ciphertext, size_t size, size_t poly_modulus_degree, size_t coeff_modulus_size) + { + ciphertext->resize_internal(size, poly_modulus_degree, coeff_modulus_size); + } + + static void set_ntt_form(Ciphertext *ciphertext, bool is_ntt_form) + { + ciphertext->is_ntt_form_ = is_ntt_form; + } + }; +} // namespace seal + +SEAL_C_FUNC Ciphertext_Create1(void *memoryPoolHandle, void **ciphertext) +{ + IfNullRet(ciphertext, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle); + + try + { + Ciphertext *cipher = new Ciphertext(*handle); + *ciphertext = cipher; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Create2(void *copy, void **ciphertext) +{ + Ciphertext *copyptr = FromVoid<Ciphertext>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(ciphertext, E_POINTER); + + Ciphertext *cipher = new Ciphertext(*copyptr); + *ciphertext = cipher; + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Create3(void *context, void *pool, void **ciphertext) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(ciphertext, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + Ciphertext *cipher = new Ciphertext(sharedctx, *pool_ptr); + *ciphertext = cipher; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Create4(void *context, uint64_t *parms_id, void *pool, void **ciphertext) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(parms_id, E_POINTER); + IfNullRet(ciphertext, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + parms_id_type parmsid; + CopyParmsId(parms_id, parmsid); + + Ciphertext *cipher = new Ciphertext(sharedctx, parmsid, *pool_ptr); + *ciphertext = cipher; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Create5(void *context, uint64_t *parms_id, uint64_t capacity, void *pool, void **ciphertext) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(parms_id, E_POINTER); + IfNullRet(ciphertext, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + parms_id_type parmsid; + CopyParmsId(parms_id, parmsid); + + Ciphertext *cipher = new Ciphertext(sharedctx, parmsid, capacity, *pool_ptr); + *ciphertext = cipher; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Reserve1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size_capacity) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + cipher->reserve(sharedctx, parms, size_capacity); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Reserve2(void *thisptr, void *context, uint64_t size_capacity) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + + try + { + cipher->reserve(sharedctx, size_capacity); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Reserve3(void *thisptr, uint64_t size_capacity) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + try + { + cipher->reserve(size_capacity); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Set(void *thisptr, void *assign) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + Ciphertext *assignptr = FromVoid<Ciphertext>(assign); + IfNullRet(assignptr, E_POINTER); + + *cipher = *assignptr; + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Destroy(void *thisptr) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + delete cipher; + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Size(void *thisptr, uint64_t *size) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(size, E_POINTER); + + *size = cipher->size(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_SizeCapacity(void *thisptr, uint64_t *size_capacity) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(size_capacity, E_POINTER); + + *size_capacity = cipher->size_capacity(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_PolyModulusDegree(void *thisptr, uint64_t *poly_modulus_degree) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(poly_modulus_degree, E_POINTER); + + *poly_modulus_degree = cipher->poly_modulus_degree(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_CoeffModulusSize(void *thisptr, uint64_t *coeff_modulus_size) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(coeff_modulus_size, E_POINTER); + + *coeff_modulus_size = cipher->coeff_modulus_size(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_ParmsId(void *thisptr, uint64_t *parms_id) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(cipher->parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_SetParmsId(void *thisptr, uint64_t *parms_id) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(parms_id, cipher->parms_id()); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Resize1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + cipher->resize(sharedctx, parms, size); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Resize2(void *thisptr, void *context, uint64_t size) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + + try + { + cipher->resize(sharedctx, size); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Resize3(void *thisptr, uint64_t size) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + try + { + cipher->resize(size); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_Resize4(void *thisptr, uint64_t size, uint64_t polyModulusDegree, uint64_t coeffModCount) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + try + { + Ciphertext::CiphertextPrivateHelper::resize(cipher, size, polyModulusDegree, coeffModCount); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Ciphertext_GetDataAt1(void *thisptr, uint64_t index, uint64_t *data) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(data, E_POINTER); + + try + { + *data = (*cipher)[index]; + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Ciphertext_GetDataAt2(void *thisptr, uint64_t poly_index, uint64_t coeff_index, uint64_t *data) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(data, E_POINTER); + + auto poly_uint64_count = util::mul_safe(cipher->poly_modulus_degree(), cipher->coeff_modulus_size()); + + // poly_index is verified by the data method, we need to verify coeff_index ourselves. + if (coeff_index >= poly_uint64_count) + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + + try + { + *data = cipher->data(poly_index)[coeff_index]; + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Ciphertext_SetDataAt(void *thisptr, uint64_t index, uint64_t value) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + try + { + (*cipher)[index] = value; + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Ciphertext_IsNTTForm(void *thisptr, bool *is_ntt_form) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(is_ntt_form, E_POINTER); + + *is_ntt_form = cipher->is_ntt_form(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_SetIsNTTForm(void *thisptr, bool is_ntt_form) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + Ciphertext::CiphertextPrivateHelper::set_ntt_form(cipher, is_ntt_form); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Scale(void *thisptr, double *scale) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(scale, E_POINTER); + + *scale = cipher->scale(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_SetScale(void *thisptr, double scale) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + cipher->scale() = scale; + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Release(void *thisptr) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + + cipher->release(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_IsTransparent(void *thisptr, bool *result) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = cipher->is_transparent(); + return S_OK; +} + +SEAL_C_FUNC Ciphertext_Pool(void *thisptr, void **pool) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(pool, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(cipher->pool()); + *pool = handleptr; + return S_OK; +} + +SEAL_C_FUNC Ciphertext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(cipher->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Ciphertext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(cipher->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC Ciphertext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + cipher->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC Ciphertext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(thisptr); + IfNullRet(cipher, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + cipher->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/ciphertext.h b/bigpiseal3.5.1/native/src/seal/c/ciphertext.h new file mode 100644 index 0000000000000000000000000000000000000000..e879ef9da5040be4c1b75343362613222d213d29 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/ciphertext.h @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Ciphertext_Create1(void *pool, void **cipher); + +SEAL_C_FUNC Ciphertext_Create2(void *copy, void **cipher); + +SEAL_C_FUNC Ciphertext_Create3(void *context, void *pool, void **cipher); + +SEAL_C_FUNC Ciphertext_Create4(void *context, uint64_t *parms_id, void *pool, void **cipher); + +SEAL_C_FUNC Ciphertext_Create5(void *context, uint64_t *parms_id, uint64_t capacity, void *pool, void **ciphertext); + +SEAL_C_FUNC Ciphertext_Reserve1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size_capacity); + +SEAL_C_FUNC Ciphertext_Reserve2(void *thisptr, void *context, uint64_t size_capacity); + +SEAL_C_FUNC Ciphertext_Reserve3(void *thisptr, uint64_t size_capacity); + +SEAL_C_FUNC Ciphertext_Set(void *thisptr, void *assign); + +SEAL_C_FUNC Ciphertext_Destroy(void *thisptr); + +SEAL_C_FUNC Ciphertext_Size(void *thisptr, uint64_t *size); + +SEAL_C_FUNC Ciphertext_SizeCapacity(void *thisptr, uint64_t *size_capacity); + +SEAL_C_FUNC Ciphertext_PolyModulusDegree(void *thisptr, uint64_t *poly_modulus_degree); + +SEAL_C_FUNC Ciphertext_CoeffModulusSize(void *thisptr, uint64_t *coeff_modulus_size); + +SEAL_C_FUNC Ciphertext_ParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC Ciphertext_SetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC Ciphertext_Resize1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size); + +SEAL_C_FUNC Ciphertext_Resize2(void *thisptr, void *context, uint64_t size); + +SEAL_C_FUNC Ciphertext_Resize3(void *thisptr, uint64_t size); + +SEAL_C_FUNC Ciphertext_Resize4(void *thisptr, uint64_t size, uint64_t polyModulusDegree, uint64_t coeffModCount); + +SEAL_C_FUNC Ciphertext_GetDataAt1(void *thisptr, uint64_t index, uint64_t *data); + +SEAL_C_FUNC Ciphertext_GetDataAt2(void *thisptr, uint64_t poly_index, uint64_t coeff_index, uint64_t *data); + +SEAL_C_FUNC Ciphertext_SetDataAt(void *thisptr, uint64_t index, uint64_t value); + +SEAL_C_FUNC Ciphertext_IsNTTForm(void *thisptr, bool *is_ntt_form); + +SEAL_C_FUNC Ciphertext_SetIsNTTForm(void *thisptr, bool is_ntt_form); + +SEAL_C_FUNC Ciphertext_Scale(void *thisptr, double *scale); + +SEAL_C_FUNC Ciphertext_SetScale(void *thisptr, double scale); + +SEAL_C_FUNC Ciphertext_Release(void *thisptr); + +SEAL_C_FUNC Ciphertext_IsTransparent(void *thisptr, bool *result); + +SEAL_C_FUNC Ciphertext_Pool(void *thisptr, void **pool); + +SEAL_C_FUNC Ciphertext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC Ciphertext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC Ciphertext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC Ciphertext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/ckksencoder.cpp b/bigpiseal3.5.1/native/src/seal/c/ckksencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cf0a52ea7a2f172cbfe64b803eaea8d5c2f3310 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/ckksencoder.cpp @@ -0,0 +1,260 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <vector> + +// SEALNet +#include "seal/c/ckksencoder.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/ckks.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC CKKSEncoder_Create(void *context, void **ckks_encoder) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(ckks_encoder, E_POINTER); + + try + { + CKKSEncoder *encoder = new CKKSEncoder(sharedctx); + *ckks_encoder = encoder; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC CKKSEncoder_Destroy(void *thisptr) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + + delete encoder; + return S_OK; +} + +// Array of doubles +SEAL_C_FUNC CKKSEncoder_Encode1( + void *thisptr, uint64_t value_count, double *values, uint64_t *parms_id, double scale, void *destination, + void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + vector<double> input(value_count); + for (uint64_t i = 0; i < value_count; i++) + { + input[i] = values[i]; + } + + try + { + encoder->encode(input, parms, scale, *destinationptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +// Array of complex numbers (two doubles per value) +SEAL_C_FUNC CKKSEncoder_Encode2( + void *thisptr, uint64_t value_count, double *complex_values, uint64_t *parms_id, double scale, void *destination, + void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + vector<complex<double>> input(value_count); + for (uint64_t i = 0; i < value_count; i++) + { + input[i] = complex<double>(complex_values[i * 2], complex_values[i * 2 + 1]); + } + + try + { + encoder->encode(input, parms, scale, *destinationptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +// Single double value +SEAL_C_FUNC CKKSEncoder_Encode3( + void *thisptr, double value, uint64_t *parms_id, double scale, void *destination, void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + encoder->encode(value, parms, scale, *destinationptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +// Single complex value +SEAL_C_FUNC CKKSEncoder_Encode4( + void *thisptr, double value_re, double value_im, uint64_t *parms_id, double scale, void *destination, void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + complex<double> input(value_re, value_im); + + try + { + encoder->encode(input, parms, scale, *destinationptr, *handle); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +// Single Int64 value +SEAL_C_FUNC CKKSEncoder_Encode5(void *thisptr, int64_t value, uint64_t *parms_id, void *destination) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + encoder->encode(value, parms, *destinationptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +// Array of doubles +SEAL_C_FUNC CKKSEncoder_Decode1(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(value_count, E_POINTER); + IfNullRet(values, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + vector<double> destination; + + try + { + encoder->decode(*plainptr, destination, *handle); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + *value_count = destination.size(); + + // Copy to actual destination + for (uint64_t i = 0; i < destination.size(); i++) + { + values[i] = destination[i]; + } + + return S_OK; +} + +// Array of complex numbers +SEAL_C_FUNC CKKSEncoder_Decode2(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(value_count, E_POINTER); + IfNullRet(values, E_POINTER); + Plaintext *plainptr = FromVoid<Plaintext>(plain); + IfNullRet(plainptr, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool); + + vector<complex<double>> destination; + + try + { + encoder->decode(*plainptr, destination, *handle); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + *value_count = destination.size(); + + // Copy to actual destination + for (uint64_t i = 0; i < destination.size(); i++) + { + values[i * 2] = destination[i].real(); + values[i * 2 + 1] = destination[i].imag(); + } + + return S_OK; +} + +SEAL_C_FUNC CKKSEncoder_SlotCount(void *thisptr, uint64_t *slot_count) +{ + CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr); + IfNullRet(encoder, E_POINTER); + IfNullRet(slot_count, E_POINTER); + + *slot_count = encoder->slot_count(); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/ckksencoder.h b/bigpiseal3.5.1/native/src/seal/c/ckksencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..3daa5bdb54e02674808078e14dbddf64bb579d38 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/ckksencoder.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC CKKSEncoder_Create(void *context, void **ckks_encoder); + +SEAL_C_FUNC CKKSEncoder_Destroy(void *thisptr); + +// Array of doubles +SEAL_C_FUNC CKKSEncoder_Encode1( + void *thisptr, uint64_t value_count, double *values, uint64_t *parms_id, double scale, void *destination, + void *pool); + +// Array of complex numbers (two doubles per value) +SEAL_C_FUNC CKKSEncoder_Encode2( + void *thisptr, uint64_t value_count, double *complex_values, uint64_t *parms_id, double scale, void *destination, + void *pool); + +// Single double value +SEAL_C_FUNC CKKSEncoder_Encode3( + void *thisptr, double value, uint64_t *parms_id, double scale, void *destination, void *pool); + +// Single complex value +SEAL_C_FUNC CKKSEncoder_Encode4( + void *thisptr, double value_re, double value_im, uint64_t *parms_id, double scale, void *destination, void *pool); + +// Single Int64 value +SEAL_C_FUNC CKKSEncoder_Encode5(void *thisptr, int64_t value, uint64_t *parms_id, void *destination); + +// Array of doubles +SEAL_C_FUNC CKKSEncoder_Decode1(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool); + +// Array of complex numbers +SEAL_C_FUNC CKKSEncoder_Decode2(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool); + +SEAL_C_FUNC CKKSEncoder_SlotCount(void *thisptr, uint64_t *slot_count); diff --git a/bigpiseal3.5.1/native/src/seal/c/contextdata.cpp b/bigpiseal3.5.1/native/src/seal/c/contextdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29b9b82bda406855aaa337043068d41af46a2e38 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/contextdata.cpp @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/contextdata.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/context.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC ContextData_Destroy(void *thisptr) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + + delete cont_data; + return S_OK; +} + +SEAL_C_FUNC ContextData_TotalCoeffModulus(void *thisptr, uint64_t *count, uint64_t *total_coeff_modulus) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = cont_data->parms().coeff_modulus().size(); + + if (nullptr == total_coeff_modulus) + { + // We only wanted the count. + return S_OK; + } + + for (uint64_t i = 0; i < *count; i++) + { + total_coeff_modulus[i] = cont_data->total_coeff_modulus()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC ContextData_TotalCoeffModulusBitCount(void *thisptr, int *bit_count) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(bit_count, E_POINTER); + + *bit_count = cont_data->total_coeff_modulus_bit_count(); + return S_OK; +} + +SEAL_C_FUNC ContextData_Parms(void *thisptr, void **parms) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + + EncryptionParameters *enc_params = new EncryptionParameters(cont_data->parms()); + *parms = enc_params; + return S_OK; +} + +SEAL_C_FUNC ContextData_Qualifiers(void *thisptr, void **epq) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(epq, E_POINTER); + + EncryptionParameterQualifiers *qualifiers = new EncryptionParameterQualifiers(cont_data->qualifiers()); + *epq = qualifiers; + return S_OK; +} + +SEAL_C_FUNC ContextData_CoeffDivPlainModulus(void *thisptr, uint64_t *count, uint64_t *coeff_div) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = cont_data->parms().coeff_modulus().size(); + + if (nullptr == coeff_div) + { + // We only wanted the size + return S_OK; + } + + for (uint64_t i = 0; i < *count; i++) + { + coeff_div[i] = cont_data->coeff_div_plain_modulus()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC ContextData_PlainUpperHalfThreshold(void *thisptr, uint64_t *puht) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(puht, E_POINTER); + + *puht = cont_data->plain_upper_half_threshold(); + return S_OK; +} + +SEAL_C_FUNC ContextData_PlainUpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *puhi) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = cont_data->parms().coeff_modulus().size(); + + if (nullptr == puhi) + { + // We only wanted the size + return S_OK; + } + + for (uint64_t i = 0; i < *count; i++) + { + puhi[i] = cont_data->plain_upper_half_increment()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC ContextData_UpperHalfThreshold(void *thisptr, uint64_t *count, uint64_t *uht) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(count, E_POINTER); + + // This is only available for CKKS + if (cont_data->upper_half_threshold() == nullptr) + { + *count = 0; + return S_OK; + } + + *count = cont_data->parms().coeff_modulus().size(); + + if (nullptr == uht) + { + // We only wanted the count + return S_OK; + } + + for (uint64_t i = 0; i < *count; i++) + { + uht[i] = cont_data->upper_half_threshold()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC ContextData_UpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *uhi) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(count, E_POINTER); + + if (cont_data->upper_half_increment() == nullptr) + { + *count = 0; + return S_OK; + } + + *count = cont_data->parms().coeff_modulus().size(); + + if (nullptr == uhi) + { + // We only wanted the size + return S_OK; + } + + for (uint64_t i = 0; i < *count; i++) + { + uhi[i] = cont_data->upper_half_increment()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC ContextData_PrevContextData(void *thisptr, void **prev_data) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(prev_data, E_POINTER); + + // The caller should not try to delete the returned pointer + *prev_data = const_cast<SEALContext::ContextData *>(cont_data->prev_context_data().get()); + return S_OK; +} + +SEAL_C_FUNC ContextData_NextContextData(void *thisptr, void **next_data) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(next_data, E_POINTER); + + // The caller should not try to delete the returned pointer + *next_data = const_cast<SEALContext::ContextData *>(cont_data->next_context_data().get()); + return S_OK; +} + +SEAL_C_FUNC ContextData_ChainIndex(void *thisptr, uint64_t *index) +{ + SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr); + IfNullRet(cont_data, E_POINTER); + IfNullRet(index, E_POINTER); + + *index = cont_data->chain_index(); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/contextdata.h b/bigpiseal3.5.1/native/src/seal/c/contextdata.h new file mode 100644 index 0000000000000000000000000000000000000000..d9ea186b99b155fcc4ea1c64ac45e6ca24f721bf --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/contextdata.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC ContextData_Destroy(void *thisptr); + +SEAL_C_FUNC ContextData_TotalCoeffModulus(void *thisptr, uint64_t *count, uint64_t *total_coeff_modulus); + +SEAL_C_FUNC ContextData_TotalCoeffModulusBitCount(void *thisptr, int *bit_count); + +SEAL_C_FUNC ContextData_Parms(void *thisptr, void **parms); + +SEAL_C_FUNC ContextData_Qualifiers(void *thisptr, void **epq); + +SEAL_C_FUNC ContextData_CoeffDivPlainModulus(void *thisptr, uint64_t *count, uint64_t *coeff_div); + +SEAL_C_FUNC ContextData_PlainUpperHalfThreshold(void *thisptr, uint64_t *puht); + +SEAL_C_FUNC ContextData_PlainUpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *puhi); + +SEAL_C_FUNC ContextData_UpperHalfThreshold(void *thisptr, uint64_t *count, uint64_t *uht); + +SEAL_C_FUNC ContextData_UpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *uhi); + +SEAL_C_FUNC ContextData_PrevContextData(void *thisptr, void **prev_data); + +SEAL_C_FUNC ContextData_NextContextData(void *thisptr, void **next_data); + +SEAL_C_FUNC ContextData_ChainIndex(void *thisptr, uint64_t *index); diff --git a/bigpiseal3.5.1/native/src/seal/c/decryptor.cpp b/bigpiseal3.5.1/native/src/seal/c/decryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90460bc3faa7c02be7d9ba1ba44933a07cee0683 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/decryptor.cpp @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/decryptor.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/decryptor.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC Decryptor_Create(void *context, void *secret_key, void **decryptor) +{ + SecretKey *secretKey = FromVoid<SecretKey>(secret_key); + IfNullRet(secretKey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(decryptor, E_POINTER); + + try + { + Decryptor *decr = new Decryptor(sharedctx, *secretKey); + *decryptor = decr; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Decryptor_Destroy(void *thisptr) +{ + Decryptor *decryptor = FromVoid<Decryptor>(thisptr); + IfNullRet(decryptor, E_POINTER); + + delete decryptor; + return S_OK; +} + +SEAL_C_FUNC Decryptor_Decrypt(void *thisptr, void *encrypted, void *destination) +{ + Decryptor *decryptor = FromVoid<Decryptor>(thisptr); + IfNullRet(decryptor, E_POINTER); + Ciphertext *encryptedptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encryptedptr, E_POINTER); + Plaintext *destinationptr = FromVoid<Plaintext>(destination); + IfNullRet(destinationptr, E_POINTER); + + try + { + decryptor->decrypt(*encryptedptr, *destinationptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Decryptor_InvariantNoiseBudget(void *thisptr, void *encrypted, int *invariant_noise_budget) +{ + Decryptor *decryptor = FromVoid<Decryptor>(thisptr); + IfNullRet(decryptor, E_POINTER); + Ciphertext *encryptedptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encryptedptr, E_POINTER); + IfNullRet(invariant_noise_budget, E_POINTER); + + try + { + *invariant_noise_budget = decryptor->invariant_noise_budget(*encryptedptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/decryptor.h b/bigpiseal3.5.1/native/src/seal/c/decryptor.h new file mode 100644 index 0000000000000000000000000000000000000000..7c5dc747a247ac79b736fafa88b9cf6d223b08bd --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/decryptor.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Decryptor_Create(void *context, void *secret_key, void **decryptor); + +SEAL_C_FUNC Decryptor_Destroy(void *thisptr); + +SEAL_C_FUNC Decryptor_Decrypt(void *thisptr, void *encrypted, void *destination); + +SEAL_C_FUNC Decryptor_InvariantNoiseBudget(void *thisptr, void *encrypted, int *invariant_noise_budget); diff --git a/bigpiseal3.5.1/native/src/seal/c/defines.h b/bigpiseal3.5.1/native/src/seal/c/defines.h new file mode 100644 index 0000000000000000000000000000000000000000..b74baaa905b01e530c88fe59f804642353754594 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/defines.h @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// STD +#include <cstddef> + +// Check that std::size_t is 64 bits +static_assert(sizeof(std::size_t) == 8, "Require sizeof(std::size_t) == 8"); + +#ifdef _MSC_VER + +// Check that architecture (platform) is x64 +#ifndef _WIN64 +static_assert(false, "Require architecture == x64"); +#endif + +#ifdef SEAL_C_EXPORTS +#define SEAL_C_DECOR extern "C" __declspec(dllexport) +#else +#define SEAL_C_DECOR extern "C" __declspec(dllimport) +#endif + +#define SEAL_C_CALL __cdecl + +#else // _MSC_VER + +#define SEAL_C_DECOR extern "C" +#define SEAL_C_CALL + +#define HRESULT long + +#define _HRESULT_TYPEDEF_(hr) ((HRESULT)hr) + +#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L) +#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L) +#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL) +#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL) +#define COR_E_IO _HRESULT_TYPEDEF_(0x80131620L) +#define COR_E_INVALIDOPERATION _HRESULT_TYPEDEF_(0x80131509L) + +#define S_OK _HRESULT_TYPEDEF_(0L) +#define S_FALSE _HRESULT_TYPEDEF_(1L) + +#define FACILITY_WIN32 7 +#define HRESULT_FROM_WIN32(x) \ + ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT)(((x)&0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) + +#define ERROR_INSUFFICIENT_BUFFER 122L +#define ERROR_INVALID_INDEX 1413L +#define ERROR_INVALID_OPERATION 4317L + +#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) +#define FAILED(hr) (((HRESULT)(hr)) < 0) + +#endif // _MSC_VER + +#define SEAL_C_FUNC SEAL_C_DECOR HRESULT SEAL_C_CALL \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/dllmain.cpp b/bigpiseal3.5.1/native/src/seal/c/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c36bcc2b4209eebe68266d88479fcb06d61cd0a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/dllmain.cpp @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// dllmain.cpp : Defines the entry point for the DLL application. +#include "seal/c/stdafx.h" + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.cpp b/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d11cc56cfeac46ebb60f681f011b20b84012e745 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.cpp @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <string.h> + +// SEALNet +#include "seal/c/encryptionparameterqualifiers.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/context.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC EPQ_Create(void *copy, void **epq) +{ + EncryptionParameterQualifiers *copyptr = FromVoid<EncryptionParameterQualifiers>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(epq, E_POINTER); + + EncryptionParameterQualifiers *result = new EncryptionParameterQualifiers(*copyptr); + *epq = result; + return S_OK; +} + +SEAL_C_FUNC EPQ_Destroy(void *thisptr) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + + delete epq; + return S_OK; +} + +SEAL_C_FUNC EPQ_ParametersSet(void *thisptr, bool *parameters_set) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(parameters_set, E_POINTER); + + *parameters_set = epq->parameters_set(); + return S_OK; +} + +SEAL_C_FUNC EPQ_UsingFFT(void *thisptr, bool *using_fft) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(using_fft, E_POINTER); + + *using_fft = epq->using_fft; + return S_OK; +} + +SEAL_C_FUNC EPQ_UsingNTT(void *thisptr, bool *using_ntt) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(using_ntt, E_POINTER); + + *using_ntt = epq->using_ntt; + return S_OK; +} + +SEAL_C_FUNC EPQ_UsingBatching(void *thisptr, bool *using_batching) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(using_batching, E_POINTER); + + *using_batching = epq->using_batching; + return S_OK; +} + +SEAL_C_FUNC EPQ_UsingFastPlainLift(void *thisptr, bool *using_fast_plain_lift) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(using_fast_plain_lift, E_POINTER); + + *using_fast_plain_lift = epq->using_fast_plain_lift; + return S_OK; +} + +SEAL_C_FUNC EPQ_UsingDescendingModulusChain(void *thisptr, bool *using_descending_modulus_chain) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(using_descending_modulus_chain, E_POINTER); + + *using_descending_modulus_chain = epq->using_descending_modulus_chain; + return S_OK; +} + +SEAL_C_FUNC EPQ_SecLevel(void *thisptr, int *sec_level) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(sec_level, E_POINTER); + + *sec_level = static_cast<int>(epq->sec_level); + return S_OK; +} + +SEAL_C_FUNC EPQ_ParameterErrorName(void *thisptr, char *outstr, uint64_t *length) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(length, E_POINTER); + + return ToStringHelper2(epq->parameter_error_name(), outstr, length); +} + +SEAL_C_FUNC EPQ_ParameterErrorMessage(void *thisptr, char *outstr, uint64_t *length) +{ + EncryptionParameterQualifiers *epq = FromVoid<EncryptionParameterQualifiers>(thisptr); + IfNullRet(epq, E_POINTER); + IfNullRet(length, E_POINTER); + + return ToStringHelper2(epq->parameter_error_message(), outstr, length); +} diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.h b/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.h new file mode 100644 index 0000000000000000000000000000000000000000..4aa6a25ef6784b9c69b5e40e7a541fd3e2b41802 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptionparameterqualifiers.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC EPQ_Create(void *copy, void **epq); + +SEAL_C_FUNC EPQ_Destroy(void *thisptr); + +SEAL_C_FUNC EPQ_ParametersSet(void *thisptr, bool *parameters_set); + +SEAL_C_FUNC EPQ_UsingFFT(void *thisptr, bool *using_fft); + +SEAL_C_FUNC EPQ_UsingNTT(void *thisptr, bool *using_ntt); + +SEAL_C_FUNC EPQ_UsingBatching(void *thisptr, bool *using_batching); + +SEAL_C_FUNC EPQ_UsingFastPlainLift(void *thisptr, bool *using_fast_plain_lift); + +SEAL_C_FUNC EPQ_UsingDescendingModulusChain(void *thisptr, bool *using_descending_modulus_chain); + +SEAL_C_FUNC EPQ_SecLevel(void *thisptr, int *sec_level); + +SEAL_C_FUNC EPQ_ParameterErrorName(void *thisptr, char *outstr, uint64_t *length); + +SEAL_C_FUNC EPQ_ParameterErrorMessage(void *thisptr, char *outstr, uint64_t *length); \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.cpp b/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c957e354e05ccd02ddebb0cb76e5847b2197bcf2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.cpp @@ -0,0 +1,298 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/encryptionparameters.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/encryptionparams.h" +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/hash.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +namespace seal +{ + /** + Enables access to private members of seal::EncryptionParameters. + */ + struct EncryptionParameters::EncryptionParametersPrivateHelper + { + static auto parms_id(const EncryptionParameters &parms) + { + return parms.parms_id(); + } + }; +} // namespace seal + +SEAL_C_FUNC EncParams_Create1(uint8_t scheme, void **enc_params) +{ + IfNullRet(enc_params, E_POINTER); + + try + { + EncryptionParameters *params = new EncryptionParameters(scheme); + *enc_params = params; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC EncParams_Create2(void *copy, void **enc_params) +{ + EncryptionParameters *copypt = FromVoid<EncryptionParameters>(copy); + IfNullRet(copypt, E_POINTER); + IfNullRet(enc_params, E_POINTER); + + EncryptionParameters *params = new EncryptionParameters(*copypt); + *enc_params = params; + return S_OK; +} + +SEAL_C_FUNC EncParams_Destroy(void *thisptr) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + + delete params; + return S_OK; +} + +SEAL_C_FUNC EncParams_Set(void *thisptr, void *assign) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + EncryptionParameters *assignpt = FromVoid<EncryptionParameters>(assign); + IfNullRet(assignpt, E_POINTER); + + *params = *assignpt; + return S_OK; +} + +SEAL_C_FUNC EncParams_GetPolyModulusDegree(void *thisptr, uint64_t *degree) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(degree, E_POINTER); + + *degree = params->poly_modulus_degree(); + return S_OK; +} + +SEAL_C_FUNC EncParams_SetPolyModulusDegree(void *thisptr, uint64_t degree) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + + try + { + params->set_poly_modulus_degree(degree); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC EncParams_GetCoeffModulus(void *thisptr, uint64_t *length, void **coeffs) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(length, E_POINTER); + + BuildModulusPointers(params->coeff_modulus(), length, coeffs); + return S_OK; +} + +SEAL_C_FUNC EncParams_SetCoeffModulus(void *thisptr, uint64_t length, void **coeffs) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(coeffs, E_POINTER); + + Modulus **coeff_array = reinterpret_cast<Modulus **>(coeffs); + vector<Modulus> coefficients(length); + + for (uint64_t i = 0; i < length; i++) + { + coefficients[i] = *coeff_array[i]; + } + + try + { + params->set_coeff_modulus(coefficients); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC EncParams_GetScheme(void *thisptr, uint8_t *scheme) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(scheme, E_POINTER); + + *scheme = static_cast<uint8_t>(params->scheme()); + return S_OK; +} + +SEAL_C_FUNC EncParams_GetParmsId(void *thisptr, uint64_t *parms_id) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + // We will assume the array is always size hash_block_uint64_count + auto parmsid = EncryptionParameters::EncryptionParametersPrivateHelper::parms_id(*params); + for (size_t i = 0; i < util::HashFunction::hash_block_uint64_count; i++) + { + parms_id[i] = parmsid[i]; + } + + return S_OK; +} + +SEAL_C_FUNC EncParams_GetPlainModulus(void *thisptr, void **plain_modulus) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(plain_modulus, E_POINTER); + + const auto plainmodulus = &params->plain_modulus(); + *plain_modulus = const_cast<Modulus *>(plainmodulus); + return S_OK; +} + +SEAL_C_FUNC EncParams_SetPlainModulus1(void *thisptr, void *plain_modulus) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + Modulus *modulus = FromVoid<Modulus>(plain_modulus); + IfNullRet(modulus, E_POINTER); + + try + { + params->set_plain_modulus(*modulus); + return S_OK; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC EncParams_SetPlainModulus2(void *thisptr, uint64_t plain_modulus) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + + try + { + params->set_plain_modulus(plain_modulus); + return S_OK; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC EncParams_Equals(void *thisptr, void *otherptr, bool *result) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + EncryptionParameters *other = FromVoid<EncryptionParameters>(otherptr); + IfNullRet(other, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*params == *other); + return S_OK; +} + +SEAL_C_FUNC EncParams_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(params->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC EncParams_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(params->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC EncParams_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + EncryptionParameters *params = FromVoid<EncryptionParameters>(thisptr); + IfNullRet(params, E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = + util::safe_cast<int64_t>(params->load(reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.h b/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.h new file mode 100644 index 0000000000000000000000000000000000000000..745b9a3e07c21fe468308dfa4adf88efb72f44d3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptionparameters.h @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC EncParams_Create1(uint8_t scheme, void **enc_params); + +SEAL_C_FUNC EncParams_Create2(void *copy, void **enc_params); + +SEAL_C_FUNC EncParams_Destroy(void *thisptr); + +SEAL_C_FUNC EncParams_Set(void *thisptr, void *assign); + +SEAL_C_FUNC EncParams_GetPolyModulusDegree(void *thisptr, uint64_t *degree); + +SEAL_C_FUNC EncParams_SetPolyModulusDegree(void *thisptr, uint64_t degree); + +SEAL_C_FUNC EncParams_GetCoeffModulus(void *thisptr, uint64_t *length, void **coeffs); + +SEAL_C_FUNC EncParams_SetCoeffModulus(void *thisptr, uint64_t length, void **coeffs); + +SEAL_C_FUNC EncParams_GetScheme(void *thisptr, uint8_t *scheme); + +SEAL_C_FUNC EncParams_GetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC EncParams_GetPlainModulus(void *thisptr, void **plain_modulus); + +SEAL_C_FUNC EncParams_SetPlainModulus1(void *thisptr, void *modulus); + +SEAL_C_FUNC EncParams_SetPlainModulus2(void *thisptr, uint64_t plain_modulus); + +SEAL_C_FUNC EncParams_Equals(void *thisptr, void *otherptr, bool *result); + +SEAL_C_FUNC EncParams_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC EncParams_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC EncParams_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptor.cpp b/bigpiseal3.5.1/native/src/seal/c/encryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e51b632e5a4cfbe1e02aa4203c6fcfa0810ed4e7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptor.cpp @@ -0,0 +1,268 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/encryptor.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/encryptor.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +struct seal::Encryptor::EncryptorPrivateHelper +{ + static void encrypt_symmetric_internal( + Encryptor *encryptor, const Plaintext &plain, bool save_seed, Ciphertext &destination, MemoryPoolHandle pool) + { + encryptor->encrypt_internal(plain, false, save_seed, destination, pool); + } + + static void encrypt_zero_symmetric_internal( + Encryptor *encryptor, parms_id_type parms_id, bool save_seed, Ciphertext &destination, MemoryPoolHandle pool) + { + encryptor->encrypt_zero_internal(parms_id, false, save_seed, destination, pool); + } + + static void encrypt_zero_symmetric_internal( + Encryptor *encryptor, bool save_seed, Ciphertext &destination, MemoryPoolHandle pool) + { + encryptor->encrypt_zero_internal(encryptor->context_->first_parms_id(), false, save_seed, destination, pool); + } +}; + +SEAL_C_FUNC Encryptor_Create(void *context, void *public_key, void *secret_key, void **encryptor) +{ + PublicKey *pkey = FromVoid<PublicKey>(public_key); + SecretKey *skey = FromVoid<SecretKey>(secret_key); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(encryptor, E_POINTER); + if (nullptr == pkey && nullptr == skey) + { + return E_POINTER; + } + + try + { + Encryptor *enc; + if (nullptr != pkey) + { + enc = new Encryptor(sharedctx, *pkey); + if (nullptr != skey) + { + enc->set_secret_key(*skey); + } + } + else + { + enc = new Encryptor(sharedctx, *skey); + } + *encryptor = enc; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Encryptor_SetPublicKey(void *thisptr, void *public_key) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + PublicKey *pkey = FromVoid<PublicKey>(public_key); + IfNullRet(pkey, E_POINTER); + + try + { + encryptor->set_public_key(*pkey); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Encryptor_SetSecretKey(void *thisptr, void *secret_key) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + SecretKey *skey = FromVoid<SecretKey>(secret_key); + IfNullRet(skey, E_POINTER); + + try + { + encryptor->set_secret_key(*skey); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Encryptor_Encrypt(void *thisptr, void *plaintext, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plaintext); + IfNullRet(plain, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + try + { + encryptor->encrypt(*plain, *cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_EncryptZero1(void *thisptr, uint64_t *parms_id, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + encryptor->encrypt_zero(parms, *cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_EncryptZero2(void *thisptr, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + try + { + encryptor->encrypt_zero(*cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_EncryptSymmetric( + void *thisptr, void *plaintext, bool save_seed, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plaintext); + IfNullRet(plain, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + try + { + Encryptor::EncryptorPrivateHelper::encrypt_symmetric_internal(encryptor, *plain, save_seed, *cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_EncryptZeroSymmetric1( + void *thisptr, uint64_t *parms_id, bool save_seed, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + Encryptor::EncryptorPrivateHelper::encrypt_zero_symmetric_internal(encryptor, parms, save_seed, *cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_EncryptZeroSymmetric2(void *thisptr, bool save_seed, void *destination, void *pool_handle) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + Ciphertext *cipher = FromVoid<Ciphertext>(destination); + IfNullRet(cipher, E_POINTER); + unique_ptr<MemoryPoolHandle> pool = MemHandleFromVoid(pool_handle); + + try + { + Encryptor::EncryptorPrivateHelper::encrypt_zero_symmetric_internal(encryptor, save_seed, *cipher, *pool); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Encryptor_Destroy(void *thisptr) +{ + Encryptor *encryptor = FromVoid<Encryptor>(thisptr); + IfNullRet(encryptor, E_POINTER); + + delete encryptor; + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/encryptor.h b/bigpiseal3.5.1/native/src/seal/c/encryptor.h new file mode 100644 index 0000000000000000000000000000000000000000..8ebf661be568b427904d1aa1b7765f00f1f357a3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/encryptor.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Encryptor_Create(void *context, void *public_key, void *secret_key, void **encryptor); + +SEAL_C_FUNC Encryptor_SetPublicKey(void *thisptr, void *public_key); + +SEAL_C_FUNC Encryptor_SetSecretKey(void *thisptr, void *secret_key); + +SEAL_C_FUNC Encryptor_Encrypt(void *thisptr, void *plaintext, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_EncryptZero1(void *thisptr, uint64_t *parms_id, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_EncryptZero2(void *thisptr, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_EncryptSymmetric( + void *thisptr, void *plaintext, bool save_seed, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_EncryptZeroSymmetric1( + void *thisptr, uint64_t *parms_id, bool save_seed, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_EncryptZeroSymmetric2(void *thisptr, bool save_seed, void *destination, void *pool_handle); + +SEAL_C_FUNC Encryptor_Destroy(void *thisptr); diff --git a/bigpiseal3.5.1/native/src/seal/c/evaluator.cpp b/bigpiseal3.5.1/native/src/seal/c/evaluator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f9172652fa65b5e9096d2cc4438e9ed82559e3a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/evaluator.cpp @@ -0,0 +1,761 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <algorithm> +#include <iterator> + +// SEALNet +#include "seal/c/evaluator.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/context.h" +#include "seal/evaluator.h" +#include "seal/util/common.h" + +using namespace std; +using namespace seal; +using namespace seal::c; +using namespace seal::util; + +struct seal::Evaluator::EvaluatorPrivateHelper +{ + static bool using_keyswitching(const Evaluator &ev) + { + return ev.context_->using_keyswitching(); + } +}; + +SEAL_C_FUNC Evaluator_Create(void *sealContext, void **evaluator) +{ + SEALContext *context = FromVoid<SEALContext>(sealContext); + IfNullRet(context, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(sealContext); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(evaluator, E_POINTER); + + try + { + Evaluator *eval = new Evaluator(sharedctx); + *evaluator = eval; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Evaluator_Destroy(void *thisptr) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + + delete eval; + return S_OK; +} + +SEAL_C_FUNC Evaluator_Negate(void *thisptr, void *encrypted, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->negate(*encrypted_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Add(void *thisptr, void *encrypted1, void *encrypted2, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted1_ptr = FromVoid<Ciphertext>(encrypted1); + IfNullRet(encrypted1_ptr, E_POINTER); + Ciphertext *encrypted2_ptr = FromVoid<Ciphertext>(encrypted2); + IfNullRet(encrypted2_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->add(*encrypted1_ptr, *encrypted2_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_AddMany(void *thisptr, uint64_t count, void **encrypteds, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + IfNullRet(encrypteds, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + Ciphertext **encrypteds_pp = reinterpret_cast<Ciphertext **>(encrypteds); + vector<Ciphertext> encrypteds_vec; + + encrypteds_vec.reserve(count); + for (uint64_t i = 0; i < count; i++) + { + encrypteds_vec.emplace_back(*encrypteds_pp[i]); + } + + try + { + eval->add_many(encrypteds_vec, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_AddPlain(void *thisptr, void *encrypted, void *plain, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->add_plain(*encrypted_ptr, *plain_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Sub(void *thisptr, void *encrypted1, void *encrypted2, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted1_ptr = FromVoid<Ciphertext>(encrypted1); + IfNullRet(encrypted1_ptr, E_POINTER); + Ciphertext *encrypted2_ptr = FromVoid<Ciphertext>(encrypted2); + IfNullRet(encrypted2_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->sub(*encrypted1_ptr, *encrypted2_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_SubPlain(void *thisptr, void *encrypted, void *plain, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->sub_plain(*encrypted_ptr, *plain_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Multiply(void *thisptr, void *encrypted1, void *encrypted2, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted1_ptr = FromVoid<Ciphertext>(encrypted1); + IfNullRet(encrypted1_ptr, E_POINTER); + Ciphertext *encrypted2_ptr = FromVoid<Ciphertext>(encrypted2); + IfNullRet(encrypted2_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->multiply(*encrypted1_ptr, *encrypted2_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_MultiplyMany( + void *thisptr, uint64_t count, void **encrypteds, void *relin_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + IfNullRet(encrypteds, E_POINTER); + RelinKeys *relin_keys_ptr = FromVoid<RelinKeys>(relin_keys); + IfNullRet(relin_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + Ciphertext **encrypteds_pp = reinterpret_cast<Ciphertext **>(encrypteds); + vector<Ciphertext> encrypteds_vec; + + encrypteds_vec.reserve(count); + for (uint64_t i = 0; i < count; i++) + { + encrypteds_vec.emplace_back(*encrypteds_pp[i]); + } + + try + { + eval->multiply_many(encrypteds_vec, *relin_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_MultiplyPlain(void *thisptr, void *encrypted, void *plain, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->multiply_plain(*encrypted_ptr, *plain_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Square(void *thisptr, void *encrypted, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->square(*encrypted_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Relinearize(void *thisptr, void *encrypted, void *relin_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + RelinKeys *relin_keys_ptr = FromVoid<RelinKeys>(relin_keys); + IfNullRet(relin_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->relinearize(*encrypted_ptr, *relin_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ModSwitchToNext1(void *thisptr, void *encrypted, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->mod_switch_to_next(*encrypted_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ModSwitchToNext2(void *thisptr, void *plain, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + Plaintext *destination_ptr = FromVoid<Plaintext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->mod_switch_to_next(*plain_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Evaluator_ModSwitchTo1(void *thisptr, void *encrypted, uint64_t *parms_id, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + eval->mod_switch_to(*encrypted_ptr, parms, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ModSwitchTo2(void *thisptr, void *plain, uint64_t *parms_id, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Plaintext *destination_ptr = FromVoid<Plaintext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + eval->mod_switch_to(*plain_ptr, parms, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Evaluator_RescaleToNext(void *thisptr, void *encrypted, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->rescale_to_next(*encrypted_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_RescaleTo(void *thisptr, void *encrypted, uint64_t *parms_id, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + eval->rescale_to(*encrypted_ptr, parms, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_Exponentiate( + void *thisptr, void *encrypted, uint64_t exponent, void *relin_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + RelinKeys *relin_keys_ptr = FromVoid<RelinKeys>(relin_keys); + IfNullRet(relin_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->exponentiate(*encrypted_ptr, exponent, *relin_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_TransformToNTT1(void *thisptr, void *plain, uint64_t *parms_id, void *destination_ntt, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Plaintext *plain_ptr = FromVoid<Plaintext>(plain); + IfNullRet(plain_ptr, E_POINTER); + IfNullRet(parms_id, E_POINTER); + Plaintext *destination_ptr = FromVoid<Plaintext>(destination_ntt); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + parms_id_type parms; + CopyParmsId(parms_id, parms); + + try + { + eval->transform_to_ntt(*plain_ptr, parms, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Evaluator_TransformToNTT2(void *thisptr, void *encrypted, void *destination_ntt) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination_ntt); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->transform_to_ntt(*encrypted_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_TransformFromNTT(void *thisptr, void *encrypted_ntt, void *destination) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted_ntt); + IfNullRet(encrypted_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + + try + { + eval->transform_from_ntt(*encrypted_ptr, *destination_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ApplyGalois( + void *thisptr, void *encrypted, uint32_t galois_elt, void *galois_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + GaloisKeys *galois_keys_ptr = FromVoid<GaloisKeys>(galois_keys); + IfNullRet(galois_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->apply_galois(*encrypted_ptr, galois_elt, *galois_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_RotateRows( + void *thisptr, void *encrypted, int steps, void *galoisKeys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + GaloisKeys *galois_keys_ptr = FromVoid<GaloisKeys>(galoisKeys); + IfNullRet(galois_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->rotate_rows(*encrypted_ptr, steps, *galois_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_RotateColumns(void *thisptr, void *encrypted, void *galois_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + GaloisKeys *galois_keys_ptr = FromVoid<GaloisKeys>(galois_keys); + IfNullRet(galois_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->rotate_columns(*encrypted_ptr, *galois_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_RotateVector( + void *thisptr, void *encrypted, int steps, void *galois_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + GaloisKeys *galois_keys_ptr = FromVoid<GaloisKeys>(galois_keys); + IfNullRet(galois_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->rotate_vector(*encrypted_ptr, steps, *galois_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ComplexConjugate(void *thisptr, void *encrypted, void *galois_keys, void *destination, void *pool) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + Ciphertext *encrypted_ptr = FromVoid<Ciphertext>(encrypted); + IfNullRet(encrypted_ptr, E_POINTER); + GaloisKeys *galois_keys_ptr = FromVoid<GaloisKeys>(galois_keys); + IfNullRet(galois_keys_ptr, E_POINTER); + Ciphertext *destination_ptr = FromVoid<Ciphertext>(destination); + IfNullRet(destination_ptr, E_POINTER); + unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool); + + try + { + eval->complex_conjugate(*encrypted_ptr, *galois_keys_ptr, *destination_ptr, *pool_ptr); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Evaluator_ContextUsingKeyswitching(void *thisptr, bool *using_keyswitching) +{ + Evaluator *eval = FromVoid<Evaluator>(thisptr); + IfNullRet(eval, E_POINTER); + IfNullRet(using_keyswitching, E_POINTER); + + *using_keyswitching = Evaluator::EvaluatorPrivateHelper::using_keyswitching(*eval); + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/evaluator.h b/bigpiseal3.5.1/native/src/seal/c/evaluator.h new file mode 100644 index 0000000000000000000000000000000000000000..37208b1ccc464f02cd4a5b568346be5122d9d463 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/evaluator.h @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Evaluator_Create(void *sealContext, void **evaluator); + +SEAL_C_FUNC Evaluator_Destroy(void *thisptr); + +SEAL_C_FUNC Evaluator_Negate(void *thisptr, void *encrypted, void *destination); + +SEAL_C_FUNC Evaluator_Add(void *thisptr, void *encrypted1, void *encrypted2, void *destination); + +SEAL_C_FUNC Evaluator_AddMany(void *thisptr, uint64_t count, void **encrypteds, void *destination); + +SEAL_C_FUNC Evaluator_AddPlain(void *thisptr, void *encrypted, void *plain, void *destination); + +SEAL_C_FUNC Evaluator_Sub(void *thisptr, void *encrypted1, void *encrypted2, void *destination); + +SEAL_C_FUNC Evaluator_SubPlain(void *thisptr, void *encrypted, void *plain, void *destination); + +SEAL_C_FUNC Evaluator_Multiply(void *thisptr, void *encrypted1, void *encrypted2, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_MultiplyMany( + void *thisptr, uint64_t count, void **encrypteds, void *relin_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_MultiplyPlain(void *thisptr, void *encrypted, void *plain, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_Square(void *thisptr, void *encrypted, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_Relinearize(void *thisptr, void *encrypted, void *relinKeys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_ModSwitchToNext1(void *thisptr, void *encrypted, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_ModSwitchToNext2(void *thisptr, void *plain, void *destination); + +SEAL_C_FUNC Evaluator_ModSwitchTo1(void *thisptr, void *encrypted, uint64_t *parms_id, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_ModSwitchTo2(void *thisptr, void *plain, uint64_t *parms_id, void *destination); + +SEAL_C_FUNC Evaluator_RescaleToNext(void *thisptr, void *encrypted, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_RescaleTo(void *thisptr, void *encrypted, uint64_t *parms_id, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_Exponentiate( + void *thisptr, void *encrypted, uint64_t exponent, void *relin_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_TransformToNTT1( + void *thisptr, void *plain, uint64_t *parms_id, void *destination_ntt, void *pool); + +SEAL_C_FUNC Evaluator_TransformToNTT2(void *thisptr, void *encrypted, void *destination_ntt); + +SEAL_C_FUNC Evaluator_TransformFromNTT(void *thisptr, void *encrypted_ntt, void *destination); + +SEAL_C_FUNC Evaluator_ApplyGalois( + void *thisptr, void *encrypted, uint32_t galois_elt, void *galois_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_RotateRows( + void *thisptr, void *encrypted, int steps, void *galoisKeys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_RotateColumns(void *thisptr, void *encrypted, void *galois_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_RotateVector( + void *thisptr, void *encrypted, int steps, void *galois_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_ComplexConjugate( + void *thisptr, void *encrypted, void *galois_keys, void *destination, void *pool); + +SEAL_C_FUNC Evaluator_ContextUsingKeyswitching(void *thisptr, bool *using_keyswitching); diff --git a/bigpiseal3.5.1/native/src/seal/c/galoiskeys.cpp b/bigpiseal3.5.1/native/src/seal/c/galoiskeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b848b6aafd0d6223d72b2f2874b09d7767512feb --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/galoiskeys.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/galoiskeys.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/galoiskeys.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC GaloisKeys_GetIndex(uint32_t galois_elt, uint64_t *index) +{ + IfNullRet(index, E_POINTER); + + try + { + *index = GaloisKeys::get_index(galois_elt); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/galoiskeys.h b/bigpiseal3.5.1/native/src/seal/c/galoiskeys.h new file mode 100644 index 0000000000000000000000000000000000000000..a458a0db87e64cd89fa86988e95e79344f797e2a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/galoiskeys.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC GaloisKeys_GetIndex(uint32_t galois_elt, uint64_t *index); diff --git a/bigpiseal3.5.1/native/src/seal/c/intencoder.cpp b/bigpiseal3.5.1/native/src/seal/c/intencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a58cf05e466ed35fd1211f9726fe0f1edb48592 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/intencoder.cpp @@ -0,0 +1,205 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/intencoder.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/intencoder.h" + +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC IntegerEncoder_Create(void *context, void **encoder) +{ + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(encoder, E_POINTER); + + try + { + IntegerEncoder *intEncoder = new IntegerEncoder(sharedctx); + *encoder = intEncoder; + return S_OK; + } + catch (const std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_Destroy(void *thisptr) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + + delete intenc; + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_Encode1(void *thisptr, int32_t value, void *plain) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *dest = FromVoid<Plaintext>(plain); + IfNullRet(dest, E_POINTER); + + intenc->encode(value, *dest); + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_Encode2(void *thisptr, uint32_t value, void *plain) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *dest = FromVoid<Plaintext>(plain); + IfNullRet(dest, E_POINTER); + + intenc->encode(value, *dest); + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_Encode3(void *thisptr, uint64_t value, void *plain) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *dest = FromVoid<Plaintext>(plain); + IfNullRet(dest, E_POINTER); + + intenc->encode(value, *dest); + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_Encode4(void *thisptr, int64_t value, void *plain) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *dest = FromVoid<Plaintext>(plain); + IfNullRet(dest, E_POINTER); + + intenc->encode(value, *dest); + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_Encode5(void *thisptr, void *biguint, void *plain) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + BigUInt *bui = FromVoid<BigUInt>(biguint); + IfNullRet(bui, E_POINTER); + Plaintext *dest = FromVoid<Plaintext>(plain); + IfNullRet(dest, E_POINTER); + + intenc->encode(*bui, *dest); + return S_OK; +} + +SEAL_C_FUNC IntegerEncoder_DecodeUInt32(void *thisptr, void *plainptr, uint32_t *result) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plainptr); + IfNullRet(plain, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = intenc->decode_uint32(*plain); + return S_OK; + } + catch (const std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_DecodeUInt64(void *thisptr, void *plainptr, uint64_t *result) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plainptr); + IfNullRet(plain, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = intenc->decode_uint64(*plain); + return S_OK; + } + catch (const std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_DecodeInt32(void *thisptr, void *plainptr, int32_t *result) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plainptr); + IfNullRet(plain, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = intenc->decode_int32(*plain); + return S_OK; + } + catch (const std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_DecodeInt64(void *thisptr, void *plainptr, int64_t *result) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plainptr); + IfNullRet(plain, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = intenc->decode_int64(*plain); + return S_OK; + } + catch (std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_DecodeBigUInt(void *thisptr, void *plainptr, void **biguint) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + Plaintext *plain = FromVoid<Plaintext>(plainptr); + IfNullRet(plain, E_POINTER); + IfNullRet(biguint, E_POINTER); + + try + { + BigUInt result = intenc->decode_biguint(*plain); + BigUInt *resultPtr = new BigUInt(result); + *biguint = resultPtr; + return S_OK; + } + catch (const std::invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC IntegerEncoder_PlainModulus(void *thisptr, void **smallModPtr) +{ + IntegerEncoder *intenc = FromVoid<IntegerEncoder>(thisptr); + IfNullRet(intenc, E_POINTER); + IfNullRet(smallModPtr, E_POINTER); + + Modulus *sm = new Modulus(intenc->plain_modulus()); + *smallModPtr = sm; + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/intencoder.h b/bigpiseal3.5.1/native/src/seal/c/intencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..868f34764cf2ae2b9e01d44edb843163abcdd3ce --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/intencoder.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC IntegerEncoder_Create(void *context, void **encoder); + +SEAL_C_FUNC IntegerEncoder_Destroy(void *thisptr); + +SEAL_C_FUNC IntegerEncoder_Encode1(void *thisptr, int32_t value, void *plain); + +SEAL_C_FUNC IntegerEncoder_Encode2(void *thisptr, uint32_t value, void *plain); + +SEAL_C_FUNC IntegerEncoder_Encode3(void *thisptr, uint64_t value, void *plain); + +SEAL_C_FUNC IntegerEncoder_Encode4(void *thisptr, int64_t value, void *plain); + +SEAL_C_FUNC IntegerEncoder_Encode5(void *thisptr, void *biguint, void *plain); + +SEAL_C_FUNC IntegerEncoder_DecodeUInt32(void *thisptr, void *plain, uint32_t *result); + +SEAL_C_FUNC IntegerEncoder_DecodeUInt64(void *thisptr, void *plain, uint64_t *result); + +SEAL_C_FUNC IntegerEncoder_DecodeInt32(void *thisptr, void *plain, int32_t *result); + +SEAL_C_FUNC IntegerEncoder_DecodeInt64(void *thisptr, void *plain, int64_t *result); + +SEAL_C_FUNC IntegerEncoder_DecodeBigUInt(void *thisptr, void *plain, void **biguint); + +SEAL_C_FUNC IntegerEncoder_PlainModulus(void *thisptr, void **smallModulus); diff --git a/bigpiseal3.5.1/native/src/seal/c/keygenerator.cpp b/bigpiseal3.5.1/native/src/seal/c/keygenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ee02170706368ba46f00561f9f93da66ad765a2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/keygenerator.cpp @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <algorithm> +#include <iterator> + +// SEALNet +#include "seal/c/keygenerator.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/keygenerator.h" +#include "seal/util/common.h" + +using namespace std; +using namespace seal; +using namespace seal::c; +using namespace seal::util; + +struct seal::KeyGenerator::KeyGeneratorPrivateHelper +{ + static RelinKeys relin_keys(KeyGenerator *keygen, bool save_seed) + { + return keygen->relin_keys(size_t(1), save_seed); + } + + static GaloisKeys galois_keys(KeyGenerator *keygen, const vector<uint32_t> &galois_elts, bool save_seed) + { + return keygen->galois_keys(galois_elts, save_seed); + } + + static const GaloisTool *galois_tool(KeyGenerator *keygen) + { + return keygen->context_->key_context_data()->galois_tool(); + } + + static bool using_keyswitching(const KeyGenerator &keygen) + { + return keygen.context_->using_keyswitching(); + } +}; + +SEAL_C_FUNC KeyGenerator_Create1(void *sealContext, void **key_generator) +{ + const auto &sharedctx = SharedContextFromVoid(sealContext); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(key_generator, E_POINTER); + + try + { + KeyGenerator *keygen = new KeyGenerator(sharedctx); + *key_generator = keygen; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC KeyGenerator_Create2(void *sealContext, void *secret_key, void **key_generator) +{ + const auto &sharedctx = SharedContextFromVoid(sealContext); + IfNullRet(sharedctx.get(), E_POINTER); + SecretKey *secret_key_ptr = FromVoid<SecretKey>(secret_key); + IfNullRet(secret_key_ptr, E_POINTER); + IfNullRet(key_generator, E_POINTER); + + try + { + KeyGenerator *keygen = new KeyGenerator(sharedctx, *secret_key_ptr); + *key_generator = keygen; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC KeyGenerator_Destroy(void *thisptr) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + + delete keygen; + return S_OK; +} + +SEAL_C_FUNC KeyGenerator_RelinKeys(void *thisptr, bool save_seed, void **relin_keys) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(relin_keys, E_POINTER); + + try + { + RelinKeys *relinKeys = new RelinKeys(KeyGenerator::KeyGeneratorPrivateHelper::relin_keys(keygen, save_seed)); + *relin_keys = relinKeys; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC KeyGenerator_GaloisKeysFromElts( + void *thisptr, uint64_t count, uint32_t *galois_elts, bool save_seed, void **galois_keys) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(galois_elts, E_POINTER); + IfNullRet(galois_keys, E_POINTER); + + vector<uint32_t> galois_elts_vec; + copy_n(galois_elts, count, back_inserter(galois_elts_vec)); + + try + { + GaloisKeys *keys = + new GaloisKeys(KeyGenerator::KeyGeneratorPrivateHelper::galois_keys(keygen, galois_elts_vec, save_seed)); + *galois_keys = keys; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC KeyGenerator_GaloisKeysFromSteps( + void *thisptr, uint64_t count, int *steps, bool save_seed, void **galois_keys) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(steps, E_POINTER); + IfNullRet(galois_keys, E_POINTER); + + vector<int> steps_vec; + copy_n(steps, count, back_inserter(steps_vec)); + vector<uint32_t> galois_elts_vec; + + try + { + galois_elts_vec = KeyGenerator::KeyGeneratorPrivateHelper::galois_tool(keygen)->get_elts_from_steps(steps_vec); + GaloisKeys *keys = + new GaloisKeys(KeyGenerator::KeyGeneratorPrivateHelper::galois_keys(keygen, galois_elts_vec, save_seed)); + *galois_keys = keys; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC KeyGenerator_GaloisKeysAll(void *thisptr, bool save_seed, void **galois_keys) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(galois_keys, E_POINTER); + + vector<uint32_t> galois_elts_vec = KeyGenerator::KeyGeneratorPrivateHelper::galois_tool(keygen)->get_elts_all(); + + try + { + GaloisKeys *keys = + new GaloisKeys(KeyGenerator::KeyGeneratorPrivateHelper::galois_keys(keygen, galois_elts_vec, save_seed)); + *galois_keys = keys; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC KeyGenerator_PublicKey(void *thisptr, void **public_key) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(public_key, E_POINTER); + + PublicKey *key = new PublicKey(keygen->public_key()); + *public_key = key; + return S_OK; +} + +SEAL_C_FUNC KeyGenerator_SecretKey(void *thisptr, void **secret_key) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(secret_key, E_POINTER); + + SecretKey *key = new SecretKey(keygen->secret_key()); + *secret_key = key; + return S_OK; +} + +SEAL_C_FUNC KeyGenerator_ContextUsingKeyswitching(void *thisptr, bool *using_keyswitching) +{ + KeyGenerator *keygen = FromVoid<KeyGenerator>(thisptr); + IfNullRet(keygen, E_POINTER); + IfNullRet(using_keyswitching, E_POINTER); + + *using_keyswitching = KeyGenerator::KeyGeneratorPrivateHelper::using_keyswitching(*keygen); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/keygenerator.h b/bigpiseal3.5.1/native/src/seal/c/keygenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..5cfe3c9dd54bc44cd53d1ae0166156403765e62f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/keygenerator.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC KeyGenerator_Create1(void *sealContext, void **key_generator); + +SEAL_C_FUNC KeyGenerator_Create2(void *sealContext, void *secret_key, void **key_generator); + +SEAL_C_FUNC KeyGenerator_Destroy(void *thisptr); + +SEAL_C_FUNC KeyGenerator_RelinKeys(void *thisptr, bool save_seed, void **relin_keys); + +SEAL_C_FUNC KeyGenerator_GaloisKeysFromElts( + void *thisptr, uint64_t count, uint32_t *galois_elts, bool save_seed, void **galois_keys); + +SEAL_C_FUNC KeyGenerator_GaloisKeysFromSteps( + void *thisptr, uint64_t count, int *steps, bool save_seed, void **galois_keys); + +SEAL_C_FUNC KeyGenerator_GaloisKeysAll(void *thisptr, bool save_seed, void **galois_keys); + +SEAL_C_FUNC KeyGenerator_PublicKey(void *thisptr, void **public_key); + +SEAL_C_FUNC KeyGenerator_SecretKey(void *thisptr, void **secret_key); + +SEAL_C_FUNC KeyGenerator_ContextUsingKeyswitching(void *thisptr, bool *using_keyswitching); diff --git a/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.cpp b/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..314a295d1edef919f3c9211c9f4600dfd4c888f9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.cpp @@ -0,0 +1,292 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/kswitchkeys.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/kswitchkeys.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +namespace +{ + HRESULT GetKeyFromVector(const vector<PublicKey> &key, uint64_t *count, void **key_list) + { + *count = key.size(); + + if (nullptr == key_list) + { + // We only wanted the count + return S_OK; + } + + auto pkeys = reinterpret_cast<PublicKey **>(key_list); + for (size_t i = 0; i < key.size(); i++) + { + pkeys[i] = new PublicKey(key[i]); + } + + return S_OK; + } +} // namespace + +namespace seal +{ + struct PublicKey::PublicKeyPrivateHelper + { + inline static PublicKey Create(MemoryPoolHandle pool) + { + return PublicKey(pool); + } + }; +} // namespace seal + +SEAL_C_FUNC KSwitchKeys_Create1(void **kswitch_keys) +{ + IfNullRet(kswitch_keys, E_POINTER); + KSwitchKeys *keys = new KSwitchKeys(); + *kswitch_keys = keys; + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_Create2(void *copy, void **kswitch_keys) +{ + KSwitchKeys *copyptr = FromVoid<KSwitchKeys>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(kswitch_keys, E_POINTER); + + KSwitchKeys *keys = new KSwitchKeys(*copyptr); + *kswitch_keys = keys; + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_Destroy(void *thisptr) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + + delete keys; + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_Set(void *thisptr, void *assign) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + KSwitchKeys *assignptr = FromVoid<KSwitchKeys>(assign); + IfNullRet(assignptr, E_POINTER); + + *keys = *assignptr; + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_Size(void *thisptr, uint64_t *size) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(size, E_POINTER); + + *size = keys->size(); + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_RawSize(void *thisptr, uint64_t *size) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(size, E_POINTER); + + *size = keys->data().size(); + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_GetKeyList(void *thisptr, uint64_t index, uint64_t *count, void **key_list) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(count, E_POINTER); + + auto key = keys->data()[index]; + return GetKeyFromVector(key, count, key_list); +} + +SEAL_C_FUNC KSwitchKeys_ClearDataAndReserve(void *thisptr, uint64_t size) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + + keys->data().clear(); + keys->data().reserve(size); + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_AddKeyList(void *thisptr, uint64_t count, void **key_list) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(key_list, E_POINTER); + + PublicKey **key = reinterpret_cast<PublicKey **>(key_list); + + // Don't resize, only reserve + keys->data().emplace_back(); + keys->data().back().reserve(count); + + for (uint64_t i = 0; i < count; i++) + { + PublicKey *pkey = key[i]; + PublicKey new_pkey(PublicKey::PublicKeyPrivateHelper::Create(keys->pool())); + new_pkey = *pkey; + + keys->data().back().emplace_back(move(new_pkey)); + } + + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_GetParmsId(void *thisptr, uint64_t *parms_id) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + for (size_t i = 0; i < keys->parms_id().size(); i++) + { + parms_id[i] = keys->parms_id()[i]; + } + + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_SetParmsId(void *thisptr, uint64_t *parms_id) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(parms_id, keys->parms_id()); + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_Pool(void *thisptr, void **pool) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(pool, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(keys->pool()); + *pool = handleptr; + return S_OK; +} + +SEAL_C_FUNC KSwitchKeys_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(keys->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC KSwitchKeys_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(keys->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC KSwitchKeys_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + keys->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC KSwitchKeys_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(thisptr); + IfNullRet(keys, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + keys->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.h b/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.h new file mode 100644 index 0000000000000000000000000000000000000000..3553afa2f8b8329a84835ca0f3397f359d06e847 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/kswitchkeys.h @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC KSwitchKeys_Create1(void **kswitch_keys); + +SEAL_C_FUNC KSwitchKeys_Create2(void *copy, void **kswitch_keys); + +SEAL_C_FUNC KSwitchKeys_Destroy(void *thisptr); + +SEAL_C_FUNC KSwitchKeys_Set(void *thisptr, void *assign); + +SEAL_C_FUNC KSwitchKeys_Size(void *thisptr, uint64_t *size); + +SEAL_C_FUNC KSwitchKeys_RawSize(void *thisptr, uint64_t *key_count); + +SEAL_C_FUNC KSwitchKeys_GetKeyList(void *thisptr, uint64_t index, uint64_t *count, void **key_list); + +SEAL_C_FUNC KSwitchKeys_ClearDataAndReserve(void *thisptr, uint64_t size); + +SEAL_C_FUNC KSwitchKeys_AddKeyList(void *thisptr, uint64_t count, void **key_list); + +SEAL_C_FUNC KSwitchKeys_GetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC KSwitchKeys_SetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC KSwitchKeys_Pool(void *thisptr, void **pool); + +SEAL_C_FUNC KSwitchKeys_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC KSwitchKeys_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC KSwitchKeys_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC KSwitchKeys_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/memorymanager.cpp b/bigpiseal3.5.1/native/src/seal/c/memorymanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec64228c12934f8f4a94b0b54fabe9712e10f9f8 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/memorymanager.cpp @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/memorymanager.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/memorymanager.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +namespace +{ + template <class T> + HRESULT GenericCreateProfileCopy(T *original, MMProf **copyptr) + { + T *copy = new T(*original); + *copyptr = copy; + return S_OK; + } + + HRESULT CreateProfileCopy(MMProf *profile, MMProf **copyptr) + { + IfNullRet(profile, E_POINTER); + IfNullRet(copyptr, E_POINTER); + + MMProfGlobal *global = dynamic_cast<MMProfGlobal *>(profile); + if (nullptr != global) + { + return GenericCreateProfileCopy(global, copyptr); + } + + MMProfFixed *fixed = dynamic_cast<MMProfFixed *>(profile); + if (nullptr != fixed) + { + return GenericCreateProfileCopy(fixed, copyptr); + } + + MMProfNew *newprof = dynamic_cast<MMProfNew *>(profile); + if (nullptr != newprof) + { + return GenericCreateProfileCopy(newprof, copyptr); + } + + MMProfThreadLocal *threadlocal = dynamic_cast<MMProfThreadLocal *>(profile); + if (nullptr != threadlocal) + { + return GenericCreateProfileCopy(threadlocal, copyptr); + } + + // No matching profile. + return E_UNEXPECTED; + } +} // namespace + +SEAL_C_FUNC MemoryManager_GetPool1(int prof_opt, bool clear_on_destruction, void **pool_handle) +{ + IfNullRet(pool_handle, E_POINTER); + + mm_prof_opt profile_opt = static_cast<mm_prof_opt>(prof_opt); + MemoryPoolHandle handle; + + // clear_on_destruction is only used when using FORCE_NEW + if (profile_opt == mm_prof_opt::FORCE_NEW) + { + handle = MemoryManager::GetPool(profile_opt, clear_on_destruction); + } + else + { + handle = MemoryManager::GetPool(profile_opt); + } + + MemoryPoolHandle *handle_ptr = new MemoryPoolHandle(move(handle)); + *pool_handle = handle_ptr; + return S_OK; +} + +SEAL_C_FUNC MemoryManager_GetPool2(void **pool_handle) +{ + IfNullRet(pool_handle, E_POINTER); + + MemoryPoolHandle handle = MemoryManager::GetPool(); + MemoryPoolHandle *handle_ptr = new MemoryPoolHandle(move(handle)); + *pool_handle = handle_ptr; + return S_OK; +} + +SEAL_C_FUNC MemoryManager_SwitchProfile(void *new_profile) +{ + MMProf *profile = FromVoid<MMProf>(new_profile); + IfNullRet(profile, E_POINTER); + + // SwitchProfile takes ownership of the profile pointer that is passed. + // The managed side will keep ownership of the new_profile parameter, so we + // need to make a copy that will be owned by the Memory Manager. + MMProf *new_mm_profile = nullptr; + IfFailRet(CreateProfileCopy(profile, &new_mm_profile)); + + MemoryManager::SwitchProfile(static_cast<MMProf *>(new_mm_profile)); + return S_OK; +} + +SEAL_C_FUNC MMProf_CreateGlobal(void **profile) +{ + IfNullRet(profile, E_POINTER); + + MMProfGlobal *global = new MMProfGlobal(); + *profile = global; + return S_OK; +} + +SEAL_C_FUNC MMProf_CreateFixed(void *pool, void **profile) +{ + MemoryPoolHandle *poolptr = FromVoid<MemoryPoolHandle>(pool); + IfNullRet(poolptr, E_POINTER); + IfNullRet(profile, E_POINTER); + + MemoryPoolHandle myhandle(*poolptr); + MMProfFixed *fixed = new MMProfFixed(myhandle); + *profile = fixed; + return S_OK; +} + +SEAL_C_FUNC MMProf_CreateNew(void **profile) +{ + IfNullRet(profile, E_POINTER); + + MMProfNew *newprof = new MMProfNew(); + *profile = newprof; + return S_OK; +} + +SEAL_C_FUNC MMProf_CreateThreadLocal(void **profile) +{ + IfNullRet(profile, E_POINTER); + + MMProfThreadLocal *threadlocal = new MMProfThreadLocal(); + *profile = threadlocal; + return S_OK; +} + +SEAL_C_FUNC MMProf_GetPool(void *thisptr, void **pool_handle) +{ + MMProf *profile = FromVoid<MMProf>(thisptr); + IfNullRet(profile, E_POINTER); + IfNullRet(pool_handle, E_POINTER); + + // The parameter to get_pool is always ignored, so just pass 0 + MemoryPoolHandle *handle_ptr = new MemoryPoolHandle(profile->get_pool(0)); + *pool_handle = handle_ptr; + return S_OK; +} + +SEAL_C_FUNC MMProf_Destroy(void *thisptr) +{ + MMProf *profile = FromVoid<MMProf>(thisptr); + IfNullRet(profile, E_POINTER); + + delete profile; + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/memorymanager.h b/bigpiseal3.5.1/native/src/seal/c/memorymanager.h new file mode 100644 index 0000000000000000000000000000000000000000..dc752da96f1956768a29bc405b16410752d41de3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/memorymanager.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC MemoryManager_GetPool1(int prof_opt, bool clear_on_destruction, void **pool_handle); + +SEAL_C_FUNC MemoryManager_GetPool2(void **pool_handle); + +SEAL_C_FUNC MemoryManager_SwitchProfile(void *new_profile); + +SEAL_C_FUNC MMProf_CreateGlobal(void **profile); + +SEAL_C_FUNC MMProf_CreateFixed(void *pool, void **profile); + +SEAL_C_FUNC MMProf_CreateNew(void **profile); + +SEAL_C_FUNC MMProf_CreateThreadLocal(void **profile); + +SEAL_C_FUNC MMProf_GetPool(void *thisptr, void **pool_handle); + +SEAL_C_FUNC MMProf_Destroy(void *thisptr); diff --git a/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.cpp b/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54a477d565dad316581dec1010f277d8757398ff --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.cpp @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/memorypoolhandle.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/memorymanager.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC MemoryPoolHandle_Create1(void **handle) +{ + IfNullRet(handle, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(); + *handle = handleptr; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_Create2(void *otherptr, void **handle) +{ + MemoryPoolHandle *other = FromVoid<MemoryPoolHandle>(otherptr); + IfNullRet(other, E_POINTER); + IfNullRet(handle, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(*other); + *handle = handleptr; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_Destroy(void *thisptr) +{ + MemoryPoolHandle *handle = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(handle, E_POINTER); + + delete handle; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_Set(void *thisptr, void *assignptr) +{ + MemoryPoolHandle *handle = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(handle, E_POINTER); + MemoryPoolHandle *assign = FromVoid<MemoryPoolHandle>(assignptr); + IfNullRet(assign, E_POINTER); + + *handle = *assign; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_Global(void **handle) +{ + IfNullRet(handle, E_POINTER); + + MemoryPoolHandle global = MemoryPoolHandle::Global(); + MemoryPoolHandle *handleptr = new MemoryPoolHandle(move(global)); + *handle = handleptr; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_ThreadLocal(void **handle) +{ + IfNullRet(handle, E_POINTER); + + MemoryPoolHandle threadlocal = MemoryPoolHandle::ThreadLocal(); + MemoryPoolHandle *handleptr = new MemoryPoolHandle(move(threadlocal)); + *handle = handleptr; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_New(bool clear_on_destruction, void **handle) +{ + IfNullRet(handle, E_POINTER); + + MemoryPoolHandle newhandle = MemoryPoolHandle::New(clear_on_destruction); + MemoryPoolHandle *handleptr = new MemoryPoolHandle(move(newhandle)); + *handle = handleptr; + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_PoolCount(void *thisptr, uint64_t *count) +{ + MemoryPoolHandle *pool = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(pool, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = pool->pool_count(); + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_AllocByteCount(void *thisptr, uint64_t *count) +{ + MemoryPoolHandle *pool = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(pool, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = pool->alloc_byte_count(); + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_UseCount(void *thisptr, long *count) +{ + MemoryPoolHandle *pool = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(pool, E_POINTER); + IfNullRet(count, E_POINTER); + + *count = pool->use_count(); + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_IsInitialized(void *thisptr, bool *result) +{ + MemoryPoolHandle *pool = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(pool, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (bool)(*pool); + return S_OK; +} + +SEAL_C_FUNC MemoryPoolHandle_Equals(void *thisptr, void *otherptr, bool *result) +{ + MemoryPoolHandle *pool = FromVoid<MemoryPoolHandle>(thisptr); + IfNullRet(pool, E_POINTER); + MemoryPoolHandle *other = FromVoid<MemoryPoolHandle>(otherptr); + IfNullRet(other, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*pool == *other); + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.h b/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.h new file mode 100644 index 0000000000000000000000000000000000000000..82b7eb9af3afb8b3a8cfa5d3e230a5f790e00ab2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/memorypoolhandle.h @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC MemoryPoolHandle_Create1(void **handle); + +SEAL_C_FUNC MemoryPoolHandle_Create2(void *otherptr, void **handle); + +SEAL_C_FUNC MemoryPoolHandle_Destroy(void *thisptr); + +SEAL_C_FUNC MemoryPoolHandle_Set(void *thisptr, void *assignptr); + +SEAL_C_FUNC MemoryPoolHandle_Global(void **handle); + +SEAL_C_FUNC MemoryPoolHandle_ThreadLocal(void **handle); + +SEAL_C_FUNC MemoryPoolHandle_New(bool clear_on_destruction, void **handle); + +SEAL_C_FUNC MemoryPoolHandle_PoolCount(void *thisptr, uint64_t *count); + +SEAL_C_FUNC MemoryPoolHandle_AllocByteCount(void *thisptr, uint64_t *count); + +SEAL_C_FUNC MemoryPoolHandle_UseCount(void *thisptr, long *count); + +SEAL_C_FUNC MemoryPoolHandle_IsInitialized(void *thisptr, bool *result); + +SEAL_C_FUNC MemoryPoolHandle_Equals(void *thisptr, void *otherptr, bool *result); diff --git a/bigpiseal3.5.1/native/src/seal/c/modulus.cpp b/bigpiseal3.5.1/native/src/seal/c/modulus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea0636fff21d282b34182779dd89632b685f9c66 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/modulus.cpp @@ -0,0 +1,300 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <algorithm> +#include <iterator> + +// SEALNet +#include "seal/c/modulus.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/modulus.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC Modulus_Create1(uint64_t value, void **small_modulus) +{ + IfNullRet(small_modulus, E_POINTER); + + try + { + Modulus *sm = new Modulus(value); + *small_modulus = sm; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Modulus_Create2(void *copy, void **small_modulus) +{ + Modulus *copypt = FromVoid<Modulus>(copy); + IfNullRet(copypt, E_POINTER); + + Modulus *sm = new Modulus(*copypt); + *small_modulus = sm; + return S_OK; +} + +SEAL_C_FUNC Modulus_Destroy(void *thisptr) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + + delete sm; + return S_OK; +} + +SEAL_C_FUNC Modulus_IsZero(void *thisptr, bool *is_zero) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(is_zero, E_POINTER); + + *is_zero = sm->is_zero(); + return S_OK; +} + +SEAL_C_FUNC Modulus_IsPrime(void *thisptr, bool *is_prime) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(is_prime, E_POINTER); + + *is_prime = sm->is_prime(); + return S_OK; +} + +SEAL_C_FUNC Modulus_Value(void *thisptr, uint64_t *value) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(value, E_POINTER); + + *value = sm->value(); + return S_OK; +} + +SEAL_C_FUNC Modulus_BitCount(void *thisptr, int *bit_count) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(bit_count, E_POINTER); + + *bit_count = sm->bit_count(); + return S_OK; +} + +SEAL_C_FUNC Modulus_UInt64Count(void *thisptr, uint64_t *uint64_count) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(uint64_count, E_POINTER); + + *uint64_count = sm->uint64_count(); + return S_OK; +} + +SEAL_C_FUNC Modulus_Set1(void *thisptr, void *assign) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + Modulus *assignpt = FromVoid<Modulus>(assign); + IfNullRet(assignpt, E_POINTER); + + *sm = *assignpt; + return S_OK; +} + +SEAL_C_FUNC Modulus_Set2(void *thisptr, uint64_t value) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + + try + { + *sm = value; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + return S_OK; +} + +SEAL_C_FUNC Modulus_ConstRatio(void *thisptr, uint64_t length, uint64_t ratio[]) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + + if (length != 3) + { + return E_INVALIDARG; + } + + auto ratio_array = sm->const_ratio(); + copy(ratio_array.begin(), ratio_array.end(), ratio); + + return S_OK; +} + +SEAL_C_FUNC Modulus_Equals1(void *thisptr, void *other, bool *result) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + Modulus *otherpt = FromVoid<Modulus>(other); + IfNullRet(otherpt, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*sm == *otherpt); + return S_OK; +} + +SEAL_C_FUNC Modulus_Equals2(void *thisptr, uint64_t other, bool *result) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*sm == other); + return S_OK; +} + +SEAL_C_FUNC Modulus_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(sm->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Modulus_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(sm->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC Modulus_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + Modulus *sm = FromVoid<Modulus>(thisptr); + IfNullRet(sm, E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = + util::safe_cast<int64_t>(sm->load(reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC CoeffModulus_MaxBitCount(uint64_t poly_modulus_degree, int sec_level, int *bit_count) +{ + IfNullRet(bit_count, E_POINTER); + + sec_level_type security_level = static_cast<sec_level_type>(sec_level); + *bit_count = CoeffModulus::MaxBitCount(poly_modulus_degree, security_level); + return S_OK; +} + +SEAL_C_FUNC CoeffModulus_BFVDefault(uint64_t poly_modulus_degree, int sec_level, uint64_t *length, void **coeffs) +{ + IfNullRet(length, E_POINTER); + + sec_level_type security_level = static_cast<sec_level_type>(sec_level); + vector<Modulus> result; + + try + { + result = CoeffModulus::BFVDefault(poly_modulus_degree, security_level); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + + BuildModulusPointers(result, length, coeffs); + return S_OK; +} + +SEAL_C_FUNC CoeffModulus_Create(uint64_t poly_modulus_degree, uint64_t length, int *bit_sizes, void **coeffs) +{ + IfNullRet(bit_sizes, E_POINTER); + IfNullRet(coeffs, E_POINTER); + + vector<int> bit_sizes_vec; + copy_n(bit_sizes, length, back_inserter(bit_sizes_vec)); + vector<Modulus> result; + + try + { + result = CoeffModulus::Create(poly_modulus_degree, bit_sizes_vec); + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + + BuildModulusPointers(result, &length, coeffs); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/modulus.h b/bigpiseal3.5.1/native/src/seal/c/modulus.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7af45070947af078cf5bf1c56f259052fab6ea --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/modulus.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Modulus_Create1(uint64_t value, void **small_modulus); + +SEAL_C_FUNC Modulus_Create2(void *copy, void **small_modulus); + +SEAL_C_FUNC Modulus_Destroy(void *thisptr); + +SEAL_C_FUNC Modulus_IsZero(void *thisptr, bool *is_zero); + +SEAL_C_FUNC Modulus_IsPrime(void *thisptr, bool *is_prime); + +SEAL_C_FUNC Modulus_Value(void *thisptr, uint64_t *value); + +SEAL_C_FUNC Modulus_BitCount(void *thisptr, int *bit_count); + +SEAL_C_FUNC Modulus_UInt64Count(void *thisptr, uint64_t *uint64_count); + +SEAL_C_FUNC Modulus_Set1(void *thisptr, void *assign); + +SEAL_C_FUNC Modulus_Set2(void *thisptr, uint64_t value); + +SEAL_C_FUNC Modulus_ConstRatio(void *thisptr, uint64_t length, uint64_t ratio[]); + +SEAL_C_FUNC Modulus_Equals1(void *thisptr, void *other, bool *result); + +SEAL_C_FUNC Modulus_Equals2(void *thisptr, uint64_t other, bool *result); + +SEAL_C_FUNC Modulus_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC Modulus_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC Modulus_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC CoeffModulus_MaxBitCount(uint64_t poly_modulus_degree, int sec_level, int *bit_count); + +SEAL_C_FUNC CoeffModulus_BFVDefault(uint64_t poly_modulus_degree, int sec_level, uint64_t *length, void **coeffs); + +SEAL_C_FUNC CoeffModulus_Create(uint64_t poly_modulus_degree, uint64_t length, int *bit_sizes, void **coeffs); diff --git a/bigpiseal3.5.1/native/src/seal/c/plaintext.cpp b/bigpiseal3.5.1/native/src/seal/c/plaintext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52d279833c2c9e4c9fd280fdf763ff37e33da28c --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/plaintext.cpp @@ -0,0 +1,568 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <algorithm> +#include <string> + +// SEALNet +#include "seal/c/plaintext.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/plaintext.h" +#include "seal/util/common.h" + +using namespace std; +using namespace seal; +using namespace seal::c; +using namespace seal::util; + +namespace seal +{ + /** + Enables access to private members of seal::Plaintext. + */ + struct Plaintext::PlaintextPrivateHelper + { + static void set_scale(seal::Plaintext *plain, double new_scale) + { + plain->scale_ = new_scale; + } + + static void swap_data(seal::Plaintext *plain, seal::IntArray<uint64_t> &new_data) + { + swap(plain->data_, new_data); + } + }; +} // namespace seal + +SEAL_C_FUNC Plaintext_Create1(void *memoryPoolHandle, void **plaintext) +{ + IfNullRet(plaintext, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle); + Plaintext *plain = nullptr; + + try + { + plain = new Plaintext(*handle); + *plaintext = plain; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Create2(uint64_t coeffCount, void *memoryPoolHandle, void **plaintext) +{ + IfNullRet(plaintext, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle); + Plaintext *plain = nullptr; + + try + { + plain = new Plaintext(coeffCount, *handle); + *plaintext = plain; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Create3(uint64_t capacity, uint64_t coeffCount, void *memoryPoolHandle, void **plaintext) +{ + IfNullRet(plaintext, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle); + Plaintext *plain = nullptr; + + try + { + plain = new Plaintext(capacity, coeffCount, *handle); + *plaintext = plain; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Create4(char *hex_poly, void *memoryPoolHandle, void **plaintext) +{ + IfNullRet(plaintext, E_POINTER); + IfNullRet(hex_poly, E_POINTER); + unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle); + string hex_poly_str(hex_poly); + + try + { + Plaintext *plain = new Plaintext(hex_poly_str, *handle); + *plaintext = plain; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Create5(void *copy, void **plaintext) +{ + Plaintext *copyptr = FromVoid<Plaintext>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(plaintext, E_POINTER); + + Plaintext *plain = new Plaintext(*copyptr); + *plaintext = plain; + return S_OK; +} + +SEAL_C_FUNC Plaintext_Set1(void *thisptr, void *assign) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + Plaintext *assignptr = FromVoid<Plaintext>(assign); + IfNullRet(assignptr, E_POINTER); + + *plain = *assignptr; + return S_OK; +} + +SEAL_C_FUNC Plaintext_Set2(void *thisptr, char *hex_poly) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(hex_poly, E_POINTER); + + try + { + string hex_poly_str(hex_poly); + *plain = hex_poly_str; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Set3(void *thisptr, uint64_t const_coeff) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + *plain = const_coeff; + return S_OK; + } + catch (const logic_error &) + { + return E_INVALIDARG; + } +} + +SEAL_C_FUNC Plaintext_Destroy(void *thisptr) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + delete plain; + return S_OK; +} + +SEAL_C_FUNC Plaintext_CoeffCount(void *thisptr, uint64_t *coeff_count) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(coeff_count, E_POINTER); + + *coeff_count = plain->coeff_count(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_CoeffAt(void *thisptr, uint64_t index, uint64_t *coeff) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(coeff, E_POINTER); + + try + { + *coeff = (*plain)[index]; + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Plaintext_SetCoeffAt(void *thisptr, uint64_t index, uint64_t value) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + (*plain)[index] = value; + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Plaintext_ToString(void *thispt, char *outstr, uint64_t *length) +{ + Plaintext *plain = FromVoid<Plaintext>(thispt); + IfNullRet(plain, E_POINTER); + IfNullRet(length, E_POINTER); + + return ToStringHelper(plain->to_string(), outstr, length); +} + +SEAL_C_FUNC Plaintext_IsNTTForm(void *thisptr, bool *is_ntt_form) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(is_ntt_form, E_POINTER); + + *is_ntt_form = plain->is_ntt_form(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_IsZero(void *thisptr, bool *is_zero) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(is_zero, E_POINTER); + + *is_zero = plain->is_zero(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_GetParmsId(void *thisptr, uint64_t *parms_id) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + for (size_t i = 0; i < plain->parms_id().size(); i++) + { + parms_id[i] = plain->parms_id()[i]; + } + return S_OK; +} + +SEAL_C_FUNC Plaintext_SetParmsId(void *thisptr, uint64_t *parms_id) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(parms_id, plain->parms_id()); + return S_OK; +} + +SEAL_C_FUNC Plaintext_SetZero1(void *thisptr) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + plain->set_zero(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_SetZero2(void *thisptr, uint64_t start_coeff) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + plain->set_zero(safe_cast<size_t>(start_coeff)); + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Plaintext_SetZero3(void *thisptr, uint64_t start_coeff, uint64_t length) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + plain->set_zero(safe_cast<size_t>(start_coeff), safe_cast<size_t>(length)); + return S_OK; + } + catch (const out_of_range &) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + } +} + +SEAL_C_FUNC Plaintext_Reserve(void *thisptr, uint64_t capacity) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + plain->reserve(capacity); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Plaintext_Resize(void *thisptr, uint64_t coeff_count) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + try + { + plain->resize(coeff_count); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Plaintext_ShrinkToFit(void *thisptr) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + plain->shrink_to_fit(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_Release(void *thisptr) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + plain->release(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_Capacity(void *thisptr, uint64_t *capacity) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(capacity, E_POINTER); + + *capacity = plain->capacity(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_SignificantCoeffCount(void *thisptr, uint64_t *significant_coeff_count) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(significant_coeff_count, E_POINTER); + + *significant_coeff_count = plain->significant_coeff_count(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_NonZeroCoeffCount(void *thisptr, uint64_t *nonzero_coeff_count) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(nonzero_coeff_count, E_POINTER); + + *nonzero_coeff_count = plain->nonzero_coeff_count(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_Scale(void *thisptr, double *scale) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(scale, E_POINTER); + + *scale = plain->scale(); + return S_OK; +} + +SEAL_C_FUNC Plaintext_SetScale(void *thisptr, double scale) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + + Plaintext::PlaintextPrivateHelper::set_scale(plain, scale); + return S_OK; +} + +SEAL_C_FUNC Plaintext_Equals(void *thisptr, void *other, bool *result) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + Plaintext *otherptr = FromVoid<Plaintext>(other); + IfNullRet(otherptr, E_POINTER); + IfNullRet(result, E_POINTER); + + *result = (*plain == *otherptr); + return S_OK; +} + +SEAL_C_FUNC Plaintext_SwapData(void *thisptr, uint64_t count, uint64_t *new_data) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(new_data, E_POINTER); + + IntArray<uint64_t> new_array(plain->pool()); + new_array.resize(count); + copy_n(new_data, count, new_array.begin()); + + Plaintext::PlaintextPrivateHelper::swap_data(plain, new_array); + return S_OK; +} + +SEAL_C_FUNC Plaintext_Pool(void *thisptr, void **pool) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(pool, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(plain->pool()); + *pool = handleptr; + return S_OK; +} + +SEAL_C_FUNC Plaintext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(plain->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC Plaintext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(plain->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC Plaintext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + plain->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC Plaintext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + Plaintext *plain = FromVoid<Plaintext>(thisptr); + IfNullRet(plain, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + plain->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/plaintext.h b/bigpiseal3.5.1/native/src/seal/c/plaintext.h new file mode 100644 index 0000000000000000000000000000000000000000..a082b4e40ce244400c5d11b4c7517dfad390769d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/plaintext.h @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Plaintext_Create1(void *memoryPoolHandle, void **plaintext); + +SEAL_C_FUNC Plaintext_Create2(uint64_t coeffCount, void *memoryPoolHandle, void **plaintext); + +SEAL_C_FUNC Plaintext_Create3(uint64_t capacity, uint64_t coeffCount, void *memoryPoolHandle, void **plaintext); + +SEAL_C_FUNC Plaintext_Create4(char *hex_poly, void *memoryPoolHandle, void **plaintext); + +SEAL_C_FUNC Plaintext_Create5(void *copy, void **plaintext); + +SEAL_C_FUNC Plaintext_Set1(void *thisptr, void *assign); + +SEAL_C_FUNC Plaintext_Set2(void *thisptr, char *hex_poly); + +SEAL_C_FUNC Plaintext_Set3(void *thisptr, uint64_t const_coeff); + +SEAL_C_FUNC Plaintext_Destroy(void *thisptr); + +SEAL_C_FUNC Plaintext_CoeffCount(void *thisptr, uint64_t *coeff_count); + +SEAL_C_FUNC Plaintext_CoeffAt(void *thisptr, uint64_t index, uint64_t *coeff); + +SEAL_C_FUNC Plaintext_SetCoeffAt(void *thisptr, uint64_t index, uint64_t value); + +SEAL_C_FUNC Plaintext_ToString(void *thispt, char *outstr, uint64_t *length); + +SEAL_C_FUNC Plaintext_IsNTTForm(void *thisptr, bool *is_ntt_form); + +SEAL_C_FUNC Plaintext_IsZero(void *thisptr, bool *is_zero); + +SEAL_C_FUNC Plaintext_SetZero1(void *thisptr); + +SEAL_C_FUNC Plaintext_SetZero2(void *thisptr, uint64_t start_coeff); + +SEAL_C_FUNC Plaintext_SetZero3(void *thisptr, uint64_t start_coeff, uint64_t length); + +SEAL_C_FUNC Plaintext_GetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC Plaintext_SetParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC Plaintext_Reserve(void *thisptr, uint64_t capacity); + +SEAL_C_FUNC Plaintext_Resize(void *thisptr, uint64_t coeff_count); + +SEAL_C_FUNC Plaintext_ShrinkToFit(void *thisptr); + +SEAL_C_FUNC Plaintext_Release(void *thisptr); + +SEAL_C_FUNC Plaintext_Capacity(void *thisptr, uint64_t *capacity); + +SEAL_C_FUNC Plaintext_SignificantCoeffCount(void *thisptr, uint64_t *significant_coeff_count); + +SEAL_C_FUNC Plaintext_NonZeroCoeffCount(void *thisptr, uint64_t *nonzero_coeff_count); + +SEAL_C_FUNC Plaintext_Scale(void *thisptr, double *scale); + +SEAL_C_FUNC Plaintext_SetScale(void *thisptr, double scale); + +SEAL_C_FUNC Plaintext_Equals(void *thisptr, void *other, bool *result); + +SEAL_C_FUNC Plaintext_SwapData(void *thisptr, uint64_t count, uint64_t *new_data); + +SEAL_C_FUNC Plaintext_Pool(void *thisptr, void **pool); + +SEAL_C_FUNC Plaintext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC Plaintext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC Plaintext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC Plaintext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/publickey.cpp b/bigpiseal3.5.1/native/src/seal/c/publickey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87d28b4048310453f302823c36addeafd98578da --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/publickey.cpp @@ -0,0 +1,195 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/publickey.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/publickey.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC PublicKey_Create1(void **public_key) +{ + IfNullRet(public_key, E_POINTER); + + PublicKey *pkey = new PublicKey(); + *public_key = pkey; + return S_OK; +} + +SEAL_C_FUNC PublicKey_Create2(void *copy, void **public_key) +{ + PublicKey *copyptr = FromVoid<PublicKey>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(public_key, E_POINTER); + + PublicKey *pkey = new PublicKey(*copyptr); + *public_key = pkey; + return S_OK; +} + +SEAL_C_FUNC PublicKey_Set(void *thisptr, void *assign) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + PublicKey *assignptr = FromVoid<PublicKey>(assign); + IfNullRet(assignptr, E_POINTER); + + *pkey = *assignptr; + return S_OK; +} + +SEAL_C_FUNC PublicKey_Data(void *thisptr, void **data) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + IfNullRet(data, E_POINTER); + + // This returns a pointer to an existing object, not a new object. + // Make sure the managed side does not try to delete it. + Ciphertext *cipher = &pkey->data(); + *data = cipher; + return S_OK; +} + +SEAL_C_FUNC PublicKey_ParmsId(void *thisptr, uint64_t *parms_id) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(pkey->parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC PublicKey_Pool(void *thisptr, void **pool) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + IfNullRet(pool, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(pkey->pool()); + *pool = handleptr; + return S_OK; +} + +SEAL_C_FUNC PublicKey_Destroy(void *thisptr) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + + delete pkey; + return S_OK; +} + +SEAL_C_FUNC PublicKey_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(pkey->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC PublicKey_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(pkey->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC PublicKey_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + pkey->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC PublicKey_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + PublicKey *pkey = FromVoid<PublicKey>(thisptr); + IfNullRet(pkey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + pkey->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/publickey.h b/bigpiseal3.5.1/native/src/seal/c/publickey.h new file mode 100644 index 0000000000000000000000000000000000000000..69253177c1dea910317a67ede930722cdc4b3dac --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/publickey.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC PublicKey_Create1(void **public_key); + +SEAL_C_FUNC PublicKey_Create2(void *copy, void **public_key); + +SEAL_C_FUNC PublicKey_Set(void *thisptr, void *assign); + +SEAL_C_FUNC PublicKey_Data(void *thisptr, void **data); + +SEAL_C_FUNC PublicKey_ParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC PublicKey_Pool(void *thisptr, void **pool); + +SEAL_C_FUNC PublicKey_Destroy(void *thisptr); + +SEAL_C_FUNC PublicKey_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC PublicKey_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC PublicKey_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC PublicKey_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/relinkeys.cpp b/bigpiseal3.5.1/native/src/seal/c/relinkeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09e208a1cb5d9dbc407733419461773f50c80d40 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/relinkeys.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/relinkeys.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/relinkeys.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC RelinKeys_GetIndex(uint64_t key_power, uint64_t *index) +{ + IfNullRet(index, E_POINTER); + + try + { + *index = RelinKeys::get_index(key_power); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/relinkeys.h b/bigpiseal3.5.1/native/src/seal/c/relinkeys.h new file mode 100644 index 0000000000000000000000000000000000000000..ec9755d1ed408ba7754d8ee59f89077786f62e38 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/relinkeys.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC RelinKeys_GetIndex(uint64_t key_power, uint64_t *index); diff --git a/bigpiseal3.5.1/native/src/seal/c/sealcontext.cpp b/bigpiseal3.5.1/native/src/seal/c/sealcontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..752e42051b1f0172b2136c0eb0bd7c234e642d91 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/sealcontext.cpp @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <unordered_map> + +// SEALNet +#include "seal/c/sealcontext.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/context.h" +#include "seal/util/locks.h" + +using namespace std; +using namespace seal; +using namespace seal::util; +using namespace seal::c; + +namespace seal +{ + namespace c + { + /** + The purpose of this map is to keep SEALContext shared pointers alive + while they are being used as regular pointers in the managed world. + */ + unordered_map<SEALContext *, shared_ptr<SEALContext>> pointer_store_; + + ReaderWriterLocker pointer_store_locker_; + } // namespace c +} // namespace seal + +SEAL_C_FUNC SEALContext_Create(void *encryptionParams, bool expand_mod_chain, int sec_level, void **context) +{ + EncryptionParameters *encParams = FromVoid<EncryptionParameters>(encryptionParams); + IfNullRet(encParams, E_POINTER); + IfNullRet(context, E_POINTER); + + sec_level_type security_level = static_cast<sec_level_type>(sec_level); + auto result = SEALContext::Create(*encParams, expand_mod_chain, security_level); + + WriterLock lock(pointer_store_locker_.acquire_write()); + pointer_store_[result.get()] = result; + + *context = result.get(); + return S_OK; +} + +SEAL_C_FUNC SEALContext_Destroy(void *thisptr) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + + WriterLock lock(pointer_store_locker_.acquire_write()); + pointer_store_.erase(context); + return S_OK; +} + +SEAL_C_FUNC SEALContext_KeyParmsId(void *thisptr, uint64_t *parms_id) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(context->key_parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC SEALContext_FirstParmsId(void *thisptr, uint64_t *parms_id) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(context->first_parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC SEALContext_LastParmsId(void *thisptr, uint64_t *parms_id) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(context->last_parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC SEALContext_ParametersSet(void *thisptr, bool *params_set) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(params_set, E_POINTER); + + *params_set = context->parameters_set(); + return S_OK; +} + +SEAL_C_FUNC SEALContext_KeyContextData(void *thisptr, void **context_data) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(context_data, E_POINTER); + + // The pointer that is returned should not be deleted. + auto data = context->key_context_data(); + *context_data = const_cast<SEALContext::ContextData *>(data.get()); + return S_OK; +} + +SEAL_C_FUNC SEALContext_FirstContextData(void *thisptr, void **context_data) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(context_data, E_POINTER); + + // The pointer that is returned should not be deleted. + auto data = context->first_context_data(); + *context_data = const_cast<SEALContext::ContextData *>(data.get()); + return S_OK; +} + +SEAL_C_FUNC SEALContext_LastContextData(void *thisptr, void **context_data) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(context_data, E_POINTER); + + // The pointer that is returned should not be deleted. + auto data = context->last_context_data(); + *context_data = const_cast<SEALContext::ContextData *>(data.get()); + return S_OK; +} + +SEAL_C_FUNC SEALContext_GetContextData(void *thisptr, uint64_t *parms_id, void **context_data) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(parms_id, E_POINTER); + IfNullRet(context_data, E_POINTER); + + // The pointer that is returned should not be deleted. + parms_id_type parms; + CopyParmsId(parms_id, parms); + auto data = context->get_context_data(parms); + *context_data = const_cast<SEALContext::ContextData *>(data.get()); + return S_OK; +} + +SEAL_C_FUNC SEALContext_UsingKeyswitching(void *thisptr, bool *using_keyswitching) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(using_keyswitching, E_POINTER); + + *using_keyswitching = context->using_keyswitching(); + return S_OK; +} + +SEAL_C_FUNC SEALContext_ParameterErrorName(void *thisptr, char *outstr, uint64_t *length) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(length, E_POINTER); + + const char *str = context->parameter_error_name(); + *length = static_cast<uint64_t>(strlen(str)); + + if (nullptr != outstr) + { + memcpy(outstr, str, *length); + } + return S_OK; +} + +SEAL_C_FUNC SEALContext_ParameterErrorMessage(void *thisptr, char *outstr, uint64_t *length) +{ + SEALContext *context = FromVoid<SEALContext>(thisptr); + IfNullRet(context, E_POINTER); + IfNullRet(length, E_POINTER); + + const char *str = context->parameter_error_message(); + *length = static_cast<uint64_t>(strlen(str)); + + if (nullptr != outstr) + { + memcpy(outstr, str, *length); + } + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/sealcontext.h b/bigpiseal3.5.1/native/src/seal/c/sealcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..bfe7f538b2f7f972c443fc087c88d8d82e97d00c --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/sealcontext.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC SEALContext_Create(void *encryptionParams, bool expand_mod_chain, int sec_level, void **context); + +SEAL_C_FUNC SEALContext_Destroy(void *thisptr); + +SEAL_C_FUNC SEALContext_KeyParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC SEALContext_FirstParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC SEALContext_LastParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC SEALContext_ParametersSet(void *thisptr, bool *params_set); + +SEAL_C_FUNC SEALContext_KeyContextData(void *thisptr, void **context_data); + +SEAL_C_FUNC SEALContext_FirstContextData(void *thisptr, void **context_data); + +SEAL_C_FUNC SEALContext_LastContextData(void *thisptr, void **context_data); + +SEAL_C_FUNC SEALContext_GetContextData(void *thisptr, uint64_t *parms_id, void **context_data); + +SEAL_C_FUNC SEALContext_UsingKeyswitching(void *thisptr, bool *using_keyswitching); + +SEAL_C_FUNC SEALContext_ParameterErrorName(void *thisptr, char *outstr, uint64_t *length); + +SEAL_C_FUNC SEALContext_ParameterErrorMessage(void *thisptr, char *outstr, uint64_t *length); \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/secretkey.cpp b/bigpiseal3.5.1/native/src/seal/c/secretkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7358a0e288986f57c6c88452f7af5d2233629e7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/secretkey.cpp @@ -0,0 +1,195 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/secretkey.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/secretkey.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC SecretKey_Create1(void **secret_key) +{ + IfNullRet(secret_key, E_POINTER); + + SecretKey *skey = new SecretKey(); + *secret_key = skey; + return S_OK; +} + +SEAL_C_FUNC SecretKey_Create2(void *copy, void **secret_key) +{ + SecretKey *copyptr = FromVoid<SecretKey>(copy); + IfNullRet(copyptr, E_POINTER); + IfNullRet(secret_key, E_POINTER); + + SecretKey *skey = new SecretKey(*copyptr); + *secret_key = skey; + return S_OK; +} + +SEAL_C_FUNC SecretKey_Set(void *thisptr, void *assign) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + SecretKey *assignptr = FromVoid<SecretKey>(assign); + IfNullRet(assignptr, E_POINTER); + + *skey = *assignptr; + return S_OK; +} + +SEAL_C_FUNC SecretKey_Data(void *thisptr, void **data) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + IfNullRet(data, E_POINTER); + + // This returns a pointer to an existing object, not a new object. + // Make sure the managed side does not try to delete it. + const Plaintext *plaintext = &skey->data(); + *data = const_cast<Plaintext *>(plaintext); + return S_OK; +} + +SEAL_C_FUNC SecretKey_Destroy(void *thisptr) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + + delete skey; + return S_OK; +} + +SEAL_C_FUNC SecretKey_ParmsId(void *thisptr, uint64_t *parms_id) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + IfNullRet(parms_id, E_POINTER); + + CopyParmsId(skey->parms_id(), parms_id); + return S_OK; +} + +SEAL_C_FUNC SecretKey_Pool(void *thisptr, void **pool) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + IfNullRet(pool, E_POINTER); + + MemoryPoolHandle *handleptr = new MemoryPoolHandle(skey->pool()); + *pool = handleptr; + return S_OK; +} + +SEAL_C_FUNC SecretKey_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + IfNullRet(result, E_POINTER); + + try + { + *result = static_cast<int64_t>(skey->save_size(static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } +} + +SEAL_C_FUNC SecretKey_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + IfNullRet(outptr, E_POINTER); + IfNullRet(out_bytes, E_POINTER); + + try + { + *out_bytes = util::safe_cast<int64_t>(skey->save( + reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size), + static_cast<compr_mode_type>(compr_mode))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC SecretKey_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + skey->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} + +SEAL_C_FUNC SecretKey_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes) +{ + SecretKey *skey = FromVoid<SecretKey>(thisptr); + IfNullRet(skey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(inptr, E_POINTER); + IfNullRet(in_bytes, E_POINTER); + + try + { + *in_bytes = util::safe_cast<int64_t>( + skey->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size))); + return S_OK; + } + catch (const invalid_argument &) + { + return E_INVALIDARG; + } + catch (const logic_error &) + { + return COR_E_INVALIDOPERATION; + } + catch (const runtime_error &) + { + return COR_E_IO; + } +} diff --git a/bigpiseal3.5.1/native/src/seal/c/secretkey.h b/bigpiseal3.5.1/native/src/seal/c/secretkey.h new file mode 100644 index 0000000000000000000000000000000000000000..bbe5819607313bf4ea4677804eb325a793e662b6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/secretkey.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC SecretKey_Create1(void **secret_key); + +SEAL_C_FUNC SecretKey_Create2(void *copy, void **secret_key); + +SEAL_C_FUNC SecretKey_Set(void *thisptr, void *assign); + +SEAL_C_FUNC SecretKey_Data(void *thisptr, void **data); + +SEAL_C_FUNC SecretKey_Destroy(void *thisptr); + +SEAL_C_FUNC SecretKey_ParmsId(void *thisptr, uint64_t *parms_id); + +SEAL_C_FUNC SecretKey_Pool(void *thisptr, void **pool); + +SEAL_C_FUNC SecretKey_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result); + +SEAL_C_FUNC SecretKey_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes); + +SEAL_C_FUNC SecretKey_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); + +SEAL_C_FUNC SecretKey_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes); diff --git a/bigpiseal3.5.1/native/src/seal/c/serialization.cpp b/bigpiseal3.5.1/native/src/seal/c/serialization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f908d4a0460d6666ceb0fe1d10ad5d2a864b4cf --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/serialization.cpp @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/serialization.h" +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/serialization.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC Serialization_SEALMagic(uint16_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = Serialization::seal_magic; + return S_OK; +} + +SEAL_C_FUNC Serialization_SEALHeaderSize(uint8_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = Serialization::seal_header_size; + return S_OK; +} + +SEAL_C_FUNC Serialization_IsSupportedComprMode(uint8_t compr_mode, bool *result) +{ + IfNullRet(result, E_POINTER); + + *result = Serialization::IsSupportedComprMode(compr_mode); + return S_OK; +} + +SEAL_C_FUNC Serialization_ComprModeDefault(uint8_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = static_cast<uint8_t>(Serialization::compr_mode_default); + return S_OK; +} + +SEAL_C_FUNC Serialization_IsCompatibleVersion(uint8_t *headerptr, uint64_t size, bool *result) +{ + IfNullRet(headerptr, E_POINTER); + IfNullRet(result, E_POINTER); + if (size != static_cast<uint64_t>(sizeof(Serialization::SEALHeader))) + { + *result = false; + } + + Serialization::SEALHeader header; + memcpy( + reinterpret_cast<SEAL_BYTE *>(&header), reinterpret_cast<SEAL_BYTE *>(headerptr), + sizeof(Serialization::SEALHeader)); + *result = Serialization::IsCompatibleVersion(header); + return S_OK; +} + +SEAL_C_FUNC Serialization_IsValidHeader(uint8_t *headerptr, uint64_t size, bool *result) +{ + IfNullRet(headerptr, E_POINTER); + IfNullRet(result, E_POINTER); + if (size != static_cast<uint64_t>(sizeof(Serialization::SEALHeader))) + { + *result = false; + } + + Serialization::SEALHeader header; + memcpy( + reinterpret_cast<SEAL_BYTE *>(&header), reinterpret_cast<SEAL_BYTE *>(headerptr), + sizeof(Serialization::SEALHeader)); + *result = Serialization::IsValidHeader(header); + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/serialization.h b/bigpiseal3.5.1/native/src/seal/c/serialization.h new file mode 100644 index 0000000000000000000000000000000000000000..0d4dfff009d9bbbca02c1340211c01520aef7d4d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/serialization.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Serialization_SEALMagic(uint16_t *result); + +SEAL_C_FUNC Serialization_SEALHeaderSize(uint8_t *result); + +SEAL_C_FUNC Serialization_IsSupportedComprMode(uint8_t compr_mode, bool *result); + +SEAL_C_FUNC Serialization_ComprModeDefault(uint8_t *result); + +SEAL_C_FUNC Serialization_IsCompatibleVersion(uint8_t *headerptr, uint64_t size, bool *result); + +SEAL_C_FUNC Serialization_IsValidHeader(uint8_t *headerptr, uint64_t size, bool *result); diff --git a/bigpiseal3.5.1/native/src/seal/c/stdafx.cpp b/bigpiseal3.5.1/native/src/seal/c/stdafx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..add7a14ea605772bb8c8c9c17d96b797533b3f76 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/stdafx.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/c/stdafx.h" diff --git a/bigpiseal3.5.1/native/src/seal/c/stdafx.h b/bigpiseal3.5.1/native/src/seal/c/stdafx.h new file mode 100644 index 0000000000000000000000000000000000000000..00ebf827a8d38d866237a0e28e98415b3a1ae95d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/stdafx.h @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#ifdef _MSC_VER +#include "seal/c/targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include <CorError.h> +#include <windows.h> +#endif // _MSC_VER + +#define IfNullRet(expr, ret) \ + { \ + if ((expr) == nullptr) \ + { \ + return ret; \ + } \ + } + +#define IfFailRet(expr) \ + { \ + HRESULT __hr__ = (expr); \ + if (FAILED(__hr__)) \ + { \ + return __hr__; \ + } \ + } diff --git a/bigpiseal3.5.1/native/src/seal/c/targetver.h b/bigpiseal3.5.1/native/src/seal/c/targetver.h new file mode 100644 index 0000000000000000000000000000000000000000..ec8135de610e43eaccb9cf8f7ef295a4f43a5be6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/targetver.h @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include <SDKDDKVer.h> diff --git a/bigpiseal3.5.1/native/src/seal/c/utilities.cpp b/bigpiseal3.5.1/native/src/seal/c/utilities.cpp new file mode 100644 index 0000000000000000000000000000000000000000..786c9a57b9e0b9cf036ae9a6f1da674fdc95d188 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/utilities.cpp @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// STD +#include <algorithm> +#include <iterator> + +// SEALNet +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" + +// SEAL +#include "seal/context.h" +#include "seal/encryptionparams.h" +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/locks.h" + +using namespace std; +using namespace seal; +using namespace seal::c; +using namespace seal::util; + +namespace seal +{ + namespace c + { + extern unordered_map<SEALContext *, shared_ptr<SEALContext>> pointer_store_; + + extern ReaderWriterLocker pointer_store_locker_; + + // This is here only so we have a null shared pointer to return. + shared_ptr<SEALContext> null_context_; + } // namespace c +} // namespace seal + +unique_ptr<MemoryPoolHandle> seal::c::MemHandleFromVoid(void *voidptr) +{ + if (nullptr == voidptr) + { + return make_unique<MemoryPoolHandle>(MemoryManager::GetPool()); + } + + MemoryPoolHandle *handle = reinterpret_cast<MemoryPoolHandle *>(voidptr); + return make_unique<MemoryPoolHandle>(*handle); +} + +void seal::c::BuildModulusPointers(const vector<Modulus> &in_mods, uint64_t *length, void **out_mods) +{ + *length = static_cast<uint64_t>(in_mods.size()); + if (out_mods == nullptr) + { + // The caller is only interested in the size + return; + } + + Modulus **mod_ptr_array = reinterpret_cast<Modulus **>(out_mods); + transform(in_mods.begin(), in_mods.end(), mod_ptr_array, [](const auto &mod) { return new Modulus(mod); }); +} + +const shared_ptr<SEALContext> &seal::c::SharedContextFromVoid(void *context) +{ + SEALContext *ctx = FromVoid<SEALContext>(context); + if (nullptr == ctx) + { + return null_context_; + } + + ReaderLock lock(pointer_store_locker_.acquire_read()); + + const auto &ctxiter = pointer_store_.find(ctx); + if (ctxiter == pointer_store_.end()) + { + return null_context_; + } + + return ctxiter->second; +} + +HRESULT seal::c::ToStringHelper(const string &str, char *outstr, uint64_t *length) +{ + *length = static_cast<uint64_t>(str.size()); + + if (nullptr != outstr) + { + memcpy(outstr, str.c_str(), util::add_safe(*length, uint64_t(1))); + } + return S_OK; +} + +HRESULT seal::c::ToStringHelper2(const char *str, char *outstr, uint64_t *length) +{ + *length = static_cast<uint64_t>(strlen(str)); + + if (nullptr != outstr) + { + memcpy(outstr, str, util::add_safe(*length, uint64_t(1))); + } + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/utilities.h b/bigpiseal3.5.1/native/src/seal/c/utilities.h new file mode 100644 index 0000000000000000000000000000000000000000..49aeb89aa0379c38d4ac39b3597a6d1e9a3d162e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/utilities.h @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// STD +#include <algorithm> +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + +// SEALNet +#include "seal/c/defines.h" + +// SEAL +#include "seal/encryptionparams.h" + +namespace seal +{ + class Modulus; + class SEALContext; + class MemoryPoolHandle; +} // namespace seal + +namespace seal +{ + namespace c + { + /** + Return a pointer of the given type from a void pointer. + */ + template <class T> + inline T *FromVoid(void *voidptr) + { + T *result = reinterpret_cast<T *>(voidptr); + return result; + } + + /** + Get MemoryPoolHandle from a void pointer. + Returns a default if void pointer is null. + */ + std::unique_ptr<seal::MemoryPoolHandle> MemHandleFromVoid(void *voidptr); + + /** + Build and array of Modulus pointers from a vector + */ + void BuildModulusPointers(const std::vector<seal::Modulus> &in_mods, uint64_t *length, void **out_mods); + + /** + Get a shared pointer to a SEALContext from a void pointer. + */ + const std::shared_ptr<seal::SEALContext> &SharedContextFromVoid(void *context); + + /** + Get a parms_id_type from an uint64_t pointer + */ + inline void CopyParmsId(const uint64_t *src, seal::parms_id_type &dest) + { + if (nullptr != src) + { + std::copy_n(src, dest.size(), std::begin(dest)); + } + } + + /** + Copy parms_id_type to a uint64_t pointer + */ + inline void CopyParmsId(const seal::parms_id_type &src, uint64_t *dest) + { + if (nullptr != dest) + { + std::copy_n(std::cbegin(src), src.size(), dest); + } + } + + /** + Convert std::string to char* with null terminator + */ + HRESULT ToStringHelper(const std::string &str, char *outstr, uint64_t *length); + + /** + Convert const char * to char* with null terminator + */ + HRESULT ToStringHelper2(const char *str, char *outstr, uint64_t *length); + } // namespace c +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/c/valcheck.cpp b/bigpiseal3.5.1/native/src/seal/c/valcheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55abcd1b49ca805a59918cfb90f6b12ed83dd47e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/valcheck.cpp @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" +#include "seal/c/valcheck.h" + +// SEAL +#include "seal/valcheck.h" + +using namespace std; +using namespace seal; +using namespace seal::c; + +SEAL_C_FUNC ValCheck_Plaintext_IsValidFor(void *plaintext, void *context, bool *result) +{ + Plaintext *plain = FromVoid<Plaintext>(plaintext); + IfNullRet(plain, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*plain, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_Ciphertext_IsValidFor(void *ciphertext, void *context, bool *result) +{ + Ciphertext *cipher = FromVoid<Ciphertext>(ciphertext); + IfNullRet(cipher, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*cipher, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_SecretKey_IsValidFor(void *secret_key, void *context, bool *result) +{ + SecretKey *skey = FromVoid<SecretKey>(secret_key); + IfNullRet(skey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*skey, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_PublicKey_IsValidFor(void *public_key, void *context, bool *result) +{ + PublicKey *pkey = FromVoid<PublicKey>(public_key); + IfNullRet(pkey, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*pkey, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_KSwitchKeys_IsValidFor(void *kswitch_keys, void *context, bool *result) +{ + KSwitchKeys *keys = FromVoid<KSwitchKeys>(kswitch_keys); + IfNullRet(keys, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*keys, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_RelinKeys_IsValidFor(void *relin_keys, void *context, bool *result) +{ + RelinKeys *keys = FromVoid<RelinKeys>(relin_keys); + IfNullRet(keys, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*keys, sharedctx); + return S_OK; +} + +SEAL_C_FUNC ValCheck_GaloisKeys_IsValidFor(void *galois_keys, void *context, bool *result) +{ + GaloisKeys *keys = FromVoid<GaloisKeys>(galois_keys); + IfNullRet(keys, E_POINTER); + const auto &sharedctx = SharedContextFromVoid(context); + IfNullRet(sharedctx.get(), E_POINTER); + IfNullRet(result, E_POINTER); + + *result = is_valid_for(*keys, sharedctx); + return S_OK; +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/c/valcheck.h b/bigpiseal3.5.1/native/src/seal/c/valcheck.h new file mode 100644 index 0000000000000000000000000000000000000000..7a154a70e77edee461ab1f7775dccdad99c28deb --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/valcheck.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC ValCheck_Plaintext_IsValidFor(void *plaintext, void *context, bool *result); + +SEAL_C_FUNC ValCheck_Ciphertext_IsValidFor(void *ciphertext, void *context, bool *result); + +SEAL_C_FUNC ValCheck_SecretKey_IsValidFor(void *secret_key, void *context, bool *result); + +SEAL_C_FUNC ValCheck_PublicKey_IsValidFor(void *public_key, void *context, bool *result); + +SEAL_C_FUNC ValCheck_KSwitchKeys_IsValidFor(void *kswitch_keys, void *context, bool *result); + +SEAL_C_FUNC ValCheck_RelinKeys_IsValidFor(void *relin_keys, void *context, bool *result); + +SEAL_C_FUNC ValCheck_GaloisKeys_IsValidFor(void *galois_keys, void *context, bool *result); diff --git a/bigpiseal3.5.1/native/src/seal/c/version.cpp b/bigpiseal3.5.1/native/src/seal/c/version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..206560b90f5e932ac2fc30e16feee0179438a1f9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/version.cpp @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// SEALNet +#include "seal/c/stdafx.h" +#include "seal/c/utilities.h" +#include "seal/c/version.h" + +// SEAL +#include "seal/util/config.h" + +using namespace std; +using namespace seal::c; + +SEAL_C_FUNC Version_Major(uint8_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = (uint8_t)SEAL_VERSION_MAJOR; + return S_OK; +} + +SEAL_C_FUNC Version_Minor(uint8_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = (uint8_t)SEAL_VERSION_MINOR; + return S_OK; +} + +SEAL_C_FUNC Version_Patch(uint8_t *result) +{ + IfNullRet(result, E_POINTER); + + *result = (uint8_t)SEAL_VERSION_PATCH; + return S_OK; +} diff --git a/bigpiseal3.5.1/native/src/seal/c/version.h b/bigpiseal3.5.1/native/src/seal/c/version.h new file mode 100644 index 0000000000000000000000000000000000000000..a77b296c293440ab522dd0b734c5eff5ad1bdac7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/c/version.h @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +/////////////////////////////////////////////////////////////////////////// +// +// This API is provided as a simple interface for Microsoft SEAL library +// that can be PInvoked by .Net code. +// +/////////////////////////////////////////////////////////////////////////// + +#include "seal/c/defines.h" +#include <stdint.h> + +SEAL_C_FUNC Version_Major(uint8_t *result); + +SEAL_C_FUNC Version_Minor(uint8_t *result); + +SEAL_C_FUNC Version_Patch(uint8_t *result); \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/ciphertext.cpp b/bigpiseal3.5.1/native/src/seal/ciphertext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e339fd17778ba48886bb644eb9db56b1fd037c7d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/ciphertext.cpp @@ -0,0 +1,331 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ciphertext.h" +#include "seal/randomgen.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/rlwe.h" +#include <algorithm> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + Ciphertext &Ciphertext::operator=(const Ciphertext &assign) + { + // Check for self-assignment + if (this == &assign) + { + return *this; + } + + // Copy over fields + parms_id_ = assign.parms_id_; + is_ntt_form_ = assign.is_ntt_form_; + scale_ = assign.scale_; + + // Then resize + resize_internal(assign.size_, assign.poly_modulus_degree_, assign.coeff_modulus_size_); + + // Size is guaranteed to be OK now so copy over + copy(assign.data_.cbegin(), assign.data_.cend(), data_.begin()); + + return *this; + } + + void Ciphertext::reserve(shared_ptr<SEALContext> context, parms_id_type parms_id, size_t size_capacity) + { + // Verify parameters + if (!context) + { + throw invalid_argument("invalid context"); + } + if (!context->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + auto context_data_ptr = context->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + + // Need to set parms_id first + auto &parms = context_data_ptr->parms(); + parms_id_ = context_data_ptr->parms_id(); + + reserve_internal(size_capacity, parms.poly_modulus_degree(), parms.coeff_modulus().size()); + } + + void Ciphertext::reserve_internal(size_t size_capacity, size_t poly_modulus_degree, size_t coeff_modulus_size) + { + if (size_capacity < SEAL_CIPHERTEXT_SIZE_MIN || size_capacity > SEAL_CIPHERTEXT_SIZE_MAX) + { + throw invalid_argument("invalid size_capacity"); + } + + size_t new_data_capacity = mul_safe(size_capacity, poly_modulus_degree, coeff_modulus_size); + size_t new_data_size = min<size_t>(new_data_capacity, data_.size()); + + // First reserve, then resize + data_.reserve(new_data_capacity); + data_.resize(new_data_size); + + // Set the size + size_ = min<size_t>(size_capacity, size_); + poly_modulus_degree_ = poly_modulus_degree; + coeff_modulus_size_ = coeff_modulus_size; + } + + void Ciphertext::resize(shared_ptr<SEALContext> context, parms_id_type parms_id, size_t size) + { + // Verify parameters + if (!context) + { + throw invalid_argument("invalid context"); + } + if (!context->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + auto context_data_ptr = context->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + + // Need to set parms_id first + auto &parms = context_data_ptr->parms(); + parms_id_ = context_data_ptr->parms_id(); + + resize_internal(size, parms.poly_modulus_degree(), parms.coeff_modulus().size()); + } + + void Ciphertext::resize_internal(size_t size, size_t poly_modulus_degree, size_t coeff_modulus_size) + { + if ((size < SEAL_CIPHERTEXT_SIZE_MIN && size != 0) || size > SEAL_CIPHERTEXT_SIZE_MAX) + { + throw invalid_argument("invalid size"); + } + + // Resize the data + size_t new_data_size = mul_safe(size, poly_modulus_degree, coeff_modulus_size); + data_.resize(new_data_size); + + // Set the size parameters + size_ = size; + poly_modulus_degree_ = poly_modulus_degree; + coeff_modulus_size_ = coeff_modulus_size; + } + + void Ciphertext::expand_seed(shared_ptr<SEALContext> context, const random_seed_type &seed) + { + auto context_data_ptr = context->get_context_data(parms_id_); + + // Set up the BlakePRNG with a given seed. + // Rejection sampling to generate a uniform random polynomial. + sample_poly_uniform(make_shared<BlakePRNG>(seed), context_data_ptr->parms(), data(1)); + } + + streamoff Ciphertext::save_size(compr_mode_type compr_mode) const + { + // We need to consider two cases: seeded and unseeded; these have very + // different size characteristics and we need the exact size when + // compr_mode is compr_mode_type::none. + size_t data_size; + if (has_seed_marker()) + { + // Create a temporary aliased IntArray of smaller size + IntArray<ct_coeff_type> alias_data( + Pointer<ct_coeff_type>::Aliasing(const_cast<ct_coeff_type *>(data_.cbegin())), data_.size() / 2, false, + data_.pool()); + + data_size = add_safe( + safe_cast<size_t>(alias_data.save_size(compr_mode_type::none)), // data_(0) + sizeof(random_seed_type)); // seed + } + else + { + data_size = safe_cast<size_t>(data_.save_size(compr_mode_type::none)); // data_ + } + + size_t members_size = Serialization::ComprSizeEstimate( + add_safe( + sizeof(parms_id_), + sizeof(SEAL_BYTE), // is_ntt_form_ + sizeof(uint64_t), // size_ + sizeof(uint64_t), // poly_modulus_degree_ + sizeof(uint64_t), // coeff_modulus_size_ + sizeof(scale_), data_size), + compr_mode); + + return safe_cast<streamoff>(add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + void Ciphertext::save_members(ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + stream.write(reinterpret_cast<const char *>(&parms_id_), sizeof(parms_id_type)); + SEAL_BYTE is_ntt_form_byte = static_cast<SEAL_BYTE>(is_ntt_form_); + stream.write(reinterpret_cast<const char *>(&is_ntt_form_byte), sizeof(SEAL_BYTE)); + uint64_t size64 = safe_cast<uint64_t>(size_); + stream.write(reinterpret_cast<const char *>(&size64), sizeof(uint64_t)); + uint64_t poly_modulus_degree64 = safe_cast<uint64_t>(poly_modulus_degree_); + stream.write(reinterpret_cast<const char *>(&poly_modulus_degree64), sizeof(uint64_t)); + uint64_t coeff_modulus_size64 = safe_cast<uint64_t>(coeff_modulus_size_); + stream.write(reinterpret_cast<const char *>(&coeff_modulus_size64), sizeof(uint64_t)); + stream.write(reinterpret_cast<const char *>(&scale_), sizeof(double)); + + if (has_seed_marker()) + { + random_seed_type seed; + copy_n(data(1) + 1, seed.size(), seed.begin()); + + size_t data_size = data_.size(); + size_t half_size = data_size / 2; + // Save_members must be a const method. + // Create an alias of data_, must be handled with care. + // Alternatively, create and serialize a half copy of data_. + IntArray<ct_coeff_type> alias_data(data_.pool_); + alias_data.size_ = half_size; + alias_data.capacity_ = half_size; + auto alias_ptr = util::Pointer<ct_coeff_type>::Aliasing(const_cast<ct_coeff_type *>(data_.cbegin())); + swap(alias_data.data_, alias_ptr); + alias_data.save(stream, compr_mode_type::none); + + // Save the seed + stream.write(reinterpret_cast<char *>(&seed), sizeof(random_seed_type)); + } + else + { + // Save the IntArray + data_.save(stream, compr_mode_type::none); + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void Ciphertext::load_members(shared_ptr<SEALContext> context, istream &stream) + { + // Verify parameters + if (!context) + { + throw invalid_argument("invalid context"); + } + if (!context->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + Ciphertext new_data(data_.pool()); + + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + parms_id_type parms_id{}; + stream.read(reinterpret_cast<char *>(&parms_id), sizeof(parms_id_type)); + SEAL_BYTE is_ntt_form_byte; + stream.read(reinterpret_cast<char *>(&is_ntt_form_byte), sizeof(SEAL_BYTE)); + uint64_t size64 = 0; + stream.read(reinterpret_cast<char *>(&size64), sizeof(uint64_t)); + uint64_t poly_modulus_degree64 = 0; + stream.read(reinterpret_cast<char *>(&poly_modulus_degree64), sizeof(uint64_t)); + uint64_t coeff_modulus_size64 = 0; + stream.read(reinterpret_cast<char *>(&coeff_modulus_size64), sizeof(uint64_t)); + double scale = 0; + stream.read(reinterpret_cast<char *>(&scale), sizeof(double)); + + // Set values already at this point for the metadata validity check + new_data.parms_id_ = parms_id; + new_data.is_ntt_form_ = (is_ntt_form_byte == SEAL_BYTE(0)) ? false : true; + new_data.size_ = safe_cast<size_t>(size64); + new_data.poly_modulus_degree_ = safe_cast<size_t>(poly_modulus_degree64); + new_data.coeff_modulus_size_ = safe_cast<size_t>(coeff_modulus_size64); + new_data.scale_ = scale; + + // Checking the validity of loaded metadata + // Note: We allow pure key levels here! This is to allow load_members + // to be used also when loading derived objects like PublicKey. This + // further means that functions reading in Ciphertext objects must check + // that for those use-cases the Ciphertext truly is at the data level + // if it is supposed to be. In other words, one cannot assume simply + // based on load_members succeeding that the Ciphertext is valid for + // computations. + if (!is_metadata_valid_for(new_data, context, true)) + { + throw logic_error("ciphertext data is invalid"); + } + + // Compute the total uint64 count required and reserve memory. + // Note that this must be done after the metadata is checked for validity. + auto total_uint64_count = + mul_safe(new_data.size_, new_data.poly_modulus_degree_, new_data.coeff_modulus_size_); + + // Reserve memory for the entire (expected) ciphertext data + new_data.data_.reserve(total_uint64_count); + + // Load the data. Note that we are supplying also the expected maximum + // size of the loaded IntArray. This is an important security measure to + // prevent a malformed IntArray from causing arbitrarily large memory + // allocations. + new_data.data_.load(stream, total_uint64_count); + + // Expected buffer size in the seeded case + auto seeded_uint64_count = poly_modulus_degree64 * coeff_modulus_size64; + + // This is the case where we need to expand a seed, otherwise full + // ciphertext data was (possibly) loaded and do nothing + if (unsigned_eq(new_data.data_.size(), seeded_uint64_count)) + { + // Single polynomial size data was loaded, so we are in the + // seeded ciphertext case. Next load the seed. + random_seed_type seed; + stream.read(reinterpret_cast<char *>(&seed), sizeof(random_seed_type)); + new_data.data_.resize(total_uint64_count); + new_data.expand_seed(move(context), seed); + } + + // Verify that the buffer is correct + if (!is_buffer_valid(new_data)) + { + throw logic_error("ciphertext data is invalid"); + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + swap(*this, new_data); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/ciphertext.h b/bigpiseal3.5.1/native/src/seal/ciphertext.h new file mode 100644 index 0000000000000000000000000000000000000000..f02ceb781f9aa022c9fb289883a6c58f47f7e922 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/ciphertext.h @@ -0,0 +1,723 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/randomgen.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/ztools.h" +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <functional> +#include <iostream> +#include <iterator> +#include <memory> +#include <stdexcept> +#include <string> + +namespace seal +{ + /** + Class to store a ciphertext element. The data for a ciphertext consists + of two or more polynomials, which are in Microsoft SEAL stored in a CRT + form with respect to the factors of the coefficient modulus. This data + itself is not meant to be modified directly by the user, but is instead + operated on by functions in the Evaluator class. The size of the backing + array of a ciphertext depends on the encryption parameters and the size + of the ciphertext (at least 2). If the poly_modulus_degree encryption + parameter is N, and the number of primes in the coeff_modulus encryption + parameter is K, then the ciphertext backing array requires precisely + 8*N*K*size bytes of memory. A ciphertext also carries with it the + parms_id of its associated encryption parameters, which is used to check + the validity of the ciphertext for homomorphic operations and decryption. + + @par Memory Management + The size of a ciphertext refers to the number of polynomials it contains, + whereas its capacity refers to the number of polynomials that fit in the + current memory allocation. In high-performance applications unnecessary + re-allocations should be avoided by reserving enough memory for the + ciphertext to begin with either by providing the desired capacity to the + constructor as an extra argument, or by calling the reserve function at + any time. + + @par Thread Safety + In general, reading from ciphertext is thread-safe as long as no other + thread is concurrently mutating it. This is due to the underlying data + structure storing the ciphertext not being thread-safe. + + @see Plaintext for the class that stores plaintexts. + */ + class Ciphertext + { + public: + using ct_coeff_type = std::uint64_t; + + /** + Constructs an empty ciphertext allocating no memory. + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + Ciphertext(MemoryPoolHandle pool = MemoryManager::GetPool()) : data_(std::move(pool)) + {} + + /** + Constructs an empty ciphertext with capacity 2. In addition to the + capacity, the allocation size is determined by the highest-level + parameters associated to the given SEALContext. + + @param[in] context The SEALContext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if pool is uninitialized + */ + explicit Ciphertext(std::shared_ptr<SEALContext> context, MemoryPoolHandle pool = MemoryManager::GetPool()) + : data_(std::move(pool)) + { + // Allocate memory but don't resize + reserve(std::move(context), 2); + } + + /** + Constructs an empty ciphertext with capacity 2. In addition to the + capacity, the allocation size is determined by the encryption parameters + with given parms_id. + + @param[in] context The SEALContext + @param[in] parms_id The parms_id corresponding to the encryption + parameters to be used + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + explicit Ciphertext( + std::shared_ptr<SEALContext> context, parms_id_type parms_id, + MemoryPoolHandle pool = MemoryManager::GetPool()) + : data_(std::move(pool)) + { + // Allocate memory but don't resize + reserve(std::move(context), parms_id, 2); + } + + /** + Constructs an empty ciphertext with given capacity. In addition to + the capacity, the allocation size is determined by the given + encryption parameters. + + @param[in] context The SEALContext + @param[in] parms_id The parms_id corresponding to the encryption + parameters to be used + @param[in] size_capacity The capacity + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if size_capacity is less than 2 or too large + @throws std::invalid_argument if pool is uninitialized + */ + explicit Ciphertext( + std::shared_ptr<SEALContext> context, parms_id_type parms_id, std::size_t size_capacity, + MemoryPoolHandle pool = MemoryManager::GetPool()) + : data_(std::move(pool)) + { + // Allocate memory but don't resize + reserve(std::move(context), parms_id, size_capacity); + } + + /** + Constructs a new ciphertext by copying a given one. + + @param[in] copy The ciphertext to copy from + */ + Ciphertext(const Ciphertext &copy) = default; + + /** + Creates a new ciphertext by moving a given one. + + @param[in] source The ciphertext to move from + */ + Ciphertext(Ciphertext &&source) = default; + + /** + Constructs a new ciphertext by copying a given one. + + @param[in] copy The ciphertext to copy from + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + Ciphertext(const Ciphertext &copy, MemoryPoolHandle pool) : Ciphertext(std::move(pool)) + { + *this = copy; + } + + /** + Allocates enough memory to accommodate the backing array of a ciphertext + with given capacity. In addition to the capacity, the allocation size is + determined by the encryption parameters corresponing to the given + parms_id. + + @param[in] context The SEALContext + @param[in] parms_id The parms_id corresponding to the encryption + parameters to be used + @param[in] size_capacity The capacity + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if size_capacity is less than 2 or too large + */ + void reserve(std::shared_ptr<SEALContext> context, parms_id_type parms_id, std::size_t size_capacity); + + /** + Allocates enough memory to accommodate the backing array of a ciphertext + with given capacity. In addition to the capacity, the allocation size is + determined by the highest-level parameters associated to the given + SEALContext. + + @param[in] context The SEALContext + @param[in] size_capacity The capacity + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if size_capacity is less than 2 or too large + */ + inline void reserve(std::shared_ptr<SEALContext> context, std::size_t size_capacity) + { + // Verify parameters + if (!context) + { + throw std::invalid_argument("invalid context"); + } + + auto parms_id = context->first_parms_id(); + reserve(std::move(context), parms_id, size_capacity); + } + + /** + Allocates enough memory to accommodate the backing array of a ciphertext + with given capacity. In addition to the capacity, the allocation size is + determined by the current encryption parameters. + + @param[in] size_capacity The capacity + @throws std::invalid_argument if size_capacity is less than 2 or too large + @throws std::logic_error if the encryption parameters are not + */ + inline void reserve(std::size_t size_capacity) + { + // Note: poly_modulus_degree_ and coeff_modulus_size_ are either valid + // or coeff_modulus_size_ is zero (in which case no memory is allocated). + reserve_internal(size_capacity, poly_modulus_degree_, coeff_modulus_size_); + } + + /** + Resizes the ciphertext to given size, reallocating if the capacity + of the ciphertext is too small. The ciphertext parameters are + determined by the given SEALContext and parms_id. + + This function is mainly intended for internal use and is called + automatically by functions such as Evaluator::multiply and + Evaluator::relinearize. A normal user should never have a reason + to manually resize a ciphertext. + + @param[in] context The SEALContext + @param[in] parms_id The parms_id corresponding to the encryption + parameters to be used + @param[in] size The new size + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if size is less than 2 or too large + */ + void resize(std::shared_ptr<SEALContext> context, parms_id_type parms_id, std::size_t size); + + /** + Resizes the ciphertext to given size, reallocating if the capacity + of the ciphertext is too small. The ciphertext parameters are + determined by the highest-level parameters associated to the given + SEALContext. + + This function is mainly intended for internal use and is called + automatically by functions such as Evaluator::multiply and + Evaluator::relinearize. A normal user should never have a reason + to manually resize a ciphertext. + + @param[in] context The SEALContext + @param[in] size The new size + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if size is less than 2 or too large + */ + inline void resize(std::shared_ptr<SEALContext> context, std::size_t size) + { + // Verify parameters + if (!context) + { + throw std::invalid_argument("invalid context"); + } + + auto parms_id = context->first_parms_id(); + resize(std::move(context), parms_id, size); + } + + /** + Resizes the ciphertext to given size, reallocating if the capacity + of the ciphertext is too small. + + This function is mainly intended for internal use and is called + automatically by functions such as Evaluator::multiply and + Evaluator::relinearize. A normal user should never have a reason + to manually resize a ciphertext. + + @param[in] size The new size + @throws std::invalid_argument if size is less than 2 or too large + */ + inline void resize(std::size_t size) + { + // Note: poly_modulus_degree_ and coeff_modulus_size_ are either valid + // or coeff_modulus_size_ is zero (in which case no memory is allocated). + resize_internal(size, poly_modulus_degree_, coeff_modulus_size_); + } + + /** + Resets the ciphertext. This function releases any memory allocated + by the ciphertext, returning it to the memory pool. It also sets all + encryption parameter specific size information to zero. + */ + inline void release() noexcept + { + parms_id_ = parms_id_zero; + is_ntt_form_ = false; + size_ = 0; + poly_modulus_degree_ = 0; + coeff_modulus_size_ = 0; + scale_ = 1.0; + data_.release(); + } + + /** + Copies a given ciphertext to the current one. + + @param[in] assign The ciphertext to copy from + */ + Ciphertext &operator=(const Ciphertext &assign); + + /** + Moves a given ciphertext to the current one. + + @param[in] assign The ciphertext to move from + */ + Ciphertext &operator=(Ciphertext &&assign) = default; + + /** + Returns a reference to the backing IntArray object. + */ + SEAL_NODISCARD inline const auto &int_array() const noexcept + { + return data_; + } + + /** + Returns a pointer to the beginning of the ciphertext data. + */ + SEAL_NODISCARD inline ct_coeff_type *data() noexcept + { + return data_.begin(); + } + + /** + Returns a const pointer to the beginning of the ciphertext data. + */ + SEAL_NODISCARD inline const ct_coeff_type *data() const noexcept + { + return data_.cbegin(); + } + + /** + Returns a pointer to a particular polynomial in the ciphertext + data. Note that Microsoft SEAL stores each polynomial in the ciphertext + modulo all of the K primes in the coefficient modulus. The pointer + returned by this function is to the beginning (constant coefficient) + of the first one of these K polynomials. + + @param[in] poly_index The index of the polynomial in the ciphertext + @throws std::out_of_range if poly_index is less than 0 or bigger + than the size of the ciphertext + */ + SEAL_NODISCARD inline ct_coeff_type *data(std::size_t poly_index) + { + auto poly_uint64_count = util::mul_safe(poly_modulus_degree_, coeff_modulus_size_); + if (poly_uint64_count == 0) + { + return nullptr; + } + if (poly_index >= size_) + { + throw std::out_of_range("poly_index must be within [0, size)"); + } + return data_.begin() + util::safe_cast<std::size_t>(util::mul_safe(poly_index, poly_uint64_count)); + } + + /** + Returns a const pointer to a particular polynomial in the + ciphertext data. Note that Microsoft SEAL stores each polynomial in the + ciphertext modulo all of the K primes in the coefficient modulus. + The pointer returned by this function is to the beginning + (constant coefficient) of the first one of these K polynomials. + + @param[in] poly_index The index of the polynomial in the ciphertext + @throws std::out_of_range if poly_index is out of range + */ + SEAL_NODISCARD inline const ct_coeff_type *data(std::size_t poly_index) const + { + auto poly_uint64_count = util::mul_safe(poly_modulus_degree_, coeff_modulus_size_); + if (poly_uint64_count == 0) + { + return nullptr; + } + if (poly_index >= size_) + { + throw std::out_of_range("poly_index must be within [0, size)"); + } + return data_.cbegin() + util::safe_cast<std::size_t>(util::mul_safe(poly_index, poly_uint64_count)); + } + + /** + Returns a reference to a polynomial coefficient at a particular + index in the ciphertext data. If the polynomial modulus has degree N, + and the number of primes in the coefficient modulus is K, then the + ciphertext contains size*N*K coefficients. Thus, the coeff_index has + a range of [0, size*N*K). + + @param[in] coeff_index The index of the coefficient + @throws std::out_of_range if coeff_index is out of range + */ + SEAL_NODISCARD inline ct_coeff_type &operator[](std::size_t coeff_index) + { + return data_.at(coeff_index); + } + + /** + Returns a const reference to a polynomial coefficient at a particular + index in the ciphertext data. If the polynomial modulus has degree N, + and the number of primes in the coefficient modulus is K, then the + ciphertext contains size*N*K coefficients. Thus, the coeff_index has + a range of [0, size*N*K). + + @param[in] coeff_index The index of the coefficient + @throws std::out_of_range if coeff_index is out of range + */ + SEAL_NODISCARD inline const ct_coeff_type &operator[](std::size_t coeff_index) const + { + return data_.at(coeff_index); + } + + /** + Returns the number of primes in the coefficient modulus of the + associated encryption parameters. This directly affects the + allocation size of the ciphertext. + */ + SEAL_NODISCARD inline std::size_t coeff_modulus_size() const noexcept + { + return coeff_modulus_size_; + } + + /** + Returns the degree of the polynomial modulus of the associated + encryption parameters. This directly affects the allocation size + of the ciphertext. + */ + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return poly_modulus_degree_; + } + + /** + Returns the size of the ciphertext. + */ + SEAL_NODISCARD inline std::size_t size() const noexcept + { + return size_; + } + + /** + Returns the capacity of the allocation. This means the largest size + of the ciphertext that can be stored in the current allocation with + the current encryption parameters. + */ + SEAL_NODISCARD inline std::size_t size_capacity() const noexcept + { + std::size_t poly_uint64_count = poly_modulus_degree_ * coeff_modulus_size_; + return poly_uint64_count ? data_.capacity() / poly_uint64_count : std::size_t(0); + } + + /** + Check whether the current ciphertext is transparent, i.e. does not require + a secret key to decrypt. In typical security models such transparent + ciphertexts would not be considered to be valid. Starting from the second + polynomial in the current ciphertext, this function returns true if all + following coefficients are identically zero. Otherwise, returns false. + */ + SEAL_NODISCARD inline bool is_transparent() const + { + return ( + !data_.size() || (size_ < SEAL_CIPHERTEXT_SIZE_MIN) || + std::all_of(data(1), data_.cend(), util::is_zero<ct_coeff_type>)); + } + + /** + Returns an upper bound on the size of the ciphertext, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD std::streamoff save_size(compr_mode_type compr_mode = Serialization::compr_mode_default) const; + + /** + Saves the ciphertext to an output stream. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the ciphertext to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Ciphertext::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a ciphertext from an input stream overwriting the current ciphertext. + No checking of the validity of the ciphertext data against encryption + parameters is performed. This function should not be used unless the + ciphertext comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] stream The stream to load the ciphertext from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Ciphertext::load_members, this, std::move(context), _1), stream); + } + + /** + Loads a ciphertext from an input stream overwriting the current ciphertext. + The loaded ciphertext is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] stream The stream to load the ciphertext from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + Ciphertext new_data(pool()); + auto in_size = new_data.unsafe_load(context, stream); + if (!is_valid_for(new_data, std::move(context))) + { + throw std::logic_error("ciphertext data is invalid"); + } + std::swap(*this, new_data); + return in_size; + } + + /** + Saves the ciphertext to a given memory location. The output is in binary + format and is not human-readable. + + @param[out] out The memory location to write the ciphertext to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Ciphertext::save_members, this, _1), save_size(compr_mode_type::none), out, size, + compr_mode); + } + + /** + Loads a ciphertext from a given memory location overwriting the current + ciphertext. No checking of the validity of the ciphertext data against + encryption parameters is performed. This function should not be used + unless the ciphertext comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] in The memory location to load the ciphertext from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Ciphertext::load_members, this, std::move(context), _1), in, size); + } + + /** + Loads a ciphertext from a given memory location overwriting the current + ciphertext. The loaded ciphertext is verified to be valid for the given + SEALContext. + + @param[in] context The SEALContext + @param[in] in The memory location to load the ciphertext from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + Ciphertext new_data(pool()); + auto in_size = new_data.unsafe_load(context, in, size); + if (!is_valid_for(new_data, std::move(context))) + { + throw std::logic_error("ciphertext data is invalid"); + } + std::swap(*this, new_data); + return in_size; + } + + /** + Returns whether the ciphertext is in NTT form. + */ + SEAL_NODISCARD inline bool is_ntt_form() const noexcept + { + return is_ntt_form_; + } + + /** + Returns whether the ciphertext is in NTT form. + */ + SEAL_NODISCARD inline bool &is_ntt_form() noexcept + { + return is_ntt_form_; + } + + /** + Returns a reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() noexcept + { + return parms_id_; + } + + /** + Returns a const reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return parms_id_; + } + + /** + Returns a reference to the scale. This is only needed when using the + CKKS encryption scheme. The user should have little or no reason to ever + change the scale by hand. + */ + SEAL_NODISCARD inline auto &scale() noexcept + { + return scale_; + } + + /** + Returns a constant reference to the scale. This is only needed when + using the CKKS encryption scheme. + */ + SEAL_NODISCARD inline auto &scale() const noexcept + { + return scale_; + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return data_.pool(); + } + + /** + Enables access to private members of seal::Ciphertext for .NET wrapper. + */ + struct CiphertextPrivateHelper; + + private: + void reserve_internal( + std::size_t size_capacity, std::size_t poly_modulus_degree, std::size_t coeff_modulus_size); + + void resize_internal(std::size_t size, std::size_t poly_modulus_degree, std::size_t coeff_modulus_size); + + void expand_seed(std::shared_ptr<SEALContext> context, const random_seed_type &seed); + + void save_members(std::ostream &stream) const; + + void load_members(std::shared_ptr<SEALContext> context, std::istream &stream); + + inline bool has_seed_marker() const noexcept + { + return data_.size() && (size_ == 2) ? (data(1)[0] == 0xFFFFFFFFFFFFFFFFULL) : false; + } + + parms_id_type parms_id_ = parms_id_zero; + + bool is_ntt_form_ = false; + + std::size_t size_ = 0; + + std::size_t poly_modulus_degree_ = 0; + + std::size_t coeff_modulus_size_ = 0; + + double scale_ = 1.0; + + IntArray<ct_coeff_type> data_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/ckks.cpp b/bigpiseal3.5.1/native/src/seal/ckks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8b76027f4e443346df1bfff73d2a2c44fbdd0ce --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/ckks.cpp @@ -0,0 +1,275 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ckks.h" +#include <cinttypes> +#include <limits> +#include <random> +#include <stdexcept> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + CKKSEncoder::CKKSEncoder(shared_ptr<SEALContext> context) : context_(context) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + auto &context_data = *context_->first_context_data(); + if (context_data.parms().scheme() != scheme_type::CKKS) + { + throw invalid_argument("unsupported scheme"); + } + + size_t coeff_count = context_data.parms().poly_modulus_degree(); + slots_ = coeff_count >> 1; + int logn = get_power_of_two(coeff_count); + + matrix_reps_index_map_ = allocate<size_t>(coeff_count, pool_); + + // Copy from the matrix to the value vectors + uint64_t gen = 3; + uint64_t pos = 1; + uint64_t m = static_cast<uint64_t>(coeff_count) << 1; + for (size_t i = 0; i < slots_; i++) + { + // Position in normal bit order + uint64_t index1 = (pos - 1) >> 1; + uint64_t index2 = (m - pos - 1) >> 1; + + // Set the bit-reversed locations + matrix_reps_index_map_[i] = safe_cast<size_t>(reverse_bits(index1, logn)); + matrix_reps_index_map_[slots_ | i] = safe_cast<size_t>(reverse_bits(index2, logn)); + + // Next primitive root + pos *= gen; + pos &= (m - 1); + } + + // we need 0~(n-1)-th powers of the primitive 2n-th root, m = 2n + roots_ = allocate<complex<double>>(coeff_count, pool_); + inv_roots_ = allocate<complex<double>>(coeff_count, pool_); + // 0~(n-1)-th powers of the primitive 2n-th root have 4-fold symmetry + if (m >= 8) + { + complex_roots_ = make_shared<util::ComplexRoots>(util::ComplexRoots(static_cast<size_t>(m), pool_)); + for (size_t i = 0; i < coeff_count; i++) + { + roots_[i] = complex_roots_->get_root(static_cast<size_t>(reverse_bits(i, logn))); + inv_roots_[i] = conj(roots_[i]); + } + } + else if (m == 4) + { + roots_[0] = { 0, 1 }; + roots_[1] = { 0, -1 }; + inv_roots_[0] = conj(roots_[0]); + inv_roots_[1] = conj(roots_[1]); + } + } + + void CKKSEncoder::encode_internal( + double value, parms_id_type parms_id, double scale, Plaintext &destination, MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + + // Quick sanity check + if (!product_fits_in(coeff_modulus_size, coeff_count)) + { + throw logic_error("invalid parameters"); + } + + // Check that scale is positive and not too large + if (scale <= 0 || (static_cast<int>(log2(scale)) >= context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // Compute the scaled value + value *= scale; + + int coeff_bit_count = static_cast<int>(log2(fabs(value))) + 2; + if (coeff_bit_count >= context_data.total_coeff_modulus_bit_count()) + { + throw invalid_argument("encoded value is too large"); + } + + double two_pow_64 = pow(2.0, 64); + + // Resize destination to appropriate size + // Need to first set parms_id to zero, otherwise resize + // will throw an exception. + destination.parms_id() = parms_id_zero; + destination.resize(coeff_count * coeff_modulus_size); + + double coeffd = round(value); + bool is_negative = signbit(coeffd); + coeffd = fabs(coeffd); + + // Use faster decomposition methods when possible + if (coeff_bit_count <= 64) + { + uint64_t coeffu = static_cast<uint64_t>(fabs(coeffd)); + + if (is_negative) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n( + destination.data() + (j * coeff_count), coeff_count, + negate_uint_mod(coeffu % coeff_modulus[j].value(), coeff_modulus[j])); + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n(destination.data() + (j * coeff_count), coeff_count, coeffu % coeff_modulus[j].value()); + } + } + } + else if (coeff_bit_count <= 128) + { + uint64_t coeffu[2]{ static_cast<uint64_t>(fmod(coeffd, two_pow_64)), + static_cast<uint64_t>(coeffd / two_pow_64) }; + + if (is_negative) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n( + destination.data() + (j * coeff_count), coeff_count, + negate_uint_mod(barrett_reduce_128(coeffu, coeff_modulus[j]), coeff_modulus[j])); + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n( + destination.data() + (j * coeff_count), coeff_count, + barrett_reduce_128(coeffu, coeff_modulus[j])); + } + } + } + else + { + // Slow case + auto coeffu(allocate_uint(coeff_modulus_size, pool)); + + // We are at this point guaranteed to fit in the allocated space + set_zero_uint(coeff_modulus_size, coeffu.get()); + auto coeffu_ptr = coeffu.get(); + while (coeffd >= 1) + { + *coeffu_ptr++ = static_cast<uint64_t>(fmod(coeffd, two_pow_64)); + coeffd /= two_pow_64; + } + + // Next decompose this coefficient + context_data.rns_tool()->base_q()->decompose(coeffu.get(), pool); + + // Finally replace the sign if necessary + if (is_negative) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n( + destination.data() + (j * coeff_count), coeff_count, + negate_uint_mod(coeffu[j], coeff_modulus[j])); + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + fill_n(destination.data() + (j * coeff_count), coeff_count, coeffu[j]); + } + } + } + + destination.parms_id() = parms_id; + destination.scale() = scale; + } + + void CKKSEncoder::encode_internal(int64_t value, parms_id_type parms_id, Plaintext &destination) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + + // Quick sanity check + if (!product_fits_in(coeff_modulus_size, coeff_count)) + { + throw logic_error("invalid parameters"); + } + + int coeff_bit_count = get_significant_bit_count(static_cast<uint64_t>(llabs(value))) + 2; + if (coeff_bit_count >= context_data.total_coeff_modulus_bit_count()) + { + throw invalid_argument("encoded value is too large"); + } + + // Resize destination to appropriate size + // Need to first set parms_id to zero, otherwise resize + // will throw an exception. + destination.parms_id() = parms_id_zero; + destination.resize(coeff_count * coeff_modulus_size); + + if (value < 0) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t tmp = static_cast<uint64_t>(value); + tmp += coeff_modulus[j].value(); + tmp %= coeff_modulus[j].value(); + fill_n(destination.data() + (j * coeff_count), coeff_count, tmp); + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t tmp = static_cast<uint64_t>(value); + tmp %= coeff_modulus[j].value(); + fill_n(destination.data() + (j * coeff_count), coeff_count, tmp); + } + } + + destination.parms_id() = parms_id; + destination.scale() = 1.0; + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/ckks.h b/bigpiseal3.5.1/native/src/seal/ckks.h new file mode 100644 index 0000000000000000000000000000000000000000..70fd91520a913714d02ebe307efad61ebf9a3ea5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/ckks.h @@ -0,0 +1,779 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/plaintext.h" +#include "seal/util/common.h" +#include "seal/util/croots.h" +#include "seal/util/defines.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <cmath> +#include <complex> +#include <limits> +#include <memory> +#include <type_traits> +#include <vector> +#ifdef SEAL_USE_MSGSL +#include <gsl/span> +#endif + +namespace seal +{ + template < + typename T_out, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T_out>, double>::value || + std::is_same<std::remove_cv_t<T_out>, std::complex<double>>::value>> + SEAL_NODISCARD inline T_out from_complex(std::complex<double> in); + + template <> + SEAL_NODISCARD inline double from_complex(std::complex<double> in) + { + return in.real(); + } + + template <> + SEAL_NODISCARD inline std::complex<double> from_complex(std::complex<double> in) + { + return in; + } + + /** + Provides functionality for encoding vectors of complex or real numbers into + plaintext polynomials to be encrypted and computed on using the CKKS scheme. + If the polynomial modulus degree is N, then CKKSEncoder converts vectors of + N/2 complex numbers into plaintext elements. Homomorphic operations performed + on such encrypted vectors are applied coefficient (slot-)wise, enabling + powerful SIMD functionality for computations that are vectorizable. This + functionality is often called "batching" in the homomorphic encryption + literature. + + @par Mathematical Background + Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of + two, the CKKSEncoder implements an approximation of the canonical embedding + of the ring of integers Z[X]/(X^N+1) into C^(N/2), where C denotes the complex + numbers. The Galois group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) + whose action on the primitive roots of unity modulo coeff_modulus is easy to + describe. Since the batching slots correspond 1-to-1 to the primitive roots + of unity, applying Galois automorphisms on the plaintext acts by permuting + the slots. By applying generators of the two cyclic subgroups of the Galois + group, we can effectively enable cyclic rotations and complex conjugations + of the encrypted complex vectors. + */ + class CKKSEncoder + { + public: + /** + Creates a CKKSEncoder instance initialized with the specified SEALContext. + + @param[in] context The SEALContext + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if scheme is not scheme_type::CKKS + */ + CKKSEncoder(std::shared_ptr<SEALContext> context); + + /** + Encodes a vector of double-precision floating-point real or complex numbers + into a plaintext polynomial. Append zeros if vector size is less than N/2. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + @tparam T Vector value type (double or std::complex<double>) + @param[in] values The vector of double-precision floating-point numbers + (of type T) to encode + @param[in] parms_id parms_id determining the encryption parameters to + be used by the result plaintext + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if values has invalid size + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void encode( + const std::vector<T> &values, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode_internal(values.data(), values.size(), parms_id, scale, destination, std::move(pool)); + } + + /** + Encodes a vector of double-precision floating-point real or complex numbers + into a plaintext polynomial. Append zeros if vector size is less than N/2. + The encryption parameters used are the top level parameters for the given + context. Dynamic memory allocations in the process are allocated from the + memory pool pointed to by the given MemoryPoolHandle. + + @tparam T Vector value type (double or std::complex<double>) + @param[in] values The vector of double-precision floating-point numbers + (of type T) to encode + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if values has invalid size + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void encode( + const std::vector<T> &values, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode(values, context_->first_parms_id(), scale, destination, std::move(pool)); + } +#ifdef SEAL_USE_MSGSL + /** + Encodes a vector of double-precision floating-point real or complex numbers + into a plaintext polynomial. Append zeros if vector size is less than N/2. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + @tparam T Array value type (double or std::complex<double>) + @param[in] values The array of double-precision floating-point numbers + (of type T) to encode + @param[in] parms_id parms_id determining the encryption parameters to + be used by the result plaintext + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if values has invalid size + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void encode( + gsl::span<const T> values, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode_internal( + values.data(), static_cast<std::size_t>(values.size()), parms_id, scale, destination, std::move(pool)); + } + + /** + Encodes a vector of double-precision floating-point real or complex numbers + into a plaintext polynomial. Append zeros if vector size is less than N/2. + The encryption parameters used are the top level parameters for the given + context. Dynamic memory allocations in the process are allocated from the + memory pool pointed to by the given MemoryPoolHandle. + + @tparam T Array value type (double or std::complex<double>) + @param[in] values The array of double-precision floating-point numbers + (of type T) to encode + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if values has invalid size + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void encode( + gsl::span<const T> values, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode(values, context_->first_parms_id(), scale, destination, std::move(pool)); + } +#endif + /** + Encodes a double-precision floating-point real number into a plaintext + polynomial. The number repeats for N/2 times to fill all slots. Dynamic + memory allocations in the process are allocated from the memory pool + pointed to by the given MemoryPoolHandle. + + @param[in] value The double-precision floating-point number to encode + @param[in] parms_id parms_id determining the encryption parameters to be + used by the result plaintext + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encode( + double value, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode_internal(value, parms_id, scale, destination, std::move(pool)); + } + + /** + Encodes a double-precision floating-point real number into a plaintext + polynomial. The number repeats for N/2 times to fill all slots. The + encryption parameters used are the top level parameters for the given + context. Dynamic memory allocations in the process are allocated from + the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] value The double-precision floating-point number to encode + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encode( + double value, double scale, Plaintext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode(value, context_->first_parms_id(), scale, destination, std::move(pool)); + } + + /** + Encodes a double-precision complex number into a plaintext polynomial. + Append zeros to fill all slots. Dynamic memory allocations in the process + are allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] value The double-precision complex number to encode + @param[in] parms_id parms_id determining the encryption parameters to be + used by the result plaintext + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encode( + std::complex<double> value, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode_internal(value, parms_id, scale, destination, std::move(pool)); + } + + /** + Encodes a double-precision complex number into a plaintext polynomial. + Append zeros to fill all slots. The encryption parameters used are the + top level parameters for the given context. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the + given MemoryPoolHandle. + + @param[in] value The double-precision complex number to encode + @param[in] scale Scaling parameter defining encoding precision + @param[out] destination The plaintext polynomial to overwrite with the + result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if scale is not strictly positive + @throws std::invalid_argument if encoding is too large for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encode( + std::complex<double> value, double scale, Plaintext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + encode(value, context_->first_parms_id(), scale, destination, std::move(pool)); + } + + /** + Encodes an integer number into a plaintext polynomial without any scaling. + The number repeats for N/2 times to fill all slots. + @param[in] value The integer number to encode + @param[in] parms_id parms_id determining the encryption parameters to be + used by the result plaintext + @param[out] destination The plaintext polynomial to overwrite with the + result + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + */ + inline void encode(std::int64_t value, parms_id_type parms_id, Plaintext &destination) + { + encode_internal(value, parms_id, destination); + } + + /** + Encodes an integer number into a plaintext polynomial without any scaling. + The number repeats for N/2 times to fill all slots. The encryption + parameters used are the top level parameters for the given context. + + @param[in] value The integer number to encode + @param[out] destination The plaintext polynomial to overwrite with the + result + */ + inline void encode(std::int64_t value, Plaintext &destination) + { + encode(value, context_->first_parms_id(), destination); + } + + /** + Decodes a plaintext polynomial into double-precision floating-point + real or complex numbers. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @tparam T Vector value type (double or std::complex<double>) + @param[in] plain The plaintext to decode + @param[out] destination The vector to be overwritten with the values in + the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not in NTT form or is invalid + for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void decode( + const Plaintext &plain, std::vector<T> &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination.resize(slots_); + decode_internal(plain, destination.data(), std::move(pool)); + } +#ifdef SEAL_USE_MSGSL + /** + Decodes a plaintext polynomial into double-precision floating-point + real or complex numbers. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @tparam T Array value type (double or std::complex<double>) + @param[in] plain The plaintext to decode + @param[out] destination The array to be overwritten with the values in + the slots + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is not in NTT form or is invalid + for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + */ + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + inline void decode( + const Plaintext &plain, gsl::span<T> destination, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (destination.size() != slots_) + { + throw std::invalid_argument("destination has invalid size"); + } + decode_internal(plain, destination.data(), std::move(pool)); + } +#endif + /** + Returns the number of complex numbers encoded. + */ + SEAL_NODISCARD inline std::size_t slot_count() const noexcept + { + return slots_; + } + + private: + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + void encode_internal( + const T *values, std::size_t values_size, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw std::invalid_argument("parms_id is not valid for encryption parameters"); + } + if (!values && values_size > 0) + { + throw std::invalid_argument("values cannot be null"); + } + if (values_size > slots_) + { + throw std::invalid_argument("values_size is too large"); + } + if (!pool) + { + throw std::invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + std::size_t coeff_modulus_size = coeff_modulus.size(); + std::size_t coeff_count = parms.poly_modulus_degree(); + + // Quick sanity check + if (!util::product_fits_in(coeff_modulus_size, coeff_count)) + { + throw std::logic_error("invalid parameters"); + } + + // Check that scale is positive and not too large + if (scale <= 0 || (static_cast<int>(log2(scale)) + 1 >= context_data.total_coeff_modulus_bit_count())) + { + throw std::invalid_argument("scale out of bounds"); + } + + auto small_ntt_tables = context_data.small_ntt_tables(); + + // values_size is guaranteed to be no bigger than slots_ + std::size_t n = util::mul_safe(slots_, std::size_t(2)); + + auto conj_values = util::allocate<std::complex<double>>(n, pool, 0); + for (std::size_t i = 0; i < values_size; i++) + { + conj_values[matrix_reps_index_map_[i]] = values[i]; + conj_values[matrix_reps_index_map_[i + slots_]] = std::conj(values[i]); + } + + int logn = util::get_power_of_two(n); + std::size_t tt = 1; + for (int i = 0; i < logn; i++) + { + std::size_t mm = std::size_t(1) << (logn - i); + std::size_t k_start = 0; + std::size_t h = mm / 2; + + for (std::size_t j = 0; j < h; j++) + { + std::size_t k_end = k_start + tt; + auto s = inv_roots_[h + j]; + + for (std::size_t k = k_start; k < k_end; k++) + { + auto u = conj_values[k]; + auto v = conj_values[k + tt]; + conj_values[k] = u + v; + conj_values[k + tt] = (u - v) * s; + } + + k_start += 2 * tt; + } + tt *= 2; + } + + double n_inv = double(1.0) / static_cast<double>(n); + + // Put the scale in at this point + n_inv *= scale; + + int max_coeff_bit_count = 1; + for (std::size_t i = 0; i < n; i++) + { + // Multiply by scale and n_inv (see above) + conj_values[i] *= n_inv; + + // Verify that the values are not too large to fit in coeff_modulus + // Note that we have an extra + 1 for the sign bit + // Don't compute logarithmis of numbers less than 1 + double d = std::max(std::fabs(conj_values[i].real()), 1.0); + max_coeff_bit_count = std::max(max_coeff_bit_count, static_cast<int>(std::log2(d)) + 2); + } + if (max_coeff_bit_count >= context_data.total_coeff_modulus_bit_count()) + { + throw std::invalid_argument("encoded values are too large"); + } + + double two_pow_64 = std::pow(2.0, 64); + + // Resize destination to appropriate size + // Need to first set parms_id to zero, otherwise resize + // will throw an exception. + destination.parms_id() = parms_id_zero; + destination.resize(util::mul_safe(coeff_count, coeff_modulus_size)); + + // Use faster decomposition methods when possible + if (max_coeff_bit_count <= 64) + { + for (std::size_t i = 0; i < n; i++) + { + double coeffd = std::round(conj_values[i].real()); + bool is_negative = std::signbit(coeffd); + + std::uint64_t coeffu = static_cast<std::uint64_t>(std::fabs(coeffd)); + + if (is_negative) + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = + util::negate_uint_mod(coeffu % coeff_modulus[j].value(), coeff_modulus[j]); + } + } + else + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = coeffu % coeff_modulus[j].value(); + } + } + } + } + else if (max_coeff_bit_count <= 128) + { + for (std::size_t i = 0; i < n; i++) + { + double coeffd = std::round(conj_values[i].real()); + bool is_negative = std::signbit(coeffd); + coeffd = std::fabs(coeffd); + + std::uint64_t coeffu[2]{ static_cast<std::uint64_t>(std::fmod(coeffd, two_pow_64)), + static_cast<std::uint64_t>(coeffd / two_pow_64) }; + + if (is_negative) + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = util::negate_uint_mod( + util::barrett_reduce_128(coeffu, coeff_modulus[j]), coeff_modulus[j]); + } + } + else + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = util::barrett_reduce_128(coeffu, coeff_modulus[j]); + } + } + } + } + else + { + // Slow case + auto coeffu(util::allocate_uint(coeff_modulus_size, pool)); + for (std::size_t i = 0; i < n; i++) + { + double coeffd = std::round(conj_values[i].real()); + bool is_negative = std::signbit(coeffd); + coeffd = std::fabs(coeffd); + + // We are at this point guaranteed to fit in the allocated space + util::set_zero_uint(coeff_modulus_size, coeffu.get()); + auto coeffu_ptr = coeffu.get(); + while (coeffd >= 1) + { + *coeffu_ptr++ = static_cast<std::uint64_t>(std::fmod(coeffd, two_pow_64)); + coeffd /= two_pow_64; + } + + // Next decompose this coefficient + context_data.rns_tool()->base_q()->decompose(coeffu.get(), pool); + + // Finally replace the sign if necessary + if (is_negative) + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = util::negate_uint_mod(coeffu[j], coeff_modulus[j]); + } + } + else + { + for (std::size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + (j * coeff_count)] = coeffu[j]; + } + } + } + } + + // Transform to NTT domain + for (std::size_t i = 0; i < coeff_modulus_size; i++) + { + util::ntt_negacyclic_harvey(destination.data(i * coeff_count), small_ntt_tables[i]); + } + + destination.parms_id() = parms_id; + destination.scale() = scale; + } + + template < + typename T, typename = std::enable_if_t< + std::is_same<std::remove_cv_t<T>, double>::value || + std::is_same<std::remove_cv_t<T>, std::complex<double>>::value>> + void decode_internal(const Plaintext &plain, T *destination, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_valid_for(plain, context_)) + { + throw std::invalid_argument("plain is not valid for encryption parameters"); + } + if (!plain.is_ntt_form()) + { + throw std::invalid_argument("plain is not in NTT form"); + } + if (!destination) + { + throw std::invalid_argument("destination cannot be null"); + } + if (!pool) + { + throw std::invalid_argument("pool is uninitialized"); + } + + auto &context_data = *context_->get_context_data(plain.parms_id()); + auto &parms = context_data.parms(); + std::size_t coeff_modulus_size = parms.coeff_modulus().size(); + std::size_t coeff_count = parms.poly_modulus_degree(); + std::size_t rns_poly_uint64_count = util::mul_safe(coeff_count, coeff_modulus_size); + + auto small_ntt_tables = context_data.small_ntt_tables(); + + // Check that scale is positive and not too large + if (plain.scale() <= 0 || + (static_cast<int>(log2(plain.scale())) >= context_data.total_coeff_modulus_bit_count())) + { + throw std::invalid_argument("scale out of bounds"); + } + + auto decryption_modulus = context_data.total_coeff_modulus(); + auto upper_half_threshold = context_data.upper_half_threshold(); + int logn = util::get_power_of_two(coeff_count); + + // Quick sanity check + if ((logn < 0) || (coeff_count < SEAL_POLY_MOD_DEGREE_MIN) || (coeff_count > SEAL_POLY_MOD_DEGREE_MAX)) + { + throw std::logic_error("invalid parameters"); + } + + double inv_scale = double(1.0) / plain.scale(); + + // Create mutable copy of input + auto plain_copy(util::allocate_uint(rns_poly_uint64_count, pool)); + util::set_uint_uint(plain.data(), rns_poly_uint64_count, plain_copy.get()); + + // Transform each polynomial from NTT domain + for (std::size_t i = 0; i < coeff_modulus_size; i++) + { + util::inverse_ntt_negacyclic_harvey(plain_copy.get() + (i * coeff_count), small_ntt_tables[i]); + } + + // CRT-compose the polynomial + context_data.rns_tool()->base_q()->compose_array(plain_copy.get(), coeff_count, pool); + + // Create floating-point representations of the multi-precision integer coefficients + double two_pow_64 = std::pow(2.0, 64); + auto res(util::allocate<std::complex<double>>(coeff_count, pool)); + for (std::size_t i = 0; i < coeff_count; i++) + { + res[i] = 0.0; + if (util::is_greater_than_or_equal_uint_uint( + plain_copy.get() + (i * coeff_modulus_size), upper_half_threshold, coeff_modulus_size)) + { + double scaled_two_pow_64 = inv_scale; + for (std::size_t j = 0; j < coeff_modulus_size; j++, scaled_two_pow_64 *= two_pow_64) + { + if (plain_copy[i * coeff_modulus_size + j] > decryption_modulus[j]) + { + auto diff = plain_copy[i * coeff_modulus_size + j] - decryption_modulus[j]; + res[i] += diff ? static_cast<double>(diff) * scaled_two_pow_64 : 0.0; + } + else + { + auto diff = decryption_modulus[j] - plain_copy[i * coeff_modulus_size + j]; + res[i] -= diff ? static_cast<double>(diff) * scaled_two_pow_64 : 0.0; + } + } + } + else + { + double scaled_two_pow_64 = inv_scale; + for (std::size_t j = 0; j < coeff_modulus_size; j++, scaled_two_pow_64 *= two_pow_64) + { + auto curr_coeff = plain_copy[i * coeff_modulus_size + j]; + res[i] += curr_coeff ? static_cast<double>(curr_coeff) * scaled_two_pow_64 : 0.0; + } + } + + // Scaling instead incorporated above; this can help in cases + // where otherwise pow(two_pow_64, j) would overflow due to very + // large coeff_modulus_size and very large scale + // res[i] = res_accum * inv_scale; + } + + // Butterfly to obtain final result + std::size_t tt = coeff_count; + for (int i = 0; i < logn; i++) + { + std::size_t mm = std::size_t(1) << i; + tt >>= 1; + + for (std::size_t j = 0; j < mm; j++) + { + std::size_t j1 = 2 * j * tt; + std::size_t j2 = j1 + tt - 1; + auto s = roots_[mm + j]; + + for (std::size_t k = j1; k < j2 + 1; k++) + { + auto u = res[k]; + auto v = res[k + tt] * s; + res[k] = u + v; + res[k + tt] = u - v; + } + } + } + + for (std::size_t i = 0; i < slots_; i++) + { + destination[i] = from_complex<T>(res[static_cast<std::size_t>(matrix_reps_index_map_[i])]); + } + } + + void encode_internal( + double value, parms_id_type parms_id, double scale, Plaintext &destination, MemoryPoolHandle pool); + + inline void encode_internal( + std::complex<double> value, parms_id_type parms_id, double scale, Plaintext &destination, + MemoryPoolHandle pool) + { + auto input = util::allocate<std::complex<double>>(slots_, pool_, value); + encode_internal(input.get(), slots_, parms_id, scale, destination, std::move(pool)); + } + + void encode_internal(std::int64_t value, parms_id_type parms_id, Plaintext &destination); + + MemoryPoolHandle pool_ = MemoryManager::GetPool(); + + std::shared_ptr<SEALContext> context_{ nullptr }; + + std::size_t slots_; + + std::shared_ptr<util::ComplexRoots> complex_roots_; + + util::Pointer<std::complex<double>> roots_; + + util::Pointer<std::complex<double>> inv_roots_; + + util::Pointer<std::size_t> matrix_reps_index_map_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/context.cpp b/bigpiseal3.5.1/native/src/seal/context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30dac1be299bb2791feca7e50857008760fe5e2e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/context.cpp @@ -0,0 +1,524 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/util/numth.h" +#include "seal/util/pointer.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include <algorithm> +#include <stdexcept> +#include <utility> + +using namespace std; +using namespace seal::util; + +using error_type = seal::EncryptionParameterQualifiers::error_type; + +namespace seal +{ + const char *EncryptionParameterQualifiers::parameter_error_name() const noexcept + { + switch (parameter_error) + { + case error_type::none: + return "none"; + + case error_type::success: + return "success"; + + case error_type::invalid_scheme: + return "invalid_scheme"; + + case error_type::invalid_coeff_modulus_size: + return "invalid_coeff_modulus_size"; + + case error_type::invalid_coeff_modulus_bit_count: + return "invalid_coeff_modulus_bit_count"; + + case error_type::invalid_coeff_modulus_no_ntt: + return "invalid_coeff_modulus_no_ntt"; + + case error_type::invalid_poly_modulus_degree: + return "invalid_poly_modulus_degree"; + + case error_type::invalid_poly_modulus_degree_non_power_of_two: + return "invalid_poly_modulus_degree_non_power_of_two"; + + case error_type::invalid_parameters_too_large: + return "invalid_parameters_too_large"; + + case error_type::invalid_parameters_insecure: + return "invalid_parameters_insecure"; + + case error_type::failed_creating_rns_base: + return "failed_creating_rns_base"; + + case error_type::invalid_plain_modulus_bit_count: + return "invalid_plain_modulus_bit_count"; + + case error_type::invalid_plain_modulus_coprimality: + return "invalid_plain_modulus_coprimality"; + + case error_type::invalid_plain_modulus_too_large: + return "invalid_plain_modulus_too_large"; + + case error_type::invalid_plain_modulus_nonzero: + return "invalid_plain_modulus_nonzero"; + + case error_type::failed_creating_rns_tool: + return "failed_creating_rns_tool"; + + default: + return "invalid parameter_error"; + } + } + + const char *EncryptionParameterQualifiers::parameter_error_message() const noexcept + { + switch (parameter_error) + { + case error_type::none: + return "constructed but not yet validated"; + + case error_type::success: + return "valid"; + + case error_type::invalid_scheme: + return "scheme must be BFV or CKKS"; + + case error_type::invalid_coeff_modulus_size: + return "coeff_modulus's primes' count is not bounded by SEAL_COEFF_MOD_COUNT_MIN(MAX)"; + + case error_type::invalid_coeff_modulus_bit_count: + return "coeff_modulus's primes' bit counts are not bounded by SEAL_USER_MOD_BIT_COUNT_MIN(MAX)"; + + case error_type::invalid_coeff_modulus_no_ntt: + return "coeff_modulus's primes are not congruent to 1 modulo (2 * poly_modulus_degree)"; + + case error_type::invalid_poly_modulus_degree: + return "poly_modulus_degree is not bounded by SEAL_POLY_MOD_DEGREE_MIN(MAX)"; + + case error_type::invalid_poly_modulus_degree_non_power_of_two: + return "poly_modulus_degree is not a power of two"; + + case error_type::invalid_parameters_too_large: + return "parameters are too large to fit in size_t type"; + + case error_type::invalid_parameters_insecure: + return "parameters are not compliant with HomomorphicEncryption.org security standard"; + + case error_type::failed_creating_rns_base: + return "RNSBase cannot be constructed"; + + case error_type::invalid_plain_modulus_bit_count: + return "plain_modulus's bit count is not bounded by SEAL_PLAIN_MOD_BIT_COUNT_MIN(MAX)"; + + case error_type::invalid_plain_modulus_coprimality: + return "plain_modulus is not coprime to coeff_modulus"; + + case error_type::invalid_plain_modulus_too_large: + return "plain_modulus is not smaller than coeff_modulus"; + + case error_type::invalid_plain_modulus_nonzero: + return "plain_modulus is not zero"; + + case error_type::failed_creating_rns_tool: + return "RNSTool cannot be constructed"; + + default: + return "invalid parameter_error"; + } + } + + SEALContext::ContextData SEALContext::validate(EncryptionParameters parms) + { + ContextData context_data(parms, pool_); + context_data.qualifiers_.parameter_error = error_type::success; + + // Is a scheme set? + if (parms.scheme() == scheme_type::none) + { + context_data.qualifiers_.parameter_error = error_type::invalid_scheme; + return context_data; + } + + auto &coeff_modulus = parms.coeff_modulus(); + auto &plain_modulus = parms.plain_modulus(); + + // The number of coeff moduli is restricted to 64 to prevent unexpected behaviors + if (coeff_modulus.size() > SEAL_COEFF_MOD_COUNT_MAX || coeff_modulus.size() < SEAL_COEFF_MOD_COUNT_MIN) + { + context_data.qualifiers_.parameter_error = error_type::invalid_coeff_modulus_size; + return context_data; + } + + size_t coeff_modulus_size = coeff_modulus.size(); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Check coefficient moduli bounds + if (coeff_modulus[i].value() >> SEAL_USER_MOD_BIT_COUNT_MAX || + !(coeff_modulus[i].value() >> (SEAL_USER_MOD_BIT_COUNT_MIN - 1))) + { + context_data.qualifiers_.parameter_error = error_type::invalid_coeff_modulus_bit_count; + return context_data; + } + } + + // Compute the product of all coeff moduli + context_data.total_coeff_modulus_ = allocate_uint(coeff_modulus_size, pool_); + auto coeff_modulus_values(allocate_uint(coeff_modulus_size, pool_)); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + coeff_modulus_values[i] = coeff_modulus[i].value(); + } + multiply_many_uint64( + coeff_modulus_values.get(), coeff_modulus_size, context_data.total_coeff_modulus_.get(), pool_); + context_data.total_coeff_modulus_bit_count_ = + get_significant_bit_count_uint(context_data.total_coeff_modulus_.get(), coeff_modulus_size); + + // Check polynomial modulus degree and create poly_modulus + size_t poly_modulus_degree = parms.poly_modulus_degree(); + if (poly_modulus_degree < SEAL_POLY_MOD_DEGREE_MIN || poly_modulus_degree > SEAL_POLY_MOD_DEGREE_MAX) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_poly_modulus_degree; + return context_data; + } + int coeff_count_power = get_power_of_two(poly_modulus_degree); + if (coeff_count_power < 0) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_poly_modulus_degree_non_power_of_two; + return context_data; + } + + // Quick sanity check + if (!product_fits_in(coeff_modulus_size, poly_modulus_degree)) + { + context_data.qualifiers_.parameter_error = error_type::invalid_parameters_too_large; + return context_data; + } + + // Polynomial modulus X^(2^k) + 1 is guaranteed at this point + context_data.qualifiers_.using_fft = true; + + // Assume parameters satisfy desired security level + context_data.qualifiers_.sec_level = sec_level_; + + // Check if the parameters are secure according to HomomorphicEncryption.org security standard + if (context_data.total_coeff_modulus_bit_count_ > CoeffModulus::MaxBitCount(poly_modulus_degree, sec_level_)) + { + // Not secure according to HomomorphicEncryption.org security standard + context_data.qualifiers_.sec_level = sec_level_type::none; + if (sec_level_ != sec_level_type::none) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_parameters_insecure; + return context_data; + } + } + + // Set up RNSBase for coeff_modulus + // RNSBase's constructor may fail due to: + // (1) coeff_mod not coprime + // (2) cannot find inverse of punctured products (because of (1)) + Pointer<RNSBase> coeff_modulus_base; + try + { + coeff_modulus_base = allocate<RNSBase>(pool_, coeff_modulus, pool_); + } + catch (const invalid_argument &) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::failed_creating_rns_base; + return context_data; + } + + // Can we use NTT with coeff_modulus? + context_data.qualifiers_.using_ntt = true; + try + { + CreateNTTTables(coeff_count_power, coeff_modulus, context_data.small_ntt_tables_, pool_); + } + catch (const invalid_argument &) + { + context_data.qualifiers_.using_ntt = false; + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_coeff_modulus_no_ntt; + return context_data; + } + + if (parms.scheme() == scheme_type::BFV) + { + // Plain modulus must be at least 2 and at most 60 bits + if (plain_modulus.value() >> SEAL_PLAIN_MOD_BIT_COUNT_MAX || + !(plain_modulus.value() >> (SEAL_PLAIN_MOD_BIT_COUNT_MIN - 1))) + { + context_data.qualifiers_.parameter_error = error_type::invalid_plain_modulus_bit_count; + return context_data; + } + + // Check that all coeff moduli are relatively prime to plain_modulus + for (size_t i = 0; i < coeff_modulus_size; i++) + { + if (!are_coprime(coeff_modulus[i].value(), plain_modulus.value())) + { + context_data.qualifiers_.parameter_error = error_type::invalid_plain_modulus_coprimality; + return context_data; + } + } + + // Check that plain_modulus is smaller than total coeff modulus + if (!is_less_than_uint_uint( + plain_modulus.data(), plain_modulus.uint64_count(), context_data.total_coeff_modulus_.get(), + coeff_modulus_size)) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_plain_modulus_too_large; + return context_data; + } + + // Can we use batching? (NTT with plain_modulus) + context_data.qualifiers_.using_batching = true; + try + { + CreateNTTTables(coeff_count_power, { plain_modulus }, context_data.plain_ntt_tables_, pool_); + } + catch (const invalid_argument &) + { + context_data.qualifiers_.using_batching = false; + } + + // Check for plain_lift + // If all the small coefficient moduli are larger than plain modulus, we can quickly + // lift plain coefficients to RNS form + context_data.qualifiers_.using_fast_plain_lift = true; + for (size_t i = 0; i < coeff_modulus_size; i++) + { + context_data.qualifiers_.using_fast_plain_lift &= (coeff_modulus[i].value() > plain_modulus.value()); + } + + // Calculate coeff_div_plain_modulus (BFV-"Delta") and the remainder upper_half_increment + context_data.coeff_div_plain_modulus_ = allocate_uint(coeff_modulus_size, pool_); + context_data.upper_half_increment_ = allocate_uint(coeff_modulus_size, pool_); + auto wide_plain_modulus(duplicate_uint_if_needed( + plain_modulus.data(), plain_modulus.uint64_count(), coeff_modulus_size, false, pool_)); + divide_uint_uint( + context_data.total_coeff_modulus_.get(), wide_plain_modulus.get(), coeff_modulus_size, + context_data.coeff_div_plain_modulus_.get(), context_data.upper_half_increment_.get(), pool_); + + // Store the non-RNS form of upper_half_increment for BFV encryption + context_data.coeff_modulus_mod_plain_modulus_ = context_data.upper_half_increment_[0]; + + // Decompose coeff_div_plain_modulus into RNS factors + coeff_modulus_base->decompose(context_data.coeff_div_plain_modulus_.get(), pool_); + + // Decompose upper_half_increment into RNS factors + coeff_modulus_base->decompose(context_data.upper_half_increment_.get(), pool_); + + // Calculate (plain_modulus + 1) / 2. + context_data.plain_upper_half_threshold_ = (plain_modulus.value() + 1) >> 1; + + // Calculate coeff_modulus - plain_modulus. + context_data.plain_upper_half_increment_ = allocate_uint(coeff_modulus_size, pool_); + if (context_data.qualifiers_.using_fast_plain_lift) + { + // Calculate coeff_modulus[i] - plain_modulus if using_fast_plain_lift + for (size_t i = 0; i < coeff_modulus_size; i++) + { + context_data.plain_upper_half_increment_[i] = coeff_modulus[i].value() - plain_modulus.value(); + } + } + else + { + sub_uint_uint( + context_data.total_coeff_modulus(), wide_plain_modulus.get(), coeff_modulus_size, + context_data.plain_upper_half_increment_.get()); + } + } + else if (parms.scheme() == scheme_type::CKKS) + { + // Check that plain_modulus is set to zero + if (!plain_modulus.is_zero()) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::invalid_plain_modulus_nonzero; + return context_data; + } + + // When using CKKS batching (BatchEncoder) is always enabled + context_data.qualifiers_.using_batching = true; + + // Cannot use fast_plain_lift for CKKS since the plaintext coefficients + // can easily be larger than coefficient moduli + context_data.qualifiers_.using_fast_plain_lift = false; + + // Calculate 2^64 / 2 (most negative plaintext coefficient value) + context_data.plain_upper_half_threshold_ = uint64_t(1) << 63; + + // Calculate plain_upper_half_increment = 2^64 mod coeff_modulus for CKKS plaintexts + context_data.plain_upper_half_increment_ = allocate_uint(coeff_modulus_size, pool_); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + uint64_t tmp = (uint64_t(1) << 63) % coeff_modulus[i].value(); + context_data.plain_upper_half_increment_[i] = + multiply_uint_uint_mod(tmp, sub_safe(coeff_modulus[i].value(), uint64_t(2)), coeff_modulus[i]); + } + + // Compute the upper_half_threshold for this modulus. + context_data.upper_half_threshold_ = allocate_uint(coeff_modulus_size, pool_); + increment_uint( + context_data.total_coeff_modulus(), coeff_modulus_size, context_data.upper_half_threshold_.get()); + right_shift_uint( + context_data.upper_half_threshold_.get(), 1, coeff_modulus_size, + context_data.upper_half_threshold_.get()); + } + else + { + context_data.qualifiers_.parameter_error = error_type::invalid_scheme; + return context_data; + } + + // Create RNSTool + // RNSTool's constructor may fail due to: + // (1) auxiliary base being too large + // (2) cannot find inverse of punctured products in auxiliary base + try + { + context_data.rns_tool_ = + allocate<RNSTool>(pool_, poly_modulus_degree, *coeff_modulus_base, plain_modulus, pool_); + } + catch (const exception &) + { + // Parameters are not valid + context_data.qualifiers_.parameter_error = error_type::failed_creating_rns_tool; + return context_data; + } + + // Check whether the coefficient modulus consists of a set of primes that are in decreasing order + context_data.qualifiers_.using_descending_modulus_chain = true; + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + { + context_data.qualifiers_.using_descending_modulus_chain &= + (coeff_modulus[i].value() > coeff_modulus[i + 1].value()); + } + + // Create GaloisTool + context_data.galois_tool_ = allocate<GaloisTool>(pool_, coeff_count_power, pool_); + + // Check whether the coefficient modulus consists of a set of primes that are in decreasing order + context_data.qualifiers_.using_descending_modulus_chain = true; + for (size_t i = 0; i < coeff_modulus_size - 1; i++) + { + context_data.qualifiers_.using_descending_modulus_chain &= + (coeff_modulus[i].value() > coeff_modulus[i + 1].value()); + } + + // Done with validation and pre-computations + return context_data; + } + + parms_id_type SEALContext::create_next_context_data(const parms_id_type &prev_parms_id) + { + // Create the next set of parameters by removing last modulus + auto next_parms = context_data_map_.at(prev_parms_id)->parms_; + auto next_coeff_modulus = next_parms.coeff_modulus(); + next_coeff_modulus.pop_back(); + next_parms.set_coeff_modulus(next_coeff_modulus); + auto next_parms_id = next_parms.parms_id(); + + // Validate next parameters and create next context_data + auto next_context_data = validate(next_parms); + + // If not valid then return zero parms_id + if (!next_context_data.qualifiers_.parameters_set()) + { + return parms_id_zero; + } + + // Add them to the context_data_map_ + context_data_map_.emplace(make_pair(next_parms_id, make_shared<const ContextData>(move(next_context_data)))); + + // Add pointer to next context_data to the previous one (linked list) + // Add pointer to previous context_data to the next one (doubly linked list) + // We need to remove constness first to modify this + const_pointer_cast<ContextData>(context_data_map_.at(prev_parms_id))->next_context_data_ = + context_data_map_.at(next_parms_id); + const_pointer_cast<ContextData>(context_data_map_.at(next_parms_id))->prev_context_data_ = + context_data_map_.at(prev_parms_id); + + return next_parms_id; + } + + SEALContext::SEALContext( + EncryptionParameters parms, bool expand_mod_chain, sec_level_type sec_level, MemoryPoolHandle pool) + : pool_(move(pool)), sec_level_(sec_level) + { + if (!pool_) + { + throw invalid_argument("pool is uninitialized"); + } + + // Set random generator + if (!parms.random_generator()) + { + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + } + + // Validate parameters and add new ContextData to the map + // Note that this happens even if parameters are not valid + + // First create key_parms_id_. + context_data_map_.emplace(make_pair(parms.parms_id(), make_shared<const ContextData>(validate(parms)))); + key_parms_id_ = parms.parms_id(); + + // Then create first_parms_id_ if the parameters are valid and there is + // more than one modulus in coeff_modulus. This is equivalent to expanding + // the chain by one step. Otherwise, we set first_parms_id_ to equal + // key_parms_id_. + if (!context_data_map_.at(key_parms_id_)->qualifiers_.parameters_set() || parms.coeff_modulus().size() == 1) + { + first_parms_id_ = key_parms_id_; + } + else + { + auto next_parms_id = create_next_context_data(key_parms_id_); + first_parms_id_ = (next_parms_id == parms_id_zero) ? key_parms_id_ : next_parms_id; + } + + // Set last_parms_id_ to point to first_parms_id_ + last_parms_id_ = first_parms_id_; + + // Check if keyswitching is available + using_keyswitching_ = (first_parms_id_ != key_parms_id_); + + // If modulus switching chain is to be created, compute the remaining parameter sets as long as they are valid + // to use (i.e., parameters_set() == true). + if (expand_mod_chain && context_data_map_.at(first_parms_id_)->qualifiers_.parameters_set()) + { + auto prev_parms_id = first_parms_id_; + while (context_data_map_.at(prev_parms_id)->parms().coeff_modulus().size() > 1) + { + auto next_parms_id = create_next_context_data(prev_parms_id); + if (next_parms_id == parms_id_zero) + { + break; + } + prev_parms_id = next_parms_id; + last_parms_id_ = next_parms_id; + } + } + + // Set the chain_index for each context_data + size_t parms_count = context_data_map_.size(); + auto context_data_ptr = context_data_map_.at(key_parms_id_); + while (context_data_ptr) + { + // We need to remove constness first to modify this + const_pointer_cast<ContextData>(context_data_ptr)->chain_index_ = --parms_count; + context_data_ptr = context_data_ptr->next_context_data_; + } + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/context.h b/bigpiseal3.5.1/native/src/seal/context.h new file mode 100644 index 0000000000000000000000000000000000000000..1b6e6ae3459eb66b8366a9be3d87d6b8affc2f3a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/context.h @@ -0,0 +1,666 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/encryptionparams.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/util/galois.h" +#include "seal/util/ntt.h" +#include "seal/util/numth.h" +#include "seal/util/pointer.h" +#include "seal/util/rns.h" +#include <functional> +#include <memory> +#include <unordered_map> + +namespace seal +{ + /** + Stores a set of attributes (qualifiers) of a set of encryption parameters. + These parameters are mainly used internally in various parts of the library, + e.g., to determine which algorithmic optimizations the current support. The + qualifiers are automatically created by the SEALContext class, silently passed + on to classes such as Encryptor, Evaluator, and Decryptor, and the only way to + change them is by changing the encryption parameters themselves. In other + words, a user will never have to create their own instance of this class, and + in most cases never have to worry about it at all. + */ + class EncryptionParameterQualifiers + { + public: + /** + Identifies the reason why encryption parameters are not valid. + */ + enum class error_type : int + { + /** + constructed but not yet validated + */ + none = -1, + + /** + valid + */ + success = 0, + + /** + scheme must be BFV or CKKS + */ + invalid_scheme = 1, + + /** + coeff_modulus's primes' count is not bounded by SEAL_COEFF_MOD_COUNT_MIN(MAX) + */ + invalid_coeff_modulus_size = 2, + + /** + coeff_modulus's primes' bit counts are not bounded by SEAL_USER_MOD_BIT_COUNT_MIN(MAX) + */ + invalid_coeff_modulus_bit_count = 3, + + /** + coeff_modulus's primes are not congruent to 1 modulo (2 * poly_modulus_degree) + */ + invalid_coeff_modulus_no_ntt = 4, + + /** + poly_modulus_degree is not bounded by SEAL_POLY_MOD_DEGREE_MIN(MAX) + */ + invalid_poly_modulus_degree = 5, + + /** + poly_modulus_degree is not a power of two + */ + invalid_poly_modulus_degree_non_power_of_two = 6, + + /** + parameters are too large to fit in size_t type + */ + invalid_parameters_too_large = 7, + + /** + parameters are not compliant with HomomorphicEncryption.org security standard + */ + invalid_parameters_insecure = 8, + + /** + RNSBase cannot be constructed + */ + failed_creating_rns_base = 9, + + /** + plain_modulus's bit count is not bounded by SEAL_PLAIN_MOD_BIT_COUNT_MIN(MAX) + */ + invalid_plain_modulus_bit_count = 10, + + /** + plain_modulus is not coprime to coeff_modulus + */ + invalid_plain_modulus_coprimality = 11, + + /** + plain_modulus is not smaller than coeff_modulus + */ + invalid_plain_modulus_too_large = 12, + + /** + plain_modulus is not zero + */ + invalid_plain_modulus_nonzero = 13, + + /** + RNSTool cannot be constructed + */ + failed_creating_rns_tool = 14, + }; + + /** + The variable parameter_error is set to: + - none, if parameters are not validated; + - success, if parameters are considered valid by Microsoft SEAL; + - other values, if parameters are validated and invalid. + */ + error_type parameter_error; + + /** + Returns the name of parameter_error. + */ + SEAL_NODISCARD const char *parameter_error_name() const noexcept; + + /** + Returns a comprehensive message that interprets parameter_error. + */ + SEAL_NODISCARD const char *parameter_error_message() const noexcept; + + /** + Tells whether parameter_error is error_type::success. + */ + SEAL_NODISCARD inline bool parameters_set() const noexcept + { + return parameter_error == error_type::success; + } + + /** + Tells whether FFT can be used for polynomial multiplication. If the + polynomial modulus is of the form X^N+1, where N is a power of two, then + FFT can be used for fast multiplication of polynomials modulo the polynomial + modulus. In this case the variable using_fft will be set to true. However, + currently Microsoft SEAL requires this to be the case for the parameters + to be valid. Therefore, parameters_set can only be true if using_fft is + true. + */ + bool using_fft; + + /** + Tells whether NTT can be used for polynomial multiplication. If the primes + in the coefficient modulus are congruent to 1 modulo 2N, where X^N+1 is the + polynomial modulus and N is a power of two, then the number-theoretic + transform (NTT) can be used for fast multiplications of polynomials modulo + the polynomial modulus and coefficient modulus. In this case the variable + using_ntt will be set to true. However, currently Microsoft SEAL requires + this to be the case for the parameters to be valid. Therefore, parameters_set + can only be true if using_ntt is true. + */ + bool using_ntt; + + /** + Tells whether batching is supported by the encryption parameters. If the + plaintext modulus is congruent to 1 modulo 2N, where X^N+1 is the polynomial + modulus and N is a power of two, then it is possible to use the BatchEncoder + class to view plaintext elements as 2-by-(N/2) matrices of integers modulo + the plaintext modulus. This is called batching, and allows the user to + operate on the matrix elements (slots) in a SIMD fashion, and rotate the + matrix rows and columns. When the computation is easily vectorizable, using + batching can yield a huge performance boost. If the encryption parameters + support batching, the variable using_batching is set to true. + */ + bool using_batching; + + /** + Tells whether fast plain lift is supported by the encryption parameters. + A certain performance optimization in multiplication of a ciphertext by + a plaintext (Evaluator::multiply_plain) and in transforming a plaintext + element to NTT domain (Evaluator::transform_to_ntt) can be used when the + plaintext modulus is smaller than each prime in the coefficient modulus. + In this case the variable using_fast_plain_lift is set to true. + */ + bool using_fast_plain_lift; + + /** + Tells whether the coefficient modulus consists of a set of primes that + are in decreasing order. If this is true, certain modular reductions in + base conversion can be omitted, improving performance. + */ + bool using_descending_modulus_chain; + + /** + Tells whether the encryption parameters are secure based on the standard + parameters from HomomorphicEncryption.org security standard. + */ + sec_level_type sec_level; + + private: + EncryptionParameterQualifiers() + : parameter_error(error_type::none), using_fft(false), using_ntt(false), using_batching(false), + using_fast_plain_lift(false), using_descending_modulus_chain(false), sec_level(sec_level_type::none) + {} + + friend class SEALContext; + }; + + /** + Performs sanity checks (validation) and pre-computations for a given set of encryption + parameters. While the EncryptionParameters class is intended to be a light-weight class + to store the encryption parameters, the SEALContext class is a heavy-weight class that + is constructed from a given set of encryption parameters. It validates the parameters + for correctness, evaluates their properties, and performs and stores the results of + several costly pre-computations. + + After the user has set at least the poly_modulus, coeff_modulus, and plain_modulus + parameters in a given EncryptionParameters instance, the parameters can be validated + for correctness and functionality by constructing an instance of SEALContext. The + constructor of SEALContext does all of its work automatically, and concludes by + constructing and storing an instance of the EncryptionParameterQualifiers class, with + its flags set according to the properties of the given parameters. If the created + instance of EncryptionParameterQualifiers has the parameters_set flag set to true, the + given parameter set has been deemed valid and is ready to be used. If the parameters + were for some reason not appropriately set, the parameters_set flag will be false, + and a new SEALContext will have to be created after the parameters are corrected. + + By default, SEALContext creates a chain of SEALContext::ContextData instances. The + first one in the chain corresponds to special encryption parameters that are reserved + to be used by the various key classes (SecretKey, PublicKey, etc.). These are the exact + same encryption parameters that are created by the user and passed to th constructor of + SEALContext. The functions key_context_data() and key_parms_id() return the ContextData + and the parms_id corresponding to these special parameters. The rest of the ContextData + instances in the chain correspond to encryption parameters that are derived from the + first encryption parameters by always removing the last one of the moduli in the + coeff_modulus, until the resulting parameters are no longer valid, e.g., there are no + more primes left. These derived encryption parameters are used by ciphertexts and + plaintexts and their respective ContextData can be accessed through the + get_context_data(parms_id_type) function. The functions first_context_data() and + last_context_data() return the ContextData corresponding to the first and the last + set of parameters in the "data" part of the chain, i.e., the second and the last element + in the full chain. The chain itself is a doubly linked list, and is referred to as the + modulus switching chain. + + @see EncryptionParameters for more details on the parameters. + @see EncryptionParameterQualifiers for more details on the qualifiers. + */ + class SEALContext + { + public: + /** + Class to hold pre-computation data for a given set of encryption parameters. + */ + class ContextData + { + friend class SEALContext; + + public: + ContextData() = delete; + + ContextData(const ContextData &copy) = delete; + + ContextData(ContextData &&move) = default; + + ContextData &operator=(ContextData &&move) = default; + + /** + Returns a const reference to the underlying encryption parameters. + */ + SEAL_NODISCARD inline auto &parms() const noexcept + { + return parms_; + } + + /** + Returns the parms_id of the current parameters. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return parms_.parms_id(); + } + + /** + Returns a copy of EncryptionParameterQualifiers corresponding to the + current encryption parameters. Note that to change the qualifiers it is + necessary to create a new instance of SEALContext once appropriate changes + to the encryption parameters have been made. + */ + SEAL_NODISCARD inline auto qualifiers() const noexcept + { + return qualifiers_; + } + + /** + Returns a pointer to a pre-computed product of all primes in the coefficient + modulus. The security of the encryption parameters largely depends on the + bit-length of this product, and on the degree of the polynomial modulus. + */ + SEAL_NODISCARD inline auto total_coeff_modulus() const noexcept + { + return total_coeff_modulus_.get(); + } + + /** + Returns the significant bit count of the total coefficient modulus. + */ + SEAL_NODISCARD inline int total_coeff_modulus_bit_count() const noexcept + { + return total_coeff_modulus_bit_count_; + } + + /** + Returns a constant pointer to the RNSTool. + */ + SEAL_NODISCARD inline auto rns_tool() const noexcept + { + return rns_tool_.get(); + } + + /** + Returns a constant pointer to the NTT tables. + */ + SEAL_NODISCARD inline auto small_ntt_tables() const noexcept + { + return small_ntt_tables_.get(); + } + + /** + Returns a constant pointer to the NTT tables. + */ + SEAL_NODISCARD inline auto plain_ntt_tables() const noexcept + { + return plain_ntt_tables_.get(); + } + + /** + Returns a constant pointer to the GaloisTool. + */ + SEAL_NODISCARD inline auto galois_tool() const noexcept + { + return galois_tool_.get(); + } + + /** + Return a pointer to BFV "Delta", i.e. coefficient modulus divided by + plaintext modulus. + */ + SEAL_NODISCARD inline auto coeff_div_plain_modulus() const noexcept + { + return coeff_div_plain_modulus_.get(); + } + + /** + Return the threshold for the upper half of integers modulo plain_modulus. + This is simply (plain_modulus + 1) / 2. + */ + SEAL_NODISCARD inline auto plain_upper_half_threshold() const noexcept + { + return plain_upper_half_threshold_; + } + + /** + Return a pointer to the plaintext upper half increment, i.e. coeff_modulus + minus plain_modulus. The upper half increment is represented as an integer + for the full product coeff_modulus if using_fast_plain_lift is false and is + otherwise represented modulo each of the coeff_modulus primes in order. + */ + SEAL_NODISCARD inline auto plain_upper_half_increment() const noexcept + { + return plain_upper_half_increment_.get(); + } + + /** + Return a pointer to the upper half threshold with respect to the total + coefficient modulus. This is needed in CKKS decryption. + */ + SEAL_NODISCARD inline auto upper_half_threshold() const noexcept + { + return upper_half_threshold_.get(); + } + + /** + Return a pointer to the upper half increment used for computing Delta*m + and converting the coefficients to modulo coeff_modulus. For example, + t-1 in plaintext should change into + q - Delta = Delta*t + r_t(q) - Delta + = Delta*(t-1) + r_t(q) + so multiplying the message by Delta is not enough and requires also an + addition of r_t(q). This is precisely the upper_half_increment. Note that + this operation is only done for negative message coefficients, i.e. those + that exceed plain_upper_half_threshold. + */ + SEAL_NODISCARD inline auto upper_half_increment() const noexcept + { + return upper_half_increment_.get(); + } + + /** + Return the non-RNS form of upppoer_half_increment which is q mod t. + */ + SEAL_NODISCARD inline auto coeff_modulus_mod_plain_modulus() const noexcept -> std::uint64_t + { + return coeff_modulus_mod_plain_modulus_; + } + + /** + Returns a shared_ptr to the context data corresponding to the previous parameters + in the modulus switching chain. If the current data is the first one in the + chain, then the result is nullptr. + */ + SEAL_NODISCARD inline auto prev_context_data() const noexcept + { + return prev_context_data_.lock(); + } + + /** + Returns a shared_ptr to the context data corresponding to the next parameters + in the modulus switching chain. If the current data is the last one in the + chain, then the result is nullptr. + */ + SEAL_NODISCARD inline auto next_context_data() const noexcept + { + return next_context_data_; + } + + /** + Returns the index of the parameter set in a chain. The initial parameters + have index 0 and the index increases sequentially in the parameter chain. + */ + SEAL_NODISCARD inline std::size_t chain_index() const noexcept + { + return chain_index_; + } + + private: + ContextData(EncryptionParameters parms, MemoryPoolHandle pool) : pool_(std::move(pool)), parms_(parms) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + } + + MemoryPoolHandle pool_; + + EncryptionParameters parms_; + + EncryptionParameterQualifiers qualifiers_; + + util::Pointer<util::RNSTool> rns_tool_; + + util::Pointer<util::NTTTables> small_ntt_tables_; + + util::Pointer<util::NTTTables> plain_ntt_tables_; + + util::Pointer<util::GaloisTool> galois_tool_; + + util::Pointer<std::uint64_t> total_coeff_modulus_; + + int total_coeff_modulus_bit_count_ = 0; + + util::Pointer<std::uint64_t> coeff_div_plain_modulus_; + + std::uint64_t plain_upper_half_threshold_ = 0; + + util::Pointer<std::uint64_t> plain_upper_half_increment_; + + util::Pointer<std::uint64_t> upper_half_threshold_; + + util::Pointer<std::uint64_t> upper_half_increment_; + + std::uint64_t coeff_modulus_mod_plain_modulus_ = 0; + + std::weak_ptr<const ContextData> prev_context_data_; + + std::shared_ptr<const ContextData> next_context_data_{ nullptr }; + + std::size_t chain_index_ = 0; + }; + + SEALContext() = delete; + + /** + Creates an instance of SEALContext and performs several pre-computations + on the given EncryptionParameters. + + @param[in] parms The encryption parameters + @param[in] expand_mod_chain Determines whether the modulus switching chain + should be created + @param[in] sec_level Determines whether a specific security level should be + enforced according to HomomorphicEncryption.org security standard + */ + SEAL_NODISCARD static auto Create( + const EncryptionParameters &parms, bool expand_mod_chain = true, + sec_level_type sec_level = sec_level_type::tc128) + { + return std::shared_ptr<SEALContext>( + new SEALContext(parms, expand_mod_chain, sec_level, MemoryManager::GetPool())); + } + + /** + Returns the ContextData corresponding to encryption parameters with a given + parms_id. If parameters with the given parms_id are not found then the + function returns nullptr. + + @param[in] parms_id The parms_id of the encryption parameters + */ + SEAL_NODISCARD inline auto get_context_data(parms_id_type parms_id) const + { + auto data = context_data_map_.find(parms_id); + return (data != context_data_map_.end()) ? data->second : std::shared_ptr<ContextData>{ nullptr }; + } + + /** + Returns the ContextData corresponding to encryption parameters that are + used for keys. + */ + SEAL_NODISCARD inline auto key_context_data() const + { + auto data = context_data_map_.find(key_parms_id_); + return (data != context_data_map_.end()) ? data->second : std::shared_ptr<ContextData>{ nullptr }; + } + + /** + Returns the ContextData corresponding to the first encryption parameters + that are used for data. + */ + SEAL_NODISCARD inline auto first_context_data() const + { + auto data = context_data_map_.find(first_parms_id_); + return (data != context_data_map_.end()) ? data->second : std::shared_ptr<ContextData>{ nullptr }; + } + + /** + Returns the ContextData corresponding to the last encryption parameters + that are used for data. + */ + SEAL_NODISCARD inline auto last_context_data() const + { + auto data = context_data_map_.find(last_parms_id_); + return (data != context_data_map_.end()) ? data->second : std::shared_ptr<ContextData>{ nullptr }; + } + + /** + Returns whether the first_context_data's encryption parameters are valid. + */ + SEAL_NODISCARD inline auto parameters_set() const + { + return first_context_data() ? first_context_data()->qualifiers_.parameters_set() : false; + } + + /** + Returns the name of encryption parameters' error. + */ + SEAL_NODISCARD inline const char *parameter_error_name() const + { + return first_context_data() ? first_context_data()->qualifiers_.parameter_error_name() + : "SEALContext is empty"; + } + + /** + Returns a comprehensive message that interprets encryption parameters' error. + */ + SEAL_NODISCARD inline const char *parameter_error_message() const + { + return first_context_data() ? first_context_data()->qualifiers_.parameter_error_message() + : "SEALContext is empty"; + } + + /** + Returns a parms_id_type corresponding to the set of encryption parameters + that are used for keys. + */ + SEAL_NODISCARD inline auto &key_parms_id() const noexcept + { + return key_parms_id_; + } + + /** + Returns a parms_id_type corresponding to the first encryption parameters + that are used for data. + */ + SEAL_NODISCARD inline auto &first_parms_id() const noexcept + { + return first_parms_id_; + } + + /** + Returns a parms_id_type corresponding to the last encryption parameters + that are used for data. + */ + SEAL_NODISCARD inline auto &last_parms_id() const noexcept + { + return last_parms_id_; + } + + /** + Returns whether the coefficient modulus supports keyswitching. In practice, + support for keyswitching is required by Evaluator::relinearize, + Evaluator::apply_galois, and all rotation and conjugation operations. For + keyswitching to be available, the coefficient modulus parameter must consist + of at least two prime number factors. + */ + SEAL_NODISCARD inline bool using_keyswitching() const noexcept + { + return using_keyswitching_; + } + + private: + SEALContext(const SEALContext &copy) = delete; + + SEALContext(SEALContext &&source) = delete; + + SEALContext &operator=(const SEALContext &assign) = delete; + + SEALContext &operator=(SEALContext &&assign) = delete; + + /** + Creates an instance of SEALContext, and performs several pre-computations + on the given EncryptionParameters. + + @param[in] parms The encryption parameters + @param[in] expand_mod_chain Determines whether the modulus switching chain + should be created + @param[in] sec_level Determines whether a specific security level should be + enforced according to HomomorphicEncryption.org security standard + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + SEALContext(EncryptionParameters parms, bool expand_mod_chain, sec_level_type sec_level, MemoryPoolHandle pool); + + ContextData validate(EncryptionParameters parms); + + /** + Create the next context_data by dropping the last element from coeff_modulus. + If the new encryption parameters are not valid, returns parms_id_zero. + Otherwise, returns the parms_id of the next parameter and appends the next + context_data to the chain. + */ + parms_id_type create_next_context_data(const parms_id_type &prev_parms); + + MemoryPoolHandle pool_; + + parms_id_type key_parms_id_; + + parms_id_type first_parms_id_; + + parms_id_type last_parms_id_; + + std::unordered_map<parms_id_type, std::shared_ptr<const ContextData>> context_data_map_{}; + + /** + Is HomomorphicEncryption.org security standard enforced? + */ + sec_level_type sec_level_; + + /** + Is keyswitching supported by the encryption parameters? + */ + bool using_keyswitching_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/decryptor.cpp b/bigpiseal3.5.1/native/src/seal/decryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f115d040e85785462dc194cc0a440d19ac6e203d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/decryptor.cpp @@ -0,0 +1,352 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/decryptor.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/polyarithmod.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/scalingvariant.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <stdexcept> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + Decryptor::Decryptor(shared_ptr<SEALContext> context, const SecretKey &secret_key) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + if (!is_valid_for(secret_key, context_)) + { + throw invalid_argument("secret key is not valid for encryption parameters"); + } + + auto &parms = context_->key_context_data()->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Set the secret_key_array to have size 1 (first power of secret) + // and copy over data + secret_key_array_ = allocate_poly(coeff_count, coeff_modulus_size, pool_); + set_poly_poly(secret_key.data().data(), coeff_count, coeff_modulus_size, secret_key_array_.get()); + secret_key_array_size_ = 1; + } + + void Decryptor::decrypt(const Ciphertext &encrypted, Plaintext &destination) + { + // Verify that encrypted is valid. + if (!is_valid_for(encrypted, context_)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto &context_data = *context_->first_context_data(); + auto &parms = context_data.parms(); + + switch (parms.scheme()) + { + case scheme_type::BFV: + bfv_decrypt(encrypted, destination, pool_); + return; + + case scheme_type::CKKS: + ckks_decrypt(encrypted, destination, pool_); + return; + + default: + throw invalid_argument("unsupported scheme"); + } + } + + void Decryptor::bfv_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool) + { + if (encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted cannot be in NTT form"); + } + + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Firstly find c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q + // This is equal to Delta m + v where ||v|| < Delta/2. + // Add Delta / 2 and now we have something which is Delta * (m + epsilon) where epsilon < 1 + // Therefore, we can (integer) divide by Delta and the answer will round down to m. + + // Make a temp destination for all the arithmetic mod qi before calling FastBConverse + auto tmp_dest_modq(allocate_zero_poly(coeff_count, coeff_modulus_size, pool)); + + // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination + // Now do the dot product of encrypted_copy and the secret key array using NTT. + // The secret key powers are already NTT transformed. + dot_product_ct_sk_array(encrypted, tmp_dest_modq.get(), pool_); + + // Allocate a full size destination to write to + destination.resize(coeff_count); + + // Divide scaling variant using BEHZ FullRNS techniques + context_data.rns_tool()->decrypt_scale_and_round(tmp_dest_modq.get(), destination.data(), pool); + + // How many non-zero coefficients do we really have in the result? + size_t plain_coeff_count = get_significant_uint64_count_uint(destination.data(), coeff_count); + + // Resize destination to appropriate size + destination.resize(max(plain_coeff_count, size_t(1))); + destination.parms_id() = parms_id_zero; + } + + void Decryptor::ckks_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool) + { + if (!encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted must be in NTT form"); + } + + // We already know that the parameters are valid + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t rns_poly_uint64_count = mul_safe(coeff_count, coeff_modulus_size); + + // Decryption consists in finding + // c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q_1 * q_2 * q_3 + // as long as ||m + v|| < q_1 * q_2 * q_3. + // This is equal to m + v where ||v|| is small enough. + + // Since we overwrite destination, we zeroize destination parameters + // This is necessary, otherwise resize will throw an exception. + destination.parms_id() = parms_id_zero; + + // Resize destination to appropriate size + destination.resize(rns_poly_uint64_count); + + // Make a temp destination for all the arithmetic mod q1, q2, q3 + // auto tmp_dest_modq(allocate_zero_poly(coeff_count, decryption_coeff_modulus_size, pool)); + // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination + // Now do the dot product of encrypted_copy and the secret key array using NTT. + // The secret key powers are already NTT transformed. + dot_product_ct_sk_array(encrypted, destination.data(), pool); + + // Set destination parameters as in encrypted + destination.parms_id() = encrypted.parms_id(); + destination.scale() = encrypted.scale(); + } + + void Decryptor::compute_secret_key_array(size_t max_power) + { +#ifdef SEAL_DEBUG + if (max_power < 1) + { + throw invalid_argument("max_power must be at least 1"); + } + if (!secret_key_array_size_ || !secret_key_array_) + { + throw logic_error("secret_key_array_ is uninitialized"); + } +#endif + // WARNING: This function must be called with the original context_data + auto &context_data = *context_->key_context_data(); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t key_rns_poly_uint64_count = mul_safe(coeff_count, coeff_modulus_size); + + ReaderLock reader_lock(secret_key_array_locker_.acquire_read()); + + size_t old_size = secret_key_array_size_; + size_t new_size = max(max_power, old_size); + + if (old_size == new_size) + { + return; + } + + reader_lock.unlock(); + + // Need to extend the array + // Compute powers of secret key until max_power + auto new_secret_key_array(allocate_poly(mul_safe(new_size, coeff_count), coeff_modulus_size, pool_)); + set_poly_poly(secret_key_array_.get(), old_size * coeff_count, coeff_modulus_size, new_secret_key_array.get()); + + set_poly_poly( + secret_key_array_.get(), mul_safe(old_size, coeff_count), coeff_modulus_size, new_secret_key_array.get()); + + uint64_t *prev_poly_ptr = new_secret_key_array.get() + mul_safe(old_size - 1, key_rns_poly_uint64_count); + uint64_t *next_poly_ptr = prev_poly_ptr + key_rns_poly_uint64_count; + + // Since all of the key powers in secret_key_array_ are already NTT transformed, + // to get the next one we simply need to compute a dyadic product of the last + // one with the first one [which is equal to NTT(secret_key_)]. + for (size_t i = old_size; i < new_size; i++) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + dyadic_product_coeffmod( + prev_poly_ptr + (j * coeff_count), new_secret_key_array.get() + (j * coeff_count), coeff_count, + coeff_modulus[j], next_poly_ptr + (j * coeff_count)); + } + prev_poly_ptr = next_poly_ptr; + next_poly_ptr += key_rns_poly_uint64_count; + } + + // Take writer lock to update array + WriterLock writer_lock(secret_key_array_locker_.acquire_write()); + + // Do we still need to update size? + old_size = secret_key_array_size_; + new_size = max(max_power, secret_key_array_size_); + + if (old_size == new_size) + { + return; + } + + // Acquire new array + secret_key_array_size_ = new_size; + secret_key_array_.acquire(new_secret_key_array); + } + + // Compute c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q. + // Store result in destination in RNS form. + void Decryptor::dot_product_ct_sk_array(const Ciphertext &encrypted, uint64_t *destination, MemoryPoolHandle pool) + { + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t rns_poly_uint64_count = mul_safe(coeff_count, coeff_modulus_size); + size_t key_rns_poly_uint64_count = + mul_safe(coeff_count, context_->key_context_data()->parms().coeff_modulus().size()); + size_t encrypted_size = encrypted.size(); + auto is_ntt_form = encrypted.is_ntt_form(); + + auto small_ntt_tables = context_data.small_ntt_tables(); + + // Make sure we have enough secret key powers computed + compute_secret_key_array(encrypted_size - 1); + + // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination + + // Now do the dot product of encrypted_copy and the secret key array using NTT. + // The secret key powers are already NTT transformed. + auto copy_operand1(allocate_uint(coeff_count, pool)); + + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Initialize pointers for multiplication + const uint64_t *encrypted_ptr = encrypted.data(1) + (i * coeff_count); + const uint64_t *secret_key_ptr = secret_key_array_.get() + (i * coeff_count); + uint64_t *destination_ptr = destination + (i * coeff_count); + set_zero_uint(coeff_count, destination_ptr); + for (size_t j = 0; j < encrypted_size - 1; j++) + { + set_uint_uint(encrypted_ptr, coeff_count, copy_operand1.get()); + if (!is_ntt_form) + { + ntt_negacyclic_harvey_lazy(copy_operand1.get(), small_ntt_tables[i]); + } + // compute c_{j+1} * s^{j+1} + dyadic_product_coeffmod( + copy_operand1.get(), secret_key_ptr, coeff_count, coeff_modulus[i], copy_operand1.get()); + // add c_{j+1} * s^{j+1} to destination + add_poly_poly_coeffmod( + destination_ptr, copy_operand1.get(), coeff_count, coeff_modulus[i], destination_ptr); + encrypted_ptr += rns_poly_uint64_count; + secret_key_ptr += key_rns_poly_uint64_count; + } + if (!is_ntt_form) + { + inverse_ntt_negacyclic_harvey(destination_ptr, small_ntt_tables[i]); + } + // add c_0 into destination + add_poly_poly_coeffmod( + destination_ptr, encrypted.data() + (i * coeff_count), coeff_count, coeff_modulus[i], destination_ptr); + } + } + + int Decryptor::invariant_noise_budget(const Ciphertext &encrypted) + { + // Verify that encrypted is valid. + if (!is_valid_for(encrypted, context_)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + if (context_->key_context_data()->parms().scheme() != scheme_type::BFV) + { + throw logic_error("unsupported scheme"); + } + if (encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted cannot be in NTT form"); + } + + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + auto &plain_modulus = parms.plain_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Storage for the infinity norm of noise poly + auto norm(allocate_uint(coeff_modulus_size, pool_)); + + // Storage for noise poly + auto noise_poly(allocate_zero_poly(coeff_count, coeff_modulus_size, pool_)); + + // Now need to compute c(s) - Delta*m (mod q) + // Firstly find c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q + // This is equal to Delta m + v where ||v|| < Delta/2. + // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q + // in destination_poly. + // Now do the dot product of encrypted_copy and the secret key array using NTT. + // The secret key powers are already NTT transformed. + dot_product_ct_sk_array(encrypted, noise_poly.get(), pool_); + + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Multiply by plain_modulus and reduce mod coeff_modulus to get + // coeff_modulus()*noise. + multiply_poly_scalar_coeffmod( + noise_poly.get() + i * coeff_count, coeff_count, plain_modulus.value(), coeff_modulus[i], + noise_poly.get() + i * coeff_count); + } + + // CRT-compose the noise + context_data.rns_tool()->base_q()->compose_array(noise_poly.get(), coeff_count, pool_); + + // Next we compute the infinity norm mod parms.coeff_modulus() + poly_infty_norm_coeffmod( + noise_poly.get(), coeff_count, coeff_modulus_size, context_data.total_coeff_modulus(), norm.get(), pool_); + + // The -1 accounts for scaling the invariant noise by 2; + // note that we already took plain_modulus into account in compose + // so no need to subtract log(plain_modulus) from this + int bit_count_diff = context_data.total_coeff_modulus_bit_count() - + get_significant_bit_count_uint(norm.get(), coeff_modulus_size) - 1; + return max(0, bit_count_diff); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/decryptor.h b/bigpiseal3.5.1/native/src/seal/decryptor.h new file mode 100644 index 0000000000000000000000000000000000000000..d212043d71251bb0c8038697a9888a401dba0d9b --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/decryptor.h @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/encryptionparams.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/plaintext.h" +#include "seal/randomgen.h" +#include "seal/secretkey.h" +#include "seal/util/defines.h" +#include "seal/util/locks.h" +#include "seal/util/ntt.h" +#include "seal/util/rns.h" +#include <memory> + +namespace seal +{ + /** + Decrypts Ciphertext objects into Plaintext objects. Constructing a Decryptor + requires a SEALContext with valid encryption parameters, and the secret key. + The Decryptor is also used to compute the invariant noise budget in a given + ciphertext. + + @par Overloads + For the decrypt function we provide two overloads concerning the memory pool + used in allocations needed during the operation. In one overload the global + memory pool is used for this purpose, and in another overload the user can + supply a MemoryPoolHandle to be used instead. This is to allow one single + Decryptor to be used concurrently by several threads without running into + thread contention in allocations taking place during operations. For example, + one can share one single Decryptor across any number of threads, but in each + thread call the decrypt function by giving it a thread-local MemoryPoolHandle + to use. It is important for a developer to understand how this works to avoid + unnecessary performance bottlenecks. + + + @par NTT form + When using the BFV scheme (scheme_type::BFV), all plaintext and ciphertexts + should remain by default in the usual coefficient representation, i.e. not in + NTT form. When using the CKKS scheme (scheme_type::CKKS), all plaintexts and + ciphertexts should remain by default in NTT form. We call these scheme-specific + NTT states the "default NTT form". Decryption requires the input ciphertexts + to be in the default NTT form, and will throw an exception if this is not the + case. + */ + class Decryptor + { + public: + /** + Creates a Decryptor instance initialized with the specified SEALContext + and secret key. + + @param[in] context The SEALContext + @param[in] secret_key The secret key + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if secret_key is not valid + */ + Decryptor(std::shared_ptr<SEALContext> context, const SecretKey &secret_key); + + /* + Decrypts a Ciphertext and stores the result in the destination parameter. + + @param[in] encrypted The ciphertext to decrypt + @param[out] destination The plaintext to overwrite with the decrypted + ciphertext + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + */ + void decrypt(const Ciphertext &encrypted, Plaintext &destination); + + /* + Computes the invariant noise budget (in bits) of a ciphertext. The + invariant noise budget measures the amount of room there is for the noise + to grow while ensuring correct decryptions. This function works only with + the BFV scheme. + + @par Invariant Noise Budget + The invariant noise polynomial of a ciphertext is a rational coefficient + polynomial, such that a ciphertext decrypts correctly as long as the + coefficients of the invariantnoise polynomial are of absolute value less + than 1/2. Thus, we call the infinity-norm of the invariant noise polynomial + the invariant noise, and for correct decryption requireit to be less than + 1/2. If v denotes the invariant noise, we define the invariant noise budget + as -log2(2v). Thus, the invariant noise budget starts from some initial + value, which depends on the encryption parameters, and decreases when + computations are performed. When the budget reaches zero, the ciphertext + becomes too noisy to decrypt correctly. + + @param[in] encrypted The ciphertext + @throws std::invalid_argument if the scheme is not BFV + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is in NTT form + */ + SEAL_NODISCARD int invariant_noise_budget(const Ciphertext &encrypted); + + private: + void bfv_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool); + + void ckks_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool); + + Decryptor(const Decryptor &copy) = delete; + + Decryptor(Decryptor &&source) = delete; + + Decryptor &operator=(const Decryptor &assign) = delete; + + Decryptor &operator=(Decryptor &&assign) = delete; + + void compute_secret_key_array(std::size_t max_power); + + // Compute c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q. + // Store result in destination in RNS form. + // destination has the size of an RNS polynomial. + void dot_product_ct_sk_array(const Ciphertext &encrypted, std::uint64_t *destination, MemoryPoolHandle pool); + + // We use a fresh memory pool with `clear_on_destruction' enabled. + MemoryPoolHandle pool_ = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true); + + std::shared_ptr<SEALContext> context_{ nullptr }; + + std::size_t secret_key_array_size_ = 0; + + util::Pointer<std::uint64_t> secret_key_array_; + + mutable util::ReaderWriterLocker secret_key_array_locker_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/encryptionparams.cpp b/bigpiseal3.5.1/native/src/seal/encryptionparams.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ac2d017fc31c1df8ba04211d3fc29007c0d80f7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/encryptionparams.cpp @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/encryptionparams.h" +#include "seal/util/uintcore.h" +#include <limits> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + const parms_id_type parms_id_zero = util::HashFunction::hash_zero_block; + + void EncryptionParameters::save_members(ostream &stream) const + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + auto old_except_mask = stream.exceptions(); + try + { + stream.exceptions(ios_base::badbit | ios_base::failbit); + + uint64_t poly_modulus_degree64 = static_cast<uint64_t>(poly_modulus_degree_); + uint64_t coeff_modulus_size64 = static_cast<uint64_t>(coeff_modulus_.size()); + uint8_t scheme = static_cast<uint8_t>(scheme_); + + stream.write(reinterpret_cast<const char *>(&scheme), sizeof(uint8_t)); + stream.write(reinterpret_cast<const char *>(&poly_modulus_degree64), sizeof(uint64_t)); + stream.write(reinterpret_cast<const char *>(&coeff_modulus_size64), sizeof(uint64_t)); + for (const auto &mod : coeff_modulus_) + { + mod.save(stream, compr_mode_type::none); + } + + // Only BFV uses plain_modulus but save it in any case for simplicity + plain_modulus_.save(stream, compr_mode_type::none); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void EncryptionParameters::load_members(istream &stream) + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + auto old_except_mask = stream.exceptions(); + try + { + stream.exceptions(ios_base::badbit | ios_base::failbit); + + // Read the scheme identifier + uint8_t scheme; + stream.read(reinterpret_cast<char *>(&scheme), sizeof(uint8_t)); + + // This constructor will throw if scheme is invalid + EncryptionParameters parms(scheme); + + // Read the poly_modulus_degree + uint64_t poly_modulus_degree64 = 0; + stream.read(reinterpret_cast<char *>(&poly_modulus_degree64), sizeof(uint64_t)); + + // Only check for upper bound; lower bound is zero for scheme_type::none + if (poly_modulus_degree64 > SEAL_POLY_MOD_DEGREE_MAX) + { + throw logic_error("poly_modulus_degree is invalid"); + } + + // Read the coeff_modulus size + uint64_t coeff_modulus_size64 = 0; + stream.read(reinterpret_cast<char *>(&coeff_modulus_size64), sizeof(uint64_t)); + + // Only check for upper bound; lower bound is zero for scheme_type::none + if (coeff_modulus_size64 > SEAL_COEFF_MOD_COUNT_MAX) + { + throw logic_error("coeff_modulus is invalid"); + } + + // Read the coeff_modulus + vector<Modulus> coeff_modulus; + for (uint64_t i = 0; i < coeff_modulus_size64; i++) + { + coeff_modulus.emplace_back(); + coeff_modulus.back().load(stream); + } + + // Read the plain_modulus + Modulus plain_modulus; + plain_modulus.load(stream); + + // Supposedly everything worked so set the values of member variables + parms.set_poly_modulus_degree(safe_cast<size_t>(poly_modulus_degree64)); + parms.set_coeff_modulus(coeff_modulus); + + // Only BFV uses plain_modulus; set_plain_modulus checks that for + // other schemes it is zero + parms.set_plain_modulus(plain_modulus); + + // Set the loaded parameters + swap(*this, parms); + + stream.exceptions(old_except_mask); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void EncryptionParameters::compute_parms_id() + { + size_t coeff_modulus_size = coeff_modulus_.size(); + + size_t total_uint64_count = add_safe( + size_t(1), // scheme + size_t(1), // poly_modulus_degree + coeff_modulus_size, plain_modulus_.uint64_count()); + + auto param_data(allocate_uint(total_uint64_count, pool_)); + uint64_t *param_data_ptr = param_data.get(); + + // Write the scheme identifier + *param_data_ptr++ = static_cast<uint64_t>(scheme_); + + // Write the poly_modulus_degree. Note that it will always be positive. + *param_data_ptr++ = static_cast<uint64_t>(poly_modulus_degree_); + + for (const auto &mod : coeff_modulus_) + { + *param_data_ptr++ = mod.value(); + } + + set_uint_uint(plain_modulus_.data(), plain_modulus_.uint64_count(), param_data_ptr); + param_data_ptr += plain_modulus_.uint64_count(); + + HashFunction::hash(param_data.get(), total_uint64_count, parms_id_); + + // Did we somehow manage to get a zero block as result? This is reserved for + // plaintexts to indicate non-NTT-transformed form. + if (parms_id_ == parms_id_zero) + { + throw logic_error("parms_id cannot be zero"); + } + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/encryptionparams.h b/bigpiseal3.5.1/native/src/seal/encryptionparams.h new file mode 100644 index 0000000000000000000000000000000000000000..3bc9c6a0ba18522be0d1c46499b19a3bbc6adeb9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/encryptionparams.h @@ -0,0 +1,522 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/randomgen.h" +#include "seal/serialization.h" +#include "seal/util/defines.h" +#include "seal/util/globals.h" +#include "seal/util/hash.h" +#include "seal/util/ztools.h" +#include <functional> +#include <iostream> +#include <memory> +#include <numeric> + +namespace seal +{ + /** + Describes the type of encryption scheme to be used. + */ + enum class scheme_type : std::uint8_t + { + // No scheme set; cannot be used for encryption + none = 0x0, + + // Brakerski/Fan-Vercauteren scheme + BFV = 0x1, + + // Cheon-Kim-Kim-Song scheme + CKKS = 0x2 + }; + + /** + The data type to store unique identifiers of encryption parameters. + */ + using parms_id_type = util::HashFunction::hash_block_type; + + /** + A parms_id_type value consisting of zeros. + */ + extern const parms_id_type parms_id_zero; + + /** + Represents user-customizable encryption scheme settings. The parameters (most + importantly poly_modulus, coeff_modulus, plain_modulus) significantly affect + the performance, capabilities, and security of the encryption scheme. Once + an instance of EncryptionParameters is populated with appropriate parameters, + it can be used to create an instance of the SEALContext class, which verifies + the validity of the parameters, and performs necessary pre-computations. + + Picking appropriate encryption parameters is essential to enable a particular + application while balancing performance and security. Some encryption settings + will not allow some inputs (e.g. attempting to encrypt a polynomial with more + coefficients than poly_modulus or larger coefficients than plain_modulus) or, + support the desired computations (with noise growing too fast due to too large + plain_modulus and too small coeff_modulus). + + @par parms_id + The EncryptionParameters class maintains at all times a 256-bit hash of the + currently set encryption parameters called the parms_id. This hash acts as + a unique identifier of the encryption parameters and is used by all further + objects created for these encryption parameters. The parms_id is not intended + to be directly modified by the user but is used internally for pre-computation + data lookup and input validity checks. In modulus switching the user can use + the parms_id to keep track of the chain of encryption parameters. The parms_id + is not exposed in the public API of EncryptionParameters, but can be accessed + through the SEALContext::ContextData class once the SEALContext has been created. + + @par Thread Safety + In general, reading from EncryptionParameters is thread-safe, while mutating + is not. + + @warning Choosing inappropriate encryption parameters may lead to an encryption + scheme that is not secure, does not perform well, and/or does not support the + input and computation of the desired application. We highly recommend consulting + an expert in RLWE-based encryption when selecting parameters, as this is where + inexperienced users seem to most often make critical mistakes. + */ + class EncryptionParameters + { + friend class SEALContext; + + public: + /** + Creates an empty set of encryption parameters. + + @param[in] scheme The encryption scheme to be used + @see scheme_type for the supported schemes + */ + EncryptionParameters(scheme_type scheme = scheme_type::none) : scheme_(scheme) + { + compute_parms_id(); + } + + /** + Creates an empty set of encryption parameters. + + @param[in] scheme The encryption scheme to be used + @throws std::invalid_argument if scheme is not supported + */ + EncryptionParameters(std::uint8_t scheme) + { + // Check that a valid scheme is given + if (!is_valid_scheme(scheme)) + { + throw std::invalid_argument("unsupported scheme"); + } + + scheme_ = static_cast<scheme_type>(scheme); + compute_parms_id(); + } + + /** + Creates a copy of a given instance of EncryptionParameters. + + @param[in] copy The EncryptionParameters to copy from + */ + EncryptionParameters(const EncryptionParameters &copy) = default; + + /** + Overwrites the EncryptionParameters instance with a copy of a given instance. + + @param[in] assign The EncryptionParameters to copy from + */ + EncryptionParameters &operator=(const EncryptionParameters &assign) = default; + + /** + Creates a new EncryptionParameters instance by moving a given instance. + + @param[in] source The EncryptionParameters to move from + */ + EncryptionParameters(EncryptionParameters &&source) = default; + + /** + Overwrites the EncryptionParameters instance by moving a given instance. + + @param[in] assign The EncryptionParameters to move from + */ + EncryptionParameters &operator=(EncryptionParameters &&assign) = default; + + /** + Sets the degree of the polynomial modulus parameter to the specified value. + The polynomial modulus directly affects the number of coefficients in + plaintext polynomials, the size of ciphertext elements, the computational + performance of the scheme (bigger is worse), and the security level (bigger + is better). In Microsoft SEAL the degree of the polynomial modulus must be + a power of 2 (e.g. 1024, 2048, 4096, 8192, 16384, or 32768). + + @param[in] poly_modulus_degree The new polynomial modulus degree + @throws std::logic_error if a valid scheme is not set and poly_modulus_degree + is non-zero + */ + inline void set_poly_modulus_degree(std::size_t poly_modulus_degree) + { + if (scheme_ == scheme_type::none && poly_modulus_degree) + { + throw std::logic_error("poly_modulus_degree is not supported for this scheme"); + } + + // Set the degree + poly_modulus_degree_ = poly_modulus_degree; + + // Re-compute the parms_id + compute_parms_id(); + } + + /** + Sets the coefficient modulus parameter. The coefficient modulus consists + of a list of distinct prime numbers, and is represented by a vector of + Modulus objects. The coefficient modulus directly affects the size + of ciphertext elements, the amount of computation that the scheme can + perform (bigger is better), and the security level (bigger is worse). In + Microsoft SEAL each of the prime numbers in the coefficient modulus must + be at most 60 bits, and must be congruent to 1 modulo 2*poly_modulus_degree. + + @param[in] coeff_modulus The new coefficient modulus + @throws std::logic_error if a valid scheme is not set and coeff_modulus is + is non-empty + @throws std::invalid_argument if size of coeff_modulus is invalid + */ + inline void set_coeff_modulus(const std::vector<Modulus> &coeff_modulus) + { + // Check that a scheme is set + if (scheme_ == scheme_type::none) + { + if (!coeff_modulus.empty()) + { + throw std::logic_error("coeff_modulus is not supported for this scheme"); + } + } + else if (coeff_modulus.size() > SEAL_COEFF_MOD_COUNT_MAX || coeff_modulus.size() < SEAL_COEFF_MOD_COUNT_MIN) + { + throw std::invalid_argument("coeff_modulus is invalid"); + } + + coeff_modulus_ = coeff_modulus; + + // Re-compute the parms_id + compute_parms_id(); + } + + /** + Sets the plaintext modulus parameter. The plaintext modulus is an integer + modulus represented by the Modulus class. The plaintext modulus + determines the largest coefficient that plaintext polynomials can represent. + It also affects the amount of computation that the scheme can perform + (bigger is worse). In Microsoft SEAL the plaintext modulus can be at most + 60 bits long, but can otherwise be any integer. Note, however, that some + features (e.g. batching) require the plaintext modulus to be of a particular + form. + + @param[in] plain_modulus The new plaintext modulus + @throws std::logic_error if scheme is not scheme_type::BFV and plain_modulus + is non-zero + */ + inline void set_plain_modulus(const Modulus &plain_modulus) + { + // Check that scheme is BFV + if (scheme_ != scheme_type::BFV && !plain_modulus.is_zero()) + { + throw std::logic_error("plain_modulus is not supported for this scheme"); + } + + plain_modulus_ = plain_modulus; + + // Re-compute the parms_id + compute_parms_id(); + } + + /** + Sets the plaintext modulus parameter. The plaintext modulus is an integer + modulus represented by the Modulus class. This constructor instead + takes a std::uint64_t and automatically creates the Modulus object. + The plaintext modulus determines the largest coefficient that plaintext + polynomials can represent. It also affects the amount of computation that + the scheme can perform (bigger is worse). In Microsoft SEAL the plaintext + modulus can be at most 60 bits long, but can otherwise be any integer. Note, + however, that some features (e.g. batching) require the plaintext modulus + to be of a particular form. + + @param[in] plain_modulus The new plaintext modulus + @throws std::invalid_argument if plain_modulus is invalid + */ + inline void set_plain_modulus(std::uint64_t plain_modulus) + { + set_plain_modulus(Modulus(plain_modulus)); + } + + /** + Sets the random number generator factory to use for encryption. By default, + the random generator is set to UniformRandomGeneratorFactory::default_factory(). + Setting this value allows a user to specify a custom random number generator + source. + + @param[in] random_generator Pointer to the random generator factory + */ + inline void set_random_generator(std::shared_ptr<UniformRandomGeneratorFactory> random_generator) noexcept + { + random_generator_ = std::move(random_generator); + } + + /** + Returns the encryption scheme type. + */ + SEAL_NODISCARD inline scheme_type scheme() const noexcept + { + return scheme_; + } + + /** + Returns the degree of the polynomial modulus parameter. + */ + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return poly_modulus_degree_; + } + + /** + Returns a const reference to the currently set coefficient modulus parameter. + */ + SEAL_NODISCARD inline auto coeff_modulus() const noexcept -> const std::vector<Modulus> & + { + return coeff_modulus_; + } + + /** + Returns a const reference to the currently set plaintext modulus parameter. + */ + SEAL_NODISCARD inline const Modulus &plain_modulus() const noexcept + { + return plain_modulus_; + } + + /** + Returns a pointer to the random number generator factory to use for encryption. + */ + SEAL_NODISCARD inline auto random_generator() const noexcept -> std::shared_ptr<UniformRandomGeneratorFactory> + { + return random_generator_; + } + + /** + Compares a given set of encryption parameters to the current set of + encryption parameters. The comparison is performed by comparing the + parms_ids of the parameter sets rather than comparing the parameters + individually. + + @parms[in] other The EncryptionParameters to compare against + */ + SEAL_NODISCARD inline bool operator==(const EncryptionParameters &other) const noexcept + { + return (parms_id_ == other.parms_id_); + } + + /** + Compares a given set of encryption parameters to the current set of + encryption parameters. The comparison is performed by comparing + parms_ids of the parameter sets rather than comparing the parameters + individually. + + @parms[in] other The EncryptionParameters to compare against + */ + SEAL_NODISCARD inline bool operator!=(const EncryptionParameters &other) const noexcept + { + return (parms_id_ != other.parms_id_); + } + + /** + Returns an upper bound on the size of the EncryptionParameters, as if it + was written to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t coeff_modulus_total_size = + coeff_modulus_.empty() + ? std::size_t(0) + : util::safe_cast<std::size_t>(coeff_modulus_[0].save_size(compr_mode_type::none)); + coeff_modulus_total_size = util::mul_safe(coeff_modulus_total_size, coeff_modulus_.size()); + + std::size_t members_size = Serialization::ComprSizeEstimate( + util::add_safe( + sizeof(scheme_), + sizeof(std::uint64_t), // poly_modulus_degree_ + sizeof(std::uint64_t), // coeff_modulus_size + coeff_modulus_total_size, + util::safe_cast<std::size_t>(plain_modulus_.save_size(compr_mode_type::none))), + compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves EncryptionParameters to an output stream. The output is in binary + format and is not human-readable. The output stream must have the "binary" + flag set. + + @param[out] stream The stream to save the EncryptionParameters to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&EncryptionParameters::save_members, this, _1), save_size(compr_mode_type::none), stream, + compr_mode); + } + + /** + Loads EncryptionParameters from an input stream overwriting the current + EncryptionParameters. + + @param[in] stream The stream to load the EncryptionParameters from + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded size exceeds in_size_bound + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::istream &stream) + { + using namespace std::placeholders; + EncryptionParameters new_parms(scheme_type::none); + auto in_size = Serialization::Load(std::bind(&EncryptionParameters::load_members, &new_parms, _1), stream); + std::swap(*this, new_parms); + return in_size; + } + + /** + Saves EncryptionParameters to a given memory location. The output is in + binary format and is not human-readable. + + @param[out] out The memory location to write the EncryptionParameters to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&EncryptionParameters::save_members, this, _1), save_size(compr_mode_type::none), out, size, + compr_mode); + } + + /** + Loads EncryptionParameters from a given memory location overwriting the + current EncryptionParameters. + + @param[in] in The memory location to load the EncryptionParameters from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded size exceeds in_size_bound + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + EncryptionParameters new_parms(scheme_type::none); + auto in_size = + Serialization::Load(std::bind(&EncryptionParameters::load_members, &new_parms, _1), in, size); + std::swap(*this, new_parms); + return in_size; + } + + /** + Enables access to private members of seal::EncryptionParameters for .NET + wrapper. + */ + struct EncryptionParametersPrivateHelper; + + private: + /** + Helper function to determine whether given std::uint8_t represents a valid + value for scheme_type. The return value will be false is the scheme is set + to scheme_type::none. + */ + SEAL_NODISCARD bool is_valid_scheme(std::uint8_t scheme) const noexcept + { + switch (scheme) + { + case static_cast<std::uint8_t>(scheme_type::none): + /* fall through */ + + case static_cast<std::uint8_t>(scheme_type::BFV): + /* fall through */ + + case static_cast<std::uint8_t>(scheme_type::CKKS): + return true; + } + return false; + } + + /** + Returns the parms_id of the current parameters. This function is intended + for internal use. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return parms_id_; + } + + void compute_parms_id(); + + void save_members(std::ostream &stream) const; + + void load_members(std::istream &stream); + + MemoryPoolHandle pool_ = MemoryManager::GetPool(); + + scheme_type scheme_; + + std::size_t poly_modulus_degree_ = 0; + + std::vector<Modulus> coeff_modulus_{}; + + std::shared_ptr<UniformRandomGeneratorFactory> random_generator_{ nullptr }; + + Modulus plain_modulus_{}; + + parms_id_type parms_id_ = parms_id_zero; + }; +} // namespace seal + +/** +Specializes the std::hash template for parms_id_type. +*/ +namespace std +{ + template <> + struct hash<seal::parms_id_type> + { + std::size_t operator()(const seal::parms_id_type &parms_id) const + { + std::uint64_t result = 17; + result = 31 * result + parms_id[0]; + result = 31 * result + parms_id[1]; + result = 31 * result + parms_id[2]; + result = 31 * result + parms_id[3]; + return static_cast<std::size_t>(result); + } + }; +} // namespace std diff --git a/bigpiseal3.5.1/native/src/seal/encryptor.cpp b/bigpiseal3.5.1/native/src/seal/encryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccc5489ebf9c1d23f0fc33f4b40302cf1ff3dc71 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/encryptor.cpp @@ -0,0 +1,259 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/encryptor.h" +#include "seal/modulus.h" +#include "seal/randomgen.h" +#include "seal/randomtostd.h" +#include "seal/util/clipnormal.h" +#include "seal/util/common.h" +#include "seal/util/ntt.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/rlwe.h" +#include "seal/util/scalingvariant.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <stdexcept> + +using namespace std; + +namespace seal +{ + Encryptor::Encryptor(shared_ptr<SEALContext> context, const PublicKey &public_key) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + set_public_key(public_key); + + auto &parms = context_->key_context_data()->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Quick sanity check + if (!util::product_fits_in(coeff_count, coeff_modulus_size, size_t(2))) + { + throw logic_error("invalid parameters"); + } + } + + Encryptor::Encryptor(shared_ptr<SEALContext> context, const SecretKey &secret_key) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + set_secret_key(secret_key); + + auto &parms = context_->key_context_data()->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Quick sanity check + if (!util::product_fits_in(coeff_count, coeff_modulus_size, size_t(2))) + { + throw logic_error("invalid parameters"); + } + } + + Encryptor::Encryptor(shared_ptr<SEALContext> context, const PublicKey &public_key, const SecretKey &secret_key) + : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + set_public_key(public_key); + set_secret_key(secret_key); + + auto &parms = context_->key_context_data()->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Quick sanity check + if (!util::product_fits_in(coeff_count, coeff_modulus_size, size_t(2))) + { + throw logic_error("invalid parameters"); + } + } + + void Encryptor::encrypt_zero_internal( + parms_id_type parms_id, bool is_asymmetric, bool save_seed, Ciphertext &destination, + MemoryPoolHandle pool) const + { + // Verify parameters. + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + auto context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + + auto &context_data = *context_->get_context_data(parms_id); + auto &parms = context_data.parms(); + size_t coeff_modulus_size = parms.coeff_modulus().size(); + size_t coeff_count = parms.poly_modulus_degree(); + bool is_ntt_form = false; + + if (parms.scheme() == scheme_type::CKKS) + { + is_ntt_form = true; + } + else if (parms.scheme() != scheme_type::BFV) + { + throw invalid_argument("unsupported scheme"); + } + + // Resize destination and save results + destination.resize(context_, parms_id, 2); + + // If asymmetric key encryption + if (is_asymmetric) + { + auto prev_context_data_ptr = context_data.prev_context_data(); + if (prev_context_data_ptr) + { + // Requires modulus switching + auto &prev_context_data = *prev_context_data_ptr; + auto &prev_parms_id = prev_context_data.parms_id(); + auto rns_tool = prev_context_data.rns_tool(); + + // Zero encryption without modulus switching + Ciphertext temp(pool); + util::encrypt_zero_asymmetric(public_key_, context_, prev_parms_id, is_ntt_form, temp); + + // Modulus switching + for (size_t j = 0; j < 2; j++) + { + if (is_ntt_form) + { + rns_tool->divide_and_round_q_last_ntt_inplace( + temp.data(j), prev_context_data.small_ntt_tables(), pool); + } + else + { + rns_tool->divide_and_round_q_last_inplace(temp.data(j), pool); + } + util::set_poly_poly(temp.data(j), coeff_count, coeff_modulus_size, destination.data(j)); + } + destination.is_ntt_form() = is_ntt_form; + destination.scale() = temp.scale(); + destination.parms_id() = parms_id; + } + else + { + // Does not require modulus switching + util::encrypt_zero_asymmetric(public_key_, context_, parms_id, is_ntt_form, destination); + } + } + else + { + util::encrypt_zero_symmetric(secret_key_, context_, parms_id, is_ntt_form, save_seed, destination); + // Does not require modulus switching + } + } + + void Encryptor::encrypt_internal( + const Plaintext &plain, bool is_asymmetric, bool save_seed, Ciphertext &destination, + MemoryPoolHandle pool) const + { + // Minimal verification that the keys are set + if (is_asymmetric) + { + if (!is_metadata_valid_for(public_key_, context_)) + { + throw logic_error("public key is not set"); + } + } + else + { + if (!is_metadata_valid_for(secret_key_, context_)) + { + throw logic_error("secret key is not set"); + } + } + + // Verify that plain is valid. + if (!is_metadata_valid_for(plain, context_) || !is_buffer_valid(plain)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + + auto scheme = context_->key_context_data()->parms().scheme(); + if (scheme == scheme_type::BFV) + { + if (plain.is_ntt_form()) + { + throw invalid_argument("plain cannot be in NTT form"); + } + + encrypt_zero_internal(context_->first_parms_id(), is_asymmetric, save_seed, destination, pool); + + // Multiply plain by scalar coeff_div_plaintext and reposition if in upper-half. + // Result gets added into the c_0 term of ciphertext (c_0,c_1). + util::multiply_add_plain_with_scaling_variant(plain, *context_->first_context_data(), destination.data()); + } + else if (scheme == scheme_type::CKKS) + { + if (!plain.is_ntt_form()) + { + throw invalid_argument("plain must be in NTT form"); + } + + auto context_data_ptr = context_->get_context_data(plain.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + encrypt_zero_internal(plain.parms_id(), is_asymmetric, save_seed, destination, pool); + + auto &parms = context_->get_context_data(plain.parms_id())->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + + // The plaintext gets added into the c_0 term of ciphertext (c_0,c_1). + for (size_t i = 0; i < coeff_modulus_size; i++) + { + util::add_poly_poly_coeffmod( + destination.data() + (i * coeff_count), plain.data() + (i * coeff_count), coeff_count, + coeff_modulus[i], destination.data() + (i * coeff_count)); + } + + destination.scale() = plain.scale(); + } + else + { + throw invalid_argument("unsupported scheme"); + } + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/encryptor.h b/bigpiseal3.5.1/native/src/seal/encryptor.h new file mode 100644 index 0000000000000000000000000000000000000000..de39775d25b487288354334c901170390eef38ba --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/encryptor.h @@ -0,0 +1,370 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/encryptionparams.h" +#include "seal/memorymanager.h" +#include "seal/plaintext.h" +#include "seal/publickey.h" +#include "seal/secretkey.h" +#include "seal/serializable.h" +#include "seal/util/defines.h" +#include "seal/util/ntt.h" +#include <memory> +#include <vector> + +namespace seal +{ + /** + Encrypts Plaintext objects into Ciphertext objects. Constructing an Encryptor + requires a SEALContext with valid encryption parameters, the public key and/or + the secret key. If an Encrytor is given a secret key, it supports symmetric-key + encryption. If an Encryptor is given a public key, it supports asymmetric-key + encryption. + + @par Overloads + For the encrypt function we provide two overloads concerning the memory pool + used in allocations needed during the operation. In one overload the global + memory pool is used for this purpose, and in another overload the user can + supply a MemoryPoolHandle to to be used instead. This is to allow one single + Encryptor to be used concurrently by several threads without running into thread + contention in allocations taking place during operations. For example, one can + share one single Encryptor across any number of threads, but in each thread + call the encrypt function by giving it a thread-local MemoryPoolHandle to use. + It is important for a developer to understand how this works to avoid unnecessary + performance bottlenecks. + + @par NTT form + When using the BFV scheme (scheme_type::BFV), all plaintext and ciphertexts should + remain by default in the usual coefficient representation, i.e. not in NTT form. + When using the CKKS scheme (scheme_type::CKKS), all plaintexts and ciphertexts + should remain by default in NTT form. We call these scheme-specific NTT states + the "default NTT form". Decryption requires the input ciphertexts to be in + the default NTT form, and will throw an exception if this is not the case. + */ + class Encryptor + { + public: + /** + Creates an Encryptor instance initialized with the specified SEALContext + and public key. + + @param[in] context The SEALContext + @param[in] public_key The public key + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if public_key is not valid + */ + Encryptor(std::shared_ptr<SEALContext> context, const PublicKey &public_key); + + /** + Creates an Encryptor instance initialized with the specified SEALContext + and secret key. + + @param[in] context The SEALContext + @param[in] secret_key The secret key + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if secret_key is not valid + */ + Encryptor(std::shared_ptr<SEALContext> context, const SecretKey &secret_key); + + /** + Creates an Encryptor instance initialized with the specified SEALContext, + secret key, and public key. + + @param[in] context The SEALContext + @param[in] public_key The public key + @param[in] secret_key The secret key + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if public_key or secret_key is not valid + */ + Encryptor(std::shared_ptr<SEALContext> context, const PublicKey &public_key, const SecretKey &secret_key); + + /** + Give a new instance of public key. + + @param[in] public_key The public key + @throws std::invalid_argument if public_key is not valid + */ + inline void set_public_key(const PublicKey &public_key) + { + if (!is_valid_for(public_key, context_)) + { + throw std::invalid_argument("public key is not valid for encryption parameters"); + } + public_key_ = public_key; + } + + /** + Give a new instance of secret key. + + @param[in] secret_key The secret key + @throws std::invalid_argument if secret_key is not valid + */ + inline void set_secret_key(const SecretKey &secret_key) + { + if (!is_valid_for(secret_key, context_)) + { + throw std::invalid_argument("secret key is not valid for encryption parameters"); + } + secret_key_ = secret_key; + } + + /** + Encrypts a plaintext with the public key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to: + 1) in BFV, the highest (data) level in the modulus switching chain, + 2) in CKKS, the encryption parameters of the plaintext. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext to encrypt + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a public key is not set + @throws std::invalid_argument if plain is not valid for the encryption + parameters + @throws std::invalid_argument if plain is not in default NTT form + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt( + const Plaintext &plain, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_internal(plain, true, false, destination, pool); + } + + /** + Encrypts a zero plaintext with the public key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to the + highest (data) level in the modulus switching chain. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a public key is not set + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt_zero(Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_zero(context_->first_parms_id(), destination, pool); + } + + /** + Encrypts a zero plaintext with the public key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to the + given parms_id. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] parms_id The parms_id for the resulting ciphertext + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a public key is not set + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt_zero( + parms_id_type parms_id, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_zero_internal(parms_id, true, false, destination, pool); + } + + /** + Encrypts a plaintext with the secret key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to: + 1) in BFV, the highest (data) level in the modulus switching chain, + 2) in CKKS, the encryption parameters of the plaintext. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext to encrypt + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if plain is not valid for the encryption + parameters + @throws std::invalid_argument if plain is not in default NTT form + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt_symmetric( + const Plaintext &plain, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_internal(plain, false, false, destination, pool); + } + + /** + Encrypts a zero plaintext with the secret key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to the + highest (data) level in the modulus switching chain. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt_zero_symmetric( + Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_zero_symmetric(context_->first_parms_id(), destination, pool); + } + + /** + Encrypts a zero plaintext with the secret key and stores the result in + destination. + + The encryption parameters for the resulting ciphertext correspond to the + given parms_id. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] parms_id The parms_id for the resulting ciphertext + @param[out] destination The ciphertext to overwrite with the encrypted + plaintext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void encrypt_zero_symmetric( + parms_id_type parms_id, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + encrypt_zero_internal(parms_id, false, false, destination, pool); + } + + /** + Encrypts a plaintext with the secret key and returns the ciphertext as + a serializable object. + + The encryption parameters for the resulting ciphertext correspond to: + 1) in BFV, the highest (data) level in the modulus switching chain, + 2) in CKKS, the encryption parameters of the plaintext. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + Half of the ciphertext data is pseudo-randomly generated from a seed to + reduce the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @param[in] plain The plaintext to encrypt + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if plain is not valid for the encryption + parameters + @throws std::invalid_argument if plain is not in default NTT form + @throws std::invalid_argument if pool is uninitialized + */ + SEAL_NODISCARD inline Serializable<Ciphertext> encrypt_symmetric( + const Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + Ciphertext destination; + encrypt_internal(plain, false, true, destination, pool); + return destination; + } + + /** + Encrypts a zero plaintext with the secret key and returns the ciphertext + as a serializable object. + + The encryption parameters for the resulting ciphertext correspond to the + given parms_id. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + Half of the ciphertext data is pseudo-randomly generated from a seed to + reduce the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @param[in] parms_id The parms_id for the resulting ciphertext + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if parms_id is not valid for the encryption + parameters + @throws std::invalid_argument if pool is uninitialized + */ + SEAL_NODISCARD inline Serializable<Ciphertext> encrypt_zero_symmetric( + parms_id_type parms_id, MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + Ciphertext destination; + encrypt_zero_internal(parms_id, false, true, destination, pool); + return destination; + } + + /** + Encrypts a zero plaintext with the secret key and returns the ciphertext + as a serializable object. + + The encryption parameters for the resulting ciphertext correspond to the + highest (data) level in the modulus switching chain. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + Half of the ciphertext data is pseudo-randomly generated from a seed to + reduce the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if a secret key is not set + @throws std::invalid_argument if pool is uninitialized + */ + SEAL_NODISCARD inline Serializable<Ciphertext> encrypt_zero_symmetric( + MemoryPoolHandle pool = MemoryManager::GetPool()) const + { + return encrypt_zero_symmetric(context_->first_parms_id(), pool); + } + + /** + Enables access to private members of seal::Encryptor for .NET wrapper. + */ + struct EncryptorPrivateHelper; + + private: + Encryptor(const Encryptor &copy) = delete; + + Encryptor(Encryptor &&source) = delete; + + Encryptor &operator=(const Encryptor &assign) = delete; + + Encryptor &operator=(Encryptor &&assign) = delete; + + MemoryPoolHandle pool_ = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true); + + void encrypt_zero_internal( + parms_id_type parms_id, bool is_asymmetric, bool save_seed, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) const; + + void encrypt_internal( + const Plaintext &plain, bool is_asymmetric, bool save_seed, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) const; + + std::shared_ptr<SEALContext> context_{ nullptr }; + + PublicKey public_key_; + + SecretKey secret_key_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/evaluator.cpp b/bigpiseal3.5.1/native/src/seal/evaluator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb7e2c2abec41c51df5be671c3133d5ee00e54a5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/evaluator.cpp @@ -0,0 +1,2524 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/evaluator.h" +#include "seal/util/common.h" +#include "seal/util/galois.h" +#include "seal/util/numth.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/scalingvariant.h" +#include "seal/util/uintarith.h" +#include <algorithm> +#include <cmath> +#include <functional> +#include <limits> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + namespace + { + template <typename T, typename S> + inline bool are_same_scale(const T &value1, const S &value2) noexcept + { + return util::are_close<double>(value1.scale(), value2.scale()); + } + } // namespace + + Evaluator::Evaluator(shared_ptr<SEALContext> context) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + // Calculate map from Zmstar to generator representation + populate_Zmstar_to_generator(); + } + + void Evaluator::populate_Zmstar_to_generator() + { + uint64_t n = static_cast<uint64_t>(context_->first_context_data()->parms().poly_modulus_degree()); + uint64_t m = n << 1; + + for (uint64_t i = 0; i < n / 2; i++) + { + uint64_t galois_elt = exponentiate_uint64(3, i) & (m - 1); + pair<uint64_t, uint64_t> temp_pair1{ i, 0 }; + Zmstar_to_generator_.emplace(galois_elt, temp_pair1); + galois_elt = (exponentiate_uint64(3, i) * (m - 1)) & (m - 1); + pair<uint64_t, uint64_t> temp_pair2{ i, 1 }; + Zmstar_to_generator_.emplace(galois_elt, temp_pair2); + } + } + + void Evaluator::negate_inplace(Ciphertext &encrypted) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t encrypted_size = encrypted.size(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Negate each poly in the array + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + SEAL_ASSERT_TYPE(I, RNSIter, "encrypted"); + for_each_n(IterTuple<RNSIter, PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), CoeffIter, "encrypted"); + SEAL_ASSERT_TYPE(get<1>(J), const Modulus *, "coeff_modulus"); + negate_poly_coeffmod(get<0>(J), coeff_count, *get<1>(J), get<0>(J)); + }); + }); +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::add_inplace(Ciphertext &encrypted1, const Ciphertext &encrypted2) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted1, context_) || !is_buffer_valid(encrypted1)) + { + throw invalid_argument("encrypted1 is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(encrypted2, context_) || !is_buffer_valid(encrypted2)) + { + throw invalid_argument("encrypted2 is not valid for encryption parameters"); + } + if (encrypted1.parms_id() != encrypted2.parms_id()) + { + throw invalid_argument("encrypted1 and encrypted2 parameter mismatch"); + } + if (encrypted1.is_ntt_form() != encrypted2.is_ntt_form()) + { + throw invalid_argument("NTT form mismatch"); + } + if (!are_same_scale(encrypted1, encrypted2)) + { + throw invalid_argument("scale mismatch"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted1.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted1_size = encrypted1.size(); + size_t encrypted2_size = encrypted2.size(); + size_t max_count = max(encrypted1_size, encrypted2_size); + size_t min_count = min(encrypted1_size, encrypted2_size); + + // Size check + if (!product_fits_in(max_count, coeff_count)) + { + throw logic_error("invalid parameters"); + } + + // Prepare destination + encrypted1.resize(context_, context_data.parms_id(), max_count); + + // Add ciphertexts + for_each_n(IterTuple<PolyIter, ConstPolyIter>(encrypted1, encrypted2), min_count, [&](auto I) { + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, [&](auto J) { + add_poly_poly_coeffmod( + get<0>(get<0>(J)), get<1>(get<0>(J)), coeff_count, *get<1>(J), get<0>(get<0>(J))); + }); + }); + + // Copy the remainding polys of the array with larger count into encrypted1 + if (encrypted1_size < encrypted2_size) + { + set_poly_poly( + encrypted2.data(min_count), coeff_count * (encrypted2_size - encrypted1_size), coeff_modulus_size, + encrypted1.data(encrypted1_size)); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted1.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::add_many(const vector<Ciphertext> &encrypteds, Ciphertext &destination) + { + if (encrypteds.empty()) + { + throw invalid_argument("encrypteds cannot be empty"); + } + for (size_t i = 0; i < encrypteds.size(); i++) + { + if (&encrypteds[i] == &destination) + { + throw invalid_argument("encrypteds must be different from destination"); + } + } + + destination = encrypteds[0]; + for (size_t i = 1; i < encrypteds.size(); i++) + { + add_inplace(destination, encrypteds[i]); + } + } + + void Evaluator::sub_inplace(Ciphertext &encrypted1, const Ciphertext &encrypted2) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted1, context_) || !is_buffer_valid(encrypted1)) + { + throw invalid_argument("encrypted1 is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(encrypted2, context_) || !is_buffer_valid(encrypted2)) + { + throw invalid_argument("encrypted2 is not valid for encryption parameters"); + } + if (encrypted1.parms_id() != encrypted2.parms_id()) + { + throw invalid_argument("encrypted1 and encrypted2 parameter mismatch"); + } + if (encrypted1.is_ntt_form() != encrypted2.is_ntt_form()) + { + throw invalid_argument("NTT form mismatch"); + } + if (!are_same_scale(encrypted1, encrypted2)) + { + throw invalid_argument("scale mismatch"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted1.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted1_size = encrypted1.size(); + size_t encrypted2_size = encrypted2.size(); + size_t max_count = max(encrypted1_size, encrypted2_size); + size_t min_count = min(encrypted1_size, encrypted2_size); + + // Size check + if (!product_fits_in(max_count, coeff_count)) + { + throw logic_error("invalid parameters"); + } + + // Prepare destination + encrypted1.resize(context_, context_data.parms_id(), max_count); + + // Set up iterators in the function scope + PolyIter encrypted1_iter(encrypted1); + ConstPolyIter encrypted2_iter(encrypted2); + + // Subtract polynomials + for_each_n(IterTuple<PolyIter, ConstPolyIter>(encrypted1_iter, encrypted2_iter), min_count, [&](auto I) { + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, [&](auto J) { + sub_poly_poly_coeffmod( + get<0>(get<0>(J)), get<1>(get<0>(J)), coeff_count, *get<1>(J), get<0>(get<0>(J))); + }); + }); + + // If encrypted2 has larger count, negate remaining entries + if (encrypted1_size < encrypted2_size) + { + // Advance encrypted1_iter and encrypted2_iter to min_count (i.e., encrypted1_size) + advance(encrypted1_iter, safe_cast<ptrdiff_t>(min_count)); + advance(encrypted2_iter, safe_cast<ptrdiff_t>(min_count)); + + for_each_n( + IterTuple<PolyIter, ConstPolyIter>(encrypted1_iter, encrypted2_iter), encrypted2_size - min_count, + [&](auto I) { + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, + [&](auto J) { + negate_poly_coeffmod(get<1>(get<0>(J)), coeff_count, *get<1>(J), get<0>(get<0>(J))); + }); + }); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted1.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::multiply_inplace(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted1, context_) || !is_buffer_valid(encrypted1)) + { + throw invalid_argument("encrypted1 is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(encrypted2, context_) || !is_buffer_valid(encrypted2)) + { + throw invalid_argument("encrypted2 is not valid for encryption parameters"); + } + if (encrypted1.parms_id() != encrypted2.parms_id()) + { + throw invalid_argument("encrypted1 and encrypted2 parameter mismatch"); + } + + auto context_data_ptr = context_->first_context_data(); + switch (context_data_ptr->parms().scheme()) + { + case scheme_type::BFV: + bfv_multiply(encrypted1, encrypted2, pool); + break; + + case scheme_type::CKKS: + ckks_multiply(encrypted1, encrypted2, pool); + break; + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted1.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::bfv_multiply(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool) + { + if (encrypted1.is_ntt_form() || encrypted2.is_ntt_form()) + { + throw invalid_argument("encrypted1 or encrypted2 cannot be in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted1.parms_id()); + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t base_q_size = parms.coeff_modulus().size(); + size_t encrypted1_size = encrypted1.size(); + size_t encrypted2_size = encrypted2.size(); + + uint64_t plain_modulus = parms.plain_modulus().value(); + auto rns_tool = context_data.rns_tool(); + size_t base_Bsk_size = rns_tool->base_Bsk()->size(); + size_t base_Bsk_m_tilde_size = rns_tool->base_Bsk_m_tilde()->size(); + + // Determine destination.size() + size_t dest_size = sub_safe(add_safe(encrypted1_size, encrypted2_size), size_t(1)); + + // Size check + if (!product_fits_in(dest_size, coeff_count, base_Bsk_m_tilde_size)) + { + throw logic_error("invalid parameters"); + } + + // Set up iterators for bases + PtrIter<const Modulus *> base_q_iter(parms.coeff_modulus()); + PtrIter<const Modulus *> base_Bsk_iter(rns_tool->base_Bsk()->base()); + + // Set up iterators for NTT tables + PtrIter<const NTTTables *> base_q_ntt_tables_iter(context_data.small_ntt_tables()); + PtrIter<const NTTTables *> base_Bsk_ntt_tables_iter(rns_tool->base_Bsk_small_ntt_tables()); + + // Microsoft SEAL uses BEHZ-style RNS multiplication. This process is somewhat complex and consists of the + // following steps: + // + // (1) Lift encrypted1 and encrypted2 (initially in base q) to an extended base q U Bsk U {m_tilde} + // (2) Remove extra multiples of q from the results with Montgomery reduction, switching base to q U Bsk + // (3) Transform the data to NTT form + // (4) Compute the ciphertext polynomial product using dyadic multiplication + // (5) Transform the data back from NTT form + // (6) Multiply the result by t (plain_modulus) + // (7) Scale the result by q using a divide-and-floor algorithm, switching base to Bsk + // (8) Use Shenoy-Kumaresan method to convert the result to base q + + // Resize encrypted1 to destination size + encrypted1.resize(context_, context_data.parms_id(), dest_size); + + // Set up iterators for input ciphertexts + PolyIter encrypted1_iter(encrypted1); + ConstPolyIter encrypted2_iter(encrypted2); + + // This lambda function takes as input an iterator_tuple with three components: + // + // 1. ConstRNSIter to read an input polynomial from + // 2. RNSIter for the output in base q + // 3. RNSIter for the output in base Bsk + // + // It performs steps (1)-(3) of the BEHZ multiplication (see above) on the given input polynomial (given as an + // RNSIter or ConstRNSIter) and writes the results in base q and base Bsk to the given output + // iterators. + auto behz_extend_base_convert_to_ntt = [&](auto I) { + // Make copy of input polynomial (in base q) and convert to NTT form + for_each_n( + IterTuple<ConstRNSIter, RNSIter, PtrIter<const NTTTables *>>( + get<0>(I), get<1>(I), base_q_ntt_tables_iter), + base_q_size, [&](auto J) { + // First copy to output + set_uint_uint(get<0>(J), coeff_count, get<1>(J)); + + // Transform to NTT form in base q + // Lazy reduction + ntt_negacyclic_harvey_lazy(get<1>(J), *get<2>(J)); + }); + + // Allocate temporary space for a polynomial in the Bsk U {m_tilde} base + auto temp(allocate_poly(coeff_count, base_Bsk_m_tilde_size, pool)); + + // (1) Convert from base q to base Bsk U {m_tilde} + rns_tool->fastbconv_m_tilde(get<0>(I), temp.get(), pool); + + // (2) Reduce q-overflows in with Montgomery reduction, switching base to Bsk + rns_tool->sm_mrq(temp.get(), get<2>(I), pool); + + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<2>(I), base_Bsk_ntt_tables_iter), base_Bsk_size, + [&](auto J) { + // Transform to NTT form in base Bsk + // Lazy reduction + ntt_negacyclic_harvey_lazy(get<0>(J), *get<1>(J)); + }); + }; + + // Allocate space for a base q output of behz_extend_base_convert_to_ntt for encrypted1 + auto encrypted1_q(allocate_poly(coeff_count * encrypted1_size, base_q_size, pool)); + PolyIter encrypted1_q_iter(encrypted1_q.get(), coeff_count, base_q_size); + + // Allocate space for a base Bsk output of behz_extend_base_convert_to_ntt for encrypted1 + auto encrypted1_Bsk(allocate_poly(coeff_count * encrypted1_size, base_Bsk_size, pool)); + PolyIter encrypted1_Bsk_iter(encrypted1_Bsk.get(), coeff_count, base_Bsk_size); + + // Perform BEHZ steps (1)-(3) for encrypted1 + for_each_n( + IterTuple<ConstPolyIter, PolyIter, PolyIter>(encrypted1_iter, encrypted1_q_iter, encrypted1_Bsk_iter), + encrypted1_size, behz_extend_base_convert_to_ntt); + + // Repeat for encrypted2 + auto encrypted2_q(allocate_poly(coeff_count * encrypted2_size, base_q_size, pool)); + PolyIter encrypted2_q_iter(encrypted2_q.get(), coeff_count, base_q_size); + + auto encrypted2_Bsk(allocate_poly(coeff_count * encrypted2_size, base_Bsk_size, pool)); + PolyIter encrypted2_Bsk_iter(encrypted2_Bsk.get(), coeff_count, base_Bsk_size); + + for_each_n( + IterTuple<ConstPolyIter, PolyIter, PolyIter>(encrypted2_iter, encrypted2_q_iter, encrypted2_Bsk_iter), + encrypted2_size, behz_extend_base_convert_to_ntt); + + // Allocate temporary space for the output of step (4) + // We allocate space separately for the base q and the base Bsk components + auto temp_dest_q(allocate_zero_poly(coeff_count * dest_size, base_q_size, pool)); + PolyIter temp_dest_q_iter(temp_dest_q.get(), coeff_count, base_q_size); + + auto temp_dest_Bsk(allocate_zero_poly(coeff_count * dest_size, base_Bsk_size, pool)); + PolyIter temp_dest_Bsk_iter(temp_dest_Bsk.get(), coeff_count, base_Bsk_size); + + // Perform BEHZ step (4): dyadic multiplication on arbitrary size ciphertexts + for (size_t secret_power_index = 0; secret_power_index < dest_size; secret_power_index++) + { + // We iterate over relevant components of encrypted1 and encrypted2 in increasing order for + // encrypted1 and reversed (decreasing) order for encrypted2. The bounds for the indices of + // the relevant terms are obtained as follows. + size_t curr_encrypted1_last = min(secret_power_index, encrypted1_size - 1); + size_t curr_encrypted2_first = min(secret_power_index, encrypted2_size - 1); + size_t curr_encrypted1_first = secret_power_index - curr_encrypted2_first; + // size_t curr_encrypted2_last = secret_power_index - curr_encrypted1_last; + + // The total number of dyadic products is now easy to compute + size_t steps = curr_encrypted1_last - curr_encrypted1_first + 1; + + // This lambda function computes the ciphertext product for BFV multiplication. Since we use the BEHZ + // approach, the multiplication of individual polynomials is done using a dyadic product where the inputs + // are already in NTT form. The arguments of the lambda function are expected to be as follows: + // + // 1. a PolyIter pointing to the beginning of the first input ciphertext (in NTT form) + // 2. a PolyIter pointing to the beginning of the second input ciphertext (in NTT form) + // 3. an PtrIter pointing to an array of Modulus elements for the base + // 4. the size of the base + // 5. a PolyIter pointing to the beginning of the output ciphertext + auto behz_ciphertext_product = [&](auto in1_iter, auto in2_iter, auto base_iter, size_t base_size, + auto out_iter) { + // Create a shifted iterator for the first input + auto shifted_in1_iter = in1_iter; + advance(shifted_in1_iter, safe_cast<ptrdiff_t>(curr_encrypted1_first)); + + // Create a shifted reverse iterator for the second input + auto shifted_in2_iter = in2_iter; + advance(shifted_in2_iter, safe_cast<ptrdiff_t>(curr_encrypted2_first)); + auto shifted_reversed_in2_iter = ReverseIter<PolyIter>(shifted_in2_iter); + + // Create a shifted iterator for the output + auto shifted_out_iter = out_iter; + advance(shifted_out_iter, safe_cast<ptrdiff_t>(secret_power_index)); + + for_each_n( + IterTuple<PolyIter, ReverseIter<PolyIter>>(shifted_in1_iter, shifted_reversed_in2_iter), steps, + [&](auto I) { + // Extra care needed here: shifted_out_iter must be dereferenced once to + // produce an appropriate RNSIter. + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>, RNSIter>(I, base_iter, *shifted_out_iter), + base_size, [&](auto J) { + auto temp(allocate_uint(coeff_count, pool)); + dyadic_product_coeffmod( + get<0>(get<0>(J)), get<1>(get<0>(J)), coeff_count, *get<1>(J), temp.get()); + add_poly_poly_coeffmod(temp.get(), get<2>(J), coeff_count, *get<1>(J), get<2>(J)); + }); + }); + }; + + // Perform the BEHZ ciphertext product both for base q and base Bsk + behz_ciphertext_product(encrypted1_q_iter, encrypted2_q_iter, base_q_iter, base_q_size, temp_dest_q_iter); + behz_ciphertext_product( + encrypted1_Bsk_iter, encrypted2_Bsk_iter, base_Bsk_iter, base_Bsk_size, temp_dest_Bsk_iter); + } + + // Perform BEHZ step (5): transform data from NTT form + for_each_n(IterTuple<PolyIter, PolyIter>(temp_dest_q_iter, temp_dest_Bsk_iter), dest_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<0>(I), base_q_ntt_tables_iter), base_q_size, + [&](auto J) { inverse_ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<1>(I), base_Bsk_ntt_tables_iter), base_Bsk_size, + [&](auto J) { inverse_ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + }); + + // Perform BEHZ steps (6)-(8) + for_each_n( + IterTuple<PolyIter, PolyIter, PolyIter>(temp_dest_q_iter, temp_dest_Bsk_iter, encrypted1_iter), dest_size, + [&](auto I) { + // Bring together the base q and base Bsk components into a single allocation + auto temp_q_Bsk(allocate_poly(coeff_count, base_q_size + base_Bsk_size, pool)); + RNSIter temp_q_Bsk_iter(temp_q_Bsk.get(), coeff_count); + + // Step (6): multiply base q components by t (plain_modulus) + for_each_n( + IterTuple<ConstRNSIter, RNSIter, PtrIter<const Modulus *>>(get<0>(I), temp_q_Bsk_iter, base_q_iter), + base_q_size, [&](auto J) { + multiply_poly_scalar_coeffmod(get<0>(J), coeff_count, plain_modulus, *get<2>(J), get<1>(J)); + }); + + // Advance to the base Bsk part in temp and multiply base Bsk components by t + advance(temp_q_Bsk_iter, safe_cast<ptrdiff_t>(base_q_size)); + for_each_n( + IterTuple<ConstRNSIter, RNSIter, PtrIter<const Modulus *>>( + get<1>(I), temp_q_Bsk_iter, base_Bsk_iter), + base_Bsk_size, [&](auto J) { + multiply_poly_scalar_coeffmod(get<0>(J), coeff_count, plain_modulus, *get<2>(J), get<1>(J)); + }); + + // Allocate yet another temporary for fast divide-and-floor result in base Bsk + auto temp_Bsk(allocate_poly(coeff_count, base_Bsk_size, pool)); + + // Step (7): divide by q and floor, producing a result in base Bsk + rns_tool->fast_floor(temp_q_Bsk.get(), temp_Bsk.get(), pool); + + // Step (8): use Shenoy-Kumaresan method to convert the result to base q and write to encrypted1 + rns_tool->fastbconv_sk(temp_Bsk.get(), get<2>(I), pool); + }); + } + + void Evaluator::ckks_multiply(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool) + { + if (!(encrypted1.is_ntt_form() && encrypted2.is_ntt_form())) + { + throw invalid_argument("encrypted1 or encrypted2 must be in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted1.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted1_size = encrypted1.size(); + size_t encrypted2_size = encrypted2.size(); + + double new_scale = encrypted1.scale() * encrypted2.scale(); + + // Check that scale is positive and not too large + if (new_scale <= 0 || (static_cast<int>(log2(new_scale)) >= context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // Determine destination.size() + // Default is 3 (c_0, c_1, c_2) + size_t dest_size = sub_safe(add_safe(encrypted1_size, encrypted2_size), size_t(1)); + + // Size check + if (!product_fits_in(dest_size, coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Set up iterator for the base + PtrIter<const Modulus *> coeff_modulus_iter(parms.coeff_modulus()); + + // Prepare destination + encrypted1.resize(context_, context_data.parms_id(), dest_size); + + // Set up iterators for input ciphertexts + PolyIter encrypted1_iter(encrypted1); + ConstPolyIter encrypted2_iter(encrypted2); + + // Allocate temporary space for the result + auto temp(allocate_zero_poly(coeff_count * dest_size, coeff_modulus_size, pool)); + PolyIter temp_iter(temp.get(), coeff_count, coeff_modulus_size); + + for (size_t secret_power_index = 0; secret_power_index < dest_size; secret_power_index++, ++temp_iter) + { + // We iterate over relevant components of encrypted1 and encrypted2 in increasing order for + // encrypted1 and reversed (decreasing) order for encrypted2. The bounds for the indices of + // the relevant terms are obtained as follows. + size_t curr_encrypted1_last = min(secret_power_index, encrypted1_size - 1); + size_t curr_encrypted2_first = min(secret_power_index, encrypted2_size - 1); + size_t curr_encrypted1_first = secret_power_index - curr_encrypted2_first; + // size_t curr_encrypted2_last = secret_power_index - curr_encrypted1_last; + + // The total number of dyadic products is now easy to compute + size_t steps = curr_encrypted1_last - curr_encrypted1_first + 1; + + // Create a shifted iterator for the first input + auto shifted_encrypted1_iter = encrypted1_iter; + advance(shifted_encrypted1_iter, safe_cast<ptrdiff_t>(curr_encrypted1_first)); + + // Create a shifted reverse iterator for the second input + auto shifted_encrypted2_iter = encrypted2_iter; + advance(shifted_encrypted2_iter, safe_cast<ptrdiff_t>(curr_encrypted2_first)); + auto shifted_reversed_encrypted2_iter = ReverseIter<ConstPolyIter>(shifted_encrypted2_iter); + + for_each_n( + IterTuple<PolyIter, ReverseIter<ConstPolyIter>>( + shifted_encrypted1_iter, shifted_reversed_encrypted2_iter), + steps, [&](auto I) { + // Extra care needed here: + // temp_iter must be dereferenced once to produce an appropriate RNSIter + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>, RNSIter>(I, coeff_modulus_iter, *temp_iter), + coeff_modulus_size, [&](auto J) { + auto prod(allocate_uint(coeff_count, pool)); + dyadic_product_coeffmod( + get<0>(get<0>(J)), get<1>(get<0>(J)), coeff_count, *get<1>(J), prod.get()); + add_poly_poly_coeffmod(prod.get(), get<2>(J), coeff_count, *get<1>(J), get<2>(J)); + }); + }); + } + + // Set the final result + set_poly_poly(temp.get(), coeff_count * dest_size, coeff_modulus_size, encrypted1.data()); + + // Set the scale + encrypted1.scale() = new_scale; + } + + void Evaluator::square_inplace(Ciphertext &encrypted, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->first_context_data(); + switch (context_data_ptr->parms().scheme()) + { + case scheme_type::BFV: + bfv_square(encrypted, move(pool)); + break; + + case scheme_type::CKKS: + ckks_square(encrypted, move(pool)); + break; + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::bfv_square(Ciphertext &encrypted, MemoryPoolHandle pool) + { + if (encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted cannot be in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t base_q_size = parms.coeff_modulus().size(); + size_t encrypted_size = encrypted.size(); + + uint64_t plain_modulus = parms.plain_modulus().value(); + auto rns_tool = context_data.rns_tool(); + size_t base_Bsk_size = rns_tool->base_Bsk()->size(); + size_t base_Bsk_m_tilde_size = rns_tool->base_Bsk_m_tilde()->size(); + + // Optimization implemented currently only for size 2 ciphertexts + if (encrypted_size != 2) + { + bfv_multiply(encrypted, encrypted, move(pool)); + return; + } + + // Determine destination.size() + size_t dest_size = sub_safe(add_safe(encrypted_size, encrypted_size), size_t(1)); + + // Size check + if (!product_fits_in(dest_size, coeff_count, base_Bsk_m_tilde_size)) + { + throw logic_error("invalid parameters"); + } + + // Set up iterators for bases + PtrIter<const Modulus *> base_q_iter(parms.coeff_modulus()); + PtrIter<const Modulus *> base_Bsk_iter(rns_tool->base_Bsk()->base()); + + // Set up iterators for NTT tables + PtrIter<const NTTTables *> base_q_ntt_tables_iter(context_data.small_ntt_tables()); + PtrIter<const NTTTables *> base_Bsk_ntt_tables_iter(rns_tool->base_Bsk_small_ntt_tables()); + + // Microsoft SEAL uses BEHZ-style RNS multiplication. For details, see Evaluator::bfv_multiply. This function + // uses additionally Karatsuba multiplication to reduce the complexity of squaring a size-2 ciphertext, but the + // steps are otherwise the same as in Evaluator::bfv_multiply. + + // Resize encrypted to destination size + encrypted.resize(context_, context_data.parms_id(), dest_size); + + // Set up iterators for input ciphertexts + PolyIter encrypted_iter(encrypted); + + // This lambda function takes as input an iterator_tuple with three components: + // + // 1. ConstRNSIter to read an input polynomial from + // 2. RNSIter for the output in base q + // 3. RNSIter for the output in base Bsk + // + // It performs steps (1)-(3) of the BEHZ multiplication on the given input polynomial (given as an RNSIter + // or ConstRNSIter) and writes the results in base q and base Bsk to the given output iterators. + auto behz_extend_base_convert_to_ntt = [&](auto I) { + // Make copy of input polynomial (in base q) and convert to NTT form + for_each_n( + IterTuple<ConstRNSIter, RNSIter, PtrIter<const NTTTables *>>( + get<0>(I), get<1>(I), base_q_ntt_tables_iter), + base_q_size, [&](auto J) { + // First copy to output + set_uint_uint(get<0>(J), coeff_count, get<1>(J)); + + // Transform to NTT form in base q + // Lazy reduction + ntt_negacyclic_harvey_lazy(get<1>(J), *get<2>(J)); + }); + + // Allocate temporary space for a polynomial in the Bsk U {m_tilde} base + auto temp(allocate_poly(coeff_count, base_Bsk_m_tilde_size, pool)); + + // (1) Convert from base q to base Bsk U {m_tilde} + rns_tool->fastbconv_m_tilde(get<0>(I), temp.get(), pool); + + // (2) Reduce q-overflows in with Montgomery reduction, switching base to Bsk + rns_tool->sm_mrq(temp.get(), get<2>(I), pool); + + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<2>(I), base_Bsk_ntt_tables_iter), base_Bsk_size, + [&](auto J) { + // Transform to NTT form in base Bsk + // Lazy reduction + ntt_negacyclic_harvey_lazy(get<0>(J), *get<1>(J)); + }); + }; + + // Allocate space for a base q output of behz_extend_base_convert_to_ntt + auto encrypted_q(allocate_poly(coeff_count * encrypted_size, base_q_size, pool)); + PolyIter encrypted_q_iter(encrypted_q.get(), coeff_count, base_q_size); + + // Allocate space for a base Bsk output of behz_extend_base_convert_to_ntt + auto encrypted_Bsk(allocate_poly(coeff_count * encrypted_size, base_Bsk_size, pool)); + PolyIter encrypted_Bsk_iter(encrypted_Bsk.get(), coeff_count, base_Bsk_size); + + // Perform BEHZ steps (1)-(3) + for_each_n( + IterTuple<ConstPolyIter, PolyIter, PolyIter>(encrypted_iter, encrypted_q_iter, encrypted_Bsk_iter), + encrypted_size, behz_extend_base_convert_to_ntt); + + // Allocate temporary space for the output of step (4) + // We allocate space separately for the base q and the base Bsk components + auto temp_dest_q(allocate_zero_poly(coeff_count * dest_size, base_q_size, pool)); + PolyIter temp_dest_q_iter(temp_dest_q.get(), coeff_count, base_q_size); + + auto temp_dest_Bsk(allocate_zero_poly(coeff_count * dest_size, base_Bsk_size, pool)); + PolyIter temp_dest_Bsk_iter(temp_dest_Bsk.get(), coeff_count, base_Bsk_size); + + // Perform BEHZ step (4): dyadic Karatsuba-squaring on size-2 ciphertexts + + // This lambda function computes the size-2 ciphertext square for BFV multiplication. Since we use the BEHZ + // approach, the multiplication of individual polynomials is done using a dyadic product where the inputs + // are already in NTT form. The arguments of the lambda function are expected to be as follows: + // + // 1. a PolyIter pointing to the beginning of the input ciphertext (in NTT form) + // 3. an PtrIter pointing to an array of Modulus elements for the base + // 4. the size of the base + // 5. a PolyIter pointing to the beginning of the output ciphertext + auto behz_ciphertext_square = [&](auto in_iter, auto base_iter, size_t base_size, auto out_iter) { + // Compute c0^2 + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>, RNSIter>(in_iter[0], base_iter, out_iter[0]), base_size, + [&](auto I) { dyadic_product_coeffmod(get<0>(I), get<0>(I), coeff_count, *get<1>(I), get<2>(I)); }); + + // Compute 2*c0*c1 + for_each_n( + IterTuple<RNSIter, RNSIter, PtrIter<const Modulus *>, RNSIter>( + in_iter[1], in_iter[0], base_iter, out_iter[1]), + base_size, [&](auto I) { + dyadic_product_coeffmod(get<0>(I), get<1>(I), coeff_count, *get<2>(I), get<3>(I)); + add_poly_poly_coeffmod(get<3>(I), get<3>(I), coeff_count, *get<2>(I), get<3>(I)); + }); + + // Compute c1^2 + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>, RNSIter>(in_iter[1], base_iter, out_iter[2]), base_size, + [&](auto I) { dyadic_product_coeffmod(get<0>(I), get<0>(I), coeff_count, *get<1>(I), get<2>(I)); }); + }; + + // Perform the BEHZ ciphertext square both for base q and base Bsk + behz_ciphertext_square(encrypted_q_iter, base_q_iter, base_q_size, temp_dest_q_iter); + behz_ciphertext_square(encrypted_Bsk_iter, base_Bsk_iter, base_Bsk_size, temp_dest_Bsk_iter); + + // Perform BEHZ step (5): transform data from NTT form + for_each_n(IterTuple<PolyIter, PolyIter>(temp_dest_q_iter, temp_dest_Bsk_iter), dest_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<0>(I), base_q_ntt_tables_iter), base_q_size, + [&](auto J) { inverse_ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(get<1>(I), base_Bsk_ntt_tables_iter), base_Bsk_size, + [&](auto J) { inverse_ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + }); + + // Perform BEHZ steps (6)-(8) + for_each_n( + IterTuple<PolyIter, PolyIter, PolyIter>(temp_dest_q_iter, temp_dest_Bsk_iter, encrypted_iter), dest_size, + [&](auto I) { + // Bring together the base q and base Bsk components into a single allocation + auto temp_q_Bsk(allocate_poly(coeff_count, base_q_size + base_Bsk_size, pool)); + RNSIter temp_q_Bsk_iter(temp_q_Bsk.get(), coeff_count); + + // Step (6): multiply base q components by t (plain_modulus) + for_each_n( + IterTuple<RNSIter, RNSIter, PtrIter<const Modulus *>>(get<0>(I), temp_q_Bsk_iter, base_q_iter), + base_q_size, [&](auto J) { + multiply_poly_scalar_coeffmod(get<0>(J), coeff_count, plain_modulus, *get<2>(J), get<1>(J)); + }); + + // Advance to the base Bsk part in temp and multiply base Bsk components by t + advance(temp_q_Bsk_iter, safe_cast<ptrdiff_t>(base_q_size)); + for_each_n( + IterTuple<RNSIter, RNSIter, PtrIter<const Modulus *>>(get<1>(I), temp_q_Bsk_iter, base_Bsk_iter), + base_Bsk_size, [&](auto J) { + multiply_poly_scalar_coeffmod(get<0>(J), coeff_count, plain_modulus, *get<2>(J), get<1>(J)); + }); + + // Allocate yet another temporary for fast divide-and-floor result in base Bsk + auto temp_Bsk(allocate_poly(coeff_count, base_Bsk_size, pool)); + + // Step (7): divide by q and floor, producing a result in base Bsk + rns_tool->fast_floor(temp_q_Bsk.get(), temp_Bsk.get(), pool); + + // Step (8): use Shenoy-Kumaresan method to convert the result to base q and write to encrypted1 + rns_tool->fastbconv_sk(temp_Bsk.get(), get<2>(I), pool); + }); + } + + void Evaluator::ckks_square(Ciphertext &encrypted, MemoryPoolHandle pool) + { + if (!encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted must be in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = parms.coeff_modulus().size(); + size_t encrypted_size = encrypted.size(); + + // Optimization implemented currently only for size 2 ciphertexts + if (encrypted_size != 2) + { + ckks_multiply(encrypted, encrypted, move(pool)); + return; + } + + double new_scale = encrypted.scale() * encrypted.scale(); + + // Check that scale is positive and not too large + if (new_scale <= 0 || (static_cast<int>(log2(new_scale)) >= context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // Determine destination.size() + // Default is 3 (c_0, c_1, c_2) + size_t dest_size = sub_safe(add_safe(encrypted_size, encrypted_size), size_t(1)); + + // Size check + if (!product_fits_in(dest_size, coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Set up iterator for the base + PtrIter<const Modulus *> coeff_modulus_iter(parms.coeff_modulus()); + + // Prepare destination + encrypted.resize(context_, context_data.parms_id(), dest_size); + + // Set up iterators for input ciphertext + PolyIter encrypted_iter(encrypted); + + // Allocate temporary space for the result + auto temp(allocate_zero_poly(coeff_count * dest_size, coeff_modulus_size, pool)); + PolyIter temp_iter(temp.get(), coeff_count, coeff_modulus_size); + + // Compute c0^2 + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>, RNSIter>(encrypted_iter[0], coeff_modulus_iter, temp_iter[0]), + coeff_modulus_size, + [&](auto I) { dyadic_product_coeffmod(get<0>(I), get<0>(I), coeff_count, *get<1>(I), get<2>(I)); }); + + // Compute 2*c0*c1 + for_each_n( + IterTuple<RNSIter, RNSIter, PtrIter<const Modulus *>, RNSIter>( + encrypted_iter[1], encrypted_iter[0], coeff_modulus_iter, temp_iter[1]), + coeff_modulus_size, [&](auto I) { + dyadic_product_coeffmod(get<0>(I), get<1>(I), coeff_count, *get<2>(I), get<3>(I)); + add_poly_poly_coeffmod(get<3>(I), get<3>(I), coeff_count, *get<2>(I), get<3>(I)); + }); + + // Compute c1^2 + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>, RNSIter>(encrypted_iter[1], coeff_modulus_iter, temp_iter[2]), + coeff_modulus_size, + [&](auto I) { dyadic_product_coeffmod(get<0>(I), get<0>(I), coeff_count, *get<1>(I), get<2>(I)); }); + + // Set the final result + set_poly_poly(temp.get(), coeff_count * dest_size, coeff_modulus_size, encrypted.data()); + + // Set the scale + encrypted.scale() = new_scale; + } + + void Evaluator::relinearize_internal( + Ciphertext &encrypted, const RelinKeys &relin_keys, size_t destination_size, MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (relin_keys.parms_id() != context_->key_parms_id()) + { + throw invalid_argument("relin_keys is not valid for encryption parameters"); + } + + size_t encrypted_size = encrypted.size(); + + // Verify parameters. + if (destination_size < 2 || destination_size > encrypted_size) + { + throw invalid_argument("destination_size must be at least 2 and less than or equal to current count"); + } + if (relin_keys.size() < sub_safe(encrypted_size, size_t(2))) + { + throw invalid_argument("not enough relinearization keys"); + } + + // If encrypted is already at the desired level, return + if (destination_size == encrypted_size) + { + return; + } + + // Calculate number of relinearize_one_step calls needed + size_t relins_needed = encrypted_size - destination_size; + + // Iterator pointing to the last component of encrypted + PolyIter encrypted_iter(encrypted); + advance(encrypted_iter, safe_cast<ptrdiff_t>(encrypted_size - 1)); + + for (size_t i = 0; i < relins_needed; i++) + { + switch_key_inplace( + encrypted, *encrypted_iter, static_cast<const KSwitchKeys &>(relin_keys), + RelinKeys::get_index(encrypted_size - 1), pool); + encrypted_size--; + } + + // Put the output of final relinearization into destination. + // Prepare destination only at this point because we are resizing down + encrypted.resize(context_, context_data_ptr->parms_id(), destination_size); +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::mod_switch_scale_to_next( + const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool) + { + // Assuming at this point encrypted is already validated. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (context_data_ptr->parms().scheme() == scheme_type::BFV && encrypted.is_ntt_form()) + { + throw invalid_argument("BFV encrypted cannot be in NTT form"); + } + if (context_data_ptr->parms().scheme() == scheme_type::CKKS && !encrypted.is_ntt_form()) + { + throw invalid_argument("CKKS encrypted must be in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + auto &next_context_data = *context_data.next_context_data(); + auto &next_parms = next_context_data.parms(); + auto rns_tool = context_data.rns_tool(); + + size_t encrypted_size = encrypted.size(); + size_t coeff_count = next_parms.poly_modulus_degree(); + size_t next_coeff_modulus_size = next_parms.coeff_modulus().size(); + + Ciphertext encrypted_copy(pool); + encrypted_copy = encrypted; + + switch (next_parms.scheme()) + { + case scheme_type::BFV: + for_each_n(PolyIter(encrypted_copy), encrypted_size, [&](auto I) { + rns_tool->divide_and_round_q_last_inplace(I, pool); + }); + break; + + case scheme_type::CKKS: + for_each_n(PolyIter(encrypted_copy), encrypted_size, [&](auto I) { + rns_tool->divide_and_round_q_last_ntt_inplace(I, context_data.small_ntt_tables(), pool); + }); + break; + + default: + throw invalid_argument("unsupported scheme"); + } + + // Copy result to destination + destination.resize(context_, next_context_data.parms_id(), encrypted_size); + for_each_n(IterTuple<ConstPolyIter, PolyIter>(encrypted_copy, destination), encrypted_size, [&](auto I) { + set_poly_poly(get<0>(I), coeff_count, next_coeff_modulus_size, get<1>(I)); + }); + + // Set other attributes + destination.is_ntt_form() = encrypted.is_ntt_form(); + if (next_parms.scheme() == scheme_type::CKKS) + { + // Change the scale when using CKKS + destination.scale() = + encrypted.scale() / static_cast<double>(context_data.parms().coeff_modulus().back().value()); + } + } + + void Evaluator::mod_switch_drop_to_next(const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool) + { + // Assuming at this point encrypted is already validated. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (context_data_ptr->parms().scheme() == scheme_type::CKKS && !encrypted.is_ntt_form()) + { + throw invalid_argument("CKKS encrypted must be in NTT form"); + } + + // Extract encryption parameters. + auto &next_context_data = *context_data_ptr->next_context_data(); + auto &next_parms = next_context_data.parms(); + + // Check that scale is positive and not too large + if (encrypted.scale() <= 0 || + (static_cast<int>(log2(encrypted.scale())) >= next_context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // q_1,...,q_{k-1} + size_t next_coeff_modulus_size = next_parms.coeff_modulus().size(); + size_t coeff_count = next_parms.poly_modulus_degree(); + size_t encrypted_size = encrypted.size(); + + // Size check + if (!product_fits_in(encrypted_size, coeff_count, next_coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + size_t rns_poly_total_count = next_coeff_modulus_size * coeff_count; + + auto drop_moduli_and_copy = [&](ConstPolyIter in_iter, PolyIter out_iter) { + for_each_n(IterTuple<ConstPolyIter, PolyIter>(in_iter, out_iter), encrypted_size, [&](auto I) { + for_each_n( + I, next_coeff_modulus_size, [&](auto J) { set_uint_uint(get<0>(J), coeff_count, get<1>(J)); }); + }); + }; + + if (&encrypted == &destination) + { + // Switching in-place so need temporary space + auto temp(allocate_uint(rns_poly_total_count * encrypted_size, pool)); + + // Copy data over to temp; only copy the RNS components relevant after modulus drop + drop_moduli_and_copy(encrypted, { temp.get(), coeff_count, next_coeff_modulus_size }); + + // Resize destination before writing + destination.resize(context_, next_context_data.parms_id(), encrypted_size); + destination.is_ntt_form() = true; + destination.scale() = encrypted.scale(); + + // Copy data to destination + set_uint_uint(temp.get(), rns_poly_total_count * encrypted_size, destination.data()); + } + else + { + // Resize destination before writing + destination.resize(context_, next_context_data.parms_id(), encrypted_size); + destination.is_ntt_form() = true; + destination.scale() = encrypted.scale(); + + // Copy data over to destination; only copy the RNS components relevant after modulus drop + drop_moduli_and_copy(encrypted, destination); + } + } + + void Evaluator::mod_switch_drop_to_next(Plaintext &plain) + { + // Assuming at this point plain is already validated. + auto context_data_ptr = context_->get_context_data(plain.parms_id()); + if (!plain.is_ntt_form()) + { + throw invalid_argument("plain is not in NTT form"); + } + if (!context_data_ptr->next_context_data()) + { + throw invalid_argument("end of modulus switching chain reached"); + } + + // Extract encryption parameters. + auto &next_context_data = *context_data_ptr->next_context_data(); + auto &next_parms = context_data_ptr->next_context_data()->parms(); + + // Check that scale is positive and not too large + if (plain.scale() <= 0 || + (static_cast<int>(log2(plain.scale())) >= next_context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // q_1,...,q_{k-1} + auto &next_coeff_modulus = next_parms.coeff_modulus(); + size_t next_coeff_modulus_size = next_coeff_modulus.size(); + size_t coeff_count = next_parms.poly_modulus_degree(); + + // Compute destination size first for exception safety + auto dest_size = mul_safe(next_coeff_modulus_size, coeff_count); + + plain.parms_id() = parms_id_zero; + plain.resize(dest_size); + plain.parms_id() = next_context_data.parms_id(); + } + + void Evaluator::mod_switch_to_next(const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (context_->last_parms_id() == encrypted.parms_id()) + { + throw invalid_argument("end of modulus switching chain reached"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + switch (context_->first_context_data()->parms().scheme()) + { + case scheme_type::BFV: + // Modulus switching with scaling + mod_switch_scale_to_next(encrypted, destination, move(pool)); + break; + + case scheme_type::CKKS: + // Modulus switching without scaling + mod_switch_drop_to_next(encrypted, destination, move(pool)); + break; + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (destination.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::mod_switch_to_inplace(Ciphertext &encrypted, parms_id_type parms_id, MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + auto target_context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!target_context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + if (context_data_ptr->chain_index() < target_context_data_ptr->chain_index()) + { + throw invalid_argument("cannot switch to higher level modulus"); + } + + while (encrypted.parms_id() != parms_id) + { + mod_switch_to_next_inplace(encrypted, pool); + } + } + + void Evaluator::mod_switch_to_inplace(Plaintext &plain, parms_id_type parms_id) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(plain.parms_id()); + auto target_context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (!context_->get_context_data(parms_id)) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + if (!plain.is_ntt_form()) + { + throw invalid_argument("plain is not in NTT form"); + } + if (context_data_ptr->chain_index() < target_context_data_ptr->chain_index()) + { + throw invalid_argument("cannot switch to higher level modulus"); + } + + while (plain.parms_id() != parms_id) + { + mod_switch_to_next_inplace(plain); + } + } + + void Evaluator::rescale_to_next(const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (context_->last_parms_id() == encrypted.parms_id()) + { + throw invalid_argument("end of modulus switching chain reached"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + switch (context_->first_context_data()->parms().scheme()) + { + case scheme_type::BFV: + throw invalid_argument("unsupported operation for scheme type"); + + case scheme_type::CKKS: + // Modulus switching with scaling + mod_switch_scale_to_next(encrypted, destination, move(pool)); + break; + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (destination.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::rescale_to_inplace(Ciphertext &encrypted, parms_id_type parms_id, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + auto target_context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!target_context_data_ptr) + { + throw invalid_argument("parms_id is not valid for encryption parameters"); + } + if (context_data_ptr->chain_index() < target_context_data_ptr->chain_index()) + { + throw invalid_argument("cannot switch to higher level modulus"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + switch (context_data_ptr->parms().scheme()) + { + case scheme_type::BFV: + throw invalid_argument("unsupported operation for scheme type"); + + case scheme_type::CKKS: + while (encrypted.parms_id() != parms_id) + { + // Modulus switching with scaling + mod_switch_scale_to_next(encrypted, encrypted, pool); + } + break; + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::multiply_many( + const vector<Ciphertext> &encrypteds, const RelinKeys &relin_keys, Ciphertext &destination, + MemoryPoolHandle pool) + { + // Verify parameters. + if (encrypteds.size() == 0) + { + throw invalid_argument("encrypteds vector must not be empty"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + for (size_t i = 0; i < encrypteds.size(); i++) + { + if (&encrypteds[i] == &destination) + { + throw invalid_argument("encrypteds must be different from destination"); + } + } + + // There is at least one ciphertext + auto context_data_ptr = context_->get_context_data(encrypteds[0].parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypteds is not valid for encryption parameters"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + + if (parms.scheme() != scheme_type::BFV) + { + throw logic_error("unsupported scheme"); + } + + // If there is only one ciphertext, return it. + if (encrypteds.size() == 1) + { + destination = encrypteds[0]; + return; + } + + // Do first level of multiplications + vector<Ciphertext> product_vec; + for (size_t i = 0; i < encrypteds.size() - 1; i += 2) + { + Ciphertext temp(context_, context_data.parms_id(), pool); + if (encrypteds[i].data() == encrypteds[i + 1].data()) + { + square(encrypteds[i], temp); + } + else + { + multiply(encrypteds[i], encrypteds[i + 1], temp); + } + relinearize_inplace(temp, relin_keys, pool); + product_vec.emplace_back(move(temp)); + } + if (encrypteds.size() & 1) + { + product_vec.emplace_back(encrypteds.back()); + } + + // Repeatedly multiply and add to the back of the vector until the end is reached + for (size_t i = 0; i < product_vec.size() - 1; i += 2) + { + Ciphertext temp(context_, context_data.parms_id(), pool); + multiply(product_vec[i], product_vec[i + 1], temp); + relinearize_inplace(temp, relin_keys, pool); + product_vec.emplace_back(move(temp)); + } + + destination = product_vec.back(); + } + + void Evaluator::exponentiate_inplace( + Ciphertext &encrypted, uint64_t exponent, const RelinKeys &relin_keys, MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!context_->get_context_data(relin_keys.parms_id())) + { + throw invalid_argument("relin_keys is not valid for encryption parameters"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + if (exponent == 0) + { + throw invalid_argument("exponent cannot be 0"); + } + + // Fast case + if (exponent == 1) + { + return; + } + + // Create a vector of copies of encrypted + vector<Ciphertext> exp_vector(static_cast<size_t>(exponent), encrypted); + multiply_many(exp_vector, relin_keys, encrypted, move(pool)); + } + + void Evaluator::add_plain_inplace(Ciphertext &encrypted, const Plaintext &plain) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(plain, context_) || !is_buffer_valid(plain)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + if (parms.scheme() == scheme_type::BFV && encrypted.is_ntt_form()) + { + throw invalid_argument("BFV encrypted cannot be in NTT form"); + } + if (parms.scheme() == scheme_type::CKKS && !encrypted.is_ntt_form()) + { + throw invalid_argument("CKKS encrypted must be in NTT form"); + } + if (plain.is_ntt_form() != encrypted.is_ntt_form()) + { + throw invalid_argument("NTT form mismatch"); + } + if (encrypted.is_ntt_form() && (encrypted.parms_id() != plain.parms_id())) + { + throw invalid_argument("encrypted and plain parameter mismatch"); + } + if (!are_same_scale(encrypted, plain)) + { + throw invalid_argument("scale mismatch"); + } + + // Extract encryption parameters. + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + switch (parms.scheme()) + { + case scheme_type::BFV: + { + multiply_add_plain_with_scaling_variant(plain, context_data, encrypted.data()); + break; + } + + case scheme_type::CKKS: + { + RNSIter encrypted_iter(encrypted.data(), coeff_count); + ConstRNSIter plain_iter(plain.data(), coeff_count); + for_each_n( + IterTuple<RNSIter, ConstRNSIter, PtrIter<const Modulus *>>(encrypted_iter, plain_iter, coeff_modulus), + coeff_modulus_size, + [&](auto I) { add_poly_poly_coeffmod(get<0>(I), get<1>(I), coeff_count, *get<2>(I), get<0>(I)); }); + break; + } + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::sub_plain_inplace(Ciphertext &encrypted, const Plaintext &plain) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(plain, context_) || !is_buffer_valid(plain)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + if (parms.scheme() == scheme_type::BFV && encrypted.is_ntt_form()) + { + throw invalid_argument("BFV encrypted cannot be in NTT form"); + } + if (parms.scheme() == scheme_type::CKKS && !encrypted.is_ntt_form()) + { + throw invalid_argument("CKKS encrypted must be in NTT form"); + } + if (plain.is_ntt_form() != encrypted.is_ntt_form()) + { + throw invalid_argument("NTT form mismatch"); + } + if (encrypted.is_ntt_form() && (encrypted.parms_id() != plain.parms_id())) + { + throw invalid_argument("encrypted and plain parameter mismatch"); + } + if (!are_same_scale(encrypted, plain)) + { + throw invalid_argument("scale mismatch"); + } + + // Extract encryption parameters. + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + switch (parms.scheme()) + { + case scheme_type::BFV: + { + multiply_sub_plain_with_scaling_variant(plain, context_data, encrypted.data()); + break; + } + + case scheme_type::CKKS: + { + RNSIter encrypted_iter(encrypted.data(), coeff_count); + ConstRNSIter plain_iter(plain.data(), coeff_count); + for_each_n( + IterTuple<RNSIter, ConstRNSIter, PtrIter<const Modulus *>>(encrypted_iter, plain_iter, coeff_modulus), + coeff_modulus_size, + [&](auto I) { sub_poly_poly_coeffmod(get<0>(I), get<1>(I), coeff_count, *get<2>(I), get<0>(I)); }); + break; + } + + default: + throw invalid_argument("unsupported scheme"); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::multiply_plain_inplace(Ciphertext &encrypted, const Plaintext &plain, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!is_metadata_valid_for(plain, context_) || !is_buffer_valid(plain)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + if (encrypted.is_ntt_form() != plain.is_ntt_form()) + { + throw invalid_argument("NTT form mismatch"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + if (encrypted.is_ntt_form()) + { + multiply_plain_ntt(encrypted, plain); + } + else + { + multiply_plain_normal(encrypted, plain, move(pool)); + } +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::multiply_plain_normal(Ciphertext &encrypted, const Plaintext &plain, MemoryPoolHandle pool) + { + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + auto plain_upper_half_threshold = context_data.plain_upper_half_threshold(); + auto plain_upper_half_increment = context_data.plain_upper_half_increment(); + auto coeff_modulus_ntt_tables = context_data.small_ntt_tables(); + + size_t encrypted_size = encrypted.size(); + size_t plain_coeff_count = plain.coeff_count(); + size_t plain_nonzero_coeff_count = plain.nonzero_coeff_count(); + + // Size check + if (!product_fits_in(encrypted_size, coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + double new_scale = encrypted.scale() * plain.scale(); + + // Check that scale is positive and not too large + if (new_scale <= 0 || (static_cast<int>(log2(new_scale)) >= context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + // Set the scale + encrypted.scale() = new_scale; + + /* + Optimizations for constant / monomial multiplication can lead to the presence of a timing side-channel in + use-cases where the plaintext data should also be kept private. + */ + if (plain_nonzero_coeff_count == 1) + { + // Multiplying by a monomial? + size_t mono_exponent = plain.significant_coeff_count() - 1; + + if (plain[mono_exponent] >= plain_upper_half_threshold) + { + if (!context_data.qualifiers().using_fast_plain_lift) + { + // Allocate temporary space for a single RNS coefficient + auto temp(allocate_uint(coeff_modulus_size, pool)); + + // We need to adjust the monomial modulo each coeff_modulus prime separately when the coeff_modulus + // primes may be larger than the plain_modulus. We add plain_upper_half_increment (i.e., q-t) to + // the monomial to ensure it is smaller than coeff_modulus and then do an RNS multiplication. Note + // that in this case plain_upper_half_increment contains a multi-precision integer, so after the + // addition we decompose the multi-precision integer into RNS components, and then multiply. + add_uint_uint64(plain_upper_half_increment, plain[mono_exponent], coeff_modulus_size, temp.get()); + context_data.rns_tool()->base_q()->decompose(temp.get(), pool); + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, ConstCoeffIter, PtrIter<const Modulus *>>(I, temp.get(), coeff_modulus), + coeff_modulus_size, [&](auto J) { + negacyclic_multiply_poly_mono_coeffmod( + get<0>(J), coeff_count, *get<1>(J), mono_exponent, *get<2>(J), get<0>(J), pool); + }); + }); + } + else + { + // Every coeff_modulus prime is larger than plain_modulus, so there is no need to adjust the + // monomial. Instead, just do an RNS multiplication. + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, + [&](auto J) { + negacyclic_multiply_poly_mono_coeffmod( + get<0>(J), coeff_count, plain[mono_exponent], mono_exponent, *get<1>(J), get<0>(J), + pool); + }); + }); + } + } + else + { + // The monomial represents a positive number, so no RNS multiplication is needed. + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, + [&](auto J) { + negacyclic_multiply_poly_mono_coeffmod( + get<0>(J), coeff_count, plain[mono_exponent], mono_exponent, *get<1>(J), get<0>(J), + pool); + }); + }); + } + + return; + } + + // Generic case: any plaintext polynomial + // Allocate temporary space for an entire RNS polynomial + auto temp(allocate_zero_uint(coeff_count * coeff_modulus_size, pool)); + + if (!context_data.qualifiers().using_fast_plain_lift) + { + // Slight semantic misuse of RNSIter here, but this works well + RNSIter temp_iter(temp.get(), coeff_modulus_size); + + for_each_n(IterTuple<ConstCoeffIter, RNSIter>(plain.data(), temp_iter), plain_coeff_count, [&](auto I) { + auto plain_value = *get<0>(I); + if (plain_value >= plain_upper_half_threshold) + { + add_uint_uint64(plain_upper_half_increment, plain_value, coeff_modulus_size, get<1>(I)); + } + else + { + **get<1>(I) = plain_value; + } + }); + + for_each_n(RNSIter(temp.get(), coeff_count), coeff_modulus_size, [&](auto I) { + context_data.rns_tool()->base_q()->decompose_array(I, coeff_count, pool); + }); + } + else + { + // Note that in this case plain_upper_half_increment holds its value in RNS form modulo the coeff_modulus + // primes. + RNSIter temp_iter(temp.get(), coeff_count); + for_each_n( + IterTuple<RNSIter, PtrIter<const uint64_t *>>(temp_iter, plain_upper_half_increment), + coeff_modulus_size, [&](auto I) { + SEAL_ASSERT_TYPE(get<0>(I), CoeffIter, "temp"); + SEAL_ASSERT_TYPE(get<1>(I), const uint64_t *, "plain_upper_half_increment"); + for_each_n( + IterTuple<CoeffIter, ConstCoeffIter>(get<0>(I), plain.data()), plain_coeff_count, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), uint64_t *, "temp"); + SEAL_ASSERT_TYPE(get<1>(J), const uint64_t *, "plain"); + *get<0>(J) = *get<1>(J) + (*get<1>(I) & static_cast<uint64_t>(-static_cast<int64_t>( + *get<1>(J) >= plain_upper_half_threshold))); + }); + }); + } + + // Need to multiply each component in encrypted with temp; first step is to transform to NTT form + RNSIter temp_iter(temp.get(), coeff_count); + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(temp_iter, coeff_modulus_ntt_tables), coeff_modulus_size, + [&](auto I) { ntt_negacyclic_harvey(get<0>(I), *get<1>(I)); }); + + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, ConstRNSIter, PtrIter<const Modulus *>, PtrIter<const NTTTables *>>( + I, temp_iter, coeff_modulus, coeff_modulus_ntt_tables), + coeff_modulus_size, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), CoeffIter, "encrypted"); + SEAL_ASSERT_TYPE(get<1>(J), ConstCoeffIter, "temp"); + SEAL_ASSERT_TYPE(get<2>(J), const Modulus *, "coeff_modulus"); + SEAL_ASSERT_TYPE(get<3>(J), const NTTTables *, "coeff_modulus_ntt_tables"); + + // Lazy reduction + ntt_negacyclic_harvey_lazy(get<0>(J), *get<3>(J)); + + dyadic_product_coeffmod(get<0>(J), get<1>(J), coeff_count, *get<2>(J), get<0>(J)); + inverse_ntt_negacyclic_harvey(get<0>(J), *get<3>(J)); + }); + }); + } + + void Evaluator::multiply_plain_ntt(Ciphertext &encrypted_ntt, const Plaintext &plain_ntt) + { + // Verify parameters. + if (!plain_ntt.is_ntt_form()) + { + throw invalid_argument("plain_ntt is not in NTT form"); + } + if (encrypted_ntt.parms_id() != plain_ntt.parms_id()) + { + throw invalid_argument("encrypted_ntt and plain_ntt parameter mismatch"); + } + + // Extract encryption parameters. + auto &context_data = *context_->get_context_data(encrypted_ntt.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted_ntt_size = encrypted_ntt.size(); + + // Size check + if (!product_fits_in(encrypted_ntt_size, coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + double new_scale = encrypted_ntt.scale() * plain_ntt.scale(); + + // Check that scale is positive and not too large + if (new_scale <= 0 || (static_cast<int>(log2(new_scale)) >= context_data.total_coeff_modulus_bit_count())) + { + throw invalid_argument("scale out of bounds"); + } + + ConstRNSIter plain_ntt_iter(plain_ntt.data(), coeff_count); + for_each_n(PolyIter(encrypted_ntt), encrypted_ntt_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, ConstRNSIter, PtrIter<const Modulus *>>(I, plain_ntt_iter, coeff_modulus), + coeff_modulus_size, + [&](auto J) { dyadic_product_coeffmod(get<0>(J), get<1>(J), coeff_count, *get<2>(J), get<0>(J)); }); + }); + + // Set the scale + encrypted_ntt.scale() = new_scale; + } + + void Evaluator::transform_to_ntt_inplace(Plaintext &plain, parms_id_type parms_id, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_valid_for(plain, context_)) + { + throw invalid_argument("plain is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->get_context_data(parms_id); + if (!context_data_ptr) + { + throw invalid_argument("parms_id is not valid for the current context"); + } + if (plain.is_ntt_form()) + { + throw invalid_argument("plain is already in NTT form"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t plain_coeff_count = plain.coeff_count(); + + auto plain_upper_half_threshold = context_data.plain_upper_half_threshold(); + auto plain_upper_half_increment = context_data.plain_upper_half_increment(); + + auto coeff_modulus_ntt_tables = context_data.small_ntt_tables(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Resize to fit the entire NTT transformed (ciphertext size) polynomial + // Note that the new coefficients are automatically set to 0 + plain.resize(coeff_count * coeff_modulus_size); + + if (!context_data.qualifiers().using_fast_plain_lift) + { + // Allocate temporary space for an entire RNS polynomial + auto temp(allocate_zero_uint(coeff_count * coeff_modulus_size, pool)); + + // Slight semantic misuse of RNSIter here, but this works well + RNSIter temp_iter(temp.get(), coeff_modulus_size); + + for_each_n(IterTuple<ConstCoeffIter, RNSIter>(plain.data(), temp_iter), plain_coeff_count, [&](auto I) { + auto plain_value = *get<0>(I); + if (plain_value >= plain_upper_half_threshold) + { + add_uint_uint64(plain_upper_half_increment, plain_value, coeff_modulus_size, get<1>(I)); + } + else + { + **get<1>(I) = plain_value; + } + }); + + for_each_n(RNSIter(temp.get(), coeff_count), coeff_modulus_size, [&](auto I) { + context_data.rns_tool()->base_q()->decompose_array(I, coeff_count, pool); + }); + + // Copy data back to plain + set_poly_poly(temp.get(), coeff_count, coeff_modulus_size, plain.data()); + } + else + { + // Note that in this case plain_upper_half_increment holds its value in RNS form modulo the coeff_modulus + // primes. + RNSIter plain_iter(plain.data(), coeff_count); + + // Create a "reversed" helper iterator that iterates in the reverse order both plain RNS components and + // the plain_upper_half_increment values. + IterTuple<RNSIter, PtrIter<const uint64_t *>> helper_iter(plain_iter, plain_upper_half_increment); + advance(helper_iter, safe_cast<ptrdiff_t>(coeff_modulus_size - 1)); + auto reversed_helper_iter = ReverseIter<decltype(helper_iter)>(helper_iter); + + for_each_n(reversed_helper_iter, coeff_modulus_size, [&](auto I) { + SEAL_ASSERT_TYPE(get<0>(I), CoeffIter, "reversed plain"); + SEAL_ASSERT_TYPE(get<1>(I), const uint64_t *, "reversed plain_upper_half_increment"); + + for_each_n(IterTuple<CoeffIter, CoeffIter>(*plain_iter, get<0>(I)), plain_coeff_count, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), uint64_t *, "plain"); + SEAL_ASSERT_TYPE(get<1>(J), uint64_t *, "reversed plain"); + *get<1>(J) = *get<0>(J) + (*get<1>(I) & static_cast<uint64_t>(-static_cast<int64_t>( + *get<0>(J) >= plain_upper_half_threshold))); + }); + }); + } + + // Transform to NTT domain + RNSIter plain_iter(plain.data(), coeff_count); + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(plain_iter, coeff_modulus_ntt_tables), coeff_modulus_size, + [&](auto I) { ntt_negacyclic_harvey(get<0>(I), *get<1>(I)); }); + + plain.parms_id() = parms_id; + } + + void Evaluator::transform_to_ntt_inplace(Ciphertext &encrypted) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (encrypted.is_ntt_form()) + { + throw invalid_argument("encrypted is already in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted_size = encrypted.size(); + + auto coeff_modulus_ntt_tables = context_data.small_ntt_tables(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Transform each polynomial to NTT domain + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(I, coeff_modulus_ntt_tables), coeff_modulus_size, + [&](auto J) { ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + }); + + // Finally change the is_ntt_transformed flag + encrypted.is_ntt_form() = true; +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::transform_from_ntt_inplace(Ciphertext &encrypted_ntt) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted_ntt, context_) || !is_buffer_valid(encrypted_ntt)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + auto context_data_ptr = context_->get_context_data(encrypted_ntt.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypted_ntt is not valid for encryption parameters"); + } + if (!encrypted_ntt.is_ntt_form()) + { + throw invalid_argument("encrypted_ntt is not in NTT form"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = parms.coeff_modulus().size(); + size_t encrypted_ntt_size = encrypted_ntt.size(); + + auto coeff_modulus_ntt_tables = context_data.small_ntt_tables(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Transform each polynomial from NTT domain + for_each_n(PolyIter(encrypted_ntt), encrypted_ntt_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(I, coeff_modulus_ntt_tables), coeff_modulus_size, + [&](auto J) { inverse_ntt_negacyclic_harvey(get<0>(J), *get<1>(J)); }); + }); + + // Finally change the is_ntt_transformed flag + encrypted_ntt.is_ntt_form() = false; +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted_ntt.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::apply_galois_inplace( + Ciphertext &encrypted, uint32_t galois_elt, const GaloisKeys &galois_keys, MemoryPoolHandle pool) + { + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + + // Don't validate all of galois_keys but just check the parms_id. + if (galois_keys.parms_id() != context_->key_parms_id()) + { + throw invalid_argument("galois_keys is not valid for encryption parameters"); + } + + auto &context_data = *context_->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t encrypted_size = encrypted.size(); + // Use key_context_data where permutation tables exist since previous runs. + auto galois_tool = context_->key_context_data()->galois_tool(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Check if Galois key is generated or not. + if (!galois_keys.has_key(galois_elt)) + { + throw invalid_argument("Galois key not present"); + } + + uint64_t m = mul_safe(static_cast<uint64_t>(coeff_count), uint64_t(2)); + + // Verify parameters + if (!(galois_elt & 1) || unsigned_geq(galois_elt, m)) + { + throw invalid_argument("Galois element is not valid"); + } + if (encrypted_size > 2) + { + throw invalid_argument("encrypted size must be 2"); + } + + auto temp(allocate_poly(coeff_count, coeff_modulus_size, pool)); + RNSIter temp_iter(temp.get(), coeff_count); + + // DO NOT CHANGE EXECUTION ORDER OF FOLLOWING SECTION + // BEGIN: Apply Galois for each ciphertext + // Execution order is sensitive, since apply_galois is not inplace! + if (parms.scheme() == scheme_type::BFV) + { + auto apply_galois_helper = [&](auto in_iter, auto out_iter) { + for_each_n( + IterTuple<RNSIter, RNSIter, PtrIter<const Modulus *>>(in_iter, out_iter, coeff_modulus), + coeff_modulus_size, + [&](auto I) { galois_tool->apply_galois(get<0>(I), galois_elt, *get<2>(I), get<1>(I)); }); + }; + + // !!! DO NOT CHANGE EXECUTION ORDER!!! + + // First transform encrypted.data(0) + PolyIter encrypted_iter(encrypted); + apply_galois_helper(encrypted_iter[0], temp_iter); + + // Copy result to encrypted.data(0) + set_poly_poly(temp.get(), coeff_count, coeff_modulus_size, encrypted.data(0)); + + // Next transform encrypted.data(1) + apply_galois_helper(encrypted_iter[1], temp_iter); + } + else if (parms.scheme() == scheme_type::CKKS) + { + auto apply_galois_helper_ntt = [&](auto in_iter, auto out_iter) { + for_each_n(IterTuple<RNSIter, RNSIter>(in_iter, out_iter), coeff_modulus_size, [&](auto I) { + const_cast<GaloisTool *>(galois_tool)->apply_galois_ntt(get<0>(I), galois_elt, get<1>(I)); + }); + }; + + // !!! DO NOT CHANGE EXECUTION ORDER!!! + + // First transform encrypted.data(0) + PolyIter encrypted_iter(encrypted); + apply_galois_helper_ntt(encrypted_iter[0], temp_iter); + + // Copy result to encrypted.data(0) + set_poly_poly(temp.get(), coeff_count, coeff_modulus_size, encrypted.data(0)); + + // Next transform encrypted.data(1) + apply_galois_helper_ntt(encrypted_iter[1], temp_iter); + } + else + { + throw logic_error("scheme not implemented"); + } + + // Wipe encrypted.data(1) + set_zero_poly(coeff_count, coeff_modulus_size, encrypted.data(1)); + + // END: Apply Galois for each ciphertext + // REORDERING IS SAFE NOW + + // Calculate (temp * galois_key[0], temp * galois_key[1]) + (ct[0], 0) + switch_key_inplace( + encrypted, temp_iter, static_cast<const KSwitchKeys &>(galois_keys), GaloisKeys::get_index(galois_elt), + pool); +#ifdef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + // Transparent ciphertext output is not allowed. + if (encrypted.is_transparent()) + { + throw logic_error("result ciphertext is transparent"); + } +#endif + } + + void Evaluator::rotate_internal( + Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, MemoryPoolHandle pool) + { + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (!context_data_ptr) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!context_data_ptr->qualifiers().using_batching) + { + throw logic_error("encryption parameters do not support batching"); + } + if (galois_keys.parms_id() != context_->key_parms_id()) + { + throw invalid_argument("galois_keys is not valid for encryption parameters"); + } + + // Is there anything to do? + if (steps == 0) + { + return; + } + + size_t coeff_count = context_data_ptr->parms().poly_modulus_degree(); + auto galois_tool = context_data_ptr->galois_tool(); + + // Check if Galois key is generated or not. + if (galois_keys.has_key(galois_tool->get_elt_from_step(steps))) + { + // Perform rotation and key switching + apply_galois_inplace(encrypted, galois_tool->get_elt_from_step(steps), galois_keys, move(pool)); + } + else + { + // Convert the steps to NAF: guarantees using smallest HW + vector<int> naf_steps = naf(steps); + + // If naf_steps contains only one element, then this is a power-of-two + // rotation and we would have expected not to get to this part of the + // if-statement. + if (naf_steps.size() == 1) + { + throw invalid_argument("Galois key not present"); + } + + for_each_n(naf_steps.cbegin(), naf_steps.size(), [&](auto step) { + // We might have a NAF-term of size coeff_count / 2; this corresponds + // to no rotation so we skip it. Otherwise call rotate_internal. + if (safe_cast<size_t>(abs(step)) != (coeff_count >> 1)) + { + // Apply rotation for this step + rotate_internal(encrypted, step, galois_keys, pool); + } + }); + } + } + + void Evaluator::switch_key_inplace( + Ciphertext &encrypted, ConstRNSIter target_iter, const KSwitchKeys &kswitch_keys, size_t kswitch_keys_index, + MemoryPoolHandle pool) + { + auto parms_id = encrypted.parms_id(); + auto &context_data = *context_->get_context_data(parms_id); + auto &parms = context_data.parms(); + auto &key_context_data = *context_->key_context_data(); + auto &key_parms = key_context_data.parms(); + auto scheme = parms.scheme(); + + // Verify parameters. + if (!is_metadata_valid_for(encrypted, context_) || !is_buffer_valid(encrypted)) + { + throw invalid_argument("encrypted is not valid for encryption parameters"); + } + if (!target_iter) + { + throw invalid_argument("target_iter"); + } + if (!context_->using_keyswitching()) + { + throw logic_error("keyswitching is not supported by the context"); + } + + // Don't validate all of kswitch_keys but just check the parms_id. + if (kswitch_keys.parms_id() != context_->key_parms_id()) + { + throw invalid_argument("parameter mismatch"); + } + + if (kswitch_keys_index >= kswitch_keys.data().size()) + { + throw out_of_range("kswitch_keys_index"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + if (scheme == scheme_type::BFV && encrypted.is_ntt_form()) + { + throw invalid_argument("BFV encrypted cannot be in NTT form"); + } + if (scheme == scheme_type::CKKS && !encrypted.is_ntt_form()) + { + throw invalid_argument("CKKS encrypted must be in NTT form"); + } + + // Extract encryption parameters. + size_t coeff_count = parms.poly_modulus_degree(); + size_t decomp_modulus_size = parms.coeff_modulus().size(); + auto &key_modulus = key_parms.coeff_modulus(); + size_t key_modulus_size = key_modulus.size(); + size_t rns_modulus_size = decomp_modulus_size + 1; + auto key_ntt_tables = key_context_data.small_ntt_tables(); + auto modswitch_factors = key_context_data.rns_tool()->inv_q_last_mod_q(); + + // Size check + if (!product_fits_in(coeff_count, rns_modulus_size, size_t(2))) + { + throw logic_error("invalid parameters"); + } + + // Prepare input + auto &key_vector = kswitch_keys.data()[kswitch_keys_index]; + size_t key_component_count = key_vector[0].data().size(); + + // Check only the used component in KSwitchKeys. + for (auto &each_key : key_vector) + { + if (!is_metadata_valid_for(each_key, context_) || !is_buffer_valid(each_key)) + { + throw invalid_argument("kswitch_keys is not valid for encryption parameters"); + } + } + + // Create a copy of target_iter + Pointer<uint64_t> t_target(allocate_poly(coeff_count, decomp_modulus_size, pool)); + RNSIter t_target_iter(t_target.get(), coeff_count); + set_uint_uint(target_iter, decomp_modulus_size * coeff_count, t_target.get()); + + // In CKKS t_target is in NTT form; switch back to normal form + if (scheme == scheme_type::CKKS) + { + for_each_n( + IterTuple<RNSIter, PtrIter<const NTTTables *>>(t_target_iter, key_ntt_tables), decomp_modulus_size, + [&](auto I) { inverse_ntt_negacyclic_harvey(get<0>(I), *get<1>(I)); }); + } + + // Temporary result + auto t_poly_prod(allocate_zero_poly(coeff_count, rns_modulus_size * key_component_count, pool)); + + for (size_t j = 0; j < rns_modulus_size; j++) + { + size_t key_index = (j == decomp_modulus_size ? key_modulus_size - 1 : j); + + // Product of two numbers is up to 60 + 60 = 120 bits, so we can sum up to 256 of them without reduction. + size_t lazy_reduction_summand_bound = size_t(SEAL_MULTIPLY_ACCUMULATE_USER_MOD_MAX); + size_t lazy_reduction_counter = lazy_reduction_summand_bound; + + // Allocate memory for a lazy accumulator (128-bit coefficients) + auto t_poly_lazy(allocate_zero_poly(coeff_count * 2, key_component_count, pool)); + + // Semantic misuse of PolyIter; this is really pointing to the data for a single RNS factor + PolyIter accumulator_iter(t_poly_lazy.get(), 2, coeff_count); + + // Multiply with keys and perform lazy reduction on product's coefficients + for (size_t i = 0; i < decomp_modulus_size; i++) + { + auto t_ntt(allocate_uint(coeff_count, pool)); + CoeffIter t_ntt_iter(t_ntt.get()); + ConstCoeffIter t_operand_iter; + + // RNS-NTT form exists in input + if ((scheme == scheme_type::CKKS) && (i == j)) + { + t_operand_iter = target_iter[i]; + } + // Perform RNS-NTT conversion + else + { + // No need to perform RNS conversion (modular reduction) + if (key_modulus[i].value() <= key_modulus[key_index].value()) + { + set_uint_uint(t_target_iter[i], coeff_count, t_ntt.get()); + } + // Perform RNS conversion (modular reduction) + else + { + modulo_poly_coeffs_63(t_target_iter[i], coeff_count, key_modulus[key_index], t_ntt_iter); + } + // NTT conversion lazy outputs in [0, 4q) + ntt_negacyclic_harvey_lazy(t_ntt_iter, key_ntt_tables[key_index]); + t_operand_iter = t_ntt_iter; + } + + // Multiply with keys and modular accumulate products in a lazy fashion + for_each_n( + IterTuple<ConstPolyIter, PolyIter>(key_vector[i].data(), accumulator_iter), key_component_count, + [&](auto I) { + SEAL_ASSERT_TYPE(get<0>(I), ConstRNSIter, "key_vector[i]"); + SEAL_ASSERT_TYPE(get<1>(I), RNSIter, "accumulator"); + + if (!lazy_reduction_counter) + { + for_each_n( + IterTuple<ConstCoeffIter, ConstCoeffIter, RNSIter>( + t_operand_iter, get<0>(I)[key_index], get<1>(I)), + coeff_count, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), const uint64_t *, "t_operand"); + SEAL_ASSERT_TYPE(get<1>(J), const uint64_t *, "key_vector[i][key_index]"); + SEAL_ASSERT_TYPE(get<2>(J), CoeffIter, "accumulator"); + + unsigned long long qword[2]{ 0, 0 }; + multiply_uint64(*get<0>(J), *get<1>(J), qword); + + // Accumulate product of t_operand and t_key_acc to t_poly_lazy and reduce + add_uint128(qword, *get<2>(J), qword); + *get<2>(J)[0] = barrett_reduce_128(qword, key_modulus[key_index]); + *get<2>(J)[1] = 0; + }); + } + else + { + // Same as above but no reduction + for_each_n( + IterTuple<ConstCoeffIter, ConstCoeffIter, RNSIter>( + t_operand_iter, get<0>(I)[key_index], get<1>(I)), + coeff_count, [&](auto J) { + unsigned long long qword[2]{ 0, 0 }; + multiply_uint64(*get<0>(J), *get<1>(J), qword); + add_uint128(qword, *get<2>(J), qword); + *get<2>(J)[0] = qword[0]; + *get<2>(J)[1] = qword[1]; + }); + } + }); + + if (!--lazy_reduction_counter) + { + lazy_reduction_counter = lazy_reduction_summand_bound; + } + } + + // PolyIter pointing to the destination t_poly_prod, shifted to the appropriate modulus + PolyIter t_poly_prod_iter(t_poly_prod.get() + (j * coeff_count), coeff_count, rns_modulus_size); + + // Final modular reduction + for_each_n( + IterTuple<ConstPolyIter, PolyIter>(accumulator_iter, t_poly_prod_iter), key_component_count, + [&](auto I) { + SEAL_ASSERT_TYPE(get<0>(I), ConstRNSIter, "accumulator"); + SEAL_ASSERT_TYPE(get<1>(I), RNSIter, "t_poly_prod"); + + if (lazy_reduction_counter == lazy_reduction_summand_bound) + { + for_each_n(IterTuple<ConstRNSIter, CoeffIter>(get<0>(I), *get<1>(I)), coeff_count, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), ConstCoeffIter, "accumulator"); + SEAL_ASSERT_TYPE(get<1>(J), uint64_t *, "t_poly_prod"); + + *get<1>(J) = static_cast<uint64_t>(**get<0>(J)); + }); + } + else + { + // Same as above except need to still do reduction + for_each_n(IterTuple<ConstRNSIter, CoeffIter>(get<0>(I), *get<1>(I)), coeff_count, [&](auto J) { + *get<1>(J) = barrett_reduce_128(*get<0>(J), key_modulus[key_index]); + }); + } + }); + } + // Accumulated products are now stored in t_poly_prod + + // Perform modulus switching with scaling + PolyIter t_poly_prod_iter(t_poly_prod.get(), coeff_count, rns_modulus_size); + for_each_n(IterTuple<PolyIter, PolyIter>(encrypted, t_poly_prod_iter), key_component_count, [&](auto I) { + SEAL_ASSERT_TYPE(get<0>(I), RNSIter, "encrypted"); + SEAL_ASSERT_TYPE(get<1>(I), RNSIter, "t_poly_prod"); + + // Lazy reduction; this needs to be then reduced mod qi + CoeffIter t_last(get<1>(I)[decomp_modulus_size]); + inverse_ntt_negacyclic_harvey_lazy(t_last, key_ntt_tables[key_modulus_size - 1]); + + // Add (p-1)/2 to change from flooring to rounding. + uint64_t half = key_modulus[key_modulus_size - 1].value() >> 1; + for_each_n(t_last, coeff_count, [&](auto J) { + *J = barrett_reduce_63(*J + half, key_modulus[key_modulus_size - 1]); + }); + + for_each_n( + IterTuple<decltype(I), PtrIter<const Modulus *>, PtrIter<const NTTTables *>, PtrIter<const uint64_t *>>( + I, key_modulus, key_ntt_tables, modswitch_factors), + decomp_modulus_size, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(get<0>(J)), CoeffIter, "encrypted"); + SEAL_ASSERT_TYPE(get<1>(get<0>(J)), CoeffIter, "t_poly_prod"); + SEAL_ASSERT_TYPE(get<1>(J), const Modulus *, "key_modulus"); + SEAL_ASSERT_TYPE(get<2>(J), const NTTTables *, "key_ntt_tables"); + SEAL_ASSERT_TYPE(get<3>(J), const uint64_t *, "modswitch_factors"); + + auto t_ntt(allocate_uint(coeff_count, pool)); + CoeffIter t_ntt_iter(t_ntt.get()); + + // (ct mod 4qk) mod qi + modulo_poly_coeffs_63(t_last, coeff_count, *get<1>(J), t_ntt_iter); + uint64_t fix = barrett_reduce_63(half, *get<1>(J)); + + for_each_n(t_ntt_iter, coeff_count, [&](auto K) { *K = sub_uint_uint_mod(*K, fix, *get<1>(J)); }); + + if (scheme == scheme_type::CKKS) + { + ntt_negacyclic_harvey(t_ntt_iter, *get<2>(J)); + } + else if (scheme == scheme_type::BFV) + { + inverse_ntt_negacyclic_harvey(get<1>(get<0>(J)), *get<2>(J)); + } + + // ((ct mod qi) - (ct mod qk)) mod qi + sub_poly_poly_coeffmod(get<1>(get<0>(J)), t_ntt_iter, coeff_count, *get<1>(J), get<1>(get<0>(J))); + // qk^(-1) * ((ct mod qi) - (ct mod qk)) mod qi + multiply_poly_scalar_coeffmod( + get<1>(get<0>(J)), coeff_count, *get<3>(J), *get<1>(J), get<1>(get<0>(J))); + add_poly_poly_coeffmod( + get<1>(get<0>(J)), get<0>(get<0>(J)), coeff_count, *get<1>(J), get<0>(get<0>(J))); + }); + }); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/evaluator.h b/bigpiseal3.5.1/native/src/seal/evaluator.h new file mode 100644 index 0000000000000000000000000000000000000000..ee1172fa5b79857c69545628ad7f0c16705bc470 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/evaluator.h @@ -0,0 +1,1379 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/galoiskeys.h" +#include "seal/kswitchkeys.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/plaintext.h" +#include "seal/relinkeys.h" +#include "seal/secretkey.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/iterator.h" +#include "seal/util/pointer.h" +#include "seal/util/uintarithsmallmod.h" +#include <map> +#include <memory> +#include <stdexcept> +#include <vector> + +namespace seal +{ + /** + Provides operations on ciphertexts. Due to the properties of the encryption + scheme, the arithmetic operations pass through the encryption layer to the + underlying plaintext, changing it according to the type of the operation. Since + the plaintext elements are fundamentally polynomials in the polynomial quotient + ring Z_T[x]/(X^N+1), where T is the plaintext modulus and X^N+1 is the polynomial + modulus, this is the ring where the arithmetic operations will take place. + BatchEncoder (batching) provider an alternative possibly more convenient view + of the plaintext elements as 2-by-(N2/2) matrices of integers modulo the plaintext + modulus. In the batching view the arithmetic operations act on the matrices + element-wise. Some of the operations only apply in the batching view, such as + matrix row and column rotations. Other operations such as relinearization have + no semantic meaning but are necessary for performance reasons. + + @par Arithmetic Operations + The core operations are arithmetic operations, in particular multiplication + and addition of ciphertexts. In addition to these, we also provide negation, + subtraction, squaring, exponentiation, and multiplication and addition of + several ciphertexts for convenience. in many cases some of the inputs to a + computation are plaintext elements rather than ciphertexts. For this we + provide fast "plain" operations: plain addition, plain subtraction, and plain + multiplication. + + @par Relinearization + One of the most important non-arithmetic operations is relinearization, which + takes as input a ciphertext of size K+1 and relinearization keys (at least K-1 + keys are needed), and changes the size of the ciphertext down to 2 (minimum size). + For most use-cases only one relinearization key suffices, in which case + relinearization should be performed after every multiplication. Homomorphic + multiplication of ciphertexts of size K+1 and L+1 outputs a ciphertext of size + K+L+1, and the computational cost of multiplication is proportional to K*L. + Plain multiplication and addition operations of any type do not change the + size. Relinearization requires relinearization keys to have been generated. + + @par Rotations + When batching is enabled, we provide operations for rotating the plaintext matrix + rows cyclically left or right, and for rotating the columns (swapping the rows). + Rotations require Galois keys to have been generated. + + @par Other Operations + We also provide operations for transforming ciphertexts to NTT form and back, + and for transforming plaintext polynomials to NTT form. These can be used in + a very fast plain multiplication variant, that assumes the inputs to be in NTT + form. Since the NTT has to be done in any case in plain multiplication, this + function can be used when e.g. one plaintext input is used in several plain + multiplication, and transforming it several times would not make sense. + + @par NTT form + When using the BFV scheme (scheme_type::BFV), all plaintexts and ciphertexts + should remain by default in the usual coefficient representation, i.e., not + in NTT form. When using the CKKS scheme (scheme_type::CKKS), all plaintexts + and ciphertexts should remain by default in NTT form. We call these scheme- + specific NTT states the "default NTT form". Some functions, such as add, work + even if the inputs are not in the default state, but others, such as multiply, + will throw an exception. The output of all evaluation functions will be in + the same state as the input(s), with the exception of the transform_to_ntt + and transform_from_ntt functions, which change the state. Ideally, unless these + two functions are called, all other functions should "just work". + + @see EncryptionParameters for more details on encryption parameters. + @see BatchEncoder for more details on batching + @see RelinKeys for more details on relinearization keys. + @see GaloisKeys for more details on Galois keys. + */ + class Evaluator + { + public: + /** + Creates an Evaluator instance initialized with the specified SEALContext. + + @param[in] context The SEALContext + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + */ + Evaluator(std::shared_ptr<SEALContext> context); + + /** + Negates a ciphertext. + + @param[in] encrypted The ciphertext to negate + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + */ + void negate_inplace(Ciphertext &encrypted); + + /** + Negates a ciphertext and stores the result in the destination parameter. + + @param[in] encrypted The ciphertext to negate + @param[out] destination The ciphertext to overwrite with the negated result + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::logic_error if result ciphertext is transparent + */ + inline void negate(const Ciphertext &encrypted, Ciphertext &destination) + { + destination = encrypted; + negate_inplace(destination); + } + + /** + Adds two ciphertexts. This function adds together encrypted1 and encrypted2 + and stores the result in encrypted1. + + @param[in] encrypted1 The first ciphertext to add + @param[in] encrypted2 The second ciphertext to add + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for + the encryption parameters + @throws std::invalid_argument if encrypted1 and encrypted2 are in different + NTT forms + @throws std::invalid_argument if encrypted1 and encrypted2 have different scale + @throws std::logic_error if result ciphertext is transparent + */ + void add_inplace(Ciphertext &encrypted1, const Ciphertext &encrypted2); + + /** + Adds two ciphertexts. This function adds together encrypted1 and encrypted2 + and stores the result in the destination parameter. + + @param[in] encrypted1 The first ciphertext to add + @param[in] encrypted2 The second ciphertext to add + @param[out] destination The ciphertext to overwrite with the addition result + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for + the encryption parameters + @throws std::invalid_argument if encrypted1 and encrypted2 are in different + NTT forms + @throws std::invalid_argument if encrypted1 and encrypted2 have different scale + @throws std::logic_error if result ciphertext is transparent + */ + inline void add(const Ciphertext &encrypted1, const Ciphertext &encrypted2, Ciphertext &destination) + { + if (&encrypted2 == &destination) + { + add_inplace(destination, encrypted1); + } + else + { + destination = encrypted1; + add_inplace(destination, encrypted2); + } + } + + /** + Adds together a vector of ciphertexts and stores the result in the destination + parameter. + + @param[in] encrypteds The ciphertexts to add + @param[out] destination The ciphertext to overwrite with the addition result + @throws std::invalid_argument if encrypteds is empty + @throws std::invalid_argument if the encrypteds are not valid for the encryption + parameters + @throws std::invalid_argument if encrypteds are in different NTT forms + @throws std::invalid_argument if encrypteds have different scale + @throws std::invalid_argument if destination is one of encrypteds + @throws std::logic_error if result ciphertext is transparent + */ + void add_many(const std::vector<Ciphertext> &encrypteds, Ciphertext &destination); + + /** + Subtracts two ciphertexts. This function computes the difference of encrypted1 + and encrypted2, and stores the result in encrypted1. + + @param[in] encrypted1 The ciphertext to subtract from + @param[in] encrypted2 The ciphertext to subtract + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted1 and encrypted2 are in different + NTT forms + @throws std::invalid_argument if encrypted1 and encrypted2 have different scale + @throws std::logic_error if result ciphertext is transparent + */ + void sub_inplace(Ciphertext &encrypted1, const Ciphertext &encrypted2); + + /** + Subtracts two ciphertexts. This function computes the difference of encrypted1 + and encrypted2 and stores the result in the destination parameter. + + @param[in] encrypted1 The ciphertext to subtract from + @param[in] encrypted2 The ciphertext to subtract + @param[out] destination The ciphertext to overwrite with the subtraction result + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted1 and encrypted2 are in different + NTT forms + @throws std::invalid_argument if encrypted1 and encrypted2 have different scale + @throws std::logic_error if result ciphertext is transparent + */ + inline void sub(const Ciphertext &encrypted1, const Ciphertext &encrypted2, Ciphertext &destination) + { + if (&encrypted2 == &destination) + { + sub_inplace(destination, encrypted1); + negate_inplace(destination); + } + else + { + destination = encrypted1; + sub_inplace(destination, encrypted2); + } + } + + /** + Multiplies two ciphertexts. This functions computes the product of encrypted1 + and encrypted2 and stores the result in encrypted1. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + @param[in] encrypted1 The first ciphertext to multiply + @param[in] encrypted2 The second ciphertext to multiply + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted1 or encrypted2 is not in the default + NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void multiply_inplace( + Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Multiplies two ciphertexts. This functions computes the product of encrypted1 + and encrypted2 and stores the result in the destination parameter. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted1 The first ciphertext to multiply + @param[in] encrypted2 The second ciphertext to multiply + @param[out] destination The ciphertext to overwrite with the multiplication result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted1 or encrypted2 is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted1 or encrypted2 is not in the default + NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void multiply( + const Ciphertext &encrypted1, const Ciphertext &encrypted2, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (&encrypted2 == &destination) + { + multiply_inplace(destination, encrypted1, std::move(pool)); + } + else + { + destination = encrypted1; + multiply_inplace(destination, encrypted2, std::move(pool)); + } + } + + /** + Squares a ciphertext. This functions computes the square of encrypted. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to square + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void square_inplace(Ciphertext &encrypted, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Squares a ciphertext. This functions computes the square of encrypted and + stores the result in the destination parameter. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + @param[in] encrypted The ciphertext to square + @param[out] destination The ciphertext to overwrite with the square + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void square( + const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + square_inplace(destination, std::move(pool)); + } + + /** + Relinearizes a ciphertext. This functions relinearizes encrypted, reducing + its size down to 2. If the size of encrypted is K+1, the given relinearization + keys need to have size at least K-1. Dynamic memory allocations in the + process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + @param[in] encrypted The ciphertext to relinearize + @param[in] relin_keys The relinearization keys + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted or relin_keys is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if relin_keys do not correspond to the top level + parameters in the current context + @throws std::invalid_argument if the size of relin_keys is too small + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void relinearize_inplace( + Ciphertext &encrypted, const RelinKeys &relin_keys, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + relinearize_internal(encrypted, relin_keys, 2, std::move(pool)); + } + + /** + Relinearizes a ciphertext. This functions relinearizes encrypted, reducing + its size down to 2, and stores the result in the destination parameter. + If the size of encrypted is K+1, the given relinearization keys need to + have size at least K-1. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to relinearize + @param[in] relin_keys The relinearization keys + @param[out] destination The ciphertext to overwrite with the relinearized result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted or relin_keys is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if relin_keys do not correspond to the top level + parameters in the current context + @throws std::invalid_argument if the size of relin_keys is too small + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void relinearize( + const Ciphertext &encrypted, const RelinKeys &relin_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + relinearize_inplace(destination, relin_keys, std::move(pool)); + } + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down to q_1...q_{k-1} and stores the result in the destination + parameter. Dynamic memory allocations in the process are allocated from + the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @param[out] destination The ciphertext to overwrite with the modulus switched result + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted is already at lowest level + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void mod_switch_to_next( + const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down to q_1...q_{k-1}. Dynamic memory allocations in the process + are allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted is already at lowest level + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void mod_switch_to_next_inplace(Ciphertext &encrypted, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + mod_switch_to_next(encrypted, encrypted, std::move(pool)); + } + + /** + Modulus switches an NTT transformed plaintext from modulo q_1...q_k down + to modulo q_1...q_{k-1}. + + @param[in] plain The plaintext to be switched to a smaller modulus + @throws std::invalid_argument if plain is not in NTT form + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is already at lowest level + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + */ + inline void mod_switch_to_next_inplace(Plaintext &plain) + { + // Verify parameters. + if (!is_valid_for(plain, context_)) + { + throw std::invalid_argument("plain is not valid for encryption parameters"); + } + mod_switch_drop_to_next(plain); + } + + /** + Modulus switches an NTT transformed plaintext from modulo q_1...q_k down + to modulo q_1...q_{k-1} and stores the result in the destination parameter. + + @param[in] plain The plaintext to be switched to a smaller modulus + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @param[out] destination The plaintext to overwrite with the modulus switched result + @throws std::invalid_argument if plain is not in NTT form + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if plain is already at lowest level + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void mod_switch_to_next(const Plaintext &plain, Plaintext &destination) + { + destination = plain; + mod_switch_to_next_inplace(destination); + } + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down until the parameters reach the given parms_id. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void mod_switch_to_inplace( + Ciphertext &encrypted, parms_id_type parms_id, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down until the parameters reach the given parms_id and stores the + result in the destination parameter. Dynamic memory allocations in the process + are allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @param[out] destination The ciphertext to overwrite with the modulus switched result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void mod_switch_to( + const Ciphertext &encrypted, parms_id_type parms_id, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + mod_switch_to_inplace(destination, parms_id, std::move(pool)); + } + + /** + Given an NTT transformed plaintext modulo q_1...q_k, this function switches + the modulus down until the parameters reach the given parms_id. + + @param[in] plain The plaintext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @throws std::invalid_argument if plain is not in NTT form + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if plain is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + */ + void mod_switch_to_inplace(Plaintext &plain, parms_id_type parms_id); + + /** + Given an NTT transformed plaintext modulo q_1...q_k, this function switches + the modulus down until the parameters reach the given parms_id and stores + the result in the destination parameter. + + @param[in] plain The plaintext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @param[out] destination The plaintext to overwrite with the modulus switched result + @throws std::invalid_argument if plain is not in NTT form + @throws std::invalid_argument if plain is not valid for the encryption parameters + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if plain is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if, when using scheme_type::CKKS, the scale is too + large for the new encryption parameters + */ + inline void mod_switch_to(const Plaintext &plain, parms_id_type parms_id, Plaintext &destination) + { + destination = plain; + mod_switch_to_inplace(destination, parms_id); + } + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down to q_1...q_{k-1}, scales the message down accordingly, and + stores the result in the destination parameter. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @param[out] destination The ciphertext to overwrite with the modulus switched result + @throws std::invalid_argument if the scheme is invalid for rescaling + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted is already at lowest level + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void rescale_to_next( + const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down to q_1...q_{k-1} and scales the message down accordingly. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the scheme is invalid for rescaling + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted is already at lowest level + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void rescale_to_next_inplace(Ciphertext &encrypted, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + rescale_to_next(encrypted, encrypted, std::move(pool)); + } + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down until the parameters reach the given parms_id and scales the + message down accordingly. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the scheme is invalid for rescaling + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void rescale_to_inplace( + Ciphertext &encrypted, parms_id_type parms_id, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Given a ciphertext encrypted modulo q_1...q_k, this function switches the + modulus down until the parameters reach the given parms_id, scales the message + down accordingly, and stores the result in the destination parameter. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to be switched to a smaller modulus + @param[in] parms_id The target parms_id + @param[out] destination The ciphertext to overwrite with the modulus switched result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the scheme is invalid for rescaling + @throws std::invalid_argument if encrypted is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if parms_id is not valid for the encryption parameters + @throws std::invalid_argument if encrypted is already at lower level in modulus chain + than the parameters corresponding to parms_id + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void rescale_to( + const Ciphertext &encrypted, parms_id_type parms_id, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + rescale_to_inplace(destination, parms_id, std::move(pool)); + } + + /** + Multiplies several ciphertexts together. This function computes the product + of several ciphertext given as an std::vector and stores the result in the + destination parameter. The multiplication is done in a depth-optimal order, + and relinearization is performed automatically after every multiplication + in the process. In relinearization the given relinearization keys are used. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypteds The ciphertexts to multiply + @param[in] relin_keys The relinearization keys + @param[out] destination The ciphertext to overwrite with the multiplication result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::invalid_argument if encrypteds is empty + @throws std::invalid_argument if the ciphertexts or relin_keys are not valid for + the encryption parameters + @throws std::invalid_argument if encrypteds are not in the default NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if the size of relin_keys is too small + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + void multiply_many( + const std::vector<Ciphertext> &encrypteds, const RelinKeys &relin_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Exponentiates a ciphertext. This functions raises encrypted to a power. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. The exponentiation is done + in a depth-optimal order, and relinearization is performed automatically + after every multiplication in the process. In relinearization the given + relinearization keys are used. + + @param[in] encrypted The ciphertext to exponentiate + @param[in] exponent The power to raise the ciphertext to + @param[in] relin_keys The relinearization keys + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::invalid_argument if encrypted or relin_keys is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if exponent is zero + @throws std::invalid_argument if the size of relin_keys is too small + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + void exponentiate_inplace( + Ciphertext &encrypted, std::uint64_t exponent, const RelinKeys &relin_keys, + MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Exponentiates a ciphertext. This functions raises encrypted to a power and + stores the result in the destination parameter. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. The exponentiation is done in a depth-optimal order, and + relinearization is performed automatically after every multiplication in + the process. In relinearization the given relinearization keys are used. + + @param[in] encrypted The ciphertext to exponentiate + @param[in] exponent The power to raise the ciphertext to + @param[in] relin_keys The relinearization keys + @param[out] destination The ciphertext to overwrite with the power + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::invalid_argument if encrypted or relin_keys is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if, when using scheme_type::CKKS, the output scale + is too large for the encryption parameters + @throws std::invalid_argument if exponent is zero + @throws std::invalid_argument if the size of relin_keys is too small + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void exponentiate( + const Ciphertext &encrypted, std::uint64_t exponent, const RelinKeys &relin_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + exponentiate_inplace(destination, exponent, relin_keys, std::move(pool)); + } + + /** + Adds a ciphertext and a plaintext. The plaintext must be valid for the current + encryption parameters. + + @param[in] encrypted The ciphertext to add + @param[in] plain The plaintext to add + @throws std::invalid_argument if encrypted or plain is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted or plain is in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + void add_plain_inplace(Ciphertext &encrypted, const Plaintext &plain); + + /** + Adds a ciphertext and a plaintext. This function adds a ciphertext and + a plaintext and stores the result in the destination parameter. The plaintext + must be valid for the current encryption parameters. + + @param[in] encrypted The ciphertext to add + @param[in] plain The plaintext to add + @param[out] destination The ciphertext to overwrite with the addition result + @throws std::invalid_argument if encrypted or plain is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted or plain is in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + inline void add_plain(const Ciphertext &encrypted, const Plaintext &plain, Ciphertext &destination) + { + destination = encrypted; + add_plain_inplace(destination, plain); + } + + /** + Subtracts a plaintext from a ciphertext. The plaintext must be valid for the + current encryption parameters. + + @param[in] encrypted The ciphertext to subtract from + @param[in] plain The plaintext to subtract + @throws std::invalid_argument if encrypted or plain is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted or plain is in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + void sub_plain_inplace(Ciphertext &encrypted, const Plaintext &plain); + + /** + Subtracts a plaintext from a ciphertext. This function subtracts a plaintext + from a ciphertext and stores the result in the destination parameter. The + plaintext must be valid for the current encryption parameters. + + @param[in] encrypted The ciphertext to subtract from + @param[in] plain The plaintext to subtract + @param[out] destination The ciphertext to overwrite with the subtraction result + @throws std::invalid_argument if encrypted or plain is not valid for the + encryption parameters + @throws std::invalid_argument if encrypted or plain is in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + inline void sub_plain(const Ciphertext &encrypted, const Plaintext &plain, Ciphertext &destination) + { + destination = encrypted; + sub_plain_inplace(destination, plain); + } + + /** + Multiplies a ciphertext with a plaintext. The plaintext must be valid for the + current encryption parameters, and cannot be identially 0. Dynamic memory + allocations in the process are allocated from the memory pool pointed to by + the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to multiply + @param[in] plain The plaintext to multiply + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the encrypted or plain is not valid for + the encryption parameters + @throws std::invalid_argument if encrypted and plain are in different NTT forms + @throws std::invalid_argument if, when using scheme_type::CKKS, the output + scale is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + void multiply_plain_inplace( + Ciphertext &encrypted, const Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Multiplies a ciphertext with a plaintext. This function multiplies + a ciphertext with a plaintext and stores the result in the destination + parameter. The plaintext must be a valid for the current encryption parameters, + and cannot be identially 0. Dynamic memory allocations in the process are + allocated from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to multiply + @param[in] plain The plaintext to multiply + @param[out] destination The ciphertext to overwrite with the multiplication result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if the encrypted or plain is not valid for + the encryption parameters + @throws std::invalid_argument if encrypted and plain are in different NTT forms + @throws std::invalid_argument if plain is zero + @throws std::invalid_argument if, when using scheme_type::CKKS, the output + scale is too large for the encryption parameters + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if result ciphertext is transparent + */ + inline void multiply_plain( + const Ciphertext &encrypted, const Plaintext &plain, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + multiply_plain_inplace(destination, plain, std::move(pool)); + } + + /** + Transforms a plaintext to NTT domain. This functions applies the Number + Theoretic Transform to a plaintext by first embedding integers modulo the + plaintext modulus to integers modulo the coefficient modulus and then + performing David Harvey's NTT on the resulting polynomial. The transformation + is done with respect to encryption parameters corresponding to a given parms_id. + For the operation to be valid, the plaintext must have degree less than + poly_modulus_degree and each coefficient must be less than the plaintext + modulus, i.e., the plaintext must be a valid plaintext under the current + encryption parameters. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] plain The plaintext to transform + @param[in] parms_id The parms_id with respect to which the NTT is done + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is already in NTT form + @throws std::invalid_argument if plain or parms_id is not valid for the + encryption parameters + @throws std::invalid_argument if pool is uninitialized + */ + void transform_to_ntt_inplace( + Plaintext &plain, parms_id_type parms_id, MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Transforms a plaintext to NTT domain. This functions applies the Number + Theoretic Transform to a plaintext by first embedding integers modulo the + plaintext modulus to integers modulo the coefficient modulus and then + performing David Harvey's NTT on the resulting polynomial. The transformation + is done with respect to encryption parameters corresponding to a given + parms_id. The result is stored in the destination_ntt parameter. For the + operation to be valid, the plaintext must have degree less than poly_modulus_degree + and each coefficient must be less than the plaintext modulus, i.e., the plaintext + must be a valid plaintext under the current encryption parameters. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] plain The plaintext to transform + @param[in] parms_id The parms_id with respect to which the NTT is done + @param[out] destinationNTT The plaintext to overwrite with the transformed result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if plain is already in NTT form + @throws std::invalid_argument if plain or parms_id is not valid for the + encryption parameters + @throws std::invalid_argument if pool is uninitialized + */ + inline void transform_to_ntt( + const Plaintext &plain, parms_id_type parms_id, Plaintext &destination_ntt, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination_ntt = plain; + transform_to_ntt_inplace(destination_ntt, parms_id, std::move(pool)); + } + + /** + Transforms a ciphertext to NTT domain. This functions applies David Harvey's + Number Theoretic Transform separately to each polynomial of a ciphertext. + + @param[in] encrypted The ciphertext to transform + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is already in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + void transform_to_ntt_inplace(Ciphertext &encrypted); + + /** + Transforms a ciphertext to NTT domain. This functions applies David Harvey's + Number Theoretic Transform separately to each polynomial of a ciphertext. + The result is stored in the destination_ntt parameter. + + @param[in] encrypted The ciphertext to transform + @param[out] destination_ntt The ciphertext to overwrite with the transformed result + @throws std::invalid_argument if encrypted is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted is already in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + inline void transform_to_ntt(const Ciphertext &encrypted, Ciphertext &destination_ntt) + { + destination_ntt = encrypted; + transform_to_ntt_inplace(destination_ntt); + } + + /** + Transforms a ciphertext back from NTT domain. This functions applies the + inverse of David Harvey's Number Theoretic Transform separately to each + polynomial of a ciphertext. + + @param[in] encrypted_ntt The ciphertext to transform + @throws std::invalid_argument if encrypted_ntt is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted_ntt is not in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + void transform_from_ntt_inplace(Ciphertext &encrypted_ntt); + + /** + Transforms a ciphertext back from NTT domain. This functions applies the + inverse of David Harvey's Number Theoretic Transform separately to each + polynomial of a ciphertext. The result is stored in the destination parameter. + + @param[in] encrypted_ntt The ciphertext to transform + @param[out] destination The ciphertext to overwrite with the transformed result + @throws std::invalid_argument if encrypted_ntt is not valid for the encryption + parameters + @throws std::invalid_argument if encrypted_ntt is not in NTT form + @throws std::logic_error if result ciphertext is transparent + */ + inline void transform_from_ntt(const Ciphertext &encrypted_ntt, Ciphertext &destination) + { + destination = encrypted_ntt; + transform_from_ntt_inplace(destination); + } + + /** + Applies a Galois automorphism to a ciphertext. To evaluate the Galois + automorphism, an appropriate set of Galois keys must also be provided. + Dynamic memory allocations in the process are allocated from the memory + pool pointed to by the given MemoryPoolHandle. + + The desired Galois automorphism is given as a Galois element, and must be + an odd integer in the interval [1, M-1], where M = 2*N, and N = poly_modulus_degree. + Used with batching, a Galois element 3^i % M corresponds to a cyclic row + rotation i steps to the left, and a Galois element 3^(N/2-i) % M corresponds + to a cyclic row rotation i steps to the right. The Galois element M-1 corresponds + to a column rotation (row swap) in BFV, and complex conjugation in CKKS. + In the polynomial view (not batching), a Galois automorphism by a Galois + element p changes Enc(plain(x)) to Enc(plain(x^p)). + + @param[in] encrypted The ciphertext to apply the Galois automorphism to + @param[in] galois_elt The Galois element + @param[in] galois_keys The Galois keys + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if the Galois element is not valid + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + void apply_galois_inplace( + Ciphertext &encrypted, std::uint32_t galois_elt, const GaloisKeys &galois_keys, + MemoryPoolHandle pool = MemoryManager::GetPool()); + + /** + Applies a Galois automorphism to a ciphertext and writes the result to the + destination parameter. To evaluate the Galois automorphism, an appropriate + set of Galois keys must also be provided. Dynamic memory allocations in + the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + The desired Galois automorphism is given as a Galois element, and must be + an odd integer in the interval [1, M-1], where M = 2*N, and N = poly_modulus_degree. + Used with batching, a Galois element 3^i % M corresponds to a cyclic row + rotation i steps to the left, and a Galois element 3^(N/2-i) % M corresponds + to a cyclic row rotation i steps to the right. The Galois element M-1 corresponds + to a column rotation (row swap) in BFV, and complex conjugation in CKKS. + In the polynomial view (not batching), a Galois automorphism by a Galois + element p changes Enc(plain(x)) to Enc(plain(x^p)). + + @param[in] encrypted The ciphertext to apply the Galois automorphism to + @param[in] galois_elt The Galois element + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if the Galois element is not valid + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void apply_galois( + const Ciphertext &encrypted, std::uint32_t galois_elt, const GaloisKeys &galois_keys, + Ciphertext &destination, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + apply_galois_inplace(destination, galois_elt, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext matrix rows cyclically. When batching is used with the + BFV scheme, this function rotates the encrypted plaintext matrix rows + cyclically to the left (steps > 0) or to the right (steps < 0). Since + the size of the batched matrix is 2-by-(N/2), where N is the degree of + the polynomial modulus, the number of steps to rotate must have absolute + value at most N/2-1. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + + @param[in] encrypted The ciphertext to rotate + @param[in] steps The number of steps to rotate (negative left, positive right) + @param[in] galois_keys The Galois keys + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support batching + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if steps has too big absolute value + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_rows_inplace( + Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (context_->key_context_data()->parms().scheme() != scheme_type::BFV) + { + throw std::logic_error("unsupported scheme"); + } + rotate_internal(encrypted, steps, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext matrix rows cyclically. When batching is used with the + BFV scheme, this function rotates the encrypted plaintext matrix rows + cyclically to the left (steps > 0) or to the right (steps < 0) and writes + the result to the destination parameter. Since the size of the batched + matrix is 2-by-(N/2), where N is the degree of the polynomial modulus, + the number of steps to rotate must have absolute value at most N/2-1. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] steps The number of steps to rotate (negative left, positive right) + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support batching + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if steps has too big absolute value + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_rows( + const Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + rotate_rows_inplace(destination, steps, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext matrix columns cyclically. When batching is used with + the BFV scheme, this function rotates the encrypted plaintext matrix + columns cyclically. Since the size of the batched matrix is 2-by-(N/2), + where N is the degree of the polynomial modulus, this means simply swapping + the two rows. Dynamic memory allocations in the process are allocated from + the memory pool pointed to by the given MemoryPoolHandle. + + + @param[in] encrypted The ciphertext to rotate + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support batching + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_columns_inplace( + Ciphertext &encrypted, const GaloisKeys &galois_keys, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (context_->key_context_data()->parms().scheme() != scheme_type::BFV) + { + throw std::logic_error("unsupported scheme"); + } + conjugate_internal(encrypted, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext matrix columns cyclically. When batching is used with + the BFV scheme, this function rotates the encrypted plaintext matrix columns + cyclically, and writes the result to the destination parameter. Since the + size of the batched matrix is 2-by-(N/2), where N is the degree of the + polynomial modulus, this means simply swapping the two rows. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support batching + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_columns( + const Ciphertext &encrypted, const GaloisKeys &galois_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + rotate_columns_inplace(destination, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext vector cyclically. When using the CKKS scheme, this function + rotates the encrypted plaintext vector cyclically to the left (steps > 0) + or to the right (steps < 0). Since the size of the batched matrix is + 2-by-(N/2), where N is the degree of the polynomial modulus, the number + of steps to rotate must have absolute value at most N/2-1. Dynamic memory + allocations in the process are allocated from the memory pool pointed to + by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] steps The number of steps to rotate (negative left, positive right) + @param[in] galois_keys The Galois keys + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::CKKS + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is not in the default NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if steps has too big absolute value + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_vector_inplace( + Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (context_->key_context_data()->parms().scheme() != scheme_type::CKKS) + { + throw std::logic_error("unsupported scheme"); + } + rotate_internal(encrypted, steps, galois_keys, std::move(pool)); + } + + /** + Rotates plaintext vector cyclically. When using the CKKS scheme, this function + rotates the encrypted plaintext vector cyclically to the left (steps > 0) + or to the right (steps < 0) and writes the result to the destination parameter. + Since the size of the batched matrix is 2-by-(N/2), where N is the degree + of the polynomial modulus, the number of steps to rotate must have absolute + value at most N/2-1. Dynamic memory allocations in the process are allocated + from the memory pool pointed to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] steps The number of steps to rotate (negative left, positive right) + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::CKKS + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if steps has too big absolute value + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void rotate_vector( + const Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + rotate_vector_inplace(destination, steps, galois_keys, std::move(pool)); + } + + /** + Complex conjugates plaintext slot values. When using the CKKS scheme, this + function complex conjugates all values in the underlying plaintext. Dynamic + memory allocations in the process are allocated from the memory pool pointed + to by the given MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::CKKS + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void complex_conjugate_inplace( + Ciphertext &encrypted, const GaloisKeys &galois_keys, MemoryPoolHandle pool = MemoryManager::GetPool()) + { + if (context_->key_context_data()->parms().scheme() != scheme_type::CKKS) + { + throw std::logic_error("unsupported scheme"); + } + conjugate_internal(encrypted, galois_keys, std::move(pool)); + } + + /** + Complex conjugates plaintext slot values. When using the CKKS scheme, this + function complex conjugates all values in the underlying plaintext, and + writes the result to the destination parameter. Dynamic memory allocations + in the process are allocated from the memory pool pointed to by the given + MemoryPoolHandle. + + @param[in] encrypted The ciphertext to rotate + @param[in] galois_keys The Galois keys + @param[out] destination The ciphertext to overwrite with the rotated result + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::logic_error if scheme is not scheme_type::CKKS + @throws std::invalid_argument if encrypted or galois_keys is not valid for + the encryption parameters + @throws std::invalid_argument if galois_keys do not correspond to the top + level parameters in the current context + @throws std::invalid_argument if encrypted is in NTT form + @throws std::invalid_argument if encrypted has size larger than 2 + @throws std::invalid_argument if necessary Galois keys are not present + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if keyswitching is not supported by the context + @throws std::logic_error if result ciphertext is transparent + */ + inline void complex_conjugate( + const Ciphertext &encrypted, const GaloisKeys &galois_keys, Ciphertext &destination, + MemoryPoolHandle pool = MemoryManager::GetPool()) + { + destination = encrypted; + complex_conjugate_inplace(destination, galois_keys, std::move(pool)); + } + + /** + Enables access to private members of seal::Evaluator for .NET wrapper. + */ + struct EvaluatorPrivateHelper; + + private: + Evaluator(const Evaluator &copy) = delete; + + Evaluator(Evaluator &&source) = delete; + + Evaluator &operator=(const Evaluator &assign) = delete; + + Evaluator &operator=(Evaluator &&assign) = delete; + + void bfv_multiply(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool); + + void ckks_multiply(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool); + + void bfv_square(Ciphertext &encrypted, MemoryPoolHandle pool); + + void ckks_square(Ciphertext &encrypted, MemoryPoolHandle pool); + + void relinearize_internal( + Ciphertext &encrypted, const RelinKeys &relin_keys, std::size_t destination_size, MemoryPoolHandle pool); + + void mod_switch_scale_to_next(const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool); + + void mod_switch_drop_to_next(const Ciphertext &encrypted, Ciphertext &destination, MemoryPoolHandle pool); + + void mod_switch_drop_to_next(Plaintext &plain); + + void rotate_internal(Ciphertext &encrypted, int steps, const GaloisKeys &galois_keys, MemoryPoolHandle pool); + + inline void conjugate_internal(Ciphertext &encrypted, const GaloisKeys &galois_keys, MemoryPoolHandle pool) + { + // Verify parameters. + auto context_data_ptr = context_->get_context_data(encrypted.parms_id()); + if (!context_data_ptr) + { + throw std::invalid_argument("encrypted is not valid for encryption parameters"); + } + + // Extract encryption parameters. + auto &context_data = *context_data_ptr; + if (!context_data.qualifiers().using_batching) + { + throw std::logic_error("encryption parameters do not support batching"); + } + + auto galois_tool = context_data.galois_tool(); + + // Perform rotation and key switching + apply_galois_inplace(encrypted, galois_tool->get_elt_from_step(0), galois_keys, std::move(pool)); + } + + void switch_key_inplace( + Ciphertext &encrypted, util::ConstRNSIter target_iter, const KSwitchKeys &kswitch_keys, + std::size_t key_index, MemoryPoolHandle pool = MemoryManager::GetPool()); + + void multiply_plain_normal(Ciphertext &encrypted, const Plaintext &plain, MemoryPoolHandle pool); + + void multiply_plain_ntt(Ciphertext &encrypted_ntt, const Plaintext &plain_ntt); + + void populate_Zmstar_to_generator(); + + std::shared_ptr<SEALContext> context_{ nullptr }; + + std::map<std::uint64_t, std::pair<std::uint64_t, std::uint64_t>> Zmstar_to_generator_{}; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/galoiskeys.h b/bigpiseal3.5.1/native/src/seal/galoiskeys.h new file mode 100644 index 0000000000000000000000000000000000000000..08783363bf091b2fa624cc105b3a070003660728 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/galoiskeys.h @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/encryptionparams.h" +#include "seal/kswitchkeys.h" +#include "seal/memorymanager.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/galois.h" +#include <iostream> +#include <numeric> +#include <vector> + +namespace seal +{ + /** + Class to store Galois keys. + + @par Slot Rotations + Galois keys are certain types of public keys that are needed to perform encrypted + vector rotation operations on batched ciphertexts. Batched ciphertexts encrypt + a 2-by-(N/2) matrix of modular integers in the BFV scheme, or an N/2-dimensional + vector of complex numbers in the CKKS scheme, where N denotes the degree of the + polynomial modulus. In the BFV scheme Galois keys can enable both cyclic rotations + of the encrypted matrix rows, as well as row swaps (column rotations). In the CKKS + scheme Galois keys can enable cyclic vector rotations, as well as a complex + conjugation operation. + + + @par Thread Safety + In general, reading from GaloisKeys is thread-safe as long as no other thread is + concurrently mutating it. This is due to the underlying data structure storing the + Galois keys not being thread-safe. + + @see RelinKeys for the class that stores the relinearization keys. + @see KeyGenerator for the class that generates the Galois keys. + */ + class GaloisKeys : public KSwitchKeys + { + public: + /** + Returns the index of a Galois key in the backing KSwitchKeys instance that + corresponds to the given Galois element, assuming that it exists in the + backing KSwitchKeys. + + @param[in] galois_elt The Galois element + @throws std::invalid_argument if galois_elt is not valid + */ + SEAL_NODISCARD inline static std::size_t get_index(std::uint32_t galois_elt) + { + return util::GaloisTool::GetIndexFromElt(galois_elt); + } + + /** + Returns whether a Galois key corresponding to a given Galois element exists. + + @param[in] galois_elt The Galois element + @throws std::invalid_argument if galois_elt is not valid + */ + SEAL_NODISCARD inline bool has_key(std::uint32_t galois_elt) const + { + std::size_t index = get_index(galois_elt); + return data().size() > index && !data()[index].empty(); + } + + /** + Returns a const reference to a Galois key. The returned Galois key corresponds + to the given Galois element. + + @param[in] galois_elt The Galois element + @throws std::invalid_argument if the key corresponding to galois_elt does not exist + */ + SEAL_NODISCARD inline const auto &key(std::uint32_t galois_elt) const + { + return KSwitchKeys::data(get_index(galois_elt)); + } + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/intarray.h b/bigpiseal3.5.1/native/src/seal/intarray.h new file mode 100644 index 0000000000000000000000000000000000000000..dae6973667cd4efaaeeff87babe365b6dccb4285 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/intarray.h @@ -0,0 +1,673 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/serialization.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include <algorithm> +#include <cstring> +#include <iostream> +#include <limits> +#include <type_traits> +#ifdef SEAL_USE_MSGSL +#include <gsl/span> +#endif + +namespace seal +{ + class Ciphertext; + + // Forward-declaring the deflate_size_bound function + namespace util + { + namespace ztools + { + template <typename SizeT> + SEAL_NODISCARD SizeT deflate_size_bound(SizeT in_size); + } // namespace ztools + } // namespace util + + /** + A resizable container for storing an array of arithmetic data types or + SEAL_BYTE types (e.g., std::byte). The allocations are done from a memory + pool. The IntArray class is mainly intended for internal use and provides + the underlying data structure for Plaintext and Ciphertext classes. + + @par Size and Capacity + IntArray allows the user to pre-allocate memory (capacity) for the array + in cases where the array is known to be resized in the future and memory + moves are to be avoided at the time of resizing. The size of the IntArray + can never exceed its capacity. The capacity and size can be changed using + the reserve and resize functions, respectively. + + @par Thread Safety + In general, reading from IntArray is thread-safe as long as no other thread + is concurrently mutating it. + */ + template < + typename T_, + typename = std::enable_if_t< + std::is_arithmetic<T_>::value || std::is_same<typename std::decay<T_>::type, SEAL_BYTE>::value>> + class IntArray + { + friend class Ciphertext; + + public: + using T = typename std::decay<T_>::type; + + /** + Creates a new IntArray. No memory is allocated by this constructor. + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + IntArray(MemoryPoolHandle pool = MemoryManager::GetPool()) : pool_(std::move(pool)) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + } + + /** + Creates a new IntArray with given size. + + @param[in] size The size of the array + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + explicit IntArray(std::size_t size, MemoryPoolHandle pool = MemoryManager::GetPool()) : pool_(std::move(pool)) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + + // Reserve memory, resize, and set to zero + resize(size); + } + + /** + Creates a new IntArray with given capacity and size. + + @param[in] capacity The capacity of the array + @param[in] size The size of the array + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if capacity is less than size + @throws std::invalid_argument if pool is uninitialized + */ + explicit IntArray(std::size_t capacity, std::size_t size, MemoryPoolHandle pool = MemoryManager::GetPool()) + : pool_(std::move(pool)) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + if (capacity < size) + { + throw std::invalid_argument("capacity cannot be smaller than size"); + } + + // Reserve memory, resize, and set to zero + reserve(capacity); + resize(size); + } + + /** + Creates a new IntArray with given size wrapping a given pointer. This + constructor allocates no memory. If the IntArray goes out of scope, the + Pointer object given here is destroyed. On resizing the IntArray to larger + size, the data will be copied over to a new allocation from the memory pool + pointer to by the given MemoryPoolHandle and the Pointer object given here + will subsequently be destroyed. Unlike the other constructors, this one + exposes the option of not automatically zero-filling the allocated memory. + + @param[in] ptr An initial Pointer object to wrap + @param[in] capacity The capacity of the array + @param[in] size The size of the array + @param[in] fill_zero If true, fills ptr with zeros + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if ptr is null and capacity is positive + @throws std::invalid_argument if capacity is less than size + @throws std::invalid_argument if pool is uninitialized + */ + explicit IntArray( + util::Pointer<T> &&ptr, std::size_t capacity, std::size_t size, bool fill_zero, + MemoryPoolHandle pool = MemoryManager::GetPool()) + : pool_(std::move(pool)), capacity_(capacity) + { + if (!ptr && capacity) + { + throw std::invalid_argument("ptr cannot be null"); + } + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + if (capacity < size) + { + throw std::invalid_argument("capacity cannot be smaller than size"); + } + + // Grab the given Pointer + data_ = std::move(ptr); + + // Resize, and optionally set to zero + resize(size, fill_zero); + } + + /** + Creates a new IntArray with given size wrapping a given pointer. This + constructor allocates no memory. If the IntArray goes out of scope, the + Pointer object given here is destroyed. On resizing the IntArray to larger + size, the data will be copied over to a new allocation from the memory pool + pointer to by the given MemoryPoolHandle and the Pointer object given here + will subsequently be destroyed. Unlike the other constructors, this one + exposes the option of not automatically zero-filling the allocated memory. + + @param[in] ptr An initial Pointer object to wrap + @param[in] size The size of the array + @param[in] fill_zero If true, fills ptr with zeros + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if ptr is null and size is positive + @throws std::invalid_argument if pool is uninitialized + */ + explicit IntArray( + util::Pointer<T> &&ptr, std::size_t size, bool fill_zero, MemoryPoolHandle pool = MemoryManager::GetPool()) + : IntArray(std::move(ptr), size, size, fill_zero, std::move(pool)) + {} + + /** + Constructs a new IntArray by copying a given one. + + @param[in] copy The IntArray to copy from + */ + IntArray(const IntArray<T> &copy) + : pool_(MemoryManager::GetPool()), capacity_(copy.size_), size_(copy.size_), + data_(util::allocate<T>(copy.size_, pool_)) + { + // Copy over value + std::copy_n(copy.cbegin(), copy.size_, begin()); + } + + /** + Constructs a new IntArray by moving a given one. + + @param[in] source The IntArray to move from + */ + IntArray(IntArray<T> &&source) noexcept + : pool_(std::move(source.pool_)), capacity_(source.capacity_), size_(source.size_), + data_(std::move(source.data_)) + {} + + /** + Destroys the IntArray. + */ + ~IntArray() + { + release(); + } + + /** + Returns a pointer to the beginning of the array data. + */ + SEAL_NODISCARD inline T *begin() noexcept + { + return data_.get(); + } + + /** + Returns a constant pointer to the beginning of the array data. + */ + SEAL_NODISCARD inline const T *cbegin() const noexcept + { + return data_.get(); + } + + /** + Returns a pointer to the end of the array data. + */ + SEAL_NODISCARD inline T *end() noexcept + { + return size_ ? begin() + size_ : begin(); + } + + /** + Returns a constant pointer to the end of the array data. + */ + SEAL_NODISCARD inline const T *cend() const noexcept + { + return size_ ? cbegin() + size_ : cbegin(); + } +#ifdef SEAL_USE_MSGSL + /** + Returns a span pointing to the beginning of the IntArray. + */ + SEAL_NODISCARD inline gsl::span<T> span() + { + return gsl::span<T>(begin(), static_cast<std::ptrdiff_t>(size_)); + } + + /** + Returns a span pointing to the beginning of the IntArray. + */ + SEAL_NODISCARD inline gsl::span<const T> span() const + { + return gsl::span<const T>(cbegin(), static_cast<std::ptrdiff_t>(size_)); + } +#endif + /** + Returns a constant reference to the array element at a given index. + This function performs bounds checking and will throw an error if + the index is out of range. + + @param[in] index The index of the array element + @throws std::out_of_range if index is out of range + */ + SEAL_NODISCARD inline const T &at(std::size_t index) const + { + if (index >= size_) + { + throw std::out_of_range("index must be within [0, size)"); + } + return data_[index]; + } + + /** + Returns a reference to the array element at a given index. This + function performs bounds checking and will throw an error if the + index is out of range. + + @param[in] index The index of the array element + @throws std::out_of_range if index is out of range + */ + SEAL_NODISCARD inline T &at(std::size_t index) + { + if (index >= size_) + { + throw std::out_of_range("index must be within [0, size)"); + } + return data_[index]; + } + + /** + Returns a constant reference to the array element at a given index. + This function does not perform bounds checking. + + @param[in] index The index of the array element + */ + SEAL_NODISCARD inline const T &operator[](std::size_t index) const + { + return data_[index]; + } + + /** + Returns a reference to the array element at a given index. This + function does not perform bounds checking. + + @param[in] index The index of the array element + */ + SEAL_NODISCARD inline T &operator[](std::size_t index) + { + return data_[index]; + } + + /** + Returns whether the array has size zero. + */ + SEAL_NODISCARD inline bool empty() const noexcept + { + return (size_ == 0); + } + + /** + Returns the largest possible array size. + */ + SEAL_NODISCARD inline std::size_t max_size() const noexcept + { + return std::numeric_limits<std::size_t>::max(); + } + + /** + Returns the size of the array. + */ + SEAL_NODISCARD inline std::size_t size() const noexcept + { + return size_; + } + + /** + Returns the capacity of the array. + */ + SEAL_NODISCARD inline std::size_t capacity() const noexcept + { + return capacity_; + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return pool_; + } + + /** + Releases any allocated memory to the memory pool and sets the size + and capacity of the array to zero. + */ + inline void release() noexcept + { + capacity_ = 0; + size_ = 0; + data_.release(); + } + + /** + Sets the size of the array to zero. The capacity is not changed. + */ + inline void clear() noexcept + { + size_ = 0; + } + + /** + Allocates enough memory for storing a given number of elements without + changing the size of the array. If the given capacity is smaller than + the current size, the size is automatically set to equal the new capacity. + + @param[in] capacity The capacity of the array + */ + inline void reserve(std::size_t capacity) + { + std::size_t copy_size = std::min(capacity, size_); + + // Create new allocation and copy over value + auto new_data(util::allocate<T>(capacity, pool_)); + std::copy_n(cbegin(), copy_size, new_data.get()); + std::swap(data_, new_data); + + // Set the coeff_count and capacity + capacity_ = capacity; + size_ = copy_size; + } + + /** + Reallocates the array so that its capacity exactly matches its size. + */ + inline void shrink_to_fit() + { + reserve(size_); + } + + /** + Resizes the array to given size. When resizing to larger size the data + in the array remains unchanged and any new space is initialized to zero + if fill_zero is set to true; when resizing to smaller size the last + elements of the array are dropped. If the capacity is not already large + enough to hold the new size, the array is also reallocated. + + @param[in] size The size of the array + @param[in] fill_zero If true, fills expanded space with zeros + */ + inline void resize(std::size_t size, bool fill_zero = true) + { + if (size <= capacity_) + { + // Are we changing size to bigger within current capacity? + // If so, need to set top terms to zero + if (size > size_ && fill_zero) + { + std::fill(end(), begin() + size, T(0)); + } + + // Set the size + size_ = size; + + return; + } + + // At this point we know for sure that size_ <= capacity_ < size so need + // to reallocate to bigger + auto new_data(util::allocate<T>(size, pool_)); + std::copy_n(cbegin(), size_, new_data.get()); + if (fill_zero) + { + std::fill(new_data.get() + size_, new_data.get() + size, T(0)); + } + std::swap(data_, new_data); + + // Set the coeff_count and capacity + capacity_ = size; + size_ = size; + } + + /** + Copies a given IntArray to the current one. + + @param[in] assign The IntArray to copy from + */ + inline IntArray<T> &operator=(const IntArray<T> &assign) + { + // Check for self-assignment + if (this == &assign) + { + return *this; + } + + // First resize to correct size + resize(assign.size_); + + // Size is guaranteed to be OK now so copy over + std::copy_n(assign.cbegin(), assign.size_, begin()); + + return *this; + } + + /** + Moves a given IntArray to the current one. + + @param[in] assign The IntArray to move from + */ + IntArray<T> &operator=(IntArray<T> &&assign) noexcept + { + capacity_ = assign.capacity_; + size_ = assign.size_; + data_ = std::move(assign.data_); + pool_ = std::move(assign.pool_); + + return *this; + } + + /** + Returns an upper bound on the size of the IntArray, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t members_size = Serialization::ComprSizeEstimate( + util::add_safe( + sizeof(std::uint64_t), // size_ + util::mul_safe(size_, sizeof(T))), // data_ + compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves the IntArray to an output stream. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the IntArray to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&IntArray<T_>::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a IntArray from an input stream overwriting the current IntArray. + This function takes optionally a bound on the size for the loaded IntArray + and throws an exception if the size indicated by the loaded metadata exceeds + the provided value. The check is omitted if in_size_bound is zero. + + @param[in] stream The stream to load the IntArray from + @param[in] in_size_bound A bound on the size of the loaded IntArray + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded size exceeds in_size_bound + @throws std::logic_error if the loaded data is invalid, if the loaded size + exceeds in_size_bound, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::istream &stream, std::size_t in_size_bound = 0) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&IntArray<T_>::load_members, this, _1, in_size_bound), stream); + } + + /** + Saves the IntArray to a given memory location. The output is in binary + format and not human-readable. + + @param[out] out The memory location to write the Modulus to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&IntArray<T_>::save_members, this, _1), save_size(compr_mode_type::none), out, size, + compr_mode); + } + + /** + Loads a IntArray from a given memory location overwriting the current + IntArray. This function takes optionally a bound on the size for the loaded + IntArray and throws an exception if the size indicated by the loaded + metadata exceeds the provided value. The check is omitted if in_size_bound + is zero. + + @param[in] in The memory location to load the Modulus from + @param[in] size The number of bytes available in the given memory location + @param[in] in_size_bound A bound on the size of the loaded IntArray + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, if decompression failed, + or if the loaded size exceeds in_size_bound + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(const SEAL_BYTE *in, std::size_t size, std::size_t in_size_bound = 0) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&IntArray<T_>::load_members, this, _1, in_size_bound), in, size); + } + + private: + void save_members(std::ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + + std::uint64_t size64 = size_; + stream.write(reinterpret_cast<const char *>(&size64), sizeof(std::uint64_t)); + if (size_) + { + stream.write( + reinterpret_cast<const char *>(cbegin()), + util::safe_cast<std::streamsize>(util::mul_safe(size_, sizeof(T)))); + } + } + catch (const std::ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw std::runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void load_members(std::istream &stream, std::size_t in_size_bound) + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + + std::uint64_t size64 = 0; + stream.read(reinterpret_cast<char *>(&size64), sizeof(std::uint64_t)); + + // Check (optionally) that the size in the metadata does not exceed + // in_size_bound + if (in_size_bound && util::unsigned_gt(size64, in_size_bound)) + { + throw std::logic_error("unexpected size"); + } + + // Set new size; this is potentially unsafe if size64 was not checked + // against expected_size + resize(util::safe_cast<std::size_t>(size64)); + + // Read data + if (size_) + { + stream.read( + reinterpret_cast<char *>(begin()), + util::safe_cast<std::streamsize>(util::mul_safe(size_, sizeof(T)))); + } + } + catch (const std::ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw std::runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + MemoryPoolHandle pool_; + + std::size_t capacity_ = 0; + + std::size_t size_ = 0; + + util::Pointer<T> data_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/intencoder.cpp b/bigpiseal3.5.1/native/src/seal/intencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..feaea36049f44a83f5bf69e0ea031f8d722483e6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/intencoder.cpp @@ -0,0 +1,292 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/intencoder.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include "seal/util/polyarith.h" +#include "seal/util/uintarithsmallmod.h" +#include <algorithm> +#include <cmath> +#include <stdexcept> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + IntegerEncoder::IntegerEncoder(shared_ptr<SEALContext> context) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + + // Unlike in other classes, we do not check "context_->parameters_set()". + // The IntegerEncoder should function without valid encryption parameters + // as long as the scheme is BFV and the plaintext modulus is at least 2. + auto &context_data = *context_->first_context_data(); + if (context_data.parms().scheme() != scheme_type::BFV) + { + throw invalid_argument("unsupported scheme"); + } + if (plain_modulus().bit_count() <= 1) + { + throw invalid_argument("plain_modulus must be at least 2"); + } + + if (plain_modulus().value() == 2) + { + // In this case we don't allow any negative numbers + coeff_neg_threshold_ = 2; + } + else + { + // Normal negative threshold case + coeff_neg_threshold_ = (plain_modulus().value() + 1) >> 1; + } + neg_one_ = plain_modulus().value() - 1; + } + + Plaintext IntegerEncoder::encode(uint64_t value) + { + Plaintext result; + encode(value, result); + return result; + } + + void IntegerEncoder::encode(uint64_t value, Plaintext &destination) + { + size_t encode_coeff_count = safe_cast<size_t>(get_significant_bit_count(value)); + destination.resize(encode_coeff_count); + destination.set_zero(); + + size_t coeff_index = 0; + while (value != 0) + { + if ((value & 1) != 0) + { + destination[coeff_index] = 1; + } + value >>= 1; + coeff_index++; + } + } + + Plaintext IntegerEncoder::encode(int64_t value) + { + Plaintext result; + encode(value, result); + return result; + } + + void IntegerEncoder::encode(int64_t value, Plaintext &destination) + { + if (value < 0) + { + uint64_t pos_value = static_cast<uint64_t>(-value); + size_t encode_coeff_count = safe_cast<size_t>(get_significant_bit_count(pos_value)); + destination.resize(encode_coeff_count); + destination.set_zero(); + + size_t coeff_index = 0; + while (pos_value != 0) + { + if ((pos_value & 1) != 0) + { + destination[coeff_index] = neg_one_; + } + pos_value >>= 1; + coeff_index++; + } + } + else + { + encode(static_cast<uint64_t>(value), destination); + } + } + + Plaintext IntegerEncoder::encode(const BigUInt &value) + { + Plaintext result; + encode(value, result); + return result; + } + + void IntegerEncoder::encode(const BigUInt &value, Plaintext &destination) + { + size_t encode_coeff_count = safe_cast<size_t>(value.significant_bit_count()); + destination.resize(encode_coeff_count); + destination.set_zero(); + + size_t coeff_index = 0; + size_t coeff_count = safe_cast<size_t>(value.significant_bit_count()); + size_t coeff_uint64_count = value.uint64_count(); + while (coeff_index < coeff_count) + { + if (is_bit_set_uint(value.data(), coeff_uint64_count, safe_cast<int>(coeff_index))) + { + destination[coeff_index] = 1; + } + coeff_index++; + } + } + + uint32_t IntegerEncoder::decode_uint32(const Plaintext &plain) + { + uint64_t value64 = decode_uint64(plain); + if (value64 > UINT32_MAX) + { + throw invalid_argument("output out of range"); + } + return static_cast<uint32_t>(value64); + } + + uint64_t IntegerEncoder::decode_uint64(const Plaintext &plain) + { + BigUInt bigvalue = decode_biguint(plain); + int bit_count = bigvalue.significant_bit_count(); + if (bit_count > bits_per_uint64) + { + // Decoded value has more bits than fit in a 64-bit uint. + throw invalid_argument("output out of range"); + } + return bit_count > 0 ? bigvalue.data()[0] : 0; + } + + int32_t IntegerEncoder::decode_int32(const Plaintext &plain) + { + int64_t value64 = decode_int64(plain); + return safe_cast<int32_t>(value64); + } + + int64_t IntegerEncoder::decode_int64(const Plaintext &plain) + { + int64_t result = 0; + for (size_t bit_index = plain.significant_coeff_count(); bit_index--;) + { + unsigned long long coeff = plain[bit_index]; + + // Left shift result. + int64_t next_result = result * 2; + if ((next_result < 0) != (result < 0)) + { + // Check for overflow. + throw invalid_argument("output out of range"); + } + + // Get sign/magnitude of coefficient. + int coeff_bit_count = get_significant_bit_count(coeff); + if (coeff >= plain_modulus().value()) + { + // Coefficient is bigger than plaintext modulus + throw invalid_argument("plain does not represent a valid plaintext polynomial"); + } + bool coeff_is_negative = coeff >= coeff_neg_threshold_; + unsigned long long pos_value = coeff; + if (coeff_is_negative) + { + pos_value = plain_modulus().value() - pos_value; + coeff_bit_count = get_significant_bit_count(pos_value); + } + + if (coeff_bit_count > bits_per_uint64 - 1) + { + // Absolute value of coefficient is too large to represent in a int64_t, so overflow. + throw invalid_argument("output out of range"); + } + + int64_t coeff_value = safe_cast<int64_t>(pos_value); + if (coeff_is_negative) + { + coeff_value = -coeff_value; + } + bool next_result_was_negative = next_result < 0; + next_result += coeff_value; + bool next_result_is_negative = next_result < 0; + if ((next_result_was_negative == coeff_is_negative) && + (next_result_was_negative != next_result_is_negative)) + { + // Accumulation and coefficient had same signs, but accumulator changed signs after addition, so must be + // overflow. + throw invalid_argument("output out of range"); + } + result = next_result; + } + return result; + } + + BigUInt IntegerEncoder::decode_biguint(const Plaintext &plain) + { + size_t result_uint64_count = 1; + size_t bits_per_uint64_sz = safe_cast<size_t>(bits_per_uint64); + size_t result_bit_capacity = result_uint64_count * bits_per_uint64_sz; + BigUInt resultint(safe_cast<int>(result_bit_capacity)); + bool result_is_negative = false; + uint64_t *result = resultint.data(); + for (size_t bit_index = plain.significant_coeff_count(); bit_index--;) + { + unsigned long long coeff = plain[bit_index]; + + // Left shift result, resizing if highest bit set. + if (is_bit_set_uint(result, result_uint64_count, safe_cast<int>(result_bit_capacity) - 1)) + { + // Resize to make bigger. + result_uint64_count++; + result_bit_capacity = mul_safe(result_uint64_count, bits_per_uint64_sz); + resultint.resize(safe_cast<int>(result_bit_capacity)); + result = resultint.data(); + } + left_shift_uint(result, 1, result_uint64_count, result); + + // Get sign/magnitude of coefficient. + if (coeff >= plain_modulus().value()) + { + // Coefficient is bigger than plaintext modulus + throw invalid_argument("plain does not represent a valid plaintext polynomial"); + } + bool coeff_is_negative = coeff >= coeff_neg_threshold_; + unsigned long long pos_value = coeff; + if (coeff_is_negative) + { + pos_value = plain_modulus().value() - pos_value; + } + + // Add or subtract-in coefficient. + if (result_is_negative == coeff_is_negative) + { + // Result and coefficient have same signs so add. + if (add_uint_uint64(result, pos_value, result_uint64_count, result)) + { + // Add produced a carry that didn't fit, so resize and put it in. + int carry_bit_index = safe_cast<int>(mul_safe(result_uint64_count, bits_per_uint64_sz)); + result_uint64_count++; + result_bit_capacity = mul_safe(result_uint64_count, bits_per_uint64_sz); + resultint.resize(safe_cast<int>(result_bit_capacity)); + result = resultint.data(); + set_bit_uint(result, result_uint64_count, carry_bit_index); + } + } + else + { + // Result and coefficient have opposite signs so subtract. + if (sub_uint_uint64(result, pos_value, result_uint64_count, result)) + { + // Subtraction produced a borrow so coefficient is larger (in magnitude) + // than result, so need to negate result. + negate_uint(result, result_uint64_count, result); + result_is_negative = !result_is_negative; + } + } + } + + // Verify result is non-negative. + if (result_is_negative && !resultint.is_zero()) + { + throw invalid_argument("poly must decode to positive value"); + } + return resultint; + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/intencoder.h b/bigpiseal3.5.1/native/src/seal/intencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..bba3d8cfeea1c3448e75fb1019db4ef82d927de5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/intencoder.h @@ -0,0 +1,235 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/biguint.h" +#include "seal/context.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/plaintext.h" +#include <cstdint> + +namespace seal +{ + /** + Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of + the IntegerEncoder class converts an integer into a plaintext polynomial by placing its + binary digits as the coefficients of the polynomial. Decoding the integer amounts to + evaluating the plaintext polynomial at x=2. + + Addition and multiplication on the integer side translate into addition and multiplication + on the encoded plaintext polynomial side, provided that the length of the polynomial + never grows to be of the size of the polynomial modulus (poly_modulus), and that the + coefficients of the plaintext polynomials appearing throughout the computations never + experience coefficients larger than the plaintext modulus (plain_modulus). + + @par Negative Integers + Negative integers are represented by using -1 instead of 1 in the binary representation, + and the negative coefficients are stored in the plaintext polynomials as unsigned integers + that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + would be stored as a polynomial coefficient plain_modulus-1. + */ + class IntegerEncoder + { + public: + /** + Creates a IntegerEncoder object. The constructor takes as input a pointer to + a SEALContext object which contains the plaintext modulus. + + @param[in] context The SEALContext + @throws std::invalid_argument if the context is not set + @throws std::invalid_argument if the plain_modulus set in context is not + at least 2 + */ + IntegerEncoder(std::shared_ptr<SEALContext> context); + + /** + Destroys the IntegerEncoder. + */ + ~IntegerEncoder() = default; + + /** + Encodes an unsigned integer (represented by std::uint64_t) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + */ + SEAL_NODISCARD Plaintext encode(std::uint64_t value); + + /** + Encodes an unsigned integer (represented by std::uint64_t) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + @param[out] destination The plaintext to overwrite with the encoding + */ + void encode(std::uint64_t value, Plaintext &destination); + + /** + Decodes a plaintext polynomial and returns the result as std::uint32_t. + Mathematically this amounts to evaluating the input polynomial at x=2. + + @param[in] plain The plaintext to be decoded + @throws std::invalid_argument if the output does not fit in std::uint32_t + */ + SEAL_NODISCARD std::uint32_t decode_uint32(const Plaintext &plain); + + /** + Decodes a plaintext polynomial and returns the result as std::uint64_t. + Mathematically this amounts to evaluating the input polynomial at x=2. + + @param[in] plain The plaintext to be decoded + @throws std::invalid_argument if the output does not fit in std::uint64_t + */ + SEAL_NODISCARD std::uint64_t decode_uint64(const Plaintext &plain); + + /** + Encodes a signed integer (represented by std::uint64_t) into a plaintext polynomial. + + @par Negative Integers + Negative integers are represented by using -1 instead of 1 in the binary representation, + and the negative coefficients are stored in the plaintext polynomials as unsigned integers + that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + would be stored as a polynomial coefficient plain_modulus-1. + + @param[in] value The signed integer to encode + */ + SEAL_NODISCARD Plaintext encode(std::int64_t value); + + /** + Encodes a signed integer (represented by std::int64_t) into a plaintext polynomial. + + @par Negative Integers + Negative integers are represented by using -1 instead of 1 in the binary representation, + and the negative coefficients are stored in the plaintext polynomials as unsigned integers + that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + would be stored as a polynomial coefficient plain_modulus-1. + + @param[in] value The signed integer to encode + @param[out] destination The plaintext to overwrite with the encoding + */ + void encode(std::int64_t value, Plaintext &destination); + + /** + Encodes an unsigned integer (represented by BigUInt) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + */ + SEAL_NODISCARD Plaintext encode(const BigUInt &value); + + /** + Encodes an unsigned integer (represented by BigUInt) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + @param[out] destination The plaintext to overwrite with the encoding + */ + void encode(const BigUInt &value, Plaintext &destination); + + /** + Decodes a plaintext polynomial and returns the result as std::int32_t. + Mathematically this amounts to evaluating the input polynomial at x=2. + + @param[in] plain The plaintext to be decoded + @throws std::invalid_argument if plain does not represent a valid plaintext polynomial + @throws std::invalid_argument if the output does not fit in std::int32_t + */ + SEAL_NODISCARD std::int32_t decode_int32(const Plaintext &plain); + + /** + Decodes a plaintext polynomial and returns the result as std::int64_t. + Mathematically this amounts to evaluating the input polynomial at x=2. + + @param[in] plain The plaintext to be decoded + @throws std::invalid_argument if plain does not represent a valid plaintext polynomial + @throws std::invalid_argument if the output does not fit in std::int64_t + */ + SEAL_NODISCARD std::int64_t decode_int64(const Plaintext &plain); + + /** + Decodes a plaintext polynomial and returns the result as BigUInt. + Mathematically this amounts to evaluating the input polynomial at x=2. + + @param[in] plain The plaintext to be decoded + @throws std::invalid_argument if plain does not represent a valid plaintext polynomial + @throws std::invalid_argument if the output is negative + */ + SEAL_NODISCARD BigUInt decode_biguint(const Plaintext &plain); + + /** + Encodes a signed integer (represented by std::int32_t) into a plaintext polynomial. + + @par Negative Integers + Negative integers are represented by using -1 instead of 1 in the binary representation, + and the negative coefficients are stored in the plaintext polynomials as unsigned integers + that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + would be stored as a polynomial coefficient plain_modulus-1. + + @param[in] value The signed integer to encode + */ + SEAL_NODISCARD inline Plaintext encode(std::int32_t value) + { + return encode(static_cast<std::int64_t>(value)); + } + + /** + Encodes an unsigned integer (represented by std::uint32_t) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + */ + SEAL_NODISCARD inline Plaintext encode(std::uint32_t value) + { + return encode(static_cast<std::uint64_t>(value)); + } + + /** + Encodes a signed integer (represented by std::int32_t) into a plaintext polynomial. + + @par Negative Integers + Negative integers are represented by using -1 instead of 1 in the binary representation, + and the negative coefficients are stored in the plaintext polynomials as unsigned integers + that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 + would be stored as a polynomial coefficient plain_modulus-1. + + @param[in] value The signed integer to encode + @param[out] destination The plaintext to overwrite with the encoding + */ + void inline encode(std::int32_t value, Plaintext &destination) + { + encode(static_cast<std::int64_t>(value), destination); + } + + /** + Encodes an unsigned integer (represented by std::uint32_t) into a plaintext polynomial. + + @param[in] value The unsigned integer to encode + @param[out] destination The plaintext to overwrite with the encoding + */ + void inline encode(std::uint32_t value, Plaintext &destination) + { + encode(static_cast<std::uint64_t>(value), destination); + } + + /** + Returns a reference to the plaintext modulus. + */ + SEAL_NODISCARD inline const Modulus &plain_modulus() const + { + auto &context_data = *context_->first_context_data(); + return context_data.parms().plain_modulus(); + } + + private: + IntegerEncoder(const IntegerEncoder &copy) = delete; + + IntegerEncoder(IntegerEncoder &&source) = delete; + + IntegerEncoder &operator=(const IntegerEncoder &assign) = delete; + + IntegerEncoder &operator=(IntegerEncoder &&assign) = delete; + + std::shared_ptr<SEALContext> context_{ nullptr }; + + std::uint64_t coeff_neg_threshold_; + + std::uint64_t neg_one_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/keygenerator.cpp b/bigpiseal3.5.1/native/src/seal/keygenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b77833ae4fcc53b4ff65589f2b500920e9972093 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/keygenerator.cpp @@ -0,0 +1,404 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/keygenerator.h" +#include "seal/randomtostd.h" +#include "seal/util/clipnormal.h" +#include "seal/util/common.h" +#include "seal/util/galois.h" +#include "seal/util/ntt.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/rlwe.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <algorithm> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + KeyGenerator::KeyGenerator(shared_ptr<SEALContext> context) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + // Secret key has not been generated + sk_generated_ = false; + + // Generate the secret and public key + generate_sk(); + } + + KeyGenerator::KeyGenerator(shared_ptr<SEALContext> context, const SecretKey &secret_key) : context_(move(context)) + { + // Verify parameters + if (!context_) + { + throw invalid_argument("invalid context"); + } + if (!context_->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + if (!is_valid_for(secret_key, context_)) + { + throw invalid_argument("secret key is not valid for encryption parameters"); + } + + // Set the secret key + secret_key_ = secret_key; + sk_generated_ = true; + + // Generate the public key + generate_sk(sk_generated_); + } + + void KeyGenerator::generate_sk(bool is_initialized) + { + // Extract encryption parameters. + auto &context_data = *context_->key_context_data(); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + if (!is_initialized) + { + // Initialize secret key. + secret_key_ = SecretKey(); + sk_generated_ = false; + secret_key_.data().resize(mul_safe(coeff_count, coeff_modulus_size)); + + shared_ptr<UniformRandomGenerator> random(parms.random_generator()->create()); + + // Generate secret key + uint64_t *secret_key = secret_key_.data().data(); + sample_poly_ternary(random, parms, secret_key); + + auto small_ntt_tables = context_data.small_ntt_tables(); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Transform the secret s into NTT representation. + ntt_negacyclic_harvey(secret_key + (i * coeff_count), small_ntt_tables[i]); + } + + // Set the parms_id for secret key + secret_key_.parms_id() = context_data.parms_id(); + } + + // Set the secret_key_array to have size 1 (first power of secret) + secret_key_array_ = allocate_poly(coeff_count, coeff_modulus_size, pool_); + set_poly_poly(secret_key_.data().data(), coeff_count, coeff_modulus_size, secret_key_array_.get()); + secret_key_array_size_ = 1; + + // Secret key has been generated + sk_generated_ = true; + } + + PublicKey KeyGenerator::generate_pk() const + { + if (!sk_generated_) + { + throw logic_error("cannot generate public key for unspecified secret key"); + } + + // Extract encryption parameters. + auto &context_data = *context_->key_context_data(); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + // Initialize public key. + // PublicKey data allocated from pool given by MemoryManager::GetPool. + PublicKey public_key; + + shared_ptr<UniformRandomGenerator> random(parms.random_generator()->create()); + encrypt_zero_symmetric(secret_key_, context_, context_data.parms_id(), true, false, public_key.data()); + + // Set the parms_id for public key + public_key.parms_id() = context_data.parms_id(); + + return public_key; + } + + RelinKeys KeyGenerator::relin_keys(size_t count, bool save_seed) + { + // Check to see if secret key and public key have been generated + if (!sk_generated_) + { + throw logic_error("cannot generate relinearization keys for unspecified secret key"); + } + if (!count || count > SEAL_CIPHERTEXT_SIZE_MAX - 2) + { + throw invalid_argument("invalid count"); + } + + // Extract encryption parameters. + auto &context_data = *context_->key_context_data(); + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = parms.coeff_modulus().size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size)) + { + throw logic_error("invalid parameters"); + } + + shared_ptr<UniformRandomGenerator> random(parms.random_generator()->create()); + + // Make sure we have enough secret keys computed + compute_secret_key_array(context_data, count + 1); + + // Create the RelinKeys object to return + RelinKeys relin_keys; + + // Assume the secret key is already transformed into NTT form. + generate_kswitch_keys( + secret_key_array_.get() + coeff_modulus_size * coeff_count, count, static_cast<KSwitchKeys &>(relin_keys), + save_seed); + + // Set the parms_id + relin_keys.parms_id() = context_data.parms_id(); + + return relin_keys; + } + + GaloisKeys KeyGenerator::galois_keys(const vector<uint32_t> &galois_elts, bool save_seed) + { + // Check to see if secret key and public key have been generated + if (!sk_generated_) + { + throw logic_error("cannot generate Galois keys for unspecified secret key"); + } + + // Extract encryption parameters. + auto &context_data = *context_->key_context_data(); + if (!context_data.qualifiers().using_batching) + { + throw logic_error("encryption parameters do not support batching"); + } + + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + auto galois_tool = context_data.galois_tool(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size, size_t(2))) + { + throw logic_error("invalid parameters"); + } + + // Create the GaloisKeys object to return + GaloisKeys galois_keys; + + // The max number of keys is equal to number of coefficients + galois_keys.data().resize(coeff_count); + + for (auto galois_elt : galois_elts) + { + // Verify coprime conditions. + if (!(galois_elt & 1) || (galois_elt >= coeff_count << 1)) + { + throw invalid_argument("Galois element is not valid"); + } + + // Do we already have the key? + if (galois_keys.has_key(galois_elt)) + { + continue; + } + + // Rotate secret key for each coeff_modulus + auto rotated_secret_key(allocate_poly(coeff_count, coeff_modulus_size, pool_)); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + const_cast<GaloisTool *>(galois_tool) + ->apply_galois_ntt( + secret_key_.data().data() + i * coeff_count, galois_elt, + rotated_secret_key.get() + i * coeff_count); + } + + // Initialize Galois key + // This is the location in the galois_keys vector + size_t index = GaloisKeys::get_index(galois_elt); + shared_ptr<UniformRandomGenerator> random(parms.random_generator()->create()); + + // Create Galois keys. + generate_one_kswitch_key(rotated_secret_key.get(), galois_keys.data()[index], save_seed); + } + + // Set the parms_id + galois_keys.parms_id_ = context_data.parms_id(); + + return galois_keys; + } + + const SecretKey &KeyGenerator::secret_key() const + { + if (!sk_generated_) + { + throw logic_error("secret key has not been generated"); + } + return secret_key_; + } + + void KeyGenerator::compute_secret_key_array(const SEALContext::ContextData &context_data, size_t max_power) + { +#ifdef SEAL_DEBUG + if (max_power < 1) + { + throw invalid_argument("max_power must be at least 1"); + } + if (!secret_key_array_size_ || !secret_key_array_) + { + throw logic_error("secret_key_array_ is uninitialized"); + } +#endif + // Extract encryption parameters. + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size, max_power)) + { + throw logic_error("invalid parameters"); + } + + ReaderLock reader_lock(secret_key_array_locker_.acquire_read()); + + size_t old_size = secret_key_array_size_; + size_t new_size = max(max_power, old_size); + + if (old_size == new_size) + { + return; + } + + reader_lock.unlock(); + + // Need to extend the array + // Compute powers of secret key until max_power + auto new_secret_key_array(allocate_poly(new_size * coeff_count, coeff_modulus_size, pool_)); + set_poly_poly(secret_key_array_.get(), old_size * coeff_count, coeff_modulus_size, new_secret_key_array.get()); + + size_t poly_ptr_increment = coeff_count * coeff_modulus_size; + uint64_t *prev_poly_ptr = new_secret_key_array.get() + (old_size - 1) * poly_ptr_increment; + uint64_t *next_poly_ptr = prev_poly_ptr + poly_ptr_increment; + + // Since all of the key powers in secret_key_array_ are already + // NTT transformed, to get the next one we simply need to compute + // a dyadic product of the last one with the first one + // [which is equal to NTT(secret_key_)]. + for (size_t i = old_size; i < new_size; i++) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + dyadic_product_coeffmod( + prev_poly_ptr + (j * coeff_count), new_secret_key_array.get() + (j * coeff_count), coeff_count, + coeff_modulus[j], next_poly_ptr + (j * coeff_count)); + } + prev_poly_ptr = next_poly_ptr; + next_poly_ptr += poly_ptr_increment; + } + + // Take writer lock to update array + WriterLock writer_lock(secret_key_array_locker_.acquire_write()); + + // Do we still need to update size? + old_size = secret_key_array_size_; + new_size = max(max_power, secret_key_array_size_); + + if (old_size == new_size) + { + return; + } + + // Acquire new array + secret_key_array_size_ = new_size; + secret_key_array_.acquire(new_secret_key_array); + } + + void KeyGenerator::generate_one_kswitch_key( + const uint64_t *new_key, std::vector<PublicKey> &destination, bool save_seed) + { + if (!context_->using_keyswitching()) + { + throw logic_error("keyswitching is not supported by the context"); + } + + size_t coeff_count = context_->key_context_data()->parms().poly_modulus_degree(); + size_t decomp_mod_count = context_->first_context_data()->parms().coeff_modulus().size(); + auto &key_context_data = *context_->key_context_data(); + auto &key_parms = key_context_data.parms(); + auto &key_modulus = key_parms.coeff_modulus(); + shared_ptr<UniformRandomGenerator> random(key_parms.random_generator()->create()); + + // Size check + if (!product_fits_in(coeff_count, decomp_mod_count)) + { + throw logic_error("invalid parameters"); + } + + // KSwitchKeys data allocated from pool given by MemoryManager::GetPool. + destination.resize(decomp_mod_count); + + auto temp(allocate_uint(coeff_count, pool_)); + uint64_t factor = 0; + for (size_t j = 0; j < decomp_mod_count; j++) + { + encrypt_zero_symmetric( + secret_key_, context_, key_context_data.parms_id(), true, save_seed, destination[j].data()); + factor = key_modulus.back().value() % key_modulus[j].value(); + multiply_poly_scalar_coeffmod(new_key + j * coeff_count, coeff_count, factor, key_modulus[j], temp.get()); + add_poly_poly_coeffmod( + destination[j].data().data() + j * coeff_count, temp.get(), coeff_count, key_modulus[j], + destination[j].data().data() + j * coeff_count); + } + } + + void KeyGenerator::generate_kswitch_keys( + const uint64_t *new_keys, size_t num_keys, KSwitchKeys &destination, bool save_seed) + { + size_t coeff_count = context_->key_context_data()->parms().poly_modulus_degree(); + auto &key_context_data = *context_->key_context_data(); + auto &key_parms = key_context_data.parms(); + size_t coeff_modulus_size = key_parms.coeff_modulus().size(); + shared_ptr<UniformRandomGenerator> random(key_parms.random_generator()->create()); + + // Size check + if (!product_fits_in(coeff_count, coeff_modulus_size, num_keys)) + { + throw logic_error("invalid parameters"); + } + + destination.data().resize(num_keys); + auto temp(allocate_uint(coeff_count, pool_)); + for (size_t l = 0; l < num_keys; l++) + { + const uint64_t *new_key_ptr = new_keys + l * coeff_modulus_size * coeff_count; + generate_one_kswitch_key(new_key_ptr, destination.data()[l], save_seed); + } + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/keygenerator.h b/bigpiseal3.5.1/native/src/seal/keygenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..7e61c0921fa3bb3639c827ecc6ec65a589ab4b5d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/keygenerator.h @@ -0,0 +1,336 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/galoiskeys.h" +#include "seal/memorymanager.h" +#include "seal/publickey.h" +#include "seal/randomgen.h" +#include "seal/relinkeys.h" +#include "seal/secretkey.h" +#include "seal/serializable.h" +#include "seal/util/defines.h" +#include "seal/util/ntt.h" +#include <memory> +#include <random> + +namespace seal +{ + /** + Generates matching secret key and public key. An existing KeyGenerator can + also at any time be used to generate relinearization keys and Galois keys. + Constructing a KeyGenerator requires only a SEALContext. + + @see EncryptionParameters for more details on encryption parameters. + @see SecretKey for more details on secret key. + @see PublicKey for more details on public key. + @see RelinKeys for more details on relinearization keys. + @see GaloisKeys for more details on Galois keys. + */ + class KeyGenerator + { + public: + /** + Creates a KeyGenerator initialized with the specified SEALContext. + + @param[in] context The SEALContext + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + */ + KeyGenerator(std::shared_ptr<SEALContext> context); + + /** + Creates an KeyGenerator instance initialized with the specified SEALContext + and specified previously secret key. This can e.g. be used to increase + the number of relinearization keys from what had earlier been generated, + or to generate Galois keys in case they had not been generated earlier. + + + @param[in] context The SEALContext + @param[in] secret_key A previously generated secret key + @throws std::invalid_argument if encryption parameters are not valid + @throws std::invalid_argument if secret_key is not valid for encryption + parameters + */ + KeyGenerator(std::shared_ptr<SEALContext> context, const SecretKey &secret_key); + + /** + Returns a const reference to the secret key. + */ + SEAL_NODISCARD const SecretKey &secret_key() const; + + /** + Generates and returns a public key. Every time this function is called, + a new public key will be generated. + */ + SEAL_NODISCARD inline PublicKey public_key() const + { + return generate_pk(); + } + + /** + Generates and returns relinearization keys. This function returns + relinearization keys in a fully expanded form and is meant to be used + primarily for demo, testing, and debugging purposes. + + @throws std::logic_error if the encryption parameters do not support + keyswitching + */ + SEAL_NODISCARD inline RelinKeys relin_keys_local() + { + return relin_keys(1, false); + } + + /** + Generates and returns relinearization keys as a serializable object. + + Half of the key data is pseudo-randomly generated from a seed to reduce + the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @throws std::logic_error if the encryption parameters do not support + keyswitching + */ + SEAL_NODISCARD inline Serializable<RelinKeys> relin_keys() + { + return relin_keys(1, true); + } + + /** + Generates and returns Galois keys. This function returns Galois keys in + a fully expanded form and is meant to be used primarily for demo, testing, + and debugging purposes. This function creates specific Galois keys that + can be used to apply specific Galois automorphisms on encrypted data. The + user needs to give as input a vector of Galois elements corresponding to + the keys that are to be created. + + The Galois elements are odd integers in the interval [1, M-1], where + M = 2*N, and N = poly_modulus_degree. Used with batching, a Galois element + 3^i % M corresponds to a cyclic row rotation i steps to the left, and + a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i + steps to the right. The Galois element M-1 corresponds to a column rotation + (row swap) in BFV, and complex conjugation in CKKS. In the polynomial view + (not batching), a Galois automorphism by a Galois element p changes + Enc(plain(x)) to Enc(plain(x^p)). + + @param[in] galois_elts The Galois elements for which to generate keys + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + @throws std::invalid_argument if the Galois elements are not valid + */ + SEAL_NODISCARD inline GaloisKeys galois_keys_local(const std::vector<std::uint32_t> &galois_elts) + { + return galois_keys(galois_elts, false); + } + + /** + Generates and returns Galois keys as a serializable object. This function + creates specific Galois keys that can be used to apply specific Galois + automorphisms on encrypted data. The user needs to give as input a vector + of Galois elements corresponding to the keys that are to be created. + + The Galois elements are odd integers in the interval [1, M-1], where + M = 2*N, and N = poly_modulus_degree. Used with batching, a Galois element + 3^i % M corresponds to a cyclic row rotation i steps to the left, and + a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i + steps to the right. The Galois element M-1 corresponds to a column rotation + (row swap) in BFV, and complex conjugation in CKKS. In the polynomial view + (not batching), a Galois automorphism by a Galois element p changes + Enc(plain(x)) to Enc(plain(x^p)). + + Half of the key data is pseudo-randomly generated from a seed to reduce + the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @param[in] galois_elts The Galois elements for which to generate keys + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + @throws std::invalid_argument if the Galois elements are not valid + */ + SEAL_NODISCARD inline Serializable<GaloisKeys> galois_keys(const std::vector<std::uint32_t> &galois_elts) + { + return galois_keys(galois_elts, true); + } + + /** + Generates and returns Galois keys. This function returns Galois keys in + a fully expanded form and is meant to be used primarily for demo, testing, + and debugging purposes. The user needs to give as input a vector of desired + Galois rotation step counts, where negative step counts correspond to + rotations to the right and positive step counts correspond to rotations to + the left. A step count of zero can be used to indicate a column rotation + in the BFV scheme complex conjugation in the CKKS scheme. + + @param[in] galois_steps The rotation step counts for which to generate keys + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + @throws std::invalid_argument if the step counts are not valid + */ + SEAL_NODISCARD inline GaloisKeys galois_keys_local(const std::vector<int> &steps) + { + return galois_keys_local(context_->key_context_data()->galois_tool()->get_elts_from_steps(steps)); + } + + /** + Generates and returns Galois keys as a serializable object. This function + creates specific Galois keys that can be used to apply specific Galois + automorphisms on encrypted data. The user needs to give as input a vector + of desired Galois rotation step counts, where negative step counts + correspond to rotations to the right and positive step counts correspond + to rotations to the left. A step count of zero can be used to indicate + a column rotation in the BFV scheme complex conjugation in the CKKS scheme. + + Half of the key data is pseudo-randomly generated from a seed to reduce + the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @param[in] galois_steps The rotation step counts for which to generate keys + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + @throws std::invalid_argument if the step counts are not valid + */ + SEAL_NODISCARD inline Serializable<GaloisKeys> galois_keys(const std::vector<int> &steps) + { + return galois_keys(context_->key_context_data()->galois_tool()->get_elts_from_steps(steps)); + } + + /** + Generates and returns Galois keys. This function returns Galois keys in + a fully expanded form and is meant to be used primarily for demo, testing, + and debugging purposes. This function creates logarithmically many (in + degree of the polynomial modulus) Galois keys that is sufficient to apply + any Galois automorphism (e.g. rotations) on encrypted data. Most users + will want to use this overload of the function. + + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + */ + SEAL_NODISCARD inline GaloisKeys galois_keys_local() + { + return galois_keys_local(context_->key_context_data()->galois_tool()->get_elts_all()); + } + + /** + Generates and returns Galois keys as a serializable object. This function + creates logarithmically many (in degree of the polynomial modulus) Galois + keys that is sufficient to apply any Galois automorphism (e.g. rotations) + on encrypted data. Most users will want to use this overload of the function. + + Half of the key data is pseudo-randomly generated from a seed to reduce + the object size. The resulting serializable object cannot be used + directly and is meant to be serialized for the size reduction to have an + impact. + + @throws std::logic_error if the encryption parameters do not support + batching and scheme is scheme_type::BFV + @throws std::logic_error if the encryption parameters do not support + keyswitching + */ + SEAL_NODISCARD inline Serializable<GaloisKeys> galois_keys() + { + return galois_keys(context_->key_context_data()->galois_tool()->get_elts_all()); + } + + /** + Enables access to private members of seal::KeyGenerator for .NET wrapper. + */ + struct KeyGeneratorPrivateHelper; + + private: + KeyGenerator(const KeyGenerator &copy) = delete; + + KeyGenerator &operator=(const KeyGenerator &assign) = delete; + + KeyGenerator(KeyGenerator &&source) = delete; + + KeyGenerator &operator=(KeyGenerator &&assign) = delete; + + void compute_secret_key_array(const SEALContext::ContextData &context_data, std::size_t max_power); + + /** + Generates new secret key. + + @param[in] is_initialized True if the secret key has already been + initialized so that only the secret_key_array_ should be initialized, for + example, if the secret key was provided in the constructor + */ + void generate_sk(bool is_initialized = false); + + /** + Generates new public key matching to existing secret key. + */ + PublicKey generate_pk() const; + + /** + Generates new key switching keys for an array of new keys. + */ + void generate_kswitch_keys( + const std::uint64_t *new_keys, std::size_t num_keys, KSwitchKeys &destination, bool save_seed = false); + + /** + Generates one key switching key for a new key. + */ + void generate_one_kswitch_key( + const uint64_t *new_key, std::vector<PublicKey> &destination, bool save_seed = false); + + /** + Generates and returns the specified number of relinearization keys. + + @param[in] count The number of relinearization keys to generate + @param[in] save_seed If true, save seed instead of a polynomial. + @throws std::invalid_argument if count is zero or too large + */ + RelinKeys relin_keys(std::size_t count, bool save_seed); + + /** + Generates and returns Galois keys. This function creates specific Galois + keys that can be used to apply specific Galois automorphisms on encrypted + data. The user needs to give as input a vector of Galois elements + corresponding to the keys that are to be created. + + The Galois elements are odd integers in the interval [1, M-1], where + M = 2*N, and N = poly_modulus_degree. Used with batching, a Galois element + 3^i % M corresponds to a cyclic row rotation i steps to the left, and + a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i + steps to the right. The Galois element M-1 corresponds to a column rotation + (row swap) in BFV, and complex conjugation in CKKS. In the polynomial view + (not batching), a Galois automorphism by a Galois element p changes + Enc(plain(x)) to Enc(plain(x^p)). + + @param[in] galois_elts The Galois elements for which to generate keys + @param[in] save_seed If true, replace second poly in Ciphertext with seed + @throws std::invalid_argument if the Galois elements are not valid + */ + GaloisKeys galois_keys(const std::vector<std::uint32_t> &galois_elts, bool save_seed); + + // We use a fresh memory pool with `clear_on_destruction' enabled. + MemoryPoolHandle pool_ = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true); + + std::shared_ptr<SEALContext> context_{ nullptr }; + + SecretKey secret_key_; + + std::size_t secret_key_array_size_ = 0; + + util::Pointer<std::uint64_t> secret_key_array_; + + mutable util::ReaderWriterLocker secret_key_array_locker_; + + bool sk_generated_ = false; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/kswitchkeys.cpp b/bigpiseal3.5.1/native/src/seal/kswitchkeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..640e5031d52882aef15a9651f616527a49df9d38 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/kswitchkeys.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/kswitchkeys.h" +#include "seal/util/defines.h" +#include <stdexcept> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + KSwitchKeys &KSwitchKeys::operator=(const KSwitchKeys &assign) + { + // Check for self-assignment + if (this == &assign) + { + return *this; + } + + // Copy over fields + parms_id_ = assign.parms_id_; + + // Then copy over keys + keys_.clear(); + size_t keys_dim1 = assign.keys_.size(); + keys_.reserve(keys_dim1); + for (size_t i = 0; i < keys_dim1; i++) + { + size_t keys_dim2 = assign.keys_[i].size(); + keys_.emplace_back(); + keys_[i].reserve(keys_dim2); + for (size_t j = 0; j < keys_dim2; j++) + { + keys_[i].emplace_back(PublicKey(pool_)); + keys_[i][j] = assign.keys_[i][j]; + } + } + + return *this; + } + + void KSwitchKeys::save_members(ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + uint64_t keys_dim1 = static_cast<uint64_t>(keys_.size()); + + // Save the parms_id + stream.write(reinterpret_cast<const char *>(&parms_id_), sizeof(parms_id_type)); + + // Save the size of keys_ + stream.write(reinterpret_cast<const char *>(&keys_dim1), sizeof(uint64_t)); + + // Now loop again over keys_dim1 + for (size_t index = 0; index < keys_dim1; index++) + { + // Save second dimension of keys_ + uint64_t keys_dim2 = static_cast<uint64_t>(keys_[index].size()); + stream.write(reinterpret_cast<const char *>(&keys_dim2), sizeof(uint64_t)); + + // Loop over keys_dim2 and save all (or none) + for (size_t j = 0; j < keys_dim2; j++) + { + // Save the key + keys_[index][j].save(stream, compr_mode_type::none); + } + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void KSwitchKeys::load_members(shared_ptr<SEALContext> context, istream &stream) + { + // Verify parameters + if (!context) + { + throw invalid_argument("invalid context"); + } + if (!context->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + // Create new keys + vector<vector<PublicKey>> new_keys; + + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + // Read the parms_id + stream.read(reinterpret_cast<char *>(&parms_id_), sizeof(parms_id_type)); + + // Read in the size of keys_ + uint64_t keys_dim1 = 0; + stream.read(reinterpret_cast<char *>(&keys_dim1), sizeof(uint64_t)); + + // Reserve first for dimension of keys_ + new_keys.reserve(safe_cast<size_t>(keys_dim1)); + + // Loop over the first dimension of keys_ + for (size_t index = 0; index < keys_dim1; index++) + { + // Read the size of the second dimension + uint64_t keys_dim2 = 0; + stream.read(reinterpret_cast<char *>(&keys_dim2), sizeof(uint64_t)); + + // Don't resize; only reserve + new_keys.emplace_back(); + new_keys.back().reserve(safe_cast<size_t>(keys_dim2)); + for (size_t j = 0; j < keys_dim2; j++) + { + PublicKey key(pool_); + key.unsafe_load(context, stream); + new_keys[index].emplace_back(move(key)); + } + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + swap(keys_, new_keys); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/kswitchkeys.h b/bigpiseal3.5.1/native/src/seal/kswitchkeys.h new file mode 100644 index 0000000000000000000000000000000000000000..5ce2ad80d7273020bb14d5c5eed8e8be4b7c39a1 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/kswitchkeys.h @@ -0,0 +1,345 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/encryptionparams.h" +#include "seal/memorymanager.h" +#include "seal/publickey.h" +#include "seal/valcheck.h" +#include <iostream> +#include <limits> +#include <vector> + +namespace seal +{ + /** + Class to store keyswitching keys. It should never be necessary for normal + users to create an instance of KSwitchKeys. This class is used strictly as + a base class for RelinKeys and GaloisKeys classes. + + @par Keyswitching + Concretely, keyswitching is used to change a ciphertext encrypted with one + key to be encrypted with another key. It is a general technique and is used + in relinearization and Galois rotations. A keyswitching key contains a sequence + (vector) of keys. In RelinKeys, each key is an encryption of a power of the + secret key. In GaloisKeys, each key corresponds to a type of rotation. + + @par Thread Safety + In general, reading from KSwitchKeys is thread-safe as long as no + other thread is concurrently mutating it. This is due to the underlying + data structure storing the keyswitching keys not being thread-safe. + + @see RelinKeys for the class that stores the relinearization keys. + @see GaloisKeys for the class that stores the Galois keys. + */ + class KSwitchKeys + { + friend class KeyGenerator; + friend class RelinKeys; + friend class GaloisKeys; + + public: + /** + Creates an empty KSwitchKeys. + */ + KSwitchKeys() = default; + + /** + Creates a new KSwitchKeys instance by copying a given instance. + + @param[in] copy The KSwitchKeys to copy from + */ + KSwitchKeys(const KSwitchKeys &copy) = default; + + /** + Creates a new KSwitchKeys instance by moving a given instance. + + @param[in] source The RelinKeys to move from + */ + KSwitchKeys(KSwitchKeys &&source) = default; + + /** + Copies a given KSwitchKeys instance to the current one. + + @param[in] assign The KSwitchKeys to copy from + */ + KSwitchKeys &operator=(const KSwitchKeys &assign); + + /** + Moves a given KSwitchKeys instance to the current one. + + @param[in] assign The KSwitchKeys to move from + */ + KSwitchKeys &operator=(KSwitchKeys &&assign) = default; + + /** + Returns the current number of keyswitching keys. Only keys that are + non-empty are counted. + */ + SEAL_NODISCARD inline std::size_t size() const noexcept + { + return std::accumulate(keys_.cbegin(), keys_.cend(), std::size_t(0), [](std::size_t res, auto &next_key) { + return res + (next_key.empty() ? 0 : 1); + }); + } + + /** + Returns a reference to the KSwitchKeys data. + */ + SEAL_NODISCARD inline auto &data() noexcept + { + return keys_; + } + + /** + Returns a const reference to the KSwitchKeys data. + */ + SEAL_NODISCARD inline auto &data() const noexcept + { + return keys_; + } + + /** + Returns a reference to a keyswitching key at a given index. + + @param[in] index The index of the keyswitching key + @throws std::invalid_argument if the key at the given index does not exist + */ + SEAL_NODISCARD inline auto &data(std::size_t index) + { + if (index >= keys_.size() || keys_[index].empty()) + { + throw std::invalid_argument("keyswitching key does not exist"); + } + return keys_[index]; + } + + /** + Returns a const reference to a keyswitching key at a given index. + + @param[in] index The index of the keyswitching key + @throws std::invalid_argument if the key at the given index does not exist + */ + SEAL_NODISCARD inline const auto &data(std::size_t index) const + { + if (index >= keys_.size() || keys_[index].empty()) + { + throw std::invalid_argument("keyswitching key does not exist"); + } + return keys_[index]; + } + + /** + Returns a reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() noexcept + { + return parms_id_; + } + + /** + Returns a const reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return parms_id_; + } + + /** + Returns an upper bound on the size of the KSwitchKeys, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t total_key_size = util::mul_safe(keys_.size(), sizeof(std::uint64_t)); // keys_dim2 + for (auto &key_dim1 : keys_) + { + for (auto &key_dim2 : key_dim1) + { + total_key_size = util::add_safe( + total_key_size, util::safe_cast<std::size_t>(key_dim2.save_size(compr_mode_type::none))); + } + } + + std::size_t members_size = Serialization::ComprSizeEstimate( + util::add_safe( + sizeof(parms_id_), + sizeof(std::uint64_t), // keys_dim1 + total_key_size), + compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves the KSwitchKeys instance to an output stream. The output is + in binary format and not human-readable. The output stream must have + the "binary" flag set. + + @param[out] stream The stream to save the KSwitchKeys to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&KSwitchKeys::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a KSwitchKeys from an input stream overwriting the current KSwitchKeys. + No checking of the validity of the KSwitchKeys data against encryption + parameters is performed. This function should not be used unless the + KSwitchKeys comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] stream The stream to load the KSwitchKeys from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&KSwitchKeys::load_members, this, std::move(context), _1), stream); + } + + /** + Loads a KSwitchKeys from an input stream overwriting the current KSwitchKeys. + The loaded KSwitchKeys is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] stream The stream to load the KSwitchKeys from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + KSwitchKeys new_keys; + new_keys.pool_ = pool_; + auto in_size = new_keys.unsafe_load(context, stream); + if (!is_valid_for(new_keys, std::move(context))) + { + throw std::logic_error("KSwitchKeys data is invalid"); + } + std::swap(*this, new_keys); + return in_size; + } + + /** + Saves the KSwitchKeys instance to a given memory location. The output is + in binary format and not human-readable. + + @param[out] out The memory location to write the KSwitchKeys to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&KSwitchKeys::save_members, this, _1), save_size(compr_mode_type::none), out, size, + compr_mode); + } + + /** + Loads a KSwitchKeys from a given memory location overwriting the current + KSwitchKeys. No checking of the validity of the KSwitchKeys data against + encryption parameters is performed. This function should not be used + unless the KSwitchKeys comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] in The memory location to load the KSwitchKeys from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&KSwitchKeys::load_members, this, std::move(context), _1), in, size); + } + + /** + Loads a KSwitchKeys from a given memory location overwriting the current + KSwitchKeys. The loaded KSwitchKeys is verified to be valid for the given + SEALContext. + + @param[in] context The SEALContext + @param[in] in The memory location to load the KSwitchKeys from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + KSwitchKeys new_keys; + new_keys.pool_ = pool_; + auto in_size = new_keys.unsafe_load(context, in, size); + if (!is_valid_for(new_keys, std::move(context))) + { + throw std::logic_error("KSwitchKeys data is invalid"); + } + std::swap(*this, new_keys); + return in_size; + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return pool_; + } + + private: + void save_members(std::ostream &stream) const; + + void load_members(std::shared_ptr<SEALContext> context, std::istream &stream); + + MemoryPoolHandle pool_ = MemoryManager::GetPool(); + + parms_id_type parms_id_ = parms_id_zero; + + /** + The vector of keyswitching keys. + */ + std::vector<std::vector<PublicKey>> keys_{}; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/memorymanager.cpp b/bigpiseal3.5.1/native/src/seal/memorymanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19d0fbbe2b28841e9934d8f20c3b36e2c1613259 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/memorymanager.cpp @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/memorymanager.h" + +namespace seal +{ + std::unique_ptr<MMProf> MemoryManager::mm_prof_{ new MMProfGlobal }; +#ifndef _M_CEE + std::mutex MemoryManager::switch_mutex_; +#else +#pragma message("WARNING: MemoryManager compiled thread-unsafe and MMProfGuard disabled to support /clr") +#endif +} // namespace seal \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/memorymanager.h b/bigpiseal3.5.1/native/src/seal/memorymanager.h new file mode 100644 index 0000000000000000000000000000000000000000..fa8414dcf36399c5f6bd6489f2ee3a249bf4881c --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/memorymanager.h @@ -0,0 +1,790 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include "seal/util/globals.h" +#include "seal/util/mempool.h" +#include <memory> +#include <stdexcept> +#include <unordered_map> +#include <utility> + +/* +For .NET Framework wrapper support (C++/CLI) we need to + (1) compile the MemoryManager class as thread-unsafe because C++ + mutexes cannot be brought through C++/CLI layer; + (2) disable thread-safe memory pools. +*/ +#ifndef _M_CEE +#include <mutex> +#include <thread> +#endif + +namespace seal +{ + /** + Manages a shared pointer to a memory pool. Microsoft SEAL uses memory pools + for improved performance due to the large number of memory allocations + needed by the homomorphic encryption operations, and the underlying polynomial + arithmetic. The library automatically creates a shared global memory pool + that is used for all dynamic allocations by default, and the user can + optionally create any number of custom memory pools to be used instead. + + @par Uses in Multi-Threaded Applications + Sometimes the user might want to use specific memory pools for dynamic + allocations in certain functions. For example, in heavily multi-threaded + applications allocating concurrently from a shared memory pool might lead + to significant performance issues due to thread contention. For these cases + Microsoft SEAL provides overloads of the functions that take a MemoryPoolHandle + as an additional argument, and uses the associated memory pool for all dynamic + allocations inside the function. Whenever these functions are called, the + user can then simply pass a thread-local MemoryPoolHandle to be used. + + @par Thread-Unsafe Memory Pools + While memory pools are by default thread-safe, in some cases it suffices + to have a memory pool be thread-unsafe. To get a little extra performance, + the user can optionally create such thread-unsafe memory pools and use them + just as they would use thread-safe memory pools. + + @par Initialized and Uninitialized Handles + A MemoryPoolHandle has to be set to point either to the global memory pool, + or to a new memory pool. If this is not done, the MemoryPoolHandle is + said to be uninitialized, and cannot be used. Initialization simple means + assigning MemoryPoolHandle::Global() or MemoryPoolHandle::New() to it. + + @par Managing Lifetime + Internally, the MemoryPoolHandle wraps an std::shared_ptr pointing to + a memory pool class. Thus, as long as a MemoryPoolHandle pointing to + a particular memory pool exists, the pool stays alive. Classes such as + Evaluator and Ciphertext store their own local copies of a MemoryPoolHandle + to guarantee that the pool stays alive as long as the managing object + itself stays alive. The global memory pool is implemented as a global + std::shared_ptr to a memory pool class, and is thus expected to stay + alive for the entire duration of the program execution. Note that it can + be problematic to create other global objects that use the memory pool + e.g. in their constructor, as one would have to ensure the initialization + order of these global variables to be correct (i.e. global memory pool + first). + */ + class MemoryPoolHandle + { + public: + /** + Creates a new uninitialized MemoryPoolHandle. + */ + MemoryPoolHandle() = default; + + /** + Creates a MemoryPoolHandle pointing to a given MemoryPool object. + */ + MemoryPoolHandle(std::shared_ptr<util::MemoryPool> pool) noexcept : pool_(std::move(pool)) + {} + + /** + Creates a copy of a given MemoryPoolHandle. As a result, the created + MemoryPoolHandle will point to the same underlying memory pool as the + copied instance. + + + @param[in] copy The MemoryPoolHandle to copy from + */ + MemoryPoolHandle(const MemoryPoolHandle &copy) noexcept + { + operator=(copy); + } + + /** + Creates a new MemoryPoolHandle by moving a given one. As a result, the + moved MemoryPoolHandle will become uninitialized. + + + @param[in] source The MemoryPoolHandle to move from + */ + MemoryPoolHandle(MemoryPoolHandle &&source) noexcept + { + operator=(std::move(source)); + } + + /** + Overwrites the MemoryPoolHandle instance with the specified instance. As + a result, the current MemoryPoolHandle will point to the same underlying + memory pool as the assigned instance. + + @param[in] assign The MemoryPoolHandle instance to assign to the current + instance + */ + inline MemoryPoolHandle &operator=(const MemoryPoolHandle &assign) noexcept + { + pool_ = assign.pool_; + return *this; + } + + /** + Moves a specified MemoryPoolHandle instance to the current instance. As + a result, the assigned MemoryPoolHandle will become uninitialized. + + @param[in] assign The MemoryPoolHandle instance to assign to the current + instance + */ + inline MemoryPoolHandle &operator=(MemoryPoolHandle &&assign) noexcept + { + pool_ = std::move(assign.pool_); + return *this; + } + + /** + Returns a MemoryPoolHandle pointing to the global memory pool. + */ + SEAL_NODISCARD inline static MemoryPoolHandle Global() noexcept + { + return util::global_variables::global_memory_pool; + } +#ifndef _M_CEE + /** + Returns a MemoryPoolHandle pointing to the thread-local memory pool. + */ + SEAL_NODISCARD inline static MemoryPoolHandle ThreadLocal() noexcept + { + return util::global_variables::tls_memory_pool; + } +#endif + /** + Returns a MemoryPoolHandle pointing to a new thread-safe memory pool. + + @param[in] clear_on_destruction Indicates whether the memory pool data + should be cleared when destroyed. This can be important when memory pools + are used to store private data. + */ + SEAL_NODISCARD inline static MemoryPoolHandle New(bool clear_on_destruction = false) + { + return MemoryPoolHandle(std::make_shared<util::MemoryPoolMT>(clear_on_destruction)); + } + + /** + Returns a reference to the internal memory pool that the MemoryPoolHandle + points to. This function is mainly for internal use. + + @throws std::logic_error if the MemoryPoolHandle is uninitialized + */ + SEAL_NODISCARD inline operator util::MemoryPool &() const + { + if (!pool_) + { + throw std::logic_error("pool not initialized"); + } + return *pool_.get(); + } + + /** + Returns the number of different allocation sizes. This function returns + the number of different allocation sizes the memory pool pointed to by + the current MemoryPoolHandle has made. For example, if the memory pool has + only allocated two allocations of sizes 128 KB, this function returns 1. + If it has instead allocated one allocation of size 64 KB and one of 128 KB, + this function returns 2. + */ + SEAL_NODISCARD inline std::size_t pool_count() const noexcept + { + return !pool_ ? std::size_t(0) : pool_->pool_count(); + } + + /** + Returns the size of allocated memory. This functions returns the total + amount of memory (in bytes) allocated by the memory pool pointed to by + the current MemoryPoolHandle. + */ + SEAL_NODISCARD inline std::size_t alloc_byte_count() const noexcept + { + return !pool_ ? std::size_t(0) : pool_->alloc_byte_count(); + } + + /** + Returns the number of MemoryPoolHandle objects sharing this memory pool. + */ + SEAL_NODISCARD inline long use_count() const noexcept + { + return !pool_ ? 0 : pool_.use_count(); + } + + /** + Returns whether the MemoryPoolHandle is initialized. + */ + SEAL_NODISCARD inline explicit operator bool() const noexcept + { + return pool_.operator bool(); + } + + /** + Compares MemoryPoolHandles. This function returns whether the current + MemoryPoolHandle points to the same memory pool as a given MemoryPoolHandle. + */ + inline bool operator==(const MemoryPoolHandle &compare) noexcept + { + return pool_ == compare.pool_; + } + + /** + Compares MemoryPoolHandles. This function returns whether the current + MemoryPoolHandle points to a different memory pool than a given + MemoryPoolHandle. + */ + inline bool operator!=(const MemoryPoolHandle &compare) noexcept + { + return pool_ != compare.pool_; + } + + private: + std::shared_ptr<util::MemoryPool> pool_ = nullptr; + }; + + using mm_prof_opt_t = std::uint64_t; + + /** + Control options for MemoryManager::GetPool function. These force the MemoryManager + to override the current MMProf and instead return a MemoryPoolHandle pointing + to a memory pool of the indicated type. + */ + enum mm_prof_opt : mm_prof_opt_t + { + DEFAULT = 0x0, + FORCE_GLOBAL = 0x1, + FORCE_NEW = 0x2, + FORCE_THREAD_LOCAL = 0x4 + }; + + /** + The MMProf is a pure virtual class that every profile for the MemoryManager + should inherit from. The only functionality this class implements is the + get_pool(mm_prof_opt_t) function that returns a MemoryPoolHandle pointing + to a pool selected by internal logic optionally using the input parameter + of type mm_prof_opt_t. The returned MemoryPoolHandle must point to a valid + memory pool. + */ + class MMProf + { + public: + /** + Creates a new MMProf. + */ + MMProf() = default; + + /** + Destroys the MMProf. + */ + virtual ~MMProf() noexcept + {} + + /** + Returns a MemoryPoolHandle pointing to a pool selected by internal logic + in a derived class and by the mm_prof_opt_t input parameter. + + */ + virtual MemoryPoolHandle get_pool(mm_prof_opt_t) = 0; + + private: + }; + + /** + A memory manager profile that always returns a MemoryPoolHandle pointing to + the global memory pool. Microsoft SEAL uses this memory manager profile by default. + */ + class MMProfGlobal : public MMProf + { + public: + /** + Creates a new MMProfGlobal. + */ + MMProfGlobal() = default; + + /** + Destroys the MMProfGlobal. + */ + virtual ~MMProfGlobal() noexcept override + {} + + /** + Returns a MemoryPoolHandle pointing to the global memory pool. The + mm_prof_opt_t input parameter has no effect. + */ + SEAL_NODISCARD inline virtual MemoryPoolHandle get_pool(mm_prof_opt_t) override + { + return MemoryPoolHandle::Global(); + } + + private: + }; + + /** + A memory manager profile that always returns a MemoryPoolHandle pointing to + the new thread-safe memory pool. This profile should not be used except in + special circumstances, as it does not result in any reuse of allocated memory. + */ + class MMProfNew : public MMProf + { + public: + /** + Creates a new MMProfNew. + */ + MMProfNew() = default; + + /** + Destroys the MMProfNew. + */ + virtual ~MMProfNew() noexcept override + {} + + /** + Returns a MemoryPoolHandle pointing to a new thread-safe memory pool. The + mm_prof_opt_t input parameter has no effect. + */ + SEAL_NODISCARD inline virtual MemoryPoolHandle get_pool(mm_prof_opt_t) override + { + return MemoryPoolHandle::New(); + } + + private: + }; + + /** + A memory manager profile that always returns a MemoryPoolHandle pointing to + specific memory pool. + */ + class MMProfFixed : public MMProf + { + public: + /** + Creates a new MMProfFixed. The MemoryPoolHandle given as argument is returned + by every call to get_pool(mm_prof_opt_t). + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + MMProfFixed(MemoryPoolHandle pool) : pool_(std::move(pool)) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + } + + /** + Destroys the MMProfFixed. + */ + virtual ~MMProfFixed() noexcept override + {} + + /** + Returns a MemoryPoolHandle pointing to the stored memory pool. The + mm_prof_opt_t input parameter has no effect. + */ + SEAL_NODISCARD inline virtual MemoryPoolHandle get_pool(mm_prof_opt_t) override + { + return pool_; + } + + private: + MemoryPoolHandle pool_; + }; +#ifndef _M_CEE + /** + A memory manager profile that always returns a MemoryPoolHandle pointing to + the thread-local memory pool. This profile should be used with care, as any + memory allocated by it will be released once the thread exits. In other words, + the thread-local memory pool cannot be used to share memory across different + threads. On the other hand, this profile can be useful when a very high number + of threads doing simultaneous allocations would cause contention in the + global memory pool. + */ + class MMProfThreadLocal : public MMProf + { + public: + /** + Creates a new MMProfThreadLocal. + */ + MMProfThreadLocal() = default; + + /** + Destroys the MMProfThreadLocal. + */ + virtual ~MMProfThreadLocal() noexcept override + {} + + /** + Returns a MemoryPoolHandle pointing to the thread-local memory pool. The + mm_prof_opt_t input parameter has no effect. + */ + SEAL_NODISCARD inline virtual MemoryPoolHandle get_pool(mm_prof_opt_t) override + { + return MemoryPoolHandle::ThreadLocal(); + } + + private: + }; +#endif + /** + The MemoryManager class can be used to create instances of MemoryPoolHandle + based on a given "profile". A profile is implemented by inheriting from the + MMProf class (pure virtual) and encapsulates internal logic for deciding which + memory pool to use. + */ + class MemoryManager + { + friend class MMProfGuard; + + public: + MemoryManager() = delete; + + /** + Sets the current profile to a given one and returns a unique_ptr pointing + to the previously set profile. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::invalid_argument if mm_prof is nullptr + */ + static inline std::unique_ptr<MMProf> SwitchProfile(MMProf *&&mm_prof) noexcept + { +#ifndef _M_CEE + std::lock_guard<std::mutex> switching_lock(switch_mutex_); +#endif + return SwitchProfileThreadUnsafe(std::move(mm_prof)); + } + + /** + Sets the current profile to a given one and returns a unique_ptr pointing + to the previously set profile. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::invalid_argument if mm_prof is nullptr + */ + static inline std::unique_ptr<MMProf> SwitchProfile(std::unique_ptr<MMProf> &&mm_prof) noexcept + { +#ifndef _M_CEE + std::lock_guard<std::mutex> switch_lock(switch_mutex_); +#endif + return SwitchProfileThreadUnsafe(std::move(mm_prof)); + } + + /** + Returns a MemoryPoolHandle according to the currently set memory manager + profile and prof_opt. The following values for prof_opt have an effect + independent of the current profile: + + mm_prof_opt::FORCE_NEW: return MemoryPoolHandle::New() + mm_prof_opt::FORCE_GLOBAL: return MemoryPoolHandle::Global() + mm_prof_opt::FORCE_THREAD_LOCAL: return MemoryPoolHandle::ThreadLocal() + + Other values for prof_opt are forwarded to the current profile and, depending + on the profile, may or may not have an effect. The value mm_prof_opt::DEFAULT + will always invoke a default behavior for the current profile. + + @param[in] prof_opt A mm_prof_opt_t parameter used to provide additional + instructions to the memory manager profile for internal logic. + */ + template <typename... Args> + SEAL_NODISCARD static inline MemoryPoolHandle GetPool(mm_prof_opt_t prof_opt, Args &&... args) + { + switch (prof_opt) + { + case mm_prof_opt::FORCE_GLOBAL: + return MemoryPoolHandle::Global(); + + case mm_prof_opt::FORCE_NEW: + return MemoryPoolHandle::New(std::forward<Args>(args)...); +#ifndef _M_CEE + case mm_prof_opt::FORCE_THREAD_LOCAL: + return MemoryPoolHandle::ThreadLocal(); +#endif + default: +#ifdef SEAL_DEBUG + { + auto pool = mm_prof_->get_pool(prof_opt); + if (!pool) + { + throw std::logic_error("cannot return uninitialized pool"); + } + return pool; + } +#endif + return mm_prof_->get_pool(prof_opt); + } + } + + SEAL_NODISCARD static inline MemoryPoolHandle GetPool() + { + return GetPool(mm_prof_opt::DEFAULT); + } + + private: + SEAL_NODISCARD static inline std::unique_ptr<MMProf> SwitchProfileThreadUnsafe(MMProf *&&mm_prof) + { + if (!mm_prof) + { + throw std::invalid_argument("mm_prof cannot be null"); + } + auto ret_mm_prof = std::move(mm_prof_); + mm_prof_.reset(mm_prof); + return ret_mm_prof; + } + + SEAL_NODISCARD static inline std::unique_ptr<MMProf> SwitchProfileThreadUnsafe( + std::unique_ptr<MMProf> &&mm_prof) + { + if (!mm_prof) + { + throw std::invalid_argument("mm_prof cannot be null"); + } + std::swap(mm_prof_, mm_prof); + return std::move(mm_prof); + } + + static std::unique_ptr<MMProf> mm_prof_; +#ifndef _M_CEE + static std::mutex switch_mutex_; +#endif + }; +#ifndef _M_CEE + /** + Class for a scoped switch of memory manager profile. This class acts as a scoped + "guard" for changing the memory manager profile so that the programmer does + not have to explicitly switch back afterwards and that other threads cannot + change the MMProf. It can also help with exception safety by guaranteeing that + the profile is switched back to the original if a function throws an exception + after changing the profile for local use. + */ + class MMProfGuard + { + public: + /** + Creates a new MMProfGuard. If start_locked is true, this function will + attempt to lock the MemoryManager for profile switch to mm_prof, perform + the switch, and keep the lock until unlocked or destroyed. If start_lock + is false, mm_prof will be stored but the switch will not be performed and + a lock will not be obtained until lock() is explicitly called. + + @param[in] mm_prof Pointer to a new memory manager profile + @param[in] start_locked Bool indicating whether the lock should be + immediately obtained (true by default) + */ + MMProfGuard(std::unique_ptr<MMProf> &&mm_prof, bool start_locked = true) noexcept + : mm_switch_lock_(MemoryManager::switch_mutex_, std::defer_lock) + { + if (start_locked) + { + lock(std::move(mm_prof)); + } + else + { + old_prof_ = std::move(mm_prof); + } + } + + /** + Creates a new MMProfGuard. If start_locked is true, this function will + attempt to lock the MemoryManager for profile switch to mm_prof, perform + the switch, and keep the lock until unlocked or destroyed. If start_lock + is false, mm_prof will be stored but the switch will not be performed and + a lock will not be obtained until lock() is explicitly called. + + @param[in] mm_prof Pointer to a new memory manager profile + @param[in] start_locked Bool indicating whether the lock should be + immediately obtained (true by default) + */ + MMProfGuard(MMProf *&&mm_prof, bool start_locked = true) noexcept + : mm_switch_lock_(MemoryManager::switch_mutex_, std::defer_lock) + { + if (start_locked) + { + lock(std::move(mm_prof)); + } + else + { + old_prof_.reset(std::move(mm_prof)); + } + } + + /** + Attempts to lock the MemoryManager for profile switch, perform the switch + to currently stored memory manager profile, store the previously held profile, + and keep the lock until unlocked or destroyed. If the lock cannot be obtained + on the first attempt, the function returns false; otherwise returns true. + + @throws std::runtime_error if the lock is already owned + */ + inline bool try_lock() + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + if (!mm_switch_lock_.try_lock()) + { + return false; + } + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(old_prof_)); + return true; + } + + /** + Locks the MemoryManager for profile switch, performs the switch to currently + stored memory manager profile, stores the previously held profile, and + keep the lock until unlocked or destroyed. The calling thread will block + until the lock can be obtained. + + @throws std::runtime_error if the lock is already owned + */ +#ifdef _MSC_VER + _Acquires_lock_(mm_switch_lock_) +#endif + inline void lock() + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + mm_switch_lock_.lock(); + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(old_prof_)); + } + + /** + Attempts to lock the MemoryManager for profile switch, perform the switch + to the given memory manager profile, store the previously held profile, + and keep the lock until unlocked or destroyed. If the lock cannot be + obtained on the first attempt, the function returns false; otherwise + returns true. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::runtime_error if the lock is already owned + */ + inline bool try_lock(std::unique_ptr<MMProf> &&mm_prof) + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + if (!mm_switch_lock_.try_lock()) + { + return false; + } + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(mm_prof)); + return true; + } + + /** + Locks the MemoryManager for profile switch, performs the switch to the given + memory manager profile, stores the previously held profile, and keep the + lock until unlocked or destroyed. The calling thread will block until the + lock can be obtained. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::runtime_error if the lock is already owned + */ +#ifdef _MSC_VER + _Acquires_lock_(mm_switch_lock_) +#endif + inline void lock(std::unique_ptr<MMProf> &&mm_prof) + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + mm_switch_lock_.lock(); + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(mm_prof)); + } + + /** + Attempts to lock the MemoryManager for profile switch, perform the switch + to the given memory manager profile, store the previously held profile, + and keep the lock until unlocked or destroyed. If the lock cannot be + obtained on the first attempt, the function returns false; otherwise returns + true. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::runtime_error if the lock is already owned + */ + inline bool try_lock(MMProf *&&mm_prof) + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + if (!mm_switch_lock_.try_lock()) + { + return false; + } + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(mm_prof)); + return true; + } + + /** + Locks the MemoryManager for profile switch, performs the switch to the + given memory manager profile, stores the previously held profile, and keep + the lock until unlocked or destroyed. The calling thread will block until + the lock can be obtained. + + @param[in] mm_prof Pointer to a new memory manager profile + @throws std::runtime_error if the lock is already owned + */ +#ifdef _MSC_VER + _Acquires_lock_(mm_switch_lock_) +#endif + inline void lock(MMProf *&&mm_prof) + { + if (mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is already owned"); + } + mm_switch_lock_.lock(); + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(mm_prof)); + } + + /** + Releases the memory manager profile switch lock for MemoryManager, stores + the current profile, and resets the profile to the one used before locking. + + @throws std::runtime_error if the lock is not owned + */ +#ifdef _MSC_VER + _Releases_lock_(mm_switch_lock_) +#endif + inline void unlock() + { + if (!mm_switch_lock_.owns_lock()) + { + throw std::runtime_error("lock is not owned"); + } + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(old_prof_)); + mm_switch_lock_.unlock(); + } + + /** + Destroys the MMProfGuard. If the memory manager profile switch lock is + owned, releases the lock, and resets the profile to the one used before + locking. + */ + ~MMProfGuard() + { + if (mm_switch_lock_.owns_lock()) + { + old_prof_ = MemoryManager::SwitchProfileThreadUnsafe(std::move(old_prof_)); + mm_switch_lock_.unlock(); + } + } + + /** + Returns whether the current MMProfGuard owns the memory manager profile + switch lock. + */ + inline bool owns_lock() noexcept + { + return mm_switch_lock_.owns_lock(); + } + + private: + std::unique_ptr<MMProf> old_prof_; + + std::unique_lock<std::mutex> mm_switch_lock_; + }; +#endif +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/modulus.cpp b/bigpiseal3.5.1/native/src/seal/modulus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..939594c24b48602e3e38d5e5e40be067d6643b6f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/modulus.cpp @@ -0,0 +1,174 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/numth.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include <numeric> +#include <stdexcept> +#include <unordered_map> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + void Modulus::save_members(ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + stream.write(reinterpret_cast<const char *>(&value_), sizeof(uint64_t)); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void Modulus::load_members(istream &stream) + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + uint64_t value; + stream.read(reinterpret_cast<char *>(&value), sizeof(uint64_t)); + set_value(value); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void Modulus::set_value(uint64_t value) + { + if (value == 0) + { + // Zero settings + bit_count_ = 0; + uint64_count_ = 1; + value_ = 0; + const_ratio_ = { { 0, 0, 0 } }; + is_prime_ = false; + } + else if ((value >> SEAL_MOD_BIT_COUNT_MAX != 0) || (value == 1)) + { + throw invalid_argument("value can be at most 61-bit and cannot be 1"); + } + else + { + // All normal, compute const_ratio and set everything + value_ = value; + bit_count_ = get_significant_bit_count(value_); + + // Compute Barrett ratios for 64-bit words (barrett_reduce_128) + uint64_t numerator[3]{ 0, 0, 1 }; + uint64_t quotient[3]{ 0, 0, 0 }; + + // Use a special method to avoid using memory pool + divide_uint192_uint64_inplace(numerator, value_, quotient); + + const_ratio_[0] = quotient[0]; + const_ratio_[1] = quotient[1]; + + // We store also the remainder + const_ratio_[2] = numerator[0]; + + uint64_count_ = 1; + + // Set the primality flag + is_prime_ = util::is_prime(*this); + } + } + + vector<Modulus> CoeffModulus::BFVDefault(size_t poly_modulus_degree, sec_level_type sec_level) + { + if (!MaxBitCount(poly_modulus_degree, sec_level)) + { + throw invalid_argument("non-standard poly_modulus_degree"); + } + if (sec_level == sec_level_type::none) + { + throw invalid_argument("invalid security level"); + } + + switch (sec_level) + { + case sec_level_type::tc128: + return global_variables::default_coeff_modulus_128.at(poly_modulus_degree); + + case sec_level_type::tc192: + return global_variables::default_coeff_modulus_192.at(poly_modulus_degree); + + case sec_level_type::tc256: + return global_variables::default_coeff_modulus_256.at(poly_modulus_degree); + + default: + throw runtime_error("invalid security level"); + } + } + + vector<Modulus> CoeffModulus::Create(size_t poly_modulus_degree, vector<int> bit_sizes) + { + if (poly_modulus_degree > SEAL_POLY_MOD_DEGREE_MAX || poly_modulus_degree < SEAL_POLY_MOD_DEGREE_MIN || + get_power_of_two(static_cast<uint64_t>(poly_modulus_degree)) < 0) + { + throw invalid_argument("poly_modulus_degree is invalid"); + } + if (bit_sizes.size() > SEAL_COEFF_MOD_COUNT_MAX) + { + throw invalid_argument("bit_sizes is invalid"); + } + if (accumulate( + bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MIN, + [](int a, int b) { return max(a, b); }) > SEAL_USER_MOD_BIT_COUNT_MAX || + accumulate(bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MAX, [](int a, int b) { + return min(a, b); + }) < SEAL_USER_MOD_BIT_COUNT_MIN) + { + throw invalid_argument("bit_sizes is invalid"); + } + + unordered_map<int, size_t> count_table; + unordered_map<int, vector<Modulus>> prime_table; + for (int size : bit_sizes) + { + ++count_table[size]; + } + for (const auto &table_elt : count_table) + { + prime_table[table_elt.first] = get_primes(poly_modulus_degree, table_elt.first, table_elt.second); + } + + vector<Modulus> result; + for (int size : bit_sizes) + { + result.emplace_back(prime_table[size].back()); + prime_table[size].pop_back(); + } + return result; + } +} // namespace seal \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/modulus.h b/bigpiseal3.5.1/native/src/seal/modulus.h new file mode 100644 index 0000000000000000000000000000000000000000..5a8d5dfcf22d9ac8f760b10648004577b4497339 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/modulus.h @@ -0,0 +1,538 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/serialization.h" +#include "seal/util/defines.h" +#include "seal/util/hestdparms.h" +#include "seal/util/uintcore.h" +#include "seal/util/ztools.h" +#include <array> +#include <cstddef> +#include <cstdint> +#include <iostream> +#include <numeric> +#include <vector> + +namespace seal +{ + /** + Represent an integer modulus of up to 61 bits. An instance of the Modulus + class represents a non-negative integer modulus up to 61 bits. In particular, + the encryption parameter plain_modulus, and the primes in coeff_modulus, are + represented by instances of Modulus. The purpose of this class is to + perform and store the pre-computation required by Barrett reduction. + + @par Thread Safety + In general, reading from Modulus is thread-safe as long as no other thread + is concurrently mutating it. + + @see EncryptionParameters for a description of the encryption parameters. + */ + class Modulus + { + public: + /** + Creates a Modulus instance. The value of the Modulus is set to + the given value, or to zero by default. + + @param[in] value The integer modulus + @throws std::invalid_argument if value is 1 or more than 61 bits + */ + Modulus(std::uint64_t value = 0) + { + set_value(value); + } + + /** + Creates a new Modulus by copying a given one. + + @param[in] copy The Modulus to copy from + */ + Modulus(const Modulus &copy) = default; + + /** + Creates a new Modulus by copying a given one. + + @param[in] source The Modulus to move from + */ + Modulus(Modulus &&source) = default; + + /** + Copies a given Modulus to the current one. + + @param[in] assign The Modulus to copy from + */ + Modulus &operator=(const Modulus &assign) = default; + + /** + Moves a given Modulus to the current one. + + @param[in] assign The Modulus to move from + */ + Modulus &operator=(Modulus &&assign) = default; + + /** + Sets the value of the Modulus. + + @param[in] value The new integer modulus + @throws std::invalid_argument if value is 1 or more than 61 bits + */ + inline Modulus &operator=(std::uint64_t value) + { + set_value(value); + return *this; + } + + /** + Returns the significant bit count of the value of the current Modulus. + */ + SEAL_NODISCARD inline int bit_count() const noexcept + { + return bit_count_; + } + + /** + Returns the size (in 64-bit words) of the value of the current Modulus. + */ + SEAL_NODISCARD inline std::size_t uint64_count() const noexcept + { + return uint64_count_; + } + + /** + Returns a const pointer to the value of the current Modulus. + */ + SEAL_NODISCARD inline const uint64_t *data() const noexcept + { + return &value_; + } + + /** + Returns the value of the current Modulus. + */ + SEAL_NODISCARD inline std::uint64_t value() const noexcept + { + return value_; + } + + /** + Returns the Barrett ratio computed for the value of the current Modulus. + The first two components of the Barrett ratio are the floor of 2^128/value, + and the third component is the remainder. + */ + SEAL_NODISCARD inline auto &const_ratio() const noexcept + { + return const_ratio_; + } + + /** + Returns whether the value of the current Modulus is zero. + */ + SEAL_NODISCARD inline bool is_zero() const noexcept + { + return value_ == 0; + } + + /** + Returns whether the value of the current Modulus is a prime number. + */ + SEAL_NODISCARD inline bool is_prime() const noexcept + { + return is_prime_; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator==(const Modulus &compare) const noexcept + { + return value_ == compare.value_; + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator==(std::uint64_t compare) const noexcept + { + return value_ == compare; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator!=(const Modulus &compare) const noexcept + { + return !(value_ == compare.value_); + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator!=(std::uint64_t compare) const noexcept + { + return value_ != compare; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator<(const Modulus &compare) const noexcept + { + return value_ < compare.value_; + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator<(std::uint64_t compare) const noexcept + { + return value_ < compare; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator<=(const Modulus &compare) const noexcept + { + return value_ <= compare.value_; + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator<=(std::uint64_t compare) const noexcept + { + return value_ <= compare; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator>(const Modulus &compare) const noexcept + { + return value_ > compare.value_; + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator>(std::uint64_t compare) const noexcept + { + return value_ > compare; + } + + /** + Compares two Modulus instances. + + @param[in] compare The Modulus to compare against + */ + SEAL_NODISCARD inline bool operator>=(const Modulus &compare) const noexcept + { + return value_ >= compare.value_; + } + + /** + Compares a Modulus value to an unsigned integer. + + @param[in] compare The unsigned integer to compare against + */ + SEAL_NODISCARD inline bool operator>=(std::uint64_t compare) const noexcept + { + return value_ >= compare; + } + + /** + Returns an upper bound on the size of the Modulus, as if it was + written to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t members_size = Serialization::ComprSizeEstimate(util::add_safe(sizeof(value_)), compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves the Modulus to an output stream. The full state of the modulus is + serialized. The output is in binary format and not human-readable. The output + stream must have the "binary" flag set. + + @param[out] stream The stream to save the Modulus to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Modulus::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a Modulus from an input stream overwriting the current + Modulus. + + @param[in] stream The stream to load the Modulus from + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::istream &stream) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Modulus::load_members, this, _1), stream); + } + + /** + Saves the Modulus to a given memory location. The full state of the + modulus is serialized. The output is in binary format and not human-readable. + + @param[out] out The memory location to write the Modulus to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Modulus::save_members, this, _1), save_size(compr_mode_type::none), out, size, compr_mode); + } + + /** + Loads a Modulus from a given memory location overwriting the current + Modulus. + + @param[in] in The memory location to load the Modulus from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Modulus::load_members, this, _1), in, size); + } + + private: + void set_value(std::uint64_t value); + + void save_members(std::ostream &stream) const; + + void load_members(std::istream &stream); + + std::uint64_t value_ = 0; + + std::array<std::uint64_t, 3> const_ratio_{ { 0, 0, 0 } }; + + std::size_t uint64_count_ = 0; + + int bit_count_ = 0; + + bool is_prime_ = false; + }; + + /** + Represents a standard security level according to the HomomorphicEncryption.org + security standard. The value sec_level_type::none signals that no standard + security level should be imposed. The value sec_level_type::tc128 provides + a very high level of security and is the default security level enforced by + Microsoft SEAL when constructing a SEALContext object. Normal users should not + have to specify the security level explicitly anywhere. + */ + enum class sec_level_type : int + { + /** + No security level specified. + */ + none = 0, + + /** + 128-bit security level according to HomomorphicEncryption.org standard. + */ + tc128 = 128, + + /** + 192-bit security level according to HomomorphicEncryption.org standard. + */ + tc192 = 192, + + /** + 256-bit security level according to HomomorphicEncryption.org standard. + */ + tc256 = 256 + }; + + /** + This class contains static methods for creating a coefficient modulus easily. + Note that while these functions take a sec_level_type argument, all security + guarantees are lost if the output is used with encryption parameters with + a mismatching value for the poly_modulus_degree. + + The default value sec_level_type::tc128 provides a very high level of security + and is the default security level enforced by Microsoft SEAL when constructing + a SEALContext object. Normal users should not have to specify the security + level explicitly anywhere. + */ + class CoeffModulus + { + public: + CoeffModulus() = delete; + + /** + Returns the largest bit-length of the coefficient modulus, i.e., bit-length + of the product of the primes in the coefficient modulus, that guarantees + a given security level when using a given poly_modulus_degree, according + to the HomomorphicEncryption.org security standard. + + @param[in] poly_modulus_degree The value of the poly_modulus_degree + encryption parameter + @param[in] sec_level The desired standard security level + */ + SEAL_NODISCARD static constexpr int MaxBitCount( + std::size_t poly_modulus_degree, sec_level_type sec_level = sec_level_type::tc128) noexcept + { + switch (sec_level) + { + case sec_level_type::tc128: + return util::SEAL_HE_STD_PARMS_128_TC(poly_modulus_degree); + + case sec_level_type::tc192: + return util::SEAL_HE_STD_PARMS_192_TC(poly_modulus_degree); + + case sec_level_type::tc256: + return util::SEAL_HE_STD_PARMS_256_TC(poly_modulus_degree); + + case sec_level_type::none: + return std::numeric_limits<int>::max(); + + default: + return 0; + } + } + + /** + Returns a default coefficient modulus for the BFV scheme that guarantees + a given security level when using a given poly_modulus_degree, according + to the HomomorphicEncryption.org security standard. Note that all security + guarantees are lost if the output is used with encryption parameters with + a mismatching value for the poly_modulus_degree. + + The coefficient modulus returned by this function will not perform well + if used with the CKKS scheme. + + @param[in] poly_modulus_degree The value of the poly_modulus_degree + encryption parameter + @param[in] sec_level The desired standard security level + @throws std::invalid_argument if poly_modulus_degree is not a power-of-two + or is too large + @throws std::invalid_argument if sec_level is sec_level_type::none + */ + SEAL_NODISCARD static std::vector<Modulus> BFVDefault( + std::size_t poly_modulus_degree, sec_level_type sec_level = sec_level_type::tc128); + + /** + Returns a custom coefficient modulus suitable for use with the specified + poly_modulus_degree. The return value will be a vector consisting of + Modulus elements representing distinct prime numbers of bit-lengths + as given in the bit_sizes parameter. The bit sizes of the prime numbers + can be at most 60 bits. + + @param[in] poly_modulus_degree The value of the poly_modulus_degree + encryption parameter + @param[in] bit_sizes The bit-lengths of the primes to be generated + @throws std::invalid_argument if poly_modulus_degree is not a power-of-two + or is too large + @throws std::invalid_argument if bit_sizes is too large or if its elements + are out of bounds + @throws std::logic_error if not enough suitable primes could be found + */ + SEAL_NODISCARD static std::vector<Modulus> Create(std::size_t poly_modulus_degree, std::vector<int> bit_sizes); + }; + + /** + This class contains static methods for creating a plaintext modulus easily. + */ + class PlainModulus + { + public: + PlainModulus() = delete; + + /** + Creates a prime number Modulus for use as plain_modulus encryption + parameter that supports batching with a given poly_modulus_degree. + + @param[in] poly_modulus_degree The value of the poly_modulus_degree + encryption parameter + @param[in] bit_size The bit-length of the prime to be generated + @throws std::invalid_argument if poly_modulus_degree is not a power-of-two + or is too large + @throws std::invalid_argument if bit_size is out of bounds + @throws std::logic_error if a suitable prime could not be found + */ + SEAL_NODISCARD static inline Modulus Batching(std::size_t poly_modulus_degree, int bit_size) + { + return CoeffModulus::Create(poly_modulus_degree, { bit_size })[0]; + } + + /** + Creates several prime number Modulus elements that can be used as + plain_modulus encryption parameters, each supporting batching with a given + poly_modulus_degree. + + @param[in] poly_modulus_degree The value of the poly_modulus_degree + encryption parameter + @param[in] bit_sizes The bit-lengths of the primes to be generated + @throws std::invalid_argument if poly_modulus_degree is not a power-of-two + or is too large + @throws std::invalid_argument if bit_sizes is too large or if its elements + are out of bounds + @throws std::logic_error if not enough suitable primes could be found + */ + SEAL_NODISCARD static inline std::vector<Modulus> Batching( + std::size_t poly_modulus_degree, std::vector<int> bit_sizes) + { + return CoeffModulus::Create(poly_modulus_degree, bit_sizes); + } + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/plaintext.cpp b/bigpiseal3.5.1/native/src/seal/plaintext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a9545d1f4baeab698c44529df311c915b9f2a7f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/plaintext.cpp @@ -0,0 +1,307 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/plaintext.h" +#include "seal/util/common.h" + +using namespace std; +using namespace seal::util; + +namespace seal +{ + namespace + { + bool is_dec_char(char c) + { + return c >= '0' && c <= '9'; + } + + int get_dec_value(char c) + { + return c - '0'; + } + + int get_coeff_length(const char *poly) + { + int length = 0; + while (is_hex_char(*poly)) + { + length++; + poly++; + } + return length; + } + + int get_coeff_power(const char *poly, int *power_length) + { + int length = 0; + if (*poly == '\0') + { + *power_length = 0; + return 0; + } + if (*poly != 'x') + { + return -1; + } + poly++; + length++; + + if (*poly != '^') + { + return -1; + } + poly++; + length++; + + int power = 0; + while (is_dec_char(*poly)) + { + power *= 10; + power += get_dec_value(*poly); + poly++; + length++; + } + *power_length = length; + return power; + } + + int get_plus(const char *poly) + { + if (*poly == '\0') + { + return 0; + } + if (*poly++ != ' ') + { + return -1; + } + if (*poly++ != '+') + { + return -1; + } + if (*poly != ' ') + { + return -1; + } + return 3; + } + } // namespace + + Plaintext &Plaintext::operator=(const string &hex_poly) + { + if (is_ntt_form()) + { + throw logic_error("cannot set an NTT transformed Plaintext"); + } + if (unsigned_gt(hex_poly.size(), numeric_limits<int>::max())) + { + throw invalid_argument("hex_poly too long"); + } + int length = safe_cast<int>(hex_poly.size()); + + // Determine size needed to store string coefficient. + int assign_coeff_count = 0; + + int assign_coeff_bit_count = 0; + int pos = 0; + int last_power = safe_cast<int>(min(data_.max_size(), safe_cast<size_t>(numeric_limits<int>::max()))); + const char *hex_poly_ptr = hex_poly.data(); + while (pos < length) + { + // Determine length of coefficient starting at pos. + int coeff_length = get_coeff_length(hex_poly_ptr + pos); + if (coeff_length == 0) + { + throw invalid_argument("unable to parse hex_poly"); + } + + // Determine bit length of coefficient. + int coeff_bit_count = get_hex_string_bit_count(hex_poly_ptr + pos, coeff_length); + if (coeff_bit_count > assign_coeff_bit_count) + { + assign_coeff_bit_count = coeff_bit_count; + } + pos += coeff_length; + + // Extract power-term. + int power_length = 0; + int power = get_coeff_power(hex_poly_ptr + pos, &power_length); + if (power == -1 || power >= last_power) + { + throw invalid_argument("unable to parse hex_poly"); + } + if (assign_coeff_count == 0) + { + assign_coeff_count = power + 1; + } + pos += power_length; + last_power = power; + + // Extract plus (unless it is the end). + int plus_length = get_plus(hex_poly_ptr + pos); + if (plus_length == -1) + { + throw invalid_argument("unable to parse hex_poly"); + } + pos += plus_length; + } + + // If string is empty, then done. + if (assign_coeff_count == 0 || assign_coeff_bit_count == 0) + { + set_zero(); + return *this; + } + + // Resize polynomial. + if (assign_coeff_bit_count > bits_per_uint64) + { + throw invalid_argument("hex_poly has too large coefficients"); + } + resize(safe_cast<size_t>(assign_coeff_count)); + + // Populate polynomial from string. + pos = 0; + last_power = safe_cast<int>(coeff_count()); + while (pos < length) + { + // Determine length of coefficient starting at pos. + const char *coeff_start = hex_poly_ptr + pos; + int coeff_length = get_coeff_length(coeff_start); + pos += coeff_length; + + // Extract power-term. + int power_length = 0; + int power = get_coeff_power(hex_poly_ptr + pos, &power_length); + pos += power_length; + + // Extract plus (unless it is the end). + int plus_length = get_plus(hex_poly_ptr + pos); + pos += plus_length; + + // Zero coefficients not set by string. + for (int zero_power = last_power - 1; zero_power > power; --zero_power) + { + data_[static_cast<size_t>(zero_power)] = 0; + } + + // Populate coefficient. + uint64_t *coeff_ptr = data_.begin() + power; + hex_string_to_uint(coeff_start, coeff_length, size_t(1), coeff_ptr); + last_power = power; + } + + // Zero coefficients not set by string. + for (int zero_power = last_power - 1; zero_power >= 0; --zero_power) + { + data_[static_cast<size_t>(zero_power)] = 0; + } + + return *this; + } + + void Plaintext::save_members(ostream &stream) const + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + stream.write(reinterpret_cast<const char *>(&parms_id_), sizeof(parms_id_type)); + uint64_t coeff_count64 = static_cast<uint64_t>(coeff_count_); + stream.write(reinterpret_cast<const char *>(&coeff_count64), sizeof(uint64_t)); + stream.write(reinterpret_cast<const char *>(&scale_), sizeof(double)); + data_.save(stream, compr_mode_type::none); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + } + + void Plaintext::load_members(shared_ptr<SEALContext> context, istream &stream) + { + // Verify parameters + if (!context) + { + throw invalid_argument("invalid context"); + } + if (!context->parameters_set()) + { + throw invalid_argument("encryption parameters are not set correctly"); + } + + Plaintext new_data(data_.pool()); + + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + parms_id_type parms_id{}; + stream.read(reinterpret_cast<char *>(&parms_id), sizeof(parms_id_type)); + + uint64_t coeff_count64 = 0; + stream.read(reinterpret_cast<char *>(&coeff_count64), sizeof(uint64_t)); + + double scale = 0; + stream.read(reinterpret_cast<char *>(&scale), sizeof(double)); + + // Set the metadata + new_data.parms_id_ = parms_id; + new_data.coeff_count_ = safe_cast<size_t>(coeff_count64); + new_data.scale_ = scale; + + // Checking the validity of loaded metadata + // Note: We allow pure key levels here! This is to allow load_members + // to be used also when loading derived objects like SecretKey. This + // further means that functions reading in Plaintext objects must check + // that for those use-cases the Plaintext truly is at the data level + // if it is supposed to be. In other words, one cannot assume simply + // based on load_members succeeding that the Plaintext is valid for + // computations. + if (!is_metadata_valid_for(new_data, context, true)) + { + throw logic_error("plaintext data is invalid"); + } + + // Reserve memory now that the metadata is checked for validity. + new_data.data_.reserve(new_data.coeff_count_); + + // Load the data. Note that we are supplying also the expected maximum + // size of the loaded IntArray. This is an important security measure to + // prevent a malformed IntArray from causing arbitrarily large memory + // allocations. + new_data.data_.load(stream, new_data.coeff_count_); + + // Verify that the buffer is correct + if (!is_buffer_valid(new_data)) + { + throw logic_error("plaintext data is invalid"); + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + throw runtime_error("I/O error"); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + swap(*this, new_data); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/plaintext.h b/bigpiseal3.5.1/native/src/seal/plaintext.h new file mode 100644 index 0000000000000000000000000000000000000000..cd736ad2cdcf6b913da6b470e3d8dbd023d2d93f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/plaintext.h @@ -0,0 +1,765 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/encryptionparams.h" +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/polycore.h" +#include "seal/util/ztools.h" +#include <algorithm> +#include <functional> +#include <iostream> +#include <memory> +#include <stdexcept> +#include <string> +#ifdef SEAL_USE_MSGSL +#include <gsl/span> +#endif + +namespace seal +{ + /** + Class to store a plaintext element. The data for the plaintext is a polynomial + with coefficients modulo the plaintext modulus. The degree of the plaintext + polynomial must be one less than the degree of the polynomial modulus. The + backing array always allocates one 64-bit word per each coefficient of the + polynomial. + + @par Memory Management + The coefficient count of a plaintext refers to the number of word-size + coefficients in the plaintext, whereas its capacity refers to the number of + word-size coefficients that fit in the current memory allocation. In high- + performance applications unnecessary re-allocations should be avoided by + reserving enough memory for the plaintext to begin with either by providing + the desired capacity to the constructor as an extra argument, or by calling + the reserve function at any time. + + When the scheme is scheme_type::BFV each coefficient of a plaintext is a 64-bit + word, but when the scheme is scheme_type::CKKS the plaintext is by default + stored in an NTT transformed form with respect to each of the primes in the + coefficient modulus. Thus, the size of the allocation that is needed is the + size of the coefficient modulus (number of primes) times the degree of the + polynomial modulus. In addition, a valid CKKS plaintext also store the parms_id + for the corresponding encryption parameters. + + @par Thread Safety + In general, reading from plaintext is thread-safe as long as no other thread + is concurrently mutating it. This is due to the underlying data structure + storing the plaintext not being thread-safe. + + @see Ciphertext for the class that stores ciphertexts. + */ + class Plaintext + { + public: + using pt_coeff_type = std::uint64_t; + + /** + Constructs an empty plaintext allocating no memory. + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + Plaintext(MemoryPoolHandle pool = MemoryManager::GetPool()) : data_(std::move(pool)) + {} + + /** + Constructs a plaintext representing a constant polynomial 0. The coefficient + count of the polynomial is set to the given value. The capacity is set to + the same value. + + @param[in] coeff_count The number of (zeroed) coefficients in the plaintext + polynomial + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if coeff_count is negative + @throws std::invalid_argument if pool is uninitialized + */ + explicit Plaintext(std::size_t coeff_count, MemoryPoolHandle pool = MemoryManager::GetPool()) + : coeff_count_(coeff_count), data_(coeff_count_, std::move(pool)) + {} + + /** + Constructs a plaintext representing a constant polynomial 0. The coefficient + count of the polynomial and the capacity are set to the given values. + + @param[in] capacity The capacity + @param[in] coeff_count The number of (zeroed) coefficients in the plaintext + polynomial + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if capacity is less than coeff_count + @throws std::invalid_argument if coeff_count is negative + @throws std::invalid_argument if pool is uninitialized + */ + explicit Plaintext( + std::size_t capacity, std::size_t coeff_count, MemoryPoolHandle pool = MemoryManager::GetPool()) + : coeff_count_(coeff_count), data_(capacity, coeff_count_, std::move(pool)) + {} + + /** + Constructs a plaintext from a given hexadecimal string describing the + plaintext polynomial. + + The string description of the polynomial must adhere to the format returned + by to_string(), + which is of the form "7FFx^3 + 1x^1 + 3" and summarized by the following + rules: + 1. Terms are listed in order of strictly decreasing exponent + 2. Coefficient values are non-negative and in hexadecimal format (upper + and lower case letters are both supported) + 3. Exponents are positive and in decimal format + 4. Zero coefficient terms (including the constant term) may be (but do + not have to be) omitted + 5. Term with the exponent value of one must be exactly written as x^1 + 6. Term with the exponent value of zero (the constant term) must be written + as just a hexadecimal number without exponent + 7. Terms must be separated by exactly <space>+<space> and minus is not + allowed + 8. Other than the +, no other terms should have whitespace + + @param[in] hex_poly The formatted polynomial string specifying the plaintext + polynomial + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if hex_poly does not adhere to the expected + format + @throws std::invalid_argument if pool is uninitialized + */ + Plaintext(const std::string &hex_poly, MemoryPoolHandle pool = MemoryManager::GetPool()) + : data_(std::move(pool)) + { + operator=(hex_poly); + } + + /** + Constructs a new plaintext by copying a given one. + + @param[in] copy The plaintext to copy from + */ + Plaintext(const Plaintext &copy) = default; + + /** + Constructs a new plaintext by moving a given one. + + @param[in] source The plaintext to move from + */ + Plaintext(Plaintext &&source) = default; + + /** + Constructs a new plaintext by copying a given one. + + @param[in] copy The plaintext to copy from + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + Plaintext(const Plaintext &copy, MemoryPoolHandle pool) : Plaintext(std::move(pool)) + { + *this = copy; + } + + /** + Allocates enough memory to accommodate the backing array of a plaintext + with given capacity. + + @param[in] capacity The capacity + @throws std::invalid_argument if capacity is negative + @throws std::logic_error if the plaintext is NTT transformed + */ + void reserve(std::size_t capacity) + { + if (is_ntt_form()) + { + throw std::logic_error("cannot reserve for an NTT transformed Plaintext"); + } + data_.reserve(capacity); + coeff_count_ = data_.size(); + } + + /** + Allocates enough memory to accommodate the backing array of the current + plaintext and copies it over to the new location. This function is meant + to reduce the memory use of the plaintext to smallest possible and can be + particularly important after modulus switching. + */ + inline void shrink_to_fit() + { + data_.shrink_to_fit(); + } + + /** + Resets the plaintext. This function releases any memory allocated by the + plaintext, returning it to the memory pool. + */ + inline void release() noexcept + { + parms_id_ = parms_id_zero; + coeff_count_ = 0; + scale_ = 1.0; + data_.release(); + } + + /** + Resizes the plaintext to have a given coefficient count. The plaintext + is automatically reallocated if the new coefficient count does not fit in + the current capacity. + + @param[in] coeff_count The number of coefficients in the plaintext polynomial + @throws std::invalid_argument if coeff_count is negative + @throws std::logic_error if the plaintext is NTT transformed + */ + inline void resize(std::size_t coeff_count) + { + if (is_ntt_form()) + { + throw std::logic_error("cannot reserve for an NTT transformed Plaintext"); + } + data_.resize(coeff_count); + coeff_count_ = coeff_count; + } + + /** + Copies a given plaintext to the current one. + + @param[in] assign The plaintext to copy from + */ + Plaintext &operator=(const Plaintext &assign) = default; + + /** + Moves a given plaintext to the current one. + + @param[in] assign The plaintext to move from + */ + Plaintext &operator=(Plaintext &&assign) = default; + + /** + Sets the value of the current plaintext to the polynomial represented by + the a given hexadecimal string. + + The string description of the polynomial must adhere to the format returned + by to_string(), which is of the form "7FFx^3 + 1x^1 + 3" and summarized + by the following rules: + 1. Terms are listed in order of strictly decreasing exponent + 2. Coefficient values are non-negative and in hexadecimal format (upper + and lower case letters are both supported) + 3. Exponents are positive and in decimal format + 4. Zero coefficient terms (including the constant term) may be (but do + not have to be) omitted + 5. Term with the exponent value of one must be exactly written as x^1 + 6. Term with the exponent value of zero (the constant term) must be + written as just a hexadecimal number without exponent + 7. Terms must be separated by exactly <space>+<space> and minus is not + allowed + 8. Other than the +, no other terms should have whitespace + + @param[in] hex_poly The formatted polynomial string specifying the plaintext + polynomial + @throws std::invalid_argument if hex_poly does not adhere to the expected + format + @throws std::invalid_argument if the coefficients of hex_poly are too wide + */ + Plaintext &operator=(const std::string &hex_poly); + + /** + Sets the value of the current plaintext to a given constant polynomial. + The coefficient count is set to one. + + @param[in] const_coeff The constant coefficient + @throws std::logic_error if the plaintext is NTT transformed + */ + Plaintext &operator=(pt_coeff_type const_coeff) + { + data_.resize(1); + data_[0] = const_coeff; + coeff_count_ = 1; + return *this; + } + + /** + Sets a given range of coefficients of a plaintext polynomial to zero; does + nothing if length is zero. + + @param[in] start_coeff The index of the first coefficient to set to zero + @param[in] length The number of coefficients to set to zero + @throws std::out_of_range if start_coeff + length - 1 is not within [0, coeff_count) + */ + inline void set_zero(std::size_t start_coeff, std::size_t length) + { + if (!length) + { + return; + } + if (start_coeff + length - 1 >= coeff_count_) + { + throw std::out_of_range( + "length must be non-negative and start_coeff + length - 1 must be within [0, coeff_count)"); + } + std::fill_n(data_.begin() + start_coeff, length, pt_coeff_type(0)); + } + + /** + Sets the plaintext polynomial coefficients to zero starting at a given index. + + @param[in] start_coeff The index of the first coefficient to set to zero + @throws std::out_of_range if start_coeff is not within [0, coeff_count) + */ + inline void set_zero(std::size_t start_coeff) + { + if (start_coeff >= coeff_count_) + { + throw std::out_of_range("start_coeff must be within [0, coeff_count)"); + } + std::fill(data_.begin() + start_coeff, data_.end(), pt_coeff_type(0)); + } + + /** + Sets the plaintext polynomial to zero. + */ + inline void set_zero() + { + std::fill(data_.begin(), data_.end(), pt_coeff_type(0)); + } + + /** + Returns a reference to the backing IntArray object. + */ + SEAL_NODISCARD inline const auto &int_array() const noexcept + { + return data_; + } + + /** + Returns a pointer to the beginning of the plaintext polynomial. + */ + SEAL_NODISCARD inline pt_coeff_type *data() + { + return data_.begin(); + } + + /** + Returns a const pointer to the beginning of the plaintext polynomial. + */ + SEAL_NODISCARD inline const pt_coeff_type *data() const + { + return data_.cbegin(); + } +#ifdef SEAL_USE_MSGSL + /** + Returns a span pointing to the beginning of the text polynomial. + */ + SEAL_NODISCARD inline gsl::span<pt_coeff_type> data_span() + { + return gsl::span<pt_coeff_type>(data_.begin(), coeff_count_); + } + + /** + Returns a span pointing to the beginning of the text polynomial. + */ + SEAL_NODISCARD inline gsl::span<const pt_coeff_type> data_span() const + { + return gsl::span<const pt_coeff_type>(data_.cbegin(), coeff_count_); + } +#endif + /** + Returns a pointer to a given coefficient of the plaintext polynomial. + + @param[in] coeff_index The index of the coefficient in the plaintext polynomial + @throws std::out_of_range if coeff_index is not within [0, coeff_count) + */ + SEAL_NODISCARD inline pt_coeff_type *data(std::size_t coeff_index) + { + if (!coeff_count_) + { + return nullptr; + } + if (coeff_index >= coeff_count_) + { + throw std::out_of_range("coeff_index must be within [0, coeff_count)"); + } + return data_.begin() + coeff_index; + } + + /** + Returns a const pointer to a given coefficient of the plaintext polynomial. + + @param[in] coeff_index The index of the coefficient in the plaintext polynomial + */ + SEAL_NODISCARD inline const pt_coeff_type *data(std::size_t coeff_index) const + { + if (!coeff_count_) + { + return nullptr; + } + if (coeff_index >= coeff_count_) + { + throw std::out_of_range("coeff_index must be within [0, coeff_count)"); + } + return data_.cbegin() + coeff_index; + } + + /** + Returns a const reference to a given coefficient of the plaintext polynomial. + + @param[in] coeff_index The index of the coefficient in the plaintext polynomial + @throws std::out_of_range if coeff_index is not within [0, coeff_count) + */ + SEAL_NODISCARD inline const pt_coeff_type &operator[](std::size_t coeff_index) const + { + return data_.at(coeff_index); + } + + /** + Returns a reference to a given coefficient of the plaintext polynomial. + + @param[in] coeff_index The index of the coefficient in the plaintext polynomial + @throws std::out_of_range if coeff_index is not within [0, coeff_count) + */ + SEAL_NODISCARD inline pt_coeff_type &operator[](std::size_t coeff_index) + { + return data_.at(coeff_index); + } + + /** + Returns whether or not the plaintext has the same semantic value as a given + plaintext. Leading zero coefficients are ignored by the comparison. + + @param[in] compare The plaintext to compare against + */ + SEAL_NODISCARD inline bool operator==(const Plaintext &compare) const + { + std::size_t sig_coeff_count = significant_coeff_count(); + std::size_t sig_coeff_count_compare = compare.significant_coeff_count(); + bool parms_id_compare = (is_ntt_form() && compare.is_ntt_form() && (parms_id_ == compare.parms_id_)) || + (!is_ntt_form() && !compare.is_ntt_form()); + return parms_id_compare && (sig_coeff_count == sig_coeff_count_compare) && + std::equal( + data_.cbegin(), data_.cbegin() + sig_coeff_count, compare.data_.cbegin(), + compare.data_.cbegin() + sig_coeff_count) && + std::all_of(data_.cbegin() + sig_coeff_count, data_.cend(), util::is_zero<pt_coeff_type>) && + std::all_of( + compare.data_.cbegin() + sig_coeff_count, compare.data_.cend(), util::is_zero<pt_coeff_type>) && + util::are_close(scale_, compare.scale_); + } + + /** + Returns whether or not the plaintext has a different semantic value than + a given plaintext. Leading zero coefficients are ignored by the comparison. + + @param[in] compare The plaintext to compare against + */ + SEAL_NODISCARD inline bool operator!=(const Plaintext &compare) const + { + return !operator==(compare); + } + + /** + Returns whether the current plaintext polynomial has all zero coefficients. + */ + SEAL_NODISCARD inline bool is_zero() const + { + return !coeff_count_ || std::all_of(data_.cbegin(), data_.cend(), util::is_zero<pt_coeff_type>); + } + + /** + Returns the capacity of the current allocation. + */ + SEAL_NODISCARD inline std::size_t capacity() const noexcept + { + return data_.capacity(); + } + + /** + Returns the coefficient count of the current plaintext polynomial. + */ + SEAL_NODISCARD inline std::size_t coeff_count() const noexcept + { + return coeff_count_; + } + + /** + Returns the significant coefficient count of the current plaintext polynomial. + */ + SEAL_NODISCARD inline std::size_t significant_coeff_count() const + { + if (!coeff_count_) + { + return 0; + } + return util::get_significant_uint64_count_uint(data_.cbegin(), coeff_count_); + } + + /** + Returns the non-zero coefficient count of the current plaintext polynomial. + */ + SEAL_NODISCARD inline std::size_t nonzero_coeff_count() const + { + if (!coeff_count_) + { + return 0; + } + return util::get_nonzero_uint64_count_uint(data_.cbegin(), coeff_count_); + } + + /** + Returns a human-readable string description of the plaintext polynomial. + + The returned string is of the form "7FFx^3 + 1x^1 + 3" with a format + summarized by the following: + 1. Terms are listed in order of strictly decreasing exponent + 2. Coefficient values are non-negative and in hexadecimal format (hexadecimal + letters are in upper-case) + 3. Exponents are positive and in decimal format + 4. Zero coefficient terms (including the constant term) are omitted unless + the polynomial is exactly 0 (see rule 9) + 5. Term with the exponent value of one is written as x^1 + 6. Term with the exponent value of zero (the constant term) is written as + just a hexadecimal number without x or exponent + 7. Terms are separated exactly by <space>+<space> + 8. Other than the +, no other terms have whitespace + 9. If the polynomial is exactly 0, the string "0" is returned + + @throws std::invalid_argument if the plaintext is in NTT transformed form + */ + SEAL_NODISCARD inline std::string to_string() const + { + if (is_ntt_form()) + { + throw std::invalid_argument("cannot convert NTT transformed plaintext to string"); + } + return util::poly_to_hex_string(data_.cbegin(), coeff_count_, 1); + } + + /** + Returns an upper bound on the size of the plaintext, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + std::size_t members_size = Serialization::ComprSizeEstimate( + util::add_safe( + sizeof(parms_id_), + sizeof(std::uint64_t), // coeff_count_ + sizeof(scale_), util::safe_cast<std::size_t>(data_.save_size(compr_mode_type::none))), + compr_mode); + + return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size)); + } + + /** + Saves the plaintext to an output stream. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the plaintext to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Plaintext::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode); + } + + /** + Loads a plaintext from an input stream overwriting the current plaintext. + No checking of the validity of the plaintext data against encryption + parameters is performed. This function should not be used unless the + plaintext comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] stream The stream to load the plaintext from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Plaintext::load_members, this, std::move(context), _1), stream); + } + + /** + Loads a plaintext from an input stream overwriting the current plaintext. + The loaded plaintext is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] stream The stream to load the plaintext from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + Plaintext new_data(pool()); + auto in_size = new_data.unsafe_load(context, stream); + if (!is_valid_for(new_data, std::move(context))) + { + throw std::logic_error("Plaintext data is invalid"); + } + std::swap(*this, new_data); + return in_size; + } + + /** + Saves the plaintext to a given memory location. The output is in binary + format and not human-readable. + + @param[out] out The memory location to write the plaintext to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + using namespace std::placeholders; + return Serialization::Save( + std::bind(&Plaintext::save_members, this, _1), save_size(compr_mode_type::none), out, size, compr_mode); + } + + /** + Loads a plaintext from a given memory location overwriting the current + plaintext. No checking of the validity of the plaintext data against + encryption parameters is performed. This function should not be used + unless the plaintext comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] in The memory location to load the plaintext from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + using namespace std::placeholders; + return Serialization::Load(std::bind(&Plaintext::load_members, this, std::move(context), _1), in, size); + } + + /** + Loads a plaintext from an input stream overwriting the current plaintext. + The loaded plaintext is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] in The memory location to load the PublicKey from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + Plaintext new_data(pool()); + auto in_size = new_data.unsafe_load(context, in, size); + if (!is_valid_for(new_data, std::move(context))) + { + throw std::logic_error("Plaintext data is invalid"); + } + std::swap(*this, new_data); + return in_size; + } + + /** + Returns whether the plaintext is in NTT form. + */ + SEAL_NODISCARD inline bool is_ntt_form() const noexcept + { + return (parms_id_ != parms_id_zero); + } + + /** + Returns a reference to parms_id. The parms_id must remain zero unless the + plaintext polynomial is in NTT form. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() noexcept + { + return parms_id_; + } + + /** + Returns a const reference to parms_id. The parms_id must remain zero unless + the plaintext polynomial is in NTT form. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return parms_id_; + } + + /** + Returns a reference to the scale. This is only needed when using the CKKS + encryption scheme. The user should have little or no reason to ever change + the scale by hand. + */ + SEAL_NODISCARD inline auto &scale() noexcept + { + return scale_; + } + + /** + Returns a constant reference to the scale. This is only needed when using + the CKKS encryption scheme. + */ + SEAL_NODISCARD inline auto &scale() const noexcept + { + return scale_; + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return data_.pool(); + } + + /** + Enables access to private members of seal::Plaintext for .NET wrapper. + */ + struct PlaintextPrivateHelper; + + private: + void save_members(std::ostream &stream) const; + + void load_members(std::shared_ptr<SEALContext> context, std::istream &stream); + + parms_id_type parms_id_ = parms_id_zero; + + std::size_t coeff_count_ = 0; + + double scale_ = 1.0; + + IntArray<pt_coeff_type> data_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/publickey.h b/bigpiseal3.5.1/native/src/seal/publickey.h new file mode 100644 index 0000000000000000000000000000000000000000..d7d3ce2293ff0d4c2244a3844558872db6af3f3a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/publickey.h @@ -0,0 +1,273 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/valcheck.h" +#include <iostream> +#include <memory> + +namespace seal +{ + /** + Class to store a public key. + + @par Thread Safety + In general, reading from PublicKey is thread-safe as long as no other thread + is concurrently mutating it. This is due to the underlying data structure + storing the public key not being thread-safe. + + @see KeyGenerator for the class that generates the public key. + @see SecretKey for the class that stores the secret key. + @see RelinKeys for the class that stores the relinearization keys. + @see GaloisKeys for the class that stores the Galois keys. + */ + class PublicKey + { + friend class KeyGenerator; + friend class KSwitchKeys; + + public: + /** + Creates an empty public key. + */ + PublicKey() = default; + + /** + Creates a new PublicKey by copying an old one. + + @param[in] copy The PublicKey to copy from + */ + PublicKey(const PublicKey &copy) = default; + + /** + Creates a new PublicKey by moving an old one. + + @param[in] source The PublicKey to move from + */ + PublicKey(PublicKey &&source) = default; + + /** + Copies an old PublicKey to the current one. + + @param[in] assign The PublicKey to copy from + */ + PublicKey &operator=(const PublicKey &assign) = default; + + /** + Moves an old PublicKey to the current one. + + @param[in] assign The PublicKey to move from + */ + PublicKey &operator=(PublicKey &&assign) = default; + + /** + Returns a reference to the underlying data. + */ + SEAL_NODISCARD inline auto &data() noexcept + { + return pk_; + } + + /** + Returns a const reference to the underlying data. + */ + SEAL_NODISCARD inline auto &data() const noexcept + { + return pk_; + } + + /** + Returns an upper bound on the size of the PublicKey, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return pk_.save_size(compr_mode); + } + + /** + Saves the PublicKey to an output stream. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the PublicKey to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return pk_.save(stream, compr_mode); + } + + /** + Loads a PublicKey from an input stream overwriting the current PublicKey. + No checking of the validity of the PublicKey data against encryption + parameters is performed. This function should not be used unless the + PublicKey comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] stream The stream to load the PublicKey from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + Ciphertext new_pk(pk_.pool()); + auto in_size = new_pk.unsafe_load(std::move(context), stream); + std::swap(pk_, new_pk); + return in_size; + } + + /** + Loads a PublicKey from an input stream overwriting the current PublicKey. + The loaded PublicKey is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] stream The stream to load the PublicKey from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + PublicKey new_pk(pool()); + auto in_size = new_pk.unsafe_load(context, stream); + if (!is_valid_for(new_pk, std::move(context))) + { + throw std::logic_error("PublicKey data is invalid"); + } + std::swap(*this, new_pk); + return in_size; + } + + /** + Saves the PublicKey to a given memory location. The output is in binary + format and is not human-readable. + + @param[out] out The memory location to write the PublicKey to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return pk_.save(out, size, compr_mode); + } + + /** + Loads a PublicKey from a given memory location overwriting the current + PublicKey. No checking of the validity of the PublicKey data against + encryption parameters is performed. This function should not be used + unless the PublicKey comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] in The memory location to load the PublicKey from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + Ciphertext new_pk(pk_.pool()); + auto in_size = new_pk.unsafe_load(std::move(context), in, size); + std::swap(pk_, new_pk); + return in_size; + } + + /** + Loads a PublicKey from a given memory location overwriting the current + PublicKey. The loaded PublicKey is verified to be valid for the given + SEALContext. + + @param[in] context The SEALContext + @param[in] in The memory location to load the PublicKey from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + PublicKey new_pk(pool()); + auto in_size = new_pk.unsafe_load(context, in, size); + if (!is_valid_for(new_pk, std::move(context))) + { + throw std::logic_error("PublicKey data is invalid"); + } + std::swap(*this, new_pk); + return in_size; + } + + /** + Returns a reference to parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() noexcept + { + return pk_.parms_id(); + } + + /** + Returns a const reference to parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return pk_.parms_id(); + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return pk_.pool(); + } + + /** + Enables access to private members of seal::PublicKey for .NET wrapper. + */ + struct PublicKeyPrivateHelper; + + private: + /** + Creates an empty public key. This is needed for loading KSwitchKeys with + the keys residing in a single memory pool. + + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + */ + PublicKey(MemoryPoolHandle pool) : pk_(std::move(pool)) + {} + + Ciphertext pk_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/randomgen.cpp b/bigpiseal3.5.1/native/src/seal/randomgen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9dfd1d0232e4c860f5d03325a87f141b97bed9e6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/randomgen.cpp @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/randomgen.h" +#include "seal/util/blake2.h" +#include <algorithm> +#include <iostream> +#include <random> +#if SEAL_SYSTEM == SEAL_SYSTEM_WINDOWS +#include <Windows.h> +#include <bcrypt.h> +#endif + +using namespace std; + +namespace seal +{ + uint64_t random_uint64() + { + uint64_t result; +#if SEAL_SYSTEM == SEAL_SYSTEM_UNIX_LIKE + random_device rd("/dev/urandom"); + result = (static_cast<uint64_t>(rd()) << 32) + static_cast<uint64_t>(rd()); +#elif SEAL_SYSTEM == SEAL_SYSTEM_WINDOWS + if (!BCRYPT_SUCCESS(BCryptGenRandom( + NULL, reinterpret_cast<unsigned char *>(&result), sizeof(result), BCRYPT_USE_SYSTEM_PREFERRED_RNG))) + { + throw runtime_error("BCryptGenRandom failed"); + } +#elif SEAL_SYSTEM == SEAL_SYSTEM_OTHER +#warning "SECURITY WARNING: System detection failed; falling back to a potentially insecure randomness source!" + random_device rd; + result = (static_cast<uint64_t>(rd()) << 32) + static_cast<uint64_t>(rd()); +#endif + return result; + } + + void UniformRandomGenerator::generate(size_t byte_count, SEAL_BYTE *destination) + { + lock_guard<mutex> lock(mutex_); + while (byte_count) + { + size_t current_bytes = min(byte_count, static_cast<size_t>(distance(buffer_head_, buffer_end_))); + copy_n(buffer_head_, current_bytes, destination); + buffer_head_ += current_bytes; + destination += current_bytes; + byte_count -= current_bytes; + + if (buffer_head_ == buffer_end_) + { + refill_buffer(); + buffer_head_ = buffer_begin_; + } + } + } + + auto UniformRandomGeneratorFactory::DefaultFactory() -> const shared_ptr<UniformRandomGeneratorFactory> + { + static const shared_ptr<UniformRandomGeneratorFactory> default_factory{ new SEAL_DEFAULT_RNG_FACTORY }; + return default_factory; + } + + void BlakePRNG::refill_buffer() + { + // Fill the randomness buffer + if (blake2xb( + buffer_begin_, buffer_size_, reinterpret_cast<const SEAL_BYTE *>(&counter_), sizeof(counter_), + seed_.cbegin(), seed_.size() * sizeof(decltype(seed_)::T)) != 0) + { + throw runtime_error("blake2xb failed"); + } + counter_++; + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/randomgen.h b/bigpiseal3.5.1/native/src/seal/randomgen.h new file mode 100644 index 0000000000000000000000000000000000000000..a397d1a73f21501624a1faa51af442ab5c129d7a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/randomgen.h @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include <algorithm> +#include <array> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <memory> +#include <mutex> +#include <stdexcept> + +namespace seal +{ + using random_seed_type = std::array<std::uint64_t, 8>; + + /** + Returns a random 64-bit integer. + */ + SEAL_NODISCARD std::uint64_t random_uint64(); + + /** + Provides the base class for a seeded uniform random number generator. Instances + of this class are meant to be created by an instance of the factory class + UniformRandomGeneratorFactory. This class is meant for users to sub-class to + implement their own random number generators. + + @see UniformRandomGeneratorFactory for the base class of a factory class that + generates UniformRandomGenerator instances. + */ + class UniformRandomGenerator + { + public: + /** + Creates a new UniformRandomGenerator instance initialized with the given seed. + + @param[in] seed The seed for the random number generator + */ + UniformRandomGenerator(random_seed_type seed) + : seed_([&seed]() { + // Create a new seed allocation + IntArray<std::uint64_t> new_seed(seed.size(), MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)); + + // Assign the given seed and return + std::copy(seed.cbegin(), seed.cend(), new_seed.begin()); + return new_seed; + }()), + buffer_(buffer_size_, MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)), + buffer_begin_(buffer_.begin()), buffer_end_(buffer_.end()), buffer_head_(buffer_.end()) + {} + + SEAL_NODISCARD inline random_seed_type seed() const noexcept + { + random_seed_type ret; + std::copy(seed_.cbegin(), seed_.cend(), ret.begin()); + return ret; + } + + /** + Fills a given buffer with a given number of bytes of randomness. + */ + void generate(std::size_t byte_count, SEAL_BYTE *destination); + + /** + Generates a new unsigned 32-bit random number. + */ + SEAL_NODISCARD inline std::uint32_t generate() + { + std::uint32_t result; + generate(sizeof(result), reinterpret_cast<SEAL_BYTE *>(&result)); + return result; + } + + /** + Discards the contents of the current randomness buffer and refills it + with fresh randomness. + */ + inline void refresh() + { + std::lock_guard<std::mutex> lock(mutex_); + refill_buffer(); + buffer_head_ = buffer_begin_; + } + + /** + Destroys the random number generator. + */ + virtual ~UniformRandomGenerator() = default; + + protected: + virtual void refill_buffer() = 0; + + const IntArray<std::uint64_t> seed_; + + const std::size_t buffer_size_ = 4096; + + private: + IntArray<SEAL_BYTE> buffer_; + + std::mutex mutex_; + + protected: + decltype(buffer_)::T *const buffer_begin_; + + decltype(buffer_)::T *const buffer_end_; + + decltype(buffer_)::T *buffer_head_; + }; + + /** + Provides the base class for a factory instance that creates instances of + UniformRandomGenerator. This class is meant for users to sub-class to implement + their own random number generators. + + @see UniformRandomGenerator for details relating to the random number generator + instances. + @see StandardRandomAdapterFactory for an implementation of + UniformRandomGeneratorFactory that supports the standard C++ library's + random number generators. + */ + class UniformRandomGeneratorFactory + { + public: + /** + Creates a new UniformRandomGeneratorFactory. The seed will be sampled + randomly for each UniformRandomGenerator instance created by the factory + instance, which is desirable in most normal use-cases. + */ + UniformRandomGeneratorFactory() : use_random_seed_(true) + {} + + /** + Creates a new UniformRandomGeneratorFactory and sets the default seed to + the given value. For debugging purposes it may sometimes be convenient to + have the same randomness be used deterministically and repeatedly. Such + randomness sampling is naturally insecure and must be strictly restricted + to debugging situations. Thus, most users should never have a reason to + use this constructor. + + @param[in] default_seed The default value for a seed to be used by all + created instances of UniformRandomGenerator + */ + UniformRandomGeneratorFactory(random_seed_type default_seed) + : default_seed_(default_seed), use_random_seed_(false) + {} + + /** + Creates a new uniform random number generator. + */ + SEAL_NODISCARD auto create() -> std::shared_ptr<UniformRandomGenerator> + { + return use_random_seed_ + ? create_impl({ random_uint64(), random_uint64(), random_uint64(), random_uint64(), + random_uint64(), random_uint64(), random_uint64(), random_uint64() }) + : create_impl(default_seed_); + } + + /** + Creates a new uniform random number generator seeded with the given seed, + overriding the default seed for this factory instance. + + @param[in] seed The seed to be used for the created random number generator + */ + SEAL_NODISCARD auto create(random_seed_type seed) -> std::shared_ptr<UniformRandomGenerator> + { + return create_impl(seed); + } + + /** + Destroys the random number generator factory. + */ + virtual ~UniformRandomGeneratorFactory() = default; + + /** + Returns the default random number generator factory. This instance should + not be destroyed. + */ + static auto DefaultFactory() -> const std::shared_ptr<UniformRandomGeneratorFactory>; + + protected: + SEAL_NODISCARD virtual auto create_impl(random_seed_type seed) -> std::shared_ptr<UniformRandomGenerator> = 0; + + private: + random_seed_type default_seed_ = {}; + + bool use_random_seed_ = false; + }; + + /** + Provides an implementation of UniformRandomGenerator for using Blake2xb for + generating randomness with given 128-bit seed. + */ + class BlakePRNG : public UniformRandomGenerator + { + public: + /** + Creates a new BlakePRNG instance initialized with the given seed. + + @param[in] seed The seed for the random number generator + */ + BlakePRNG(random_seed_type seed) : UniformRandomGenerator(seed) + {} + + /** + Destroys the random number generator. + */ + virtual ~BlakePRNG() override = default; + + protected: + virtual void refill_buffer() override; + + private: + std::uint64_t counter_ = 0; + }; + + class BlakePRNGFactory : public UniformRandomGeneratorFactory + { + public: + /** + Creates a new BlakePRNGFactory. The seed will be sampled randomly for each + BlakePRNG instance created by the factory instance, which is desirable in + most normal use-cases. + */ + BlakePRNGFactory() : UniformRandomGeneratorFactory() + {} + + /** + Creates a new BlakePRNGFactory and sets the default seed to the given value. + For debugging purposes it may sometimes be convenient to have the same + randomness be used deterministically and repeatedly. Such randomness + sampling is naturally insecure and must be strictly restricted to debugging + situations. Thus, most users should never have a reason to use this + constructor. + + @param[in] default_seed The default value for a seed to be used by all + created instances of BlakePRNG + */ + BlakePRNGFactory(random_seed_type default_seed) : UniformRandomGeneratorFactory(default_seed) + {} + + /** + Destroys the random number generator factory. + */ + virtual ~BlakePRNGFactory() = default; + + protected: + SEAL_NODISCARD virtual auto create_impl(random_seed_type seed) + -> std::shared_ptr<UniformRandomGenerator> override + { + return std::make_shared<BlakePRNG>(seed); + } + + private: + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/randomtostd.h b/bigpiseal3.5.1/native/src/seal/randomtostd.h new file mode 100644 index 0000000000000000000000000000000000000000..460a2b1aa977d610bf28b3252cd0454ccc5b32fc --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/randomtostd.h @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/randomgen.h" +#include <cstdint> +#include <limits> +#include <memory> +#include <stdexcept> + +namespace seal +{ + /** + A simple wrapper class to implement C++ UniformRandomBitGenerator type properties + for a given polymorphic UniformRandomGenerator instance. The resulting object can + be used as a randomness source in C++ standard random number distribution classes, + such as std::uniform_int_distribution, std::normal_distribution, or any of the + standard RandomNumberEngine classes. + */ + class RandomToStandardAdapter + { + public: + using result_type = std::uint32_t; + + /** + Creates a new RandomToStandardAdapter backed by a given UniformRandomGenerator. + + @param[in] generator A backing UniformRandomGenerator instance + @throws std::invalid_argument if generator is null + */ + RandomToStandardAdapter(std::shared_ptr<UniformRandomGenerator> generator) : generator_(generator) + { + if (!generator_) + { + throw std::invalid_argument("generator cannot be null"); + } + } + + /** + Returns a new random number from the backing UniformRandomGenerator. + */ + SEAL_NODISCARD inline result_type operator()() + { + return generator_->generate(); + } + + /** + Returns the backing UniformRandomGenerator. + */ + SEAL_NODISCARD inline auto generator() const noexcept + { + return generator_; + } + + /** + Returns the smallest possible output value. + */ + SEAL_NODISCARD inline static constexpr result_type min() noexcept + { + return std::numeric_limits<result_type>::min(); + } + + /** + Returns the largest possible output value. + */ + SEAL_NODISCARD static constexpr result_type max() noexcept + { + return std::numeric_limits<result_type>::max(); + } + + private: + std::shared_ptr<UniformRandomGenerator> generator_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/relinkeys.h b/bigpiseal3.5.1/native/src/seal/relinkeys.h new file mode 100644 index 0000000000000000000000000000000000000000..0f09315eb5b661aff1e3ee12e7c2c197934cd5dc --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/relinkeys.h @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/encryptionparams.h" +#include "seal/kswitchkeys.h" +#include "seal/memorymanager.h" +#include "seal/util/defines.h" +#include <iostream> +#include <limits> +#include <vector> + +namespace seal +{ + /** + Class to store relinearization keys. + + @par Relinearization + Freshly encrypted ciphertexts have a size of 2, and multiplying ciphertexts + of sizes K and L results in a ciphertext of size K+L-1. Unfortunately, this + growth in size slows down further multiplications and increases noise growth. + Relinearization is an operation that has no semantic meaning, but it reduces + the size of ciphertexts back to 2. Microsoft SEAL can only relinearize size 3 + ciphertexts back to size 2, so if the ciphertexts grow larger than size 3, + there is no way to reduce their size. Relinearization requires an instance of + RelinKeys to be created by the secret key owner and to be shared with the + evaluator. Note that plain multiplication is fundamentally different from + normal multiplication and does not result in ciphertext size growth. + + @par When to Relinearize + Typically, one should always relinearize after each multiplications. However, + in some cases relinearization should be postponed as late as possible due to + its computational cost. For example, suppose the computation involves several + homomorphic multiplications followed by a sum of the results. In this case it + makes sense to not relinearize each product, but instead add them first and + only then relinearize the sum. This is particularly important when using the + CKKS scheme, where relinearization is much more computationally costly than + multiplications and additions. + + @par Thread Safety + In general, reading from RelinKeys is thread-safe as long as no other thread + is concurrently mutating it. This is due to the underlying data structure + storing the relinearization keys not being thread-safe. + + @see GaloisKeys for the class that stores the Galois keys. + @see KeyGenerator for the class that generates the relinearization keys. + */ + class RelinKeys : public KSwitchKeys + { + public: + /** + Returns the index of a relinearization key in the backing KSwitchKeys + instance that corresponds to the given secret key power, assuming that + it exists in the backing KSwitchKeys. + + @param[in] key_power The power of the secret key + @throws std::invalid_argument if key_power is less than 2 + */ + SEAL_NODISCARD inline static std::size_t get_index(std::size_t key_power) + { + if (key_power < 2) + { + throw std::invalid_argument("key_power cannot be less than 2"); + } + return key_power - 2; + } + + /** + Returns whether a relinearization key corresponding to a given power of + the secret key exists. + + @param[in] key_power The power of the secret key + @throws std::invalid_argument if key_power is less than 2 + */ + SEAL_NODISCARD inline bool has_key(std::size_t key_power) const + { + std::size_t index = get_index(key_power); + return data().size() > index && !data()[index].empty(); + } + + /** + Returns a const reference to a relinearization key. The returned + relinearization key corresponds to the given power of the secret key. + + @param[in] key_power The power of the secret key + @throws std::invalid_argument if the key corresponding to key_power does not exist + */ + SEAL_NODISCARD inline auto &key(std::size_t key_power) const + { + return KSwitchKeys::data(get_index(key_power)); + } + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/seal.h b/bigpiseal3.5.1/native/src/seal/seal.h new file mode 100644 index 0000000000000000000000000000000000000000..aef906bce82ec210338e36606b7059059bca6b18 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/seal.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/batchencoder.h" +#include "seal/biguint.h" +#include "seal/ciphertext.h" +#include "seal/ckks.h" +#include "seal/context.h" +#include "seal/decryptor.h" +#include "seal/encryptionparams.h" +#include "seal/encryptor.h" +#include "seal/evaluator.h" +#include "seal/intarray.h" +#include "seal/intencoder.h" +#include "seal/keygenerator.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/plaintext.h" +#include "seal/publickey.h" +#include "seal/randomgen.h" +#include "seal/randomtostd.h" +#include "seal/relinkeys.h" +#include "seal/secretkey.h" +#include "seal/serialization.h" +#include "seal/valcheck.h" diff --git a/bigpiseal3.5.1/native/src/seal/secretkey.h b/bigpiseal3.5.1/native/src/seal/secretkey.h new file mode 100644 index 0000000000000000000000000000000000000000..1722fbe4d89d1b8e6ea38345798f34228dcf6eab --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/secretkey.h @@ -0,0 +1,290 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/plaintext.h" +#include "seal/randomgen.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include <cstddef> +#include <cstdint> +#include <iostream> +#include <memory> +#include <random> + +namespace seal +{ + /** + Class to store a secret key. + + @par Thread Safety + In general, reading from SecretKey is thread-safe as long as no other thread + is concurrently mutating it. This is due to the underlying data structure + storing the secret key not being thread-safe. + + @see KeyGenerator for the class that generates the secret key. + @see PublicKey for the class that stores the public key. + @see RelinKeys for the class that stores the relinearization keys. + @see GaloisKeys for the class that stores the Galois keys. + */ + class SecretKey + { + friend class KeyGenerator; + + public: + /** + Creates an empty secret key. + */ + SecretKey() = default; + + /** + Creates a new SecretKey by copying an old one. + + @param[in] copy The SecretKey to copy from + */ + SecretKey(const SecretKey &copy) + { + // Note: sk_ is at this point initialized to use a custom (new) + // memory pool with the `clear_on_destruction' property. Now use + // Plaintext::operator =(const Plaintext &) to copy over the data. + // This is very important to do right, otherwise newly created + // SecretKey may use a normal memory pool obtained from + // MemoryManager::GetPool() with currently active profile (MMProf). + sk_ = copy.sk_; + } + + /** + Destroys the SecretKey object. + */ + ~SecretKey() = default; + + /** + Creates a new SecretKey by moving an old one. + + @param[in] source The SecretKey to move from + */ + SecretKey(SecretKey &&source) = default; + + /** + Copies an old SecretKey to the current one. + + @param[in] assign The SecretKey to copy from + */ + SecretKey &operator=(const SecretKey &assign) + { + Plaintext new_sk(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)); + new_sk = assign.sk_; + std::swap(sk_, new_sk); + return *this; + } + + /** + Moves an old SecretKey to the current one. + + @param[in] assign The SecretKey to move from + */ + SecretKey &operator=(SecretKey &&assign) = default; + + /** + Returns a reference to the underlying polynomial. + */ + SEAL_NODISCARD inline auto &data() noexcept + { + return sk_; + } + + /** + Returns a const reference to the underlying polynomial. + */ + SEAL_NODISCARD inline auto &data() const noexcept + { + return sk_; + } + + /** + Returns an upper bound on the size of the SecretKey, as if it was written + to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return sk_.save_size(compr_mode); + } + + /** + Saves the SecretKey to an output stream. The output is in binary format + and not human-readable. The output stream must have the "binary" flag set. + + @param[out] stream The stream to save the SecretKey to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return sk_.save(stream, compr_mode); + } + + /** + Loads a SecretKey from an input stream overwriting the current SecretKey. + No checking of the validity of the SecretKey data against encryption + parameters is performed. This function should not be used unless the + SecretKey comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] stream The stream to load the SecretKey from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + // We use a fresh memory pool with `clear_on_destruction' enabled. + Plaintext new_sk(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)); + auto in_size = new_sk.unsafe_load(std::move(context), stream); + std::swap(sk_, new_sk); + return in_size; + } + + /** + Loads a SecretKey from an input stream overwriting the current SecretKey. + The loaded SecretKey is verified to be valid for the given SEALContext. + + @param[in] context The SEALContext + @param[in] stream The stream to load the SecretKey from + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, std::istream &stream) + { + SecretKey new_sk; + auto in_size = new_sk.unsafe_load(context, stream); + if (!is_valid_for(new_sk, std::move(context))) + { + throw std::logic_error("SecretKey data is invalid"); + } + std::swap(*this, new_sk); + return in_size; + } + + /** + Saves the SecretKey to a given memory location. The output is in binary + format and is not human-readable. + + @param[out] out The memory location to write the SecretKey to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return sk_.save(out, size, compr_mode); + } + + /** + Loads a SecretKey from a given memory location overwriting the current + SecretKey. No checking of the validity of the SecretKey data against + encryption parameters is performed. This function should not be used + unless the SecretKey comes from a fully trusted source. + + @param[in] context The SEALContext + @param[in] in The memory location to load the SecretKey from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff unsafe_load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + // We use a fresh memory pool with `clear_on_destruction' enabled. + Plaintext new_sk(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)); + auto in_size = new_sk.unsafe_load(std::move(context), in, size); + std::swap(sk_, new_sk); + return in_size; + } + + /** + Loads a SecretKey from a given memory location overwriting the current + SecretKey. The loaded SecretKey is verified to be valid for the given + SEALContext. + + @param[in] context The SEALContext + @param[in] in The memory location to load the SecretKey from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if the context is not set or encryption + parameters are not valid + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff load(std::shared_ptr<SEALContext> context, const SEAL_BYTE *in, std::size_t size) + { + SecretKey new_sk; + auto in_size = new_sk.unsafe_load(context, in, size); + if (!is_valid_for(new_sk, std::move(context))) + { + throw std::logic_error("SecretKey data is invalid"); + } + std::swap(*this, new_sk); + return in_size; + } + + /** + Returns a reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() noexcept + { + return sk_.parms_id(); + } + + /** + Returns a const reference to parms_id. + + @see EncryptionParameters for more information about parms_id. + */ + SEAL_NODISCARD inline auto &parms_id() const noexcept + { + return sk_.parms_id(); + } + + /** + Returns the currently used MemoryPoolHandle. + */ + SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept + { + return sk_.pool(); + } + + private: + // We use a fresh memory pool with `clear_on_destruction' enabled. + Plaintext sk_{ MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true) }; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/serializable.h b/bigpiseal3.5.1/native/src/seal/serializable.h new file mode 100644 index 0000000000000000000000000000000000000000..f1660290a05f59f3c29b05509b6b02c07b1177f2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/serializable.h @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/serialization.h" +#include "seal/util/defines.h" +#include "seal/util/streambuf.h" +#include <cstdint> +#include <functional> +#include <ios> +#include <iostream> + +namespace seal +{ + /** + Class to represent a serializable object. Some functions return serializable + objects rather than normal objects. For example, Encryptor can be used in + symmetric-key mode to create symmetric-key ciphertexts, where half of the + ciphertext data is pseudo-random and can be generated from a seed, reducing + the size of the newly created ciphertext object by nearly 50%. However, the + compression only has an effect when the object is serialized with compression + mode compr_mode_type::deflate due to an implementation detail. This makes + sense when, e.g., the ciphertexts need to be communicated from a client to + a server for encrypted computation. + + Serializable objects are created only by the following functions: + - Encryptor::encrypt_symmetric + - Encryptor::encrypt_zero_symmetric + - KeyGenerator::relin_keys + - KeyGenerator::galois_keys + + Serializable objects also expose the save_size function that behaves just + as the save_size functions of other objects in Microsoft SEAL: it returns + an upper bound on the size of a buffer needed to hold the serialized data. + + The following illustrates the use of serializable objects: + + +--------------------------+ + | Serializable<GaloisKeys> | Size 2 MB (example) + +------------+-------------+ + | + | Serializable<GaloisKeys>::save + | with compr_mode_type::deflate + | + +-------v-------+ + | Stream/Buffer | Size ~1 MB (example) + +-------+-------+ + | + | + +--v--+ + Network Minimized communication + +--+--+ + | + | GaloisKeys::load + | + +-----v------+ + | GaloisKeys | Size 2 MB (example) + +------------+ + */ + template <class T> + class Serializable + { + friend class KeyGenerator; + friend class Encryptor; + + public: + /** + Constructs a new serializable object by copying a given one. + + @param[in] copy The serializable object to copy from + */ + Serializable(const Serializable<T> &copy) = default; + + /** + Creates a new serializable object by moving a given one. + + @param[in] source The serializable object to move from + */ + Serializable(Serializable<T> &&source) = default; + + /** + Moves a given serializable object to the current one. + + @param[in] assign The serializable object to move from + */ + Serializable &operator=(Serializable<T> &&assign) = default; + + /** + Copies a given serializable object to the current one. + + @param[in] copy The serializable object to copy from + */ + Serializable &operator=(const Serializable<T> &copy) = default; + + /** + Returns an upper bound on the size of the serializable object, as if it + was written to an output stream. + + @param[in] compr_mode The compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the size does not fit in the return type + */ + SEAL_NODISCARD inline std::streamoff save_size( + compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return obj_.save_size(compr_mode); + } + + /** + Saves the serializable object to an output stream. The output is in binary + format and not human-readable. The output stream must have the "binary" + flag set. + + @param[out] stream The stream to save the serializable object to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return obj_.save(stream, compr_mode); + } + + /** + Saves the serializable object to a given memory location. The output is in + binary format and is not human-readable. + + @param[out] out The memory location to write the serializable object to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader, or if the compression mode is not supported + @throws std::logic_error if the data to be saved is invalid, or if + compression failed + @throws std::runtime_error if I/O operations failed + */ + inline std::streamoff save( + SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const + { + return obj_.save(out, size, compr_mode); + } + + private: + Serializable(T &&obj) : obj_(std::move(obj)) + {} + + T obj_; + }; +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/serialization.cpp b/bigpiseal3.5.1/native/src/seal/serialization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89950373dcf21eba4543e0fe00be21b20d352798 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/serialization.cpp @@ -0,0 +1,435 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/serialization.h" +#include "seal/util/common.h" +#include "seal/util/streambuf.h" +#include "seal/util/ztools.h" +#include <algorithm> +#include <stdexcept> +#include <type_traits> +#include <typeinfo> +#include <utility> + +using namespace std; +using namespace seal::util; + +namespace seal +{ + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to ensure + // symbol is created. + constexpr compr_mode_type Serialization::compr_mode_default; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to ensure + // symbol is created. + constexpr std::uint16_t Serialization::seal_magic; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to ensure + // symbol is created. + constexpr std::uint8_t Serialization::seal_header_size; + + namespace + { + [[noreturn]] void expressive_rethrow_on_ios_base_failure(const ostream &stream) + { + if (!stream.rdbuf()) + { + throw runtime_error("I/O error: output stream has no associated buffer"); + } + + // Use RTTI to determine if this is an ArrayPutBuffer + auto &rdbuf_ref = *stream.rdbuf(); + if (typeid(rdbuf_ref).hash_code() == typeid(ArrayPutBuffer).hash_code()) + { + auto buffer = reinterpret_cast<ArrayPutBuffer *>(stream.rdbuf()); + + // Determine if write overflow occurred + if (buffer->at_end()) + { + // Return a more expressive error + throw runtime_error("I/O error: insufficient output buffer"); + } + } + + // Generic message + throw runtime_error("I/O error"); + } + + [[noreturn]] void expressive_rethrow_on_ios_base_failure(const istream &stream) + { + if (!stream.rdbuf()) + { + throw runtime_error("I/O error: input stream has no associated buffer"); + } + + // Use RTTI to determine if this is an ArrayGetBuffer + if (stream.eof()) + { + auto &rdbuf_ref = *stream.rdbuf(); + if (typeid(rdbuf_ref).hash_code() == typeid(ArrayGetBuffer).hash_code()) + { + // Report buffer underflow + throw runtime_error("I/O error: input buffer ended unexpectedly"); + } + else + { + // Report generic underflow + throw runtime_error("I/O error: input stream ended unexpectedly"); + } + } + + // Generic message + throw runtime_error("I/O error"); + } + } // namespace + + size_t Serialization::ComprSizeEstimate(size_t in_size, compr_mode_type compr_mode) + { + if (!IsSupportedComprMode(compr_mode)) + { + throw invalid_argument("unsupported compression mode"); + } + + switch (compr_mode) + { +#ifdef SEAL_USE_ZLIB + case compr_mode_type::deflate: + return ztools::deflate_size_bound(in_size); +#endif + case compr_mode_type::none: + // No compression + return in_size; + + default: + throw invalid_argument("unsupported compression mode"); + } + } + + streamoff Serialization::SaveHeader(const SEALHeader &header, ostream &stream) + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + stream.write(reinterpret_cast<const char *>(&header), sizeof(SEALHeader)); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + expressive_rethrow_on_ios_base_failure(stream); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + // Return the size of the SEALHeader + return static_cast<streamoff>(sizeof(SEALHeader)); + } + + streamoff Serialization::LoadHeader(istream &stream, SEALHeader &header, bool try_upgrade_if_invalid) + { + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + stream.read(reinterpret_cast<char *>(&header), sizeof(SEALHeader)); + + // If header is invalid this may be an older header and we can try to automatically upgrade it + if (try_upgrade_if_invalid && !IsValidHeader(header)) + { + // Try interpret the data as a Microsoft SEAL 3.4 header + legacy_headers::SEALHeader_3_4 header_3_4(header); + + SEALHeader new_header; + // Copy over the fields; of course the result may not be valid depending on whether the input was a + // valid version 3.4 header + new_header.compr_mode = header_3_4.compr_mode; + new_header.size = header_3_4.size; + + // Now validate the new header and discard if still not valid; something else is probably wrong + if (IsValidHeader(new_header)) + { + header = new_header; + } + } + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + expressive_rethrow_on_ios_base_failure(stream); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + // Return the size of the SEALHeader + return static_cast<streamoff>(sizeof(SEALHeader)); + } + + streamoff Serialization::SaveHeader(const SEALHeader &header, SEAL_BYTE *out, size_t size) + { + if (!out) + { + throw invalid_argument("out cannot be null"); + } + if (size < sizeof(SEALHeader)) + { + throw invalid_argument("insufficient size"); + } + if (!fits_in<streamsize>(size)) + { + throw invalid_argument("size is too large"); + } + ArrayPutBuffer apbuf(reinterpret_cast<char *>(out), static_cast<streamsize>(size)); + ostream stream(&apbuf); + return SaveHeader(header, stream); + } + + streamoff Serialization::LoadHeader( + const SEAL_BYTE *in, size_t size, SEALHeader &header, bool try_upgrade_if_invalid) + { + if (!in) + { + throw invalid_argument("in cannot be null"); + } + if (size < sizeof(SEALHeader)) + { + throw invalid_argument("insufficient size"); + } + if (!fits_in<streamsize>(size)) + { + throw invalid_argument("size is too large"); + } + ArrayGetBuffer agbuf(reinterpret_cast<const char *>(in), static_cast<streamsize>(size)); + istream stream(&agbuf); + return LoadHeader(stream, header, try_upgrade_if_invalid); + } + + streamoff Serialization::Save( + function<void(ostream &stream)> save_members, streamoff raw_size, ostream &stream, compr_mode_type compr_mode) + { + if (!save_members) + { + throw invalid_argument("save_members is invalid"); + } + if (raw_size < static_cast<streamoff>(sizeof(SEALHeader))) + { + throw invalid_argument("raw_size is too small"); + } + if (!IsSupportedComprMode(compr_mode)) + { + throw invalid_argument("unsupported compression mode"); + } + + streamoff out_size = 0; + + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + // Save the starting position + auto stream_start_pos = stream.tellp(); + + // Create the header + SEALHeader header; + + switch (compr_mode) + { + case compr_mode_type::none: + // We set the compression mode and size here, and save the header + header.compr_mode = compr_mode; + header.size = safe_cast<uint64_t>(raw_size); + SaveHeader(header, stream); + + // Write rest of the data + save_members(stream); + break; +#ifdef SEAL_USE_ZLIB + case compr_mode_type::deflate: + { + // First save_members to a temporary byte stream; set the size + // of the temporary stream to be right from the start to avoid + // extra reallocs. + SafeByteBuffer safe_buffer( + ztools::deflate_size_bound(raw_size - static_cast<streamoff>(sizeof(SEALHeader)))); + iostream temp_stream(&safe_buffer); + temp_stream.exceptions(ios_base::badbit | ios_base::failbit); + save_members(temp_stream); + + auto safe_pool(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)); + + // Create temporary aliasing IntArray to wrap safe_buffer + IntArray<SEAL_BYTE> safe_buffer_array( + Pointer<SEAL_BYTE>::Aliasing(safe_buffer.data()), safe_buffer.size(), + static_cast<size_t>(temp_stream.tellp()), false, safe_pool); + + // After compression, write_header_deflate_buffer will write the + // final size to the given header and write the header to stream, + // before writing the compressed output. + ztools::write_header_deflate_buffer( + safe_buffer_array, reinterpret_cast<void *>(&header), stream, safe_pool); + break; + } +#endif + default: + throw invalid_argument("unsupported compression mode"); + } + + // Compute how many bytes were written + auto stream_end_pos = stream.tellp(); + out_size = stream_end_pos - stream_start_pos; + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + expressive_rethrow_on_ios_base_failure(stream); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + return out_size; + } + + streamoff Serialization::Load(function<void(istream &stream)> load_members, istream &stream) + { + if (!load_members) + { + throw invalid_argument("load_members is invalid"); + } + + streamoff in_size = 0; + SEALHeader header; + + auto old_except_mask = stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + stream.exceptions(ios_base::badbit | ios_base::failbit); + + // Save the starting position + auto stream_start_pos = stream.tellg(); + + // First read the header + LoadHeader(stream, header); + if (!IsCompatibleVersion(header)) + { + throw logic_error("incompatible version"); + } + if (!IsValidHeader(header)) + { + throw logic_error("loaded SEALHeader is invalid"); + } + + switch (header.compr_mode) + { + case compr_mode_type::none: + // Read rest of the data + load_members(stream); + if (header.size != safe_cast<uint64_t>(stream.tellg() - stream_start_pos)) + { + throw logic_error("invalid data size"); + } + break; +#ifdef SEAL_USE_ZLIB + case compr_mode_type::deflate: + { + auto compr_size = header.size - safe_cast<uint64_t>(stream.tellg() - stream_start_pos); + + // We don't know the decompressed size, but use compr_size as + // starting point for the buffer. + SafeByteBuffer safe_buffer(safe_cast<streamsize>(compr_size)); + + iostream temp_stream(&safe_buffer); + temp_stream.exceptions(ios_base::badbit | ios_base::failbit); + + constexpr int Z_OK = 0; + if (ztools::inflate_stream( + stream, safe_cast<streamoff>(compr_size), temp_stream, + MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true)) != Z_OK) + { + throw logic_error("stream inflate failed"); + } + load_members(temp_stream); + break; + } +#endif + default: + throw invalid_argument("unsupported compression mode"); + } + + in_size = safe_cast<streamoff>(header.size); + } + catch (const ios_base::failure &) + { + stream.exceptions(old_except_mask); + expressive_rethrow_on_ios_base_failure(stream); + } + catch (...) + { + stream.exceptions(old_except_mask); + throw; + } + stream.exceptions(old_except_mask); + + return in_size; + } + + streamoff Serialization::Save( + function<void(ostream &stream)> save_members, streamoff raw_size, SEAL_BYTE *out, size_t size, + compr_mode_type compr_mode) + { + if (!out) + { + throw invalid_argument("out cannot be null"); + } + if (size < sizeof(SEALHeader)) + { + throw invalid_argument("insufficient size"); + } + if (!fits_in<streamsize>(size)) + { + throw invalid_argument("size is too large"); + } + ArrayPutBuffer apbuf(reinterpret_cast<char *>(out), static_cast<streamsize>(size)); + ostream stream(&apbuf); + return Save(save_members, raw_size, stream, compr_mode); + } + + streamoff Serialization::Load(function<void(istream &stream)> load_members, const SEAL_BYTE *in, size_t size) + { + if (!in) + { + throw invalid_argument("in cannot be null"); + } + if (size < sizeof(SEALHeader)) + { + throw invalid_argument("insufficient size"); + } + if (!fits_in<streamsize>(size)) + { + throw invalid_argument("size is too large"); + } + ArrayGetBuffer agbuf(reinterpret_cast<const char *>(in), static_cast<streamsize>(size)); + istream stream(&agbuf); + return Load(load_members, stream); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/serialization.h b/bigpiseal3.5.1/native/src/seal/serialization.h new file mode 100644 index 0000000000000000000000000000000000000000..eb9f693eaa9ceea0bd2ec1968b43a7f13d0c605e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/serialization.h @@ -0,0 +1,335 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include <cstdint> +#include <cstring> +#include <functional> +#include <iostream> + +namespace seal +{ + /** + A type to describe the compression algorithm applied to serialized data. + Ciphertext and key data consist of a large number of 64-bit words storing + integers modulo prime numbers much smaller than the word size, resulting in + a large number of zero bytes in the output. Any compression algorithm should + be able to clean up these zero bytes and hence compress both ciphertext and + key data. + */ + enum class compr_mode_type : std::uint8_t + { + // No compression is used. + none = 0, +#ifdef SEAL_USE_ZLIB + // Use Deflate compression + deflate = 1, +#endif + }; + + /** + Class to provide functionality for serialization. Most users of the library + should never have to call these functions explicitly, as they are called + internally by functions such as Ciphertext::save and Ciphertext::load. + */ + class Serialization + { + public: + /** + The compression mode used by default. + */ +#ifdef SEAL_USE_ZLIB + static constexpr compr_mode_type compr_mode_default = compr_mode_type::deflate; +#else + static constexpr compr_mode_type compr_mode_default = compr_mode_type::none; +#endif + /** + The magic value indicating a Microsoft SEAL header. + */ + static constexpr std::uint16_t seal_magic = 0xA15E; + + /** + The size in bytes of the SEALHeader. + */ + static constexpr std::uint8_t seal_header_size = 0x10; + + /** + Struct to contain metadata for serialization comprising the following fields: + + 1. a magic number identifying this is a SEALHeader struct (2 bytes) + 2. size in bytes of the SEALHeader struct (1 byte) + 3. Microsoft SEAL's major version number (1 byte) + 4. Microsoft SEAL's minor version number (1 byte) + 5. a compr_mode_type indicating whether data after the header is compressed (1 byte) + 6. reserved for future use and data alignment (2 bytes) + 7. the size in bytes of the entire serialized object, including the header (8 bytes) + */ + struct SEALHeader + { + std::uint16_t magic = seal_magic; + + std::uint8_t header_size = seal_header_size; + + std::uint8_t version_major = static_cast<std::uint8_t>(SEAL_VERSION_MAJOR); + + std::uint8_t version_minor = static_cast<std::uint8_t>(SEAL_VERSION_MINOR); + + compr_mode_type compr_mode = compr_mode_type::none; + + std::uint16_t reserved = 0; + + std::uint64_t size = 0; + }; + + /** + Returns true if the given byte corresponds to a supported compression mode. + + @param[in] compr_mode The compression mode to validate + */ + SEAL_NODISCARD static bool IsSupportedComprMode(std::uint8_t compr_mode) noexcept + { + switch (compr_mode) + { + case static_cast<std::uint8_t>(compr_mode_type::none): + /* fall through */ +#ifdef SEAL_USE_ZLIB + case static_cast<std::uint8_t>(compr_mode_type::deflate): +#endif + return true; + } + return false; + } + + /** + Returns true if the given value corresponds to a supported compression mode. + + @param[in] compr_mode The compression mode to validate + */ + SEAL_NODISCARD static inline bool IsSupportedComprMode(compr_mode_type compr_mode) noexcept + { + return IsSupportedComprMode(static_cast<uint8_t>(compr_mode)); + } + + /** + Returns an upper bound on the output size of data compressed according to + a given compression mode with given input size. If compr_mode is + compr_mode_type::none, the return value is exactly in_size. + + @param[in] in_size The input size to a compression algorithm + @param[in] in_size The compression mode + @throws std::invalid_argument if the compression mode is not supported + */ + SEAL_NODISCARD static std::size_t ComprSizeEstimate(std::size_t in_size, compr_mode_type compr_mode); + + /** + Returns true if the SEALHeader has a version number compatible with this version of Microsoft SEAL. + + @param[in] header The SEALHeader + */ + SEAL_NODISCARD static bool IsCompatibleVersion(const SEALHeader &header) noexcept + { + return (header.version_major == SEAL_VERSION_MAJOR && header.version_minor == SEAL_VERSION_MINOR); + } + + /** + Returns true if the given SEALHeader is valid for this version of Microsoft SEAL. + + @param[in] header The SEALHeader + */ + SEAL_NODISCARD static bool IsValidHeader(const SEALHeader &header) noexcept + { + if (header.magic != seal_magic) + { + return false; + } + if (header.header_size != seal_header_size) + { + return false; + } + if (!IsCompatibleVersion(header)) + { + return false; + } + if (!IsSupportedComprMode(static_cast<uint8_t>(header.compr_mode))) + { + return false; + } + return true; + } + + /** + Saves a SEALHeader to a given stream. The output is in binary format and + not human-readable. The output stream must have the "binary" flag set. + + @param[in] header The SEALHeader to save to the stream + @param[out] stream The stream to save the SEALHeader to + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff SaveHeader(const SEALHeader &header, std::ostream &stream); + + /** + Loads a SEALHeader from a given stream. + + @param[in] stream The stream to load the SEALHeader from + @param[in] header The SEALHeader to populate with the loaded data + @param[in] try_upgrade_if_invalid If the loaded SEALHeader is invalid, + attempt to identify its format and upgrade to the current SEALHeader version + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff LoadHeader(std::istream &stream, SEALHeader &header, bool try_upgrade_if_invalid = true); + + /** + Saves a SEALHeader to a given memory location. The output is in binary + format and is not human-readable. + + @param[out] out The memory location to write the SEALHeader to + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if out is null or if size is too small to + contain a SEALHeader + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff SaveHeader(const SEALHeader &header, SEAL_BYTE *out, std::size_t size); + + /** + Loads a SEALHeader from a given memory location. + + @param[in] in The memory location to load the SEALHeader from + @param[in] size The number of bytes available in the given memory location + @param[in] try_upgrade_if_invalid If the loaded SEALHeader is invalid, + attempt to identify its format and upgrade to the current SEALHeader version + @throws std::invalid_argument if in is null or if size is too small to + contain a SEALHeader + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff LoadHeader( + const SEAL_BYTE *in, std::size_t size, SEALHeader &header, bool try_upgrade_if_invalid = true); + + /** + Evaluates save_members and compresses the output according to the given + compr_mode_type. The resulting data is written to stream and is prepended + by the given compr_mode_type and the total size of the data to facilitate + deserialization. In typical use-cases save_members would be a function + that serializes the member variables of an object to the given stream. + + For any given compression mode, raw_size must be the exact right size + (in bytes) of what save_members writes to a stream in the uncompressed + mode. Otherwise the behavior of Save is unspecified. + + @param[in] save_members A function taking an std::ostream reference as an + argument, possibly writing some number of bytes into it + @param[in] raw_size The exact uncompressed output size of save_members + @param[out] stream The stream to write to + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if save_members is invalid + @throws std::invalid_argument if raw_size is smaller than SEALHeader size + @throws std::logic_error if the data to be saved is invalid, if compression + mode is not supported, or if compression failed + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff Save( + std::function<void(std::ostream &stream)> save_members, std::streamoff raw_size, std::ostream &stream, + compr_mode_type compr_mode); + + /** + Deserializes data from stream that was serialized by Save. Once stream has + been decompressed (depending on compression mode), load_members is applied + to the decompressed stream. In typical use-cases load_members would be + a function that deserializes the member variables of an object from the + given stream. + + @param[in] load_members A function taking an std::istream reference as an + argument, possibly reading some number of bytes from it + @param[in] stream The stream to read from + @throws std::invalid_argument if load_members is invalid + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff Load(std::function<void(std::istream &stream)> load_members, std::istream &stream); + + /** + Evaluates save_members and compresses the output according to the given + compr_mode_type. The resulting data is written to a given memory location + and is prepended by the given compr_mode_type and the total size of the + data to facilitate deserialization. In typical use-cases save_members would + be a function that serializes the member variables of an object to the + given stream. + + For any given compression mode, raw_size must be the exact right size + (in bytes) of what save_members writes to a stream in the uncompressed + mode. Otherwise the behavior of Save is unspecified. + + @param[in] save_members A function that takes an std::ostream reference as + an argument and writes some number of bytes into it + @param[in] raw_size The exact uncompressed output size of save_members + @param[out] out The memory location to write to + @param[in] size The number of bytes available in the given memory location + @param[in] compr_mode The desired compression mode + @throws std::invalid_argument if save_members is invalid, if raw_size or + size is smaller than SEALHeader size, or if out is null + @throws std::logic_error if the data to be saved is invalid, if compression + mode is not supported, or if compression failed + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff Save( + std::function<void(std::ostream &stream)> save_members, std::streamoff raw_size, SEAL_BYTE *out, + std::size_t size, compr_mode_type compr_mode); + + /** + Deserializes data from a memory location that was serialized by Save. + Once the data has been decompressed (depending on compression mode), + load_members is applied to the decompressed stream. In typical use-cases + load_members would be a function that deserializes the member variables + of an object from the given stream. + + @param[in] load_members A function that takes an std::istream reference as + an argument and reads some number of bytes from it + @param[in] in The memory location to read from + @param[in] size The number of bytes available in the given memory location + @throws std::invalid_argument if load_members is invalid, if in is null, + or if size is too small to contain a SEALHeader + @throws std::logic_error if the data cannot be loaded by this version of + Microsoft SEAL, if the loaded data is invalid, or if decompression failed + @throws std::runtime_error if I/O operations failed + */ + static std::streamoff Load( + std::function<void(std::istream &stream)> load_members, const SEAL_BYTE *in, std::size_t size); + + private: + Serialization() = delete; + }; + + namespace legacy_headers + { + /** + Struct to enable compatibility with Microsoft SEAL 3.4 headers. + */ + struct SEALHeader_3_4 + { + std::uint16_t magic = Serialization::seal_magic; + + std::uint8_t zero_byte = 0x00; + + compr_mode_type compr_mode = compr_mode_type::none; + + std::uint32_t size = 0; + + std::uint64_t reserved = 0; + + SEALHeader_3_4 &operator=(const Serialization::SEALHeader assign) + { + std::memcpy(this, &assign, sizeof(Serialization::SEALHeader)); + return *this; + } + + SEALHeader_3_4() = default; + + SEALHeader_3_4(const Serialization::SEALHeader &copy) + { + operator=(copy); + } + }; + } // namespace legacy_headers +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/CMakeLists.txt b/bigpiseal3.5.1/native/src/seal/util/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce2b5d63cfc1f7e9419e47362842f9c88ab989f9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/CMakeLists.txt @@ -0,0 +1,71 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +# Source files in this directory +target_sources(seal_obj PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/blake2b.c + ${CMAKE_CURRENT_LIST_DIR}/blake2xb.c + ${CMAKE_CURRENT_LIST_DIR}/clipnormal.cpp + ${CMAKE_CURRENT_LIST_DIR}/croots.cpp + ${CMAKE_CURRENT_LIST_DIR}/globals.cpp + ${CMAKE_CURRENT_LIST_DIR}/galois.cpp + ${CMAKE_CURRENT_LIST_DIR}/hash.cpp + ${CMAKE_CURRENT_LIST_DIR}/mempool.cpp + ${CMAKE_CURRENT_LIST_DIR}/numth.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarith.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarithmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarithsmallmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/rlwe.cpp + ${CMAKE_CURRENT_LIST_DIR}/rns.cpp + ${CMAKE_CURRENT_LIST_DIR}/scalingvariant.cpp + ${CMAKE_CURRENT_LIST_DIR}/ntt.cpp + ${CMAKE_CURRENT_LIST_DIR}/streambuf.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarith.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarithmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarithsmallmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintcore.cpp + ${CMAKE_CURRENT_LIST_DIR}/ztools.cpp +) + +# Create the config file +configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in ${CMAKE_CURRENT_LIST_DIR}/config.h) + +# Add header files for installation +install( + FILES + ${CMAKE_CURRENT_LIST_DIR}/blake2.h + ${CMAKE_CURRENT_LIST_DIR}/blake2-impl.h + ${CMAKE_CURRENT_LIST_DIR}/clang.h + ${CMAKE_CURRENT_LIST_DIR}/clipnormal.h + ${CMAKE_CURRENT_LIST_DIR}/common.h + ${CMAKE_CURRENT_LIST_DIR}/config.h + ${CMAKE_CURRENT_LIST_DIR}/croots.h + ${CMAKE_CURRENT_LIST_DIR}/defines.h + ${CMAKE_CURRENT_LIST_DIR}/galois.h + ${CMAKE_CURRENT_LIST_DIR}/gcc.h + ${CMAKE_CURRENT_LIST_DIR}/globals.h + ${CMAKE_CURRENT_LIST_DIR}/hash.h + ${CMAKE_CURRENT_LIST_DIR}/hestdparms.h + ${CMAKE_CURRENT_LIST_DIR}/iterator.h + ${CMAKE_CURRENT_LIST_DIR}/locks.h + ${CMAKE_CURRENT_LIST_DIR}/mempool.h + ${CMAKE_CURRENT_LIST_DIR}/msvc.h + ${CMAKE_CURRENT_LIST_DIR}/numth.h + ${CMAKE_CURRENT_LIST_DIR}/pointer.h + ${CMAKE_CURRENT_LIST_DIR}/polyarith.h + ${CMAKE_CURRENT_LIST_DIR}/polyarithmod.h + ${CMAKE_CURRENT_LIST_DIR}/polyarithsmallmod.h + ${CMAKE_CURRENT_LIST_DIR}/polycore.h + ${CMAKE_CURRENT_LIST_DIR}/rlwe.h + ${CMAKE_CURRENT_LIST_DIR}/rns.h + ${CMAKE_CURRENT_LIST_DIR}/scalingvariant.h + ${CMAKE_CURRENT_LIST_DIR}/ntt.h + ${CMAKE_CURRENT_LIST_DIR}/streambuf.h + ${CMAKE_CURRENT_LIST_DIR}/uintarith.h + ${CMAKE_CURRENT_LIST_DIR}/uintarithmod.h + ${CMAKE_CURRENT_LIST_DIR}/uintarithsmallmod.h + ${CMAKE_CURRENT_LIST_DIR}/uintcore.h + ${CMAKE_CURRENT_LIST_DIR}/ztools.h + DESTINATION + ${SEAL_INCLUDES_INSTALL_DIR}/seal/util +) diff --git a/bigpiseal3.5.1/native/src/seal/util/blake2-impl.h b/bigpiseal3.5.1/native/src/seal/util/blake2-impl.h new file mode 100644 index 0000000000000000000000000000000000000000..1cc61e3d0a6cf9297f3080c4955eb174274f249e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/blake2-impl.h @@ -0,0 +1,147 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +#ifndef BLAKE2_IMPL_H +#define BLAKE2_IMPL_H + +#include <stdint.h> +#include <string.h> + +#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) +#if defined(_MSC_VER) +#define BLAKE2_INLINE __inline +#elif defined(__GNUC__) +#define BLAKE2_INLINE __inline__ +#else +#define BLAKE2_INLINE +#endif +#else +#define BLAKE2_INLINE inline +#endif + +static BLAKE2_INLINE uint32_t load32(const void *src) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = (const uint8_t *)src; + return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); +#endif +} + +static BLAKE2_INLINE uint64_t load64(const void *src) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = (const uint8_t *)src; + return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | + ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56); +#endif +} + +static BLAKE2_INLINE uint16_t load16(const void *src) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint16_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = (const uint8_t *)src; + return (uint16_t)(((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8)); +#endif +} + +static BLAKE2_INLINE void store16(void *dst, uint16_t w) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = (uint8_t *)dst; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; +#endif +} + +static BLAKE2_INLINE void store32(void *dst, uint32_t w) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +#endif +} + +static BLAKE2_INLINE void store64(void *dst, uint64_t w) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); +#endif +} + +static BLAKE2_INLINE uint64_t load48(const void *src) +{ + const uint8_t *p = (const uint8_t *)src; + return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | + ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40); +} + +static BLAKE2_INLINE void store48(void *dst, uint64_t w) +{ + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); +} + +static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) +{ + return (w >> c) | (w << (32 - c)); +} + +static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) +{ + return (w >> c) | (w << (64 - c)); +} + +/* prevents compiler optimizing out memset() */ +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); +} + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/blake2.h b/bigpiseal3.5.1/native/src/seal/util/blake2.h new file mode 100644 index 0000000000000000000000000000000000000000..5e839376b8f1f98bb6029b9736851188ff9603f0 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/blake2.h @@ -0,0 +1,204 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +/* +Minor modifications to the original file have been made and marked +as `EDIT: ...`. The sole purpose of these edits is to silence misleading +warnings in Visual Studio. +*/ + +#ifndef BLAKE2_H +#define BLAKE2_H + +#include <stddef.h> +#include <stdint.h> + +#if defined(_MSC_VER) +#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) +#else +#define BLAKE2_PACKED(x) x __attribute__((packed)) +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + + enum blake2s_constant + { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 + }; + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + + typedef struct blake2s_state__ + { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2s_state; + + typedef struct blake2b_state__ + { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + typedef struct blake2sp_state__ + { + blake2s_state S[8][1]; + blake2s_state R[1]; + uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2sp_state; + + typedef struct blake2bp_state__ + { + blake2b_state S[4][1]; + blake2b_state R[1]; + uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2bp_state; + + BLAKE2_PACKED(struct blake2s_param__ { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint16_t xof_length; /* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + /* uint8_t reserved[0]; */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + }); + + typedef struct blake2s_param__ blake2s_param; + + BLAKE2_PACKED(struct blake2b_param__ { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + typedef struct blake2xs_state__ + { + blake2s_state S[1]; + blake2s_param P[1]; + } blake2xs_state; + + typedef struct blake2xb_state__ + { + blake2b_state S[1]; + blake2b_param P[1]; + } blake2xb_state; + + /* Padded structs result in a compile-time error */ + /* + EDIT: explicit cast to int + */ + enum + { + BLAKE2_DUMMY_1 = 1 / (int)(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1 / (int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; + + /* Streaming API */ + int blake2s_init(blake2s_state *S, size_t outlen); + int blake2s_init_key(blake2s_state *S, size_t outlen, const void *key, size_t keylen); + int blake2s_init_param(blake2s_state *S, const blake2s_param *P); + int blake2s_update(blake2s_state *S, const void *in, size_t inlen); + int blake2s_final(blake2s_state *S, void *out, size_t outlen); + + int blake2b_init(blake2b_state *S, size_t outlen); + int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); + int blake2b_init_param(blake2b_state *S, const blake2b_param *P); + int blake2b_update(blake2b_state *S, const void *in, size_t inlen); + int blake2b_final(blake2b_state *S, void *out, size_t outlen); + + int blake2sp_init(blake2sp_state *S, size_t outlen); + int blake2sp_init_key(blake2sp_state *S, size_t outlen, const void *key, size_t keylen); + int blake2sp_update(blake2sp_state *S, const void *in, size_t inlen); + int blake2sp_final(blake2sp_state *S, void *out, size_t outlen); + + int blake2bp_init(blake2bp_state *S, size_t outlen); + int blake2bp_init_key(blake2bp_state *S, size_t outlen, const void *key, size_t keylen); + int blake2bp_update(blake2bp_state *S, const void *in, size_t inlen); + int blake2bp_final(blake2bp_state *S, void *out, size_t outlen); + + /* Variable output length API */ + int blake2xs_init(blake2xs_state *S, const size_t outlen); + int blake2xs_init_key(blake2xs_state *S, const size_t outlen, const void *key, size_t keylen); + int blake2xs_update(blake2xs_state *S, const void *in, size_t inlen); + int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); + + int blake2xb_init(blake2xb_state *S, const size_t outlen); + int blake2xb_init_key(blake2xb_state *S, const size_t outlen, const void *key, size_t keylen); + int blake2xb_update(blake2xb_state *S, const void *in, size_t inlen); + int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); + + /* Simple API */ + int blake2s(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + + int blake2sp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + int blake2bp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + + int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + + /* This is simply an alias for blake2b */ + int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/blake2b.c b/bigpiseal3.5.1/native/src/seal/util/blake2b.c new file mode 100644 index 0000000000000000000000000000000000000000..cd38b1ba0083c4d8125b2f27e03498376946dc37 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/blake2b.c @@ -0,0 +1,379 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +#include "blake2.h" +#include "blake2-impl.h" + +static const uint64_t blake2b_IV[8] = +{ + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +static const uint8_t blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + + +static void blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = (uint64_t)-1; +} + +/* Some helper functions, not necessarily useful */ +static int blake2b_is_lastblock( const blake2b_state *S ) +{ + return S->f[0] != 0; +} + +static void blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = (uint64_t)-1; +} + +static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); +} + +static void blake2b_init0( blake2b_state *S ) +{ + size_t i; + memset( S, 0, sizeof( blake2b_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; +} + +/* init xors IV with input parameter block */ +int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) +{ + const uint8_t *p = ( const uint8_t * )( P ); + size_t i; + + blake2b_init0( S ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); + + S->outlen = P->digest_length; + return 0; +} + + + +int blake2b_init( blake2b_state *S, size_t outlen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2b_init_param( S, P ); +} + + +int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + + if( blake2b_init_param( S, P ) < 0 ) return -1; + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset( block, 0, BLAKE2B_BLOCKBYTES ); + memcpy( block, key, keylen ); + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while(0) + +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + +static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) +{ + uint64_t m[16]; + uint64_t v[16]; + size_t i; + + for( i = 0; i < 16; ++i ) { + m[i] = load64( block + i * sizeof( m[i] ) ); + } + + for( i = 0; i < 8; ++i ) { + v[i] = S->h[i]; + } + + v[ 8] = blake2b_IV[0]; + v[ 9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + ROUND( 10 ); + ROUND( 11 ); + + for( i = 0; i < 8; ++i ) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } +} + +#undef G +#undef ROUND + +int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + if( inlen > 0 ) + { + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + if( inlen > fill ) + { + S->buflen = 0; + memcpy( S->buf + left, in, fill ); /* Fill buffer */ + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + blake2b_compress( S, S->buf ); /* Compress */ + in += fill; inlen -= fill; + while(inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress( S, in ); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + memcpy( S->buf + S->buflen, in, inlen ); + S->buflen += inlen; + } + return 0; +} + +int blake2b_final( blake2b_state *S, void *out, size_t outlen ) +{ + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + size_t i; + + if( out == NULL || outlen < S->outlen ) + return -1; + + if( blake2b_is_lastblock( S ) ) + return -1; + + blake2b_increment_counter( S, S->buflen ); + blake2b_set_lastblock( S ); + memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ + blake2b_compress( S, S->buf ); + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + memcpy( out, buffer, S->outlen ); + secure_zero_memory(buffer, sizeof(buffer)); + return 0; +} + +/* inlen, at least, should be uint64_t. Others can be size_t. */ +int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + blake2b_state S[1]; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key && keylen > 0 ) return -1; + + if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; + + if( keylen > BLAKE2B_KEYBYTES ) return -1; + + if( keylen > 0 ) + { + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2b_init( S, outlen ) < 0 ) return -1; + } + + blake2b_update( S, ( const uint8_t * )in, inlen ); + blake2b_final( S, out, outlen ); + return 0; +} + +int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { + return blake2b(out, outlen, in, inlen, key, keylen); +} + +#if defined(SUPERCOP) +int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) +{ + return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 ); +} +#endif + +#if defined(BLAKE2B_SELFTEST) +#include <string.h> +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES ); + + if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2b_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2b_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/blake2xb.c b/bigpiseal3.5.1/native/src/seal/util/blake2xb.c new file mode 100644 index 0000000000000000000000000000000000000000..188bcb76175483875fffe70598c3b111fad40f6e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/blake2xb.c @@ -0,0 +1,262 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>. + Copyright 2016, Samuel Neves <sneves@dei.uc.pt>. + + You may use this under the terms of the CC0, the OpenSSL Licence, or + the Apache Public License 2.0, at your option. The terms of these + licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +/* +Minor modifications to the original file have been made and marked +as `EDIT: ...`. The sole purpose of these edits is to silence misleading +warnings in Visual Studio. +*/ + +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +#include "blake2.h" +#include "blake2-impl.h" + +int blake2xb_init( blake2xb_state *S, const size_t outlen ) { + return blake2xb_init_key(S, outlen, NULL, 0); +} + +int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen) +{ + if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) { + return -1; + } + + if (NULL != key && keylen > BLAKE2B_KEYBYTES) { + return -1; + } + + if (NULL == key && keylen > 0) { + return -1; + } + + /* Initialize parameter block */ + S->P->digest_length = BLAKE2B_OUTBYTES; + + /* + EDIT: explicit cast to silence warnings + */ + S->P->key_length = (uint8_t)keylen; + + S->P->fanout = 1; + S->P->depth = 1; + store32( &S->P->leaf_length, 0 ); + store32( &S->P->node_offset, 0 ); + + /* + EDIT: explicit cast to silence warnings + */ + store32( &S->P->xof_length, (uint32_t)outlen ); + + S->P->node_depth = 0; + S->P->inner_length = 0; + memset( S->P->reserved, 0, sizeof( S->P->reserved ) ); + memset( S->P->salt, 0, sizeof( S->P->salt ) ); + memset( S->P->personal, 0, sizeof( S->P->personal ) ); + + if( blake2b_init_param( S->S, S->P ) < 0 ) { + return -1; + } + + if (keylen > 0) { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset(block, 0, BLAKE2B_BLOCKBYTES); + memcpy(block, key, keylen); + blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES); + secure_zero_memory(block, BLAKE2B_BLOCKBYTES); + } + return 0; +} + +int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) { + return blake2b_update( S->S, in, inlen ); +} + +int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) { + + blake2b_state C[1]; + blake2b_param P[1]; + uint32_t xof_length = load32(&S->P->xof_length); + uint8_t root[BLAKE2B_BLOCKBYTES]; + size_t i; + + if (NULL == out) { + return -1; + } + + /* outlen must match the output size defined in xof_length, */ + /* unless it was -1, in which case anything goes except 0. */ + if(xof_length == 0xFFFFFFFFUL) { + if(outlen == 0) { + return -1; + } + } else { + if(outlen != xof_length) { + return -1; + } + } + + /* Finalize the root hash */ + if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) { + return -1; + } + + /* Set common block structure values */ + /* Copy values from parent instance, and only change the ones below */ + memcpy(P, S->P, sizeof(blake2b_param)); + P->key_length = 0; + P->fanout = 0; + P->depth = 0; + store32(&P->leaf_length, BLAKE2B_OUTBYTES); + P->inner_length = BLAKE2B_OUTBYTES; + P->node_depth = 0; + + for (i = 0; outlen > 0; ++i) { + const size_t block_size = (outlen < BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES; + /* Initialize state */ + + /* + EDIT: explicit cast to silence warnings. + */ + P->digest_length = (uint8_t)block_size; + store32(&P->node_offset, (uint32_t)i); + + blake2b_init_param(C, P); + /* Process key if needed */ + blake2b_update(C, root, BLAKE2B_OUTBYTES); + if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) { + return -1; + } + outlen -= block_size; + } + secure_zero_memory(root, sizeof(root)); + secure_zero_memory(P, sizeof(P)); + secure_zero_memory(C, sizeof(C)); + /* Put blake2xb in an invalid state? cf. blake2s_is_lastblock */ + return 0; + +} + +int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) +{ + blake2xb_state S[1]; + + /* Verify parameters */ + if (NULL == in && inlen > 0) + return -1; + + if (NULL == out) + return -1; + + if (NULL == key && keylen > 0) + return -1; + + if (keylen > BLAKE2B_KEYBYTES) + return -1; + + if (outlen == 0) + return -1; + + /* Initialize the root block structure */ + if (blake2xb_init_key(S, outlen, key, keylen) < 0) { + return -1; + } + + /* Absorb the input message */ + blake2xb_update(S, in, inlen); + + /* Compute the root node of the tree and the final hash using the counter construction */ + return blake2xb_final(S, out, outlen); +} + +#if defined(BLAKE2XB_SELFTEST) +#include <string.h> +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step, outlen; + + for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) { + key[i] = ( uint8_t )i; + } + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) { + buf[i] = ( uint8_t )i; + } + + /* Testing length of outputs rather than inputs */ + /* (Test of input lengths mostly covered by blake2b tests) */ + + /* Test simple API */ + for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen ) + { + uint8_t hash[BLAKE2_KAT_LENGTH] = {0}; + if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) { + goto fail; + } + + if( 0 != memcmp( hash, blake2xb_keyed_kat[outlen-1], outlen ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) { + uint8_t hash[BLAKE2_KAT_LENGTH]; + blake2xb_state S; + uint8_t * p = buf; + size_t mlen = BLAKE2_KAT_LENGTH; + int err = 0; + + if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2xb_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2xb_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2xb_final(&S, hash, outlen)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2xb_keyed_kat[outlen-1], outlen)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/cgmanifest.json b/bigpiseal3.5.1/native/src/seal/util/cgmanifest.json new file mode 100644 index 0000000000000000000000000000000000000000..338c5e12cc0433a23e04974b3117a417f78180a5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/cgmanifest.json @@ -0,0 +1,13 @@ +{ + "Registrations": [ + { + "component": { + "type": "git", + "git": { + "repositoryUrl": "https://github.com/BLAKE2/BLAKE2", + "commitHash": "997fa5ba1e14b52c554fb03ce39e579e6f27b90c" + } + } + } + ] +} diff --git a/bigpiseal3.5.1/native/src/seal/util/clang.h b/bigpiseal3.5.1/native/src/seal/util/clang.h new file mode 100644 index 0000000000000000000000000000000000000000..8eb6838581e93312de0f86c772c19cd5c69954a3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/clang.h @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#if SEAL_COMPILER == SEAL_COMPILER_CLANG + +// We require clang >= 5 +#if (__clang_major__ < 5) || not defined(__cplusplus) +#error "SEAL requires __clang_major__ >= 5" +#endif + +// Read in config.h +#include "seal/util/config.h" + +// Are intrinsics enabled? +#ifdef SEAL_USE_INTRIN +#include <x86intrin.h> + +#ifdef SEAL_USE___BUILTIN_CLZLL +#define SEAL_MSB_INDEX_UINT64(result, value) \ + { \ + *result = 63UL - static_cast<unsigned long>(__builtin_clzll(value)); \ + } +#endif + +#ifdef SEAL_USE___INT128 +__extension__ typedef __int128 int128_t; +__extension__ typedef unsigned __int128 uint128_t; +#define SEAL_MULTIPLY_UINT64_HW64(operand1, operand2, hw64) \ + { \ + *hw64 = static_cast<unsigned long long>( \ + ((static_cast<uint128_t>(operand1) * static_cast<uint128_t>(operand2)) >> 64)); \ + } + +#define SEAL_MULTIPLY_UINT64(operand1, operand2, result128) \ + { \ + uint128_t product = static_cast<uint128_t>(operand1) * operand2; \ + result128[0] = static_cast<unsigned long long>(product); \ + result128[1] = static_cast<unsigned long long>(product >> 64); \ + } + +#define SEAL_DIVIDE_UINT128_UINT64(numerator, denominator, result) \ + { \ + uint128_t n, q; \ + n = (static_cast<uint128_t>(numerator[1]) << 64) | (static_cast<uint128_t>(numerator[0])); \ + q = n / denominator; \ + n -= q * denominator; \ + numerator[0] = static_cast<std::uint64_t>(n); \ + numerator[1] = 0; \ + result[0] = static_cast<std::uint64_t>(q); \ + result[1] = static_cast<std::uint64_t>(q >> 64); \ + } +#endif + +#ifdef SEAL_USE__ADDCARRY_U64 +#define SEAL_ADD_CARRY_UINT64(operand1, operand2, carry, result) _addcarry_u64(carry, operand1, operand2, result) +#endif + +#ifdef SEAL_USE__SUBBORROW_U64 +#define SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result) _subborrow_u64(borrow, operand1, operand2, result) +#endif + +#endif // SEAL_USE_INTRIN + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/clipnormal.cpp b/bigpiseal3.5.1/native/src/seal/util/clipnormal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8734b7046c6b0f609e90082c7b4937a176b48d0 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/clipnormal.cpp @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/clipnormal.h" +#include <stdexcept> + +using namespace std; + +namespace seal +{ + namespace util + { + ClippedNormalDistribution::ClippedNormalDistribution( + result_type mean, result_type standard_deviation, result_type max_deviation) + : normal_(mean, standard_deviation), max_deviation_(max_deviation) + { + // Verify arguments. + if (standard_deviation < 0) + { + throw invalid_argument("standard_deviation"); + } + if (max_deviation < 0) + { + throw invalid_argument("max_deviation"); + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/clipnormal.h b/bigpiseal3.5.1/native/src/seal/util/clipnormal.h new file mode 100644 index 0000000000000000000000000000000000000000..58c823f0487dbcccb5ce44d2f4e4faa15c862f94 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/clipnormal.h @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include <cmath> +#include <random> + +namespace seal +{ + namespace util + { + class ClippedNormalDistribution + { + public: + using result_type = double; + + using param_type = ClippedNormalDistribution; + + ClippedNormalDistribution(result_type mean, result_type standard_deviation, result_type max_deviation); + + template <typename RNG> + SEAL_NODISCARD inline result_type operator()(RNG &engine, const param_type &parm) noexcept + { + param(parm); + return operator()(engine); + } + + template <typename RNG> + SEAL_NODISCARD inline result_type operator()(RNG &engine) noexcept + { + result_type mean = normal_.mean(); + while (true) + { + result_type value = normal_(engine); + result_type deviation = std::abs(value - mean); + if (deviation <= max_deviation_) + { + return value; + } + } + } + + SEAL_NODISCARD inline result_type mean() const noexcept + { + return normal_.mean(); + } + + SEAL_NODISCARD inline result_type standard_deviation() const noexcept + { + return normal_.stddev(); + } + + SEAL_NODISCARD inline result_type max_deviation() const noexcept + { + return max_deviation_; + } + + SEAL_NODISCARD inline result_type min() const noexcept + { + return normal_.mean() - max_deviation_; + } + + SEAL_NODISCARD inline result_type max() const noexcept + { + return normal_.mean() + max_deviation_; + } + + SEAL_NODISCARD inline param_type param() const noexcept + { + return *this; + } + + inline void param(const param_type &parm) noexcept + { + *this = parm; + } + + inline void reset() noexcept + { + normal_.reset(); + } + + private: + std::normal_distribution<result_type> normal_; + + result_type max_deviation_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/common.h b/bigpiseal3.5.1/native/src/seal/util/common.h new file mode 100644 index 0000000000000000000000000000000000000000..979e257c4e704eac5654f22277c71e10088eb40c --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/common.h @@ -0,0 +1,568 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include <algorithm> +#include <cmath> +#include <cstdint> +#include <limits> +#include <stdexcept> +#include <type_traits> +#include <vector> + +namespace seal +{ + namespace util + { + template <typename T, typename...> + struct is_uint64 + : std::conditional< + std::is_integral<T>::value && std::is_unsigned<T>::value && (sizeof(T) == sizeof(std::uint64_t)), + std::true_type, std::false_type>::type + {}; + + template <typename T, typename U, typename... Rest> + struct is_uint64<T, U, Rest...> + : std::conditional< + is_uint64<T>::value && is_uint64<U, Rest...>::value, std::true_type, std::false_type>::type + {}; + + template <typename T, typename... Rest> + constexpr bool is_uint64_v = is_uint64<T, Rest...>::value; + + template <typename T, typename...> + struct is_uint32 + : std::conditional< + std::is_integral<T>::value && std::is_unsigned<T>::value && (sizeof(T) == sizeof(std::uint32_t)), + std::true_type, std::false_type>::type + {}; + + template <typename T, typename U, typename... Rest> + struct is_uint32<T, U, Rest...> + : std::conditional< + is_uint32<T>::value && is_uint32<U, Rest...>::value, std::true_type, std::false_type>::type + {}; + + template <typename T, typename... Rest> + constexpr bool is_uint32_v = is_uint32<T, Rest...>::value; + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_lt(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) < static_cast<std::uint64_t>(in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_leq(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) <= static_cast<std::uint64_t>(in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_gt(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) > static_cast<std::uint64_t>(in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_geq(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) >= static_cast<std::uint64_t>(in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_eq(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) == static_cast<std::uint64_t>(in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>, + typename = std::enable_if_t<std::is_integral<S>::value>> + SEAL_NODISCARD inline constexpr bool unsigned_neq(T in1, S in2) noexcept + { + return static_cast<std::uint64_t>(in1) != static_cast<std::uint64_t>(in2); + } + + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> + SEAL_NODISCARD inline constexpr T mul_safe(T in1) noexcept + { + return in1; + } + + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> + SEAL_NODISCARD inline constexpr T mul_safe(T in1, T in2) + { + SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value) + { + if (in1 && (in2 > std::numeric_limits<T>::max() / in1)) + { + throw std::logic_error("unsigned overflow"); + } + } + else + { + // Positive inputs + if ((in1 > 0) && (in2 > 0) && (in2 > std::numeric_limits<T>::max() / in1)) + { + throw std::logic_error("signed overflow"); + } +#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) && !defined(SEAL_USE_IF_CONSTEXPR) +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + // Negative inputs + else if ((in1 < 0) && (in2 < 0) && ((-in2) > std::numeric_limits<T>::max() / (-in1))) + { + throw std::logic_error("signed overflow"); + } + // Negative in1; positive in2 + else if ((in1 < 0) && (in2 > 0) && (in2 > std::numeric_limits<T>::max() / (-in1))) + { + throw std::logic_error("signed underflow"); + } +#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) && !defined(SEAL_USE_IF_CONSTEXPR) +#pragma warning(pop) +#endif + // Positive in1; negative in2 + else if ((in1 > 0) && (in2 < 0) && (in2 < std::numeric_limits<T>::min() / in1)) + { + throw std::logic_error("signed underflow"); + } + } + return static_cast<T>(in1 * in2); + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_integral<T>::value>> + SEAL_NODISCARD inline constexpr T mul_safe(T in1, T in2, Args &&... args) + { + return mul_safe(mul_safe(in1, in2), mul_safe(std::forward<Args>(args)...)); + } + + template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr T add_safe(T in1) noexcept + { + return in1; + } + + template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr T add_safe(T in1, T in2) + { + SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value) + { + if (in2 > std::numeric_limits<T>::max() - in1) + { + throw std::logic_error("unsigned overflow"); + } + } + else + { + if (in1 > 0 && (in2 > std::numeric_limits<T>::max() - in1)) + { + throw std::logic_error("signed overflow"); + } + else if (in1 < 0 && (in2 < std::numeric_limits<T>::min() - in1)) + { + throw std::logic_error("signed underflow"); + } + } + return static_cast<T>(in1 + in2); + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr T add_safe(T in1, T in2, Args &&... args) + { + return add_safe(add_safe(in1, in2), add_safe(std::forward<Args>(args)...)); + } + + template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline T sub_safe(T in1, T in2) + { + SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value) + { + if (in1 < in2) + { + throw std::logic_error("unsigned underflow"); + } + } + else + { + if (in1 < 0 && (in2 > std::numeric_limits<T>::max() + in1)) + { + throw std::logic_error("signed underflow"); + } + else if (in1 > 0 && (in2 < std::numeric_limits<T>::min() + in1)) + { + throw std::logic_error("signed overflow"); + } + } + return static_cast<T>(in1 - in2); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_arithmetic<T>::value>, + typename = std::enable_if_t<std::is_arithmetic<S>::value>> + SEAL_NODISCARD inline constexpr bool fits_in(S value SEAL_MAYBE_UNUSED) noexcept + { + SEAL_IF_CONSTEXPR(std::is_same<T, S>::value) + { + // Same type + return true; + } + + SEAL_IF_CONSTEXPR(sizeof(S) <= sizeof(T)) + { + // Converting to bigger type + SEAL_IF_CONSTEXPR(std::is_integral<T>::value && std::is_integral<S>::value) + { + // Converting to at least equally big integer type + SEAL_IF_CONSTEXPR( + (std::is_unsigned<T>::value && std::is_unsigned<S>::value) || + (!std::is_unsigned<T>::value && !std::is_unsigned<S>::value)) + { + // Both either signed or unsigned + return true; + } + else SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value && std::is_signed<S>::value) + { + // Converting from signed to at least equally big unsigned type + return value >= 0; + } + } + else SEAL_IF_CONSTEXPR(std::is_floating_point<T>::value && std::is_floating_point<S>::value) + { + // Both floating-point + return true; + } + + // Still need to consider integer-float conversions and all + // unsigned to signed conversions + } + + SEAL_IF_CONSTEXPR(std::is_integral<T>::value && std::is_integral<S>::value) + { + // Both integer types + if (value >= 0) + { + // Non-negative number; compare as std::uint64_t + // Cannot use unsigned_leq with C++14 for lack of `if constexpr' + return static_cast<std::uint64_t>(value) <= + static_cast<std::uint64_t>(std::numeric_limits<T>::max()); + } + else + { + // Negative number; compare as std::int64_t + return ( + static_cast<std::int64_t>(value) >= static_cast<std::int64_t>(std::numeric_limits<T>::min())); + } + } + else SEAL_IF_CONSTEXPR(std::is_floating_point<T>::value) + { + // Converting to floating-point + return (static_cast<double>(value) <= static_cast<double>(std::numeric_limits<T>::max())) && + (static_cast<double>(value) >= -static_cast<double>(std::numeric_limits<T>::max())); + } + else + { + // Converting from floating-point + return (static_cast<double>(value) <= static_cast<double>(std::numeric_limits<T>::max())) && + (static_cast<double>(value) >= static_cast<double>(std::numeric_limits<T>::min())); + } + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr bool sum_fits_in(Args &&... args) + { + return fits_in<T>(add_safe(std::forward<Args>(args)...)); + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr bool sum_fits_in(T in1, Args &&... args) + { + return fits_in<T>(add_safe(in1, std::forward<Args>(args)...)); + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr bool product_fits_in(Args &&... args) + { + return fits_in<T>(mul_safe(std::forward<Args>(args)...)); + } + + template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>> + SEAL_NODISCARD inline constexpr bool product_fits_in(T in1, Args &&... args) + { + return fits_in<T>(mul_safe(in1, std::forward<Args>(args)...)); + } + + template < + typename T, typename S, typename = std::enable_if_t<std::is_arithmetic<T>::value>, + typename = std::enable_if_t<std::is_arithmetic<S>::value>> + SEAL_NODISCARD inline T safe_cast(S value) + { + SEAL_IF_CONSTEXPR(!std::is_same<T, S>::value) + { + if (!fits_in<T>(value)) + { + throw std::logic_error("cast failed"); + } + } + return static_cast<T>(value); + } + + constexpr int bytes_per_uint64 = sizeof(std::uint64_t); + + constexpr int bytes_per_uint32 = sizeof(std::uint32_t); + + constexpr int uint32_per_uint64 = 2; + + constexpr int bits_per_nibble = 4; + + constexpr int bits_per_byte = 8; + + constexpr int bits_per_uint64 = bytes_per_uint64 * bits_per_byte; + + constexpr int bits_per_uint32 = bytes_per_uint32 * bits_per_byte; + + constexpr int nibbles_per_byte = 2; + + constexpr int nibbles_per_uint64 = bytes_per_uint64 * nibbles_per_byte; + + constexpr std::uint64_t uint64_high_bit = std::uint64_t(1) << (bits_per_uint64 - 1); + + template <typename T, typename = std::enable_if_t<is_uint32_v<T> || is_uint64_v<T>>> + SEAL_NODISCARD inline constexpr T reverse_bits(T operand) noexcept + { + SEAL_IF_CONSTEXPR(is_uint32_v<T>) + { + operand = (((operand & T(0xaaaaaaaa)) >> 1) | ((operand & T(0x55555555)) << 1)); + operand = (((operand & T(0xcccccccc)) >> 2) | ((operand & T(0x33333333)) << 2)); + operand = (((operand & T(0xf0f0f0f0)) >> 4) | ((operand & T(0x0f0f0f0f)) << 4)); + operand = (((operand & T(0xff00ff00)) >> 8) | ((operand & T(0x00ff00ff)) << 8)); + return static_cast<T>(operand >> 16) | static_cast<T>(operand << 16); + } + else SEAL_IF_CONSTEXPR(is_uint64_v<T>) + { +// Temporarily disable UB warnings when `if constexpr` is not available. +#ifndef SEAL_USE_IF_CONSTEXPR +#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) +#pragma warning(push) +#pragma warning(disable : 4293) +#elif (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshift-count-overflow" +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshift-count-overflow" +#endif +#endif + return static_cast<T>(reverse_bits(static_cast<std::uint32_t>(operand >> 32))) | + (static_cast<T>(reverse_bits(static_cast<std::uint32_t>(operand & T(0xFFFFFFFF)))) << 32); +#ifndef SEAL_USE_IF_CONSTEXPR +#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) +#pragma warning(pop) +#elif (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic pop +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic pop +#endif +#endif + } + } + + template <typename T, typename = std::enable_if_t<is_uint32_v<T> || is_uint64_v<T>>> + SEAL_NODISCARD inline T reverse_bits(T operand, int bit_count) + { +#ifdef SEAL_DEBUG + if (bit_count < 0 || + static_cast<std::size_t>(bit_count) > mul_safe(sizeof(T), static_cast<std::size_t>(bits_per_byte))) + { + throw std::invalid_argument("bit_count"); + } +#endif + // Just return zero if bit_count is zero + return (bit_count == 0) ? T(0) + : reverse_bits(operand) >> (sizeof(T) * static_cast<std::size_t>(bits_per_byte) - + static_cast<std::size_t>(bit_count)); + } + + inline void get_msb_index_generic(unsigned long *result, std::uint64_t value) + { +#ifdef SEAL_DEBUG + if (result == nullptr) + { + throw std::invalid_argument("result"); + } +#endif + static const unsigned long deBruijnTable64[64] = { 63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, + 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, + 34, 11, 43, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, + 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31, + 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5 }; + + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value |= value >> 32; + + *result = deBruijnTable64[((value - (value >> 1)) * std::uint64_t(0x07EDD5E59A4E28C2)) >> 58]; + } + + SEAL_NODISCARD inline int get_significant_bit_count(std::uint64_t value) + { + if (value == 0) + { + return 0; + } + + unsigned long result; + SEAL_MSB_INDEX_UINT64(&result, value); + return static_cast<int>(result + 1); + } + + SEAL_NODISCARD inline bool is_hex_char(char hex) + { + if (hex >= '0' && hex <= '9') + { + return true; + } + if (hex >= 'A' && hex <= 'F') + { + return true; + } + if (hex >= 'a' && hex <= 'f') + { + return true; + } + return false; + } + + SEAL_NODISCARD inline char nibble_to_upper_hex(int nibble) + { +#ifdef SEAL_DEBUG + if (nibble < 0 || nibble > 15) + { + throw std::invalid_argument("nibble"); + } +#endif + if (nibble < 10) + { + return static_cast<char>(nibble + static_cast<int>('0')); + } + return static_cast<char>(nibble + static_cast<int>('A') - 10); + } + + SEAL_NODISCARD inline int hex_to_nibble(char hex) + { + if (hex >= '0' && hex <= '9') + { + return static_cast<int>(hex) - static_cast<int>('0'); + } + if (hex >= 'A' && hex <= 'F') + { + return static_cast<int>(hex) - static_cast<int>('A') + 10; + } + if (hex >= 'a' && hex <= 'f') + { + return static_cast<int>(hex) - static_cast<int>('a') + 10; + } +#ifdef SEAL_DEBUG + throw std::invalid_argument("hex"); +#endif + return -1; + } + + SEAL_NODISCARD inline SEAL_BYTE *get_uint64_byte(std::uint64_t *value, std::size_t byte_index) + { +#ifdef SEAL_DEBUG + if (value == nullptr) + { + throw std::invalid_argument("value"); + } +#endif + return reinterpret_cast<SEAL_BYTE *>(value) + byte_index; + } + + SEAL_NODISCARD inline const SEAL_BYTE *get_uint64_byte(const std::uint64_t *value, std::size_t byte_index) + { +#ifdef SEAL_DEBUG + if (value == nullptr) + { + throw std::invalid_argument("value"); + } +#endif + return reinterpret_cast<const SEAL_BYTE *>(value) + byte_index; + } + + SEAL_NODISCARD inline int get_hex_string_bit_count(const char *hex_string, int char_count) + { +#ifdef SEAL_DEBUG + if (hex_string == nullptr && char_count > 0) + { + throw std::invalid_argument("hex_string"); + } + if (char_count < 0) + { + throw std::invalid_argument("char_count"); + } +#endif + for (int i = 0; i < char_count; i++) + { + char hex = *hex_string++; + int nibble = hex_to_nibble(hex); + if (nibble != 0) + { + int nibble_bits = get_significant_bit_count(static_cast<std::uint64_t>(nibble)); + int remaining_nibbles = (char_count - i - 1) * bits_per_nibble; + return nibble_bits + remaining_nibbles; + } + } + return 0; + } + + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> + SEAL_NODISCARD inline T divide_round_up(T value, T divisor) + { +#ifdef SEAL_DEBUG + if (value < 0) + { + throw std::invalid_argument("value"); + } + if (divisor <= 0) + { + throw std::invalid_argument("divisor"); + } +#endif + return (add_safe(value, divisor - 1)) / divisor; + } + + template <typename T> + constexpr double epsilon = std::numeric_limits<T>::epsilon(); + + template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>> + SEAL_NODISCARD inline bool are_close(T value1, T value2) noexcept + { + double scale_factor = std::max<T>({ std::fabs(value1), std::fabs(value2), T{ 1.0 } }); + return std::fabs(value1 - value2) < epsilon<T> * scale_factor; + } + + template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>> + SEAL_NODISCARD inline constexpr bool is_zero(T value) noexcept + { + return value == T{ 0 }; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/config.h.in b/bigpiseal3.5.1/native/src/seal/util/config.h.in new file mode 100644 index 0000000000000000000000000000000000000000..473233975b5b53ad52164a50a37a66157b999bce --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/config.h.in @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#define SEAL_VERSION "@SEAL_VERSION@" +#define SEAL_VERSION_MAJOR @SEAL_VERSION_MAJOR@ +#define SEAL_VERSION_MINOR @SEAL_VERSION_MINOR@ +#define SEAL_VERSION_PATCH @SEAL_VERSION_PATCH@ + +// Are we in debug mode? +#cmakedefine SEAL_DEBUG + +// C++17 features +#cmakedefine SEAL_USE_STD_BYTE +#cmakedefine SEAL_USE_SHARED_MUTEX +#cmakedefine SEAL_USE_IF_CONSTEXPR +#cmakedefine SEAL_USE_MAYBE_UNUSED +#cmakedefine SEAL_USE_NODISCARD +#cmakedefine SEAL_USE_STD_FOR_EACH_N + +// Security +#cmakedefine SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + +// Intrinsics +#cmakedefine SEAL_USE_INTRIN +#cmakedefine SEAL_USE__UMUL128 +#cmakedefine SEAL_USE__BITSCANREVERSE64 +#cmakedefine SEAL_USE___BUILTIN_CLZLL +#cmakedefine SEAL_USE___INT128 +#cmakedefine SEAL_USE__ADDCARRY_U64 +#cmakedefine SEAL_USE__SUBBORROW_U64 + +// Third-party dependencies +#cmakedefine SEAL_USE_MSGSL +#cmakedefine SEAL_USE_ZLIB diff --git a/bigpiseal3.5.1/native/src/seal/util/croots.cpp b/bigpiseal3.5.1/native/src/seal/util/croots.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68151fdebcdeab4c719e92143c9a1cc55aa2e440 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/croots.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/croots.h" +#include <complex> +#include <iostream> +using namespace std; + +namespace seal +{ + namespace util + { + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr double ComplexRoots::PI_; + + ComplexRoots::ComplexRoots(size_t degree_of_roots, MemoryPoolHandle pool) + : degree_of_roots_(degree_of_roots), pool_(std::move(pool)) + { +#ifdef SEAL_DEBUG + int power = util::get_power_of_two(degree_of_roots_); + if (power < 0) + { + throw std::invalid_argument("degree_of_roots must be a power of two"); + } + else if (power < 3) + { + throw std::invalid_argument("degree_of_roots must be at least 8"); + } +#endif + roots_ = allocate<complex<double>>(degree_of_roots_ / 8 + 1, pool_); + + // Generate 1/8 of all roots. + // Alternatively, choose from precomputed high-precision roots in files. + for (size_t i = 0; i <= degree_of_roots_ / 8; i++) + { + roots_[i] = + std::polar<double>(1.0, 2 * PI_ * static_cast<double>(i) / static_cast<double>(degree_of_roots_)); + } + } + + SEAL_NODISCARD complex<double> ComplexRoots::get_root(size_t index) const + { + index &= degree_of_roots_ - 1; + auto mirror = [](complex<double> a) { + return complex<double>{ a.imag(), a.real() }; + }; + + // This express the 8-fold symmetry of all n-th roots. + if (index <= degree_of_roots_ / 8) + { + return roots_[index]; + } + else if (index <= degree_of_roots_ / 4) + { + return mirror(roots_[degree_of_roots_ / 4 - index]); + } + else if (index <= degree_of_roots_ / 2) + { + return -conj(get_root(degree_of_roots_ / 2 - index)); + } + else if (index <= 3 * degree_of_roots_ / 4) + { + return -get_root(index - degree_of_roots_ / 2); + } + else + { + return conj(get_root(degree_of_roots_ - index)); + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/croots.h b/bigpiseal3.5.1/native/src/seal/util/croots.h new file mode 100644 index 0000000000000000000000000000000000000000..4861fb914e18f037df59f9432e9029b0d4acd0e5 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/croots.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/util/defines.h" +#include "seal/util/uintcore.h" +#include <complex> +#include <cstddef> +#include <stdexcept> + +namespace seal +{ + namespace util + { + class ComplexRoots + { + public: + ComplexRoots() = delete; + + ComplexRoots(std::size_t degree_of_roots, MemoryPoolHandle pool); + + SEAL_NODISCARD std::complex<double> get_root(std::size_t index) const; + + private: + static constexpr double PI_ = 3.1415926535897932384626433832795028842; + + // Contains 0~(n/8-1)-th powers of the n-th primitive root. + util::Pointer<std::complex<double>> roots_; + + std::size_t degree_of_roots_; + + MemoryPoolHandle pool_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/defines.h b/bigpiseal3.5.1/native/src/seal/util/defines.h new file mode 100644 index 0000000000000000000000000000000000000000..399e1b7fcf31167a2d1736d4f0664c0b43db3e4f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/defines.h @@ -0,0 +1,190 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// Debugging help +#define SEAL_ASSERT(condition) \ + { \ + if (!(condition)) \ + { \ + std::cerr << "ASSERT FAILED: " << #condition << " @ " << __FILE__ << " (" << __LINE__ << ")" << std::endl; \ + } \ + } + +// String expansion +#define _SEAL_STRINGIZE(x) #x +#define SEAL_STRINGIZE(x) _SEAL_STRINGIZE(x) + +// Check that double is 64 bits +static_assert(sizeof(double) == 8, "Require sizeof(double) == 8"); + +// Check that int is 32 bits +static_assert(sizeof(int) == 4, "Require sizeof(int) == 4"); + +// Check that unsigned long long is 64 bits +static_assert(sizeof(unsigned long long) == 8, "Require sizeof(unsigned long long) == 8"); + +// Bounds for bit-length of all coefficient moduli +#define SEAL_MOD_BIT_COUNT_MAX 61 +#define SEAL_MOD_BIT_COUNT_MIN 2 + +// Bit-length of internally used coefficient moduli, e.g., auxiliary base in BFV +#define SEAL_INTERNAL_MOD_BIT_COUNT 61 + +// Bounds for bit-length of user-defined coefficient moduli +#define SEAL_USER_MOD_BIT_COUNT_MAX 60 +#define SEAL_USER_MOD_BIT_COUNT_MIN 2 + +// Bounds for bit-length of the plaintext modulus +#define SEAL_PLAIN_MOD_BIT_COUNT_MAX SEAL_USER_MOD_BIT_COUNT_MAX +#define SEAL_PLAIN_MOD_BIT_COUNT_MIN SEAL_USER_MOD_BIT_COUNT_MIN + +// Bounds for number of coefficient moduli (no hard requirement) +#define SEAL_COEFF_MOD_COUNT_MAX 64 +#define SEAL_COEFF_MOD_COUNT_MIN 1 + +// Bounds for polynomial modulus degree (no hard requirement) +#define SEAL_POLY_MOD_DEGREE_MAX 131072 +#define SEAL_POLY_MOD_DEGREE_MIN 2 + +// Upper bound on the size of a ciphertext (no hard requirement) +#define SEAL_CIPHERTEXT_SIZE_MAX 16 +#define SEAL_CIPHERTEXT_SIZE_MIN 2 + +// How many pairs of modular integers can we multiply and accumulate in a 128-bit data type +#if SEAL_MOD_BIT_COUNT_MAX > 32 +#define SEAL_MULTIPLY_ACCUMULATE_MOD_MAX (1 << (128 - (SEAL_MOD_BIT_COUNT_MAX << 1))) +#define SEAL_MULTIPLY_ACCUMULATE_INTERNAL_MOD_MAX (1 << (128 - (SEAL_INTERNAL_MOD_BIT_COUNT_MAX << 1))) +#define SEAL_MULTIPLY_ACCUMULATE_USER_MOD_MAX (1 << (128 - (SEAL_USER_MOD_BIT_COUNT_MAX << 1))) +#else +#define SEAL_MULTIPLY_ACCUMULATE_MOD_MAX SIZE_MAX +#define SEAL_MULTIPLY_ACCUMULATE_INTERNAL_MOD_MAX SIZE_MAX +#define SEAL_MULTIPLY_ACCUMULATE_USER_MOD_MAX SIZE_MAX +#endif + +// Detect system +#define SEAL_SYSTEM_OTHER 1 +#define SEAL_SYSTEM_WINDOWS 2 +#define SEAL_SYSTEM_UNIX_LIKE 3 + +#if defined(_WIN32) +#define SEAL_SYSTEM SEAL_SYSTEM_WINDOWS +#elif defined(__linux__) || defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)) +#define SEAL_SYSTEM SEAL_SYSTEM_UNIX_LIKE +#else +#define SEAL_SYSTEM SEAL_SYSTEM_OTHER +#error "Unsupported system" +#endif + +// Detect compiler +#define SEAL_COMPILER_MSVC 1 +#define SEAL_COMPILER_CLANG 2 +#define SEAL_COMPILER_GCC 3 + +#if defined(_MSC_VER) +#define SEAL_COMPILER SEAL_COMPILER_MSVC +#elif defined(__clang__) +#define SEAL_COMPILER SEAL_COMPILER_CLANG +#elif defined(__GNUC__) && !defined(__clang__) +#define SEAL_COMPILER SEAL_COMPILER_GCC +#else +#error "Unsupported compiler" +#endif + +// MSVC support +#include "seal/util/msvc.h" + +// clang support +#include "seal/util/clang.h" + +// gcc support +#include "seal/util/gcc.h" + +// Create a true/false value for indicating debug mode +#ifdef SEAL_DEBUG +#define SEAL_DEBUG_V true +#else +#define SEAL_DEBUG_V false +#endif + +// Use std::byte as byte type +#ifdef SEAL_USE_STD_BYTE +#include <cstddef> +namespace seal +{ + using SEAL_BYTE = std::byte; +} +#else +namespace seal +{ + enum class SEAL_BYTE : unsigned char + { + }; +} +#endif + +// Use `if constexpr' from C++17 +#ifdef SEAL_USE_IF_CONSTEXPR +#define SEAL_IF_CONSTEXPR if constexpr +#else +#define SEAL_IF_CONSTEXPR if +#endif + +// Use [[maybe_unused]] from C++17 +#ifdef SEAL_USE_MAYBE_UNUSED +#define SEAL_MAYBE_UNUSED [[maybe_unused]] +#else +#define SEAL_MAYBE_UNUSED +#endif + +// Use [[nodiscard]] from C++17 +#ifdef SEAL_USE_NODISCARD +#define SEAL_NODISCARD [[nodiscard]] +#else +#define SEAL_NODISCARD +#endif + +// Which random number generator factory to use by default +#define SEAL_DEFAULT_RNG_FACTORY BlakePRNGFactory() + +// Use generic functions as (slower) fallback +#ifndef SEAL_ADD_CARRY_UINT64 +#define SEAL_ADD_CARRY_UINT64(operand1, operand2, carry, result) add_uint64_generic(operand1, operand2, carry, result) +#endif + +#ifndef SEAL_SUB_BORROW_UINT64 +#define SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result) \ + sub_uint64_generic(operand1, operand2, borrow, result) +#endif + +#ifndef SEAL_MULTIPLY_UINT64 +#define SEAL_MULTIPLY_UINT64(operand1, operand2, result128) \ + { \ + multiply_uint64_generic(operand1, operand2, result128); \ + } +#endif + +#ifndef SEAL_DIVIDE_UINT128_UINT64 +#define SEAL_DIVIDE_UINT128_UINT64(numerator, denominator, result) \ + { \ + divide_uint128_uint64_inplace_generic(numerator, denominator, result); \ + } +#endif + +#ifndef SEAL_MULTIPLY_UINT64_HW64 +#define SEAL_MULTIPLY_UINT64_HW64(operand1, operand2, hw64) \ + { \ + multiply_uint64_hw64_generic(operand1, operand2, hw64); \ + } +#endif + +#ifndef SEAL_MSB_INDEX_UINT64 +#define SEAL_MSB_INDEX_UINT64(result, value) get_msb_index_generic(result, value) +#endif + +// Check whether an object is of expected type; this requires the type_traits header to be included +#define SEAL_ASSERT_TYPE(obj, expected, message) \ + static_assert( \ + std::is_same<decltype(obj), expected>::value, \ + "In " __FILE__ ":" SEAL_STRINGIZE(__LINE__) " expected " SEAL_STRINGIZE(expected) " (message: " message ")"); diff --git a/bigpiseal3.5.1/native/src/seal/util/galois.cpp b/bigpiseal3.5.1/native/src/seal/util/galois.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1c3788b67749c8b7c69917e7e2ec4604f39425e --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/galois.cpp @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/galois.h" +#include "seal/util/numth.h" +#include "seal/util/uintcore.h" + +using namespace std; + +namespace seal +{ + namespace util + { + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr uint32_t GaloisTool::generator_; + + void GaloisTool::generate_table_ntt(uint32_t galois_elt, Pointer<uint32_t> &result) + { +#ifdef SEAL_DEBUG + if (!(galois_elt & 1) || (galois_elt >= 2 * (uint64_t(1) << coeff_count_power_))) + { + throw std::invalid_argument("Galois element is not valid"); + } +#endif + ReaderLock reader_lock(permutation_tables_locker_.acquire_read()); + if (result) + { + return; + } + reader_lock.unlock(); + + WriterLock writer_lock(permutation_tables_locker_.acquire_write()); + result = allocate<uint32_t>(coeff_count_, pool_); + auto result_ptr = result.get(); + + uint32_t coeff_count_minus_one = safe_cast<uint32_t>(coeff_count_) - 1; + for (size_t i = coeff_count_; i < coeff_count_ << 1; i++) + { + uint32_t reversed = reverse_bits<uint32_t>(safe_cast<uint32_t>(i), coeff_count_power_ + 1); + uint64_t index_raw = (static_cast<uint64_t>(galois_elt) * static_cast<uint64_t>(reversed)) >> 1; + index_raw &= static_cast<uint64_t>(coeff_count_minus_one); + *result_ptr++ = reverse_bits<uint32_t>(static_cast<uint32_t>(index_raw), coeff_count_power_); + } + writer_lock.unlock(); + return; + } + + uint32_t GaloisTool::get_elt_from_step(int step) const + { + uint32_t n = safe_cast<uint32_t>(coeff_count_); + uint32_t m32 = mul_safe(n, uint32_t(2)); + uint64_t m = static_cast<uint64_t>(m32); + + if (step == 0) + { + return static_cast<uint32_t>(m - 1); + } + else + { + // Extract sign of steps. When steps is positive, the rotation + // is to the left; when steps is negative, it is to the right. + bool sign = step < 0; + uint32_t pos_step = safe_cast<uint32_t>(abs(step)); + + if (pos_step >= (n >> 1)) + { + throw invalid_argument("step count too large"); + } + + pos_step &= m32 - 1; + if (sign) + { + step = safe_cast<int>(n >> 1) - safe_cast<int>(pos_step); + } + else + { + step = safe_cast<int>(pos_step); + } + + // Construct Galois element for row rotation + uint64_t gen = static_cast<uint64_t>(generator_); + uint64_t galois_elt = 1; + while (step--) + { + galois_elt *= gen; + galois_elt &= m - 1; + } + return static_cast<uint32_t>(galois_elt); + } + } + + vector<uint32_t> GaloisTool::get_elts_from_steps(const vector<int> &steps) const + { + vector<uint32_t> galois_elts; + transform(steps.begin(), steps.end(), back_inserter(galois_elts), [&](auto s) { + return this->get_elt_from_step(s); + }); + return galois_elts; + } + + vector<uint32_t> GaloisTool::get_elts_all() const noexcept + { + uint32_t m = safe_cast<uint32_t>(static_cast<uint64_t>(coeff_count_) << 1); + vector<uint32_t> galois_elts{}; + + // Generate Galois keys for m - 1 (X -> X^{m-1}) + galois_elts.push_back(m - 1); + + // Generate Galois key for power of generator_ mod m (X -> X^{3^k}) and + // for negative power of generator_ mod m (X -> X^{-3^k}) + uint64_t pos_power = generator_; + uint64_t neg_power = 0; + try_invert_uint_mod(generator_, m, neg_power); + for (int i = 0; i < coeff_count_power_ - 1; i++) + { + galois_elts.push_back(static_cast<uint32_t>(pos_power)); + pos_power *= pos_power; + pos_power &= (m - 1); + + galois_elts.push_back(static_cast<uint32_t>(neg_power)); + neg_power *= neg_power; + neg_power &= (m - 1); + } + + return galois_elts; + } + + void GaloisTool::initialize(int coeff_count_power) + { + if ((coeff_count_power < get_power_of_two(SEAL_POLY_MOD_DEGREE_MIN)) || + coeff_count_power > get_power_of_two(SEAL_POLY_MOD_DEGREE_MAX)) + { + throw invalid_argument("coeff_count_power out of range"); + } + + coeff_count_power_ = coeff_count_power; + coeff_count_ = size_t(1) << coeff_count_power_; + + // Capacity for coeff_count_ number of tables + permutation_tables_ = allocate<Pointer<uint32_t>>(coeff_count_, pool_); + } + + void GaloisTool::apply_galois( + const uint64_t *operand, uint32_t galois_elt, const Modulus &modulus, uint64_t *result) const + { +#ifdef SEAL_DEBUG + if (operand == nullptr) + { + throw std::invalid_argument("operand"); + } + if (result == nullptr) + { + throw std::invalid_argument("result"); + } + if (operand == result) + { + throw std::invalid_argument("result cannot point to the same value as operand"); + } + // Verify coprime conditions. + if (!(galois_elt & 1) || (galois_elt >= 2 * (uint64_t(1) << coeff_count_power_))) + { + throw std::invalid_argument("Galois element is not valid"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } +#endif + const uint64_t modulus_value = modulus.value(); + uint64_t coeff_count_minus_one = (uint64_t(1) << coeff_count_power_) - 1; + for (uint64_t i = 0; i <= coeff_count_minus_one; i++) + { + uint64_t index_raw = i * galois_elt; + uint64_t index = index_raw & coeff_count_minus_one; + uint64_t result_value = *operand++; + if ((index_raw >> coeff_count_power_) & 1) + { + // Explicit inline + // result[index] = negate_uint_mod(result[index], modulus); + int64_t non_zero = (result_value != 0); + result_value = (modulus_value - result_value) & static_cast<uint64_t>(-non_zero); + } + result[index] = result_value; + } + } + + void GaloisTool::apply_galois_ntt(const uint64_t *operand, uint32_t galois_elt, uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand == nullptr) + { + throw std::invalid_argument("operand"); + } + if (result == nullptr) + { + throw std::invalid_argument("result"); + } + if (operand == result) + { + throw std::invalid_argument("result cannot point to the same value as operand"); + } + // Verify coprime conditions. + if (!(galois_elt & 1) || (galois_elt >= 2 * (uint64_t(1) << coeff_count_power_))) + { + throw std::invalid_argument("Galois element is not valid"); + } +#endif + generate_table_ntt(galois_elt, permutation_tables_[GetIndexFromElt(galois_elt)]); + + auto &table = permutation_tables_[GetIndexFromElt(galois_elt)]; + // Perform permutation. + for (size_t i = 0; i < coeff_count_; i++) + { + result[i] = operand[table[i]]; + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/galois.h b/bigpiseal3.5.1/native/src/seal/util/galois.h new file mode 100644 index 0000000000000000000000000000000000000000..ebfdcb337c9582aaa9099e6f25219d5fabd42fa9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/galois.h @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/util/pointer.h" +#include <cstddef> +#include <cstdint> +#include <stdexcept> + +namespace seal +{ + namespace util + { + class GaloisTool + { + public: + GaloisTool(int coeff_count_power, MemoryPoolHandle pool) : pool_(std::move(pool)) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + + initialize(coeff_count_power); + } + + void apply_galois( + const std::uint64_t *operand, std::uint32_t galois_elt, const Modulus &modulus, + std::uint64_t *result) const; + + void apply_galois_ntt(const std::uint64_t *operand, std::uint32_t galois_elt, std::uint64_t *result); + + /** + Compute the Galois element corresponding to a given rotation step. + */ + SEAL_NODISCARD std::uint32_t get_elt_from_step(int step) const; + + /** + Compute the Galois elements corresponding to a vector of given rotation steps. + */ + SEAL_NODISCARD std::vector<std::uint32_t> get_elts_from_steps(const std::vector<int> &steps) const; + + /** + Compute a vector of all necessary galois_elts. + */ + SEAL_NODISCARD std::vector<std::uint32_t> get_elts_all() const noexcept; + + /** + Compute the index in the range of 0 to (coeff_count_ - 1) of a given Galois element. + */ + SEAL_NODISCARD static inline std::size_t GetIndexFromElt(std::uint32_t galois_elt) + { +#ifdef SEAL_DEBUG + if (!(galois_elt & 1)) + { + throw std::invalid_argument("galois_elt is not valid"); + } +#endif + return util::safe_cast<std::size_t>((galois_elt - 1) >> 1); + } + + private: + GaloisTool(const GaloisTool &copy) = delete; + + GaloisTool(GaloisTool &&source) = delete; + + GaloisTool &operator=(const GaloisTool &assign) = delete; + + GaloisTool &operator=(GaloisTool &&assign) = delete; + + void initialize(int coeff_count_power); + + void generate_table_ntt(std::uint32_t galois_elt, Pointer<std::uint32_t> &result); + + MemoryPoolHandle pool_; + + int coeff_count_power_ = 0; + + std::size_t coeff_count_ = 0; + + static constexpr std::uint32_t generator_ = 3; + + Pointer<Pointer<std::uint32_t>> permutation_tables_; + + mutable util::ReaderWriterLocker permutation_tables_locker_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/gcc.h b/bigpiseal3.5.1/native/src/seal/util/gcc.h new file mode 100644 index 0000000000000000000000000000000000000000..d425880f98db44b5b938e9fdebee83e4111d40bf --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/gcc.h @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#if SEAL_COMPILER == SEAL_COMPILER_GCC + +// We require GCC >= 6 +#if (__GNUC__ < 6) || not defined(__cplusplus) +#pragma GCC error "SEAL requires __GNUC__ >= 6" +#endif + +// Read in config.h +#include "seal/util/config.h" + +#if (__GNUC__ == 6) && defined(SEAL_USE_IF_CONSTEXPR) +#pragma GCC error "g++-6 cannot compile Microsoft SEAL as C++17; set CMake build option `SEAL_USE_CXX17' to OFF" +#endif + +// Are intrinsics enabled? +#ifdef SEAL_USE_INTRIN +#include <x86intrin.h> + +#ifdef SEAL_USE___BUILTIN_CLZLL +#define SEAL_MSB_INDEX_UINT64(result, value) \ + { \ + *result = 63UL - static_cast<unsigned long>(__builtin_clzll(value)); \ + } +#endif + +#ifdef SEAL_USE___INT128 +__extension__ typedef __int128 int128_t; +__extension__ typedef unsigned __int128 uint128_t; +#define SEAL_MULTIPLY_UINT64_HW64(operand1, operand2, hw64) \ + { \ + *hw64 = static_cast<unsigned long long>( \ + ((static_cast<uint128_t>(operand1) * static_cast<uint128_t>(operand2)) >> 64)); \ + } + +#define SEAL_MULTIPLY_UINT64(operand1, operand2, result128) \ + { \ + uint128_t product = static_cast<uint128_t>(operand1) * operand2; \ + result128[0] = static_cast<unsigned long long>(product); \ + result128[1] = static_cast<unsigned long long>(product >> 64); \ + } + +#define SEAL_DIVIDE_UINT128_UINT64(numerator, denominator, result) \ + { \ + uint128_t n, q; \ + n = (static_cast<uint128_t>(numerator[1]) << 64) | (static_cast<uint128_t>(numerator[0])); \ + q = n / denominator; \ + n -= q * denominator; \ + numerator[0] = static_cast<std::uint64_t>(n); \ + numerator[1] = 0; \ + result[0] = static_cast<std::uint64_t>(q); \ + result[1] = static_cast<std::uint64_t>(q >> 64); \ + } +#endif + +#ifdef SEAL_USE__ADDCARRY_U64 +#define SEAL_ADD_CARRY_UINT64(operand1, operand2, carry, result) _addcarry_u64(carry, operand1, operand2, result) +#endif + +#ifdef SEAL_USE__SUBBORROW_U64 +#if ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 2)) || (__GNUC__ >= 8) +// The inverted arguments problem was fixed in GCC-7.2 +// (https://patchwork.ozlabs.org/patch/784309/) +#define SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result) _subborrow_u64(borrow, operand1, operand2, result) +#else +// Warning: Note the inverted order of operand1 and operand2 +#define SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result) _subborrow_u64(borrow, operand2, operand1, result) +#endif //(__GNUC__ == 7) && (__GNUC_MINOR__ >= 2) +#endif + +#endif // SEAL_USE_INTRIN + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/globals.cpp b/bigpiseal3.5.1/native/src/seal/util/globals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..432ce5574631d667c8b47d064327e726abf8bb23 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/globals.cpp @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/globals.h" +#include <cstdint> + +using namespace std; + +namespace seal +{ + namespace util + { + namespace global_variables + { + std::shared_ptr<MemoryPool> const global_memory_pool{ std::make_shared<MemoryPoolMT>() }; +#ifndef _M_CEE + thread_local std::shared_ptr<MemoryPool> const tls_memory_pool{ std::make_shared<MemoryPoolST>() }; +#else +#pragma message("WARNING: Thread-local memory pools disabled to support /clr") +#endif + const map<size_t, vector<Modulus>> default_coeff_modulus_128{ + /* + Polynomial modulus: 1x^1024 + 1 + Modulus count: 1 + Total bit count: 27 + */ + { 1024, { 0x7e00001 } }, + + /* + Polynomial modulus: 1x^2048 + 1 + Modulus count: 1 + Total bit count: 54 + */ + { 2048, { 0x3fffffff000001 } }, + + /* + Polynomial modulus: 1x^4096 + 1 + Modulus count: 3 + Total bit count: 109 = 2 * 36 + 37 + */ + { 4096, { 0xffffee001, 0xffffc4001, 0x1ffffe0001 } }, + + /* + Polynomial modulus: 1x^8192 + 1 + Modulus count: 5 + Total bit count: 218 = 2 * 43 + 3 * 44 + */ + { 8192, { 0x7fffffd8001, 0x7fffffc8001, 0xfffffffc001, 0xffffff6c001, 0xfffffebc001 } }, + + /* + Polynomial modulus: 1x^16384 + 1 + Modulus count: 9 + Total bit count: 438 = 3 * 48 + 6 * 49 + */ + { 16384, + { 0xfffffffd8001, 0xfffffffa0001, 0xfffffff00001, 0x1fffffff68001, 0x1fffffff50001, 0x1ffffffee8001, + 0x1ffffffea0001, 0x1ffffffe88001, 0x1ffffffe48001 } }, + + /* + Polynomial modulus: 1x^32768 + 1 + Modulus count: 16 + Total bit count: 881 = 15 * 55 + 56 + */ + { 32768, + { 0x7fffffffe90001, 0x7fffffffbf0001, 0x7fffffffbd0001, 0x7fffffffba0001, 0x7fffffffaa0001, + 0x7fffffffa50001, 0x7fffffff9f0001, 0x7fffffff7e0001, 0x7fffffff770001, 0x7fffffff380001, + 0x7fffffff330001, 0x7fffffff2d0001, 0x7fffffff170001, 0x7fffffff150001, 0x7ffffffef00001, + 0xfffffffff70001 } } + }; + + const map<size_t, vector<Modulus>> default_coeff_modulus_192{ + /* + Polynomial modulus: 1x^1024 + 1 + Modulus count: 1 + Total bit count: 19 + */ + { 1024, { 0x7f001 } }, + + /* + Polynomial modulus: 1x^2048 + 1 + Modulus count: 1 + Total bit count: 37 + */ + { 2048, { 0x1ffffc0001 } }, + + /* + Polynomial modulus: 1x^4096 + 1 + Modulus count: 3 + Total bit count: 75 = 3 * 25 + */ + { 4096, { 0x1ffc001, 0x1fce001, 0x1fc0001 } }, + + /* + Polynomial modulus: 1x^8192 + 1 + Modulus count: 4 + Total bit count: 152 = 4 * 38 + */ + { 8192, { 0x3ffffac001, 0x3ffff54001, 0x3ffff48001, 0x3ffff28001 } }, + + /* + Polynomial modulus: 1x^16384 + 1 + Modulus count: 6 + Total bit count: 300 = 6 * 50 + */ + { 16384, + { 0x3ffffffdf0001, 0x3ffffffd48001, 0x3ffffffd20001, 0x3ffffffd18001, 0x3ffffffcd0001, + 0x3ffffffc70001 } }, + + /* + Polynomial modulus: 1x^32768 + 1 + Modulus count: 11 + Total bit count: 600 = 5 * 54 + 6 * 55 + */ + { 32768, + { 0x3fffffffd60001, 0x3fffffffca0001, 0x3fffffff6d0001, 0x3fffffff5d0001, 0x3fffffff550001, + 0x7fffffffe90001, 0x7fffffffbf0001, 0x7fffffffbd0001, 0x7fffffffba0001, 0x7fffffffaa0001, + 0x7fffffffa50001 } } + }; + + const map<size_t, vector<Modulus>> default_coeff_modulus_256{ + /* + Polynomial modulus: 1x^1024 + 1 + Modulus count: 1 + Total bit count: 14 + */ + { 1024, { 0x3001 } }, + + /* + Polynomial modulus: 1x^2048 + 1 + Modulus count: 1 + Total bit count: 29 + */ + { 2048, { 0x1ffc0001 } }, + + /* + Polynomial modulus: 1x^4096 + 1 + Modulus count: 1 + Total bit count: 58 + */ + { 4096, { 0x3ffffffff040001 } }, + + /* + Polynomial modulus: 1x^8192 + 1 + Modulus count: 3 + Total bit count: 118 = 2 * 39 + 40 + */ + { 8192, { 0x7ffffec001, 0x7ffffb0001, 0xfffffdc001 } }, + + /* + Polynomial modulus: 1x^16384 + 1 + Modulus count: 5 + Total bit count: 237 = 3 * 47 + 2 * 48 + */ + { 16384, { 0x7ffffffc8001, 0x7ffffff00001, 0x7fffffe70001, 0xfffffffd8001, 0xfffffffa0001 } }, + + /* + Polynomial modulus: 1x^32768 + 1 + Modulus count: 9 + Total bit count: 476 = 52 + 8 * 53 + */ + { 32768, + { 0xffffffff00001, 0x1fffffffe30001, 0x1fffffffd80001, 0x1fffffffd10001, 0x1fffffffc50001, + 0x1fffffffbf0001, 0x1fffffffb90001, 0x1fffffffb60001, 0x1fffffffa50001 } } + }; + } // namespace global_variables + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/globals.h b/bigpiseal3.5.1/native/src/seal/util/globals.h new file mode 100644 index 0000000000000000000000000000000000000000..b4a8a1d175dee1f5df25e1e18e53d754129591c7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/globals.h @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include "seal/util/hestdparms.h" +#include <cstddef> +#include <cstdint> +#include <map> +#include <memory> +#include <vector> + +namespace seal +{ + class Modulus; + + namespace util + { + class MemoryPool; + + namespace global_variables + { + extern std::shared_ptr<MemoryPool> const global_memory_pool; + +/* +For .NET Framework wrapper support (C++/CLI) we need to + (1) compile the MemoryManager class as thread-unsafe because C++ + mutexes cannot be brought through C++/CLI layer; + (2) disable thread-safe memory pools. +*/ +#ifndef _M_CEE + extern thread_local std::shared_ptr<MemoryPool> const tls_memory_pool; +#endif + /** + Default value for the standard deviation of the noise (error) distribution. + */ + constexpr double noise_standard_deviation = SEAL_HE_STD_PARMS_ERROR_STD_DEV; + + constexpr double noise_distribution_width_multiplier = 6; + + constexpr double noise_max_deviation = noise_standard_deviation * noise_distribution_width_multiplier; + + /** + This data structure is a key-value storage that maps degrees of the polynomial modulus + to vectors of Modulus elements so that when used with the default value for the + standard deviation of the noise distribution (noise_standard_deviation), the security + level is at least 128 bits according to http://HomomorphicEncryption.org. This makes + it easy for non-expert users to select secure parameters. + */ + extern const std::map<std::size_t, std::vector<Modulus>> default_coeff_modulus_128; + + /** + This data structure is a key-value storage that maps degrees of the polynomial modulus + to vectors of Modulus elements so that when used with the default value for the + standard deviation of the noise distribution (noise_standard_deviation), the security + level is at least 192 bits according to http://HomomorphicEncryption.org. This makes + it easy for non-expert users to select secure parameters. + */ + extern const std::map<std::size_t, std::vector<Modulus>> default_coeff_modulus_192; + + /** + This data structure is a key-value storage that maps degrees of the polynomial modulus + to vectors of Modulus elements so that when used with the default value for the + standard deviation of the noise distribution (noise_standard_deviation), the security + level is at least 256 bits according to http://HomomorphicEncryption.org. This makes + it easy for non-expert users to select secure parameters. + */ + extern const std::map<std::size_t, std::vector<Modulus>> default_coeff_modulus_256; + } // namespace global_variables + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/hash.cpp b/bigpiseal3.5.1/native/src/seal/util/hash.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7a0d19946e206ccf44d9df52460acb853a2df57 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/hash.cpp @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/hash.h" + +using namespace std; + +namespace seal +{ + namespace util + { + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr std::size_t HashFunction::hash_block_uint64_count; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr std::size_t HashFunction::hash_block_byte_count; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr HashFunction::hash_block_type HashFunction::hash_zero_block; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/hash.h b/bigpiseal3.5.1/native/src/seal/util/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..5d64dd9c53605ac09e5f8c0e08ecf3ccf8ee9249 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/hash.h @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/blake2.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include <array> +#include <cstddef> +#include <cstdint> + +namespace seal +{ + namespace util + { + class HashFunction + { + public: + HashFunction() = delete; + + static constexpr std::size_t hash_block_uint64_count = 4; + + static constexpr std::size_t hash_block_byte_count = hash_block_uint64_count * bytes_per_uint64; + + using hash_block_type = std::array<std::uint64_t, hash_block_uint64_count>; + + static constexpr hash_block_type hash_zero_block{ { 0, 0, 0, 0 } }; + + inline static void hash(const std::uint64_t *input, std::size_t uint64_count, hash_block_type &destination) + { + if (blake2b( + reinterpret_cast<SEAL_BYTE *>(&destination), hash_block_byte_count, + reinterpret_cast<const SEAL_BYTE *>(input), uint64_count * bytes_per_uint64, nullptr, 0) != 0) + { + throw std::runtime_error("blake2b failed"); + } + } + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/hestdparms.h b/bigpiseal3.5.1/native/src/seal/util/hestdparms.h new file mode 100644 index 0000000000000000000000000000000000000000..53103f088f18b1b31568228c2b052e17f93c09bb --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/hestdparms.h @@ -0,0 +1,147 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" +#include <cstddef> + +namespace seal +{ + namespace util + { + /** + Largest allowed bit counts for coeff_modulus based on the security estimates from + HomomorphicEncryption.org security standard. Microsoft SEAL samples the secret key + from a ternary {-1, 0, 1} distribution. + */ + // Ternary secret; 128 bits classical security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_128_TC(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 27; + case std::size_t(2048): + return 54; + case std::size_t(4096): + return 109; + case std::size_t(8192): + return 218; + case std::size_t(16384): + return 438; + case std::size_t(32768): + return 881; + } + return 0; + } + + // Ternary secret; 192 bits classical security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_192_TC(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 19; + case std::size_t(2048): + return 37; + case std::size_t(4096): + return 75; + case std::size_t(8192): + return 152; + case std::size_t(16384): + return 305; + case std::size_t(32768): + return 611; + } + return 0; + } + + // Ternary secret; 256 bits classical security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_256_TC(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 14; + case std::size_t(2048): + return 29; + case std::size_t(4096): + return 58; + case std::size_t(8192): + return 118; + case std::size_t(16384): + return 237; + case std::size_t(32768): + return 476; + } + return 0; + } + + // Ternary secret; 128 bits quantum security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_128_TQ(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 25; + case std::size_t(2048): + return 51; + case std::size_t(4096): + return 101; + case std::size_t(8192): + return 202; + case std::size_t(16384): + return 411; + case std::size_t(32768): + return 827; + } + return 0; + } + + // Ternary secret; 192 bits quantum security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_192_TQ(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 17; + case std::size_t(2048): + return 35; + case std::size_t(4096): + return 70; + case std::size_t(8192): + return 141; + case std::size_t(16384): + return 284; + case std::size_t(32768): + return 571; + } + return 0; + } + + // Ternary secret; 256 bits quantum security + SEAL_NODISCARD constexpr int SEAL_HE_STD_PARMS_256_TQ(std::size_t poly_modulus_degree) noexcept + { + switch (poly_modulus_degree) + { + case std::size_t(1024): + return 13; + case std::size_t(2048): + return 27; + case std::size_t(4096): + return 54; + case std::size_t(8192): + return 109; + case std::size_t(16384): + return 220; + case std::size_t(32768): + return 443; + } + return 0; + } + + // Standard deviation for error distribution + constexpr double SEAL_HE_STD_PARMS_ERROR_STD_DEV = 3.20; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/iterator.h b/bigpiseal3.5.1/native/src/seal/util/iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..fe63406dd1d4a05bade516cf4795c70f8fef50fa --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/iterator.h @@ -0,0 +1,1738 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/plaintext.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <stdexcept> +#include <type_traits> +#include <utility> +#include <vector> + +namespace seal +{ + namespace util + { + /** + In this file we define a set of custom iterator classes ("SEAL iterators") that are used throughout Microsoft + SEAL for easier iteration over ciphertext polynomials, their RNS components, and the coefficients in the RNS + components. All SEAL iterators satisfy the C++ LegacyBidirectionalIterator requirements. Please note that they + are *not* random access iterators. The SEAL iterators are very helpful when used with std::for_each_n in C++17. + For C++14 compilers we have defined our own implementation of for_each_n below. + + The SEAL iterator classes behave as illustrated by the following diagram: + + +-------------------+ + | Pointer & Size | Construct +-----------------+ + | or Ciphertext +------------>+ (Const)PolyIter | Iterates over RNS polynomials in a ciphertext + +-------------------+ +-----------------+ (coeff_modulus_size-many RNS components) + | + | + | Dereference + | + | + v + +----------------+ Construct +----------------+ + | Pointer & Size +------------->+ (Const)RNSIter | Iterates over RNS components in an RNS polynomial + +----------------+ +----------------+ (poly_modulus_degree-many coefficients) + | + | + | Dereference + | + | + v + +----------------+ Construct +------------------+ + | Pointer & Size +------------>+ (Const)CoeffIter | Iterates over coefficients (std::uint64_t) in a single + +----------------+ +------------------+ RNS polynomial component + | + | + | Dereference + | + | + v + +------------------------+ Construct +---------------+ + | (const) std::uint64_t* +------------>+ PtrIter<PtrT> | Simple wrapper + +------------------------+ +---------------+ for raw pointers + ^ | + +---------+ Construct | | + | MyType* +-----------------------------------------+ | Dereference + +---------+ | + | + v + +------+ + | PtrT | Unusual dereference to PtrT + +------+ + + In addition to the types above, we define a ReverseIter<SEALIter> that reverses the direction of iteration. + However, ReverseIter<SEALIter> dereferences to the same type as SEALIter: for example, dereferencing + ReverseIter<RNSIter> results in CoeffIter, not ReverseIter<CoeffIter>. + + An extremely useful template class is the (variadic) IterTuple<...> that allows multiple SEAL iterators to be + zipped together. An IterTuple is itself a SEAL iterator and nested IterTuple types are used commonly in the + library. Dereferencing an IterTuple always yields another valid IterTuple, with each component dereferenced + individually. An IterTuple can in fact also hold raw pointers as its components, but such an IterTuple cannot + be dereferenced. Instead, the raw pointer must be first wrapped into a PtrIter object. Dereferencing a PtrIter + yields the wrapped raw pointer; hence, an IterTuple holding PtrIter objects can be dereferenced only once. + + The individual components of an IterTuple can be accessed with the seal::util::get<i>(...) functions. The + behavior of IterTuple is summarized in the following diagram: + + +-----------------------------------------+ + | IterTuple<PolyIter, RNSIter, CoeffIter> | + +--------------------+--------------------+ + | + | + | Dereference + | + | + v + +-----------------------------+--------------------------+ + | IterTuple<RNSIter, CoeffIter, PtrIter<std::uint64_t*>> | + +------+----------------------+----------------------+---+ + | | | + | | | + | get<0> | get<1> | get<2> + | | | + | | | + v v v + +------+------+ +-------+-------+ +-------------------------+ + | RNSIter | | CoeffIter | | PtrIter<std::uint64_t*> | + +-------------+ +---------------+ +-------------------------+ + + As an example, the following snippet from Evaluator::negate_inplace iterates over the polynomials in an input + ciphertext, and for each polynomial iterates over the RNS components, and for each RNS component negates the + polynomial coefficients modulo a Modulus element corresponding to the RNS component: + + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, + [&](auto J) { negate_poly_coeffmod(get<0>(J), coeff_count, *get<1>(J), get<0>(J)); }); + }); + + Here coeff_modulus is a std::vector<Modulus>, and PtrIter<const Modulus *> was constructed directly + from it. PtrIter provides a similar constructor from a seal::util::Pointer type. Note also how we had to + dereference get<1>(J) in the innermost lambda function to access the value (NTTTables). This is because + get<1>(J) is const NTTTables *, as was discussed above. + + There are two important coding conventions in the above code snippet that are to be observed: + + 1. Always explicitly write the class template arguments. This is important for C++14 compatibility, and can + help avoid confusing bugs resulting from mistakes in iterator types in nested for_each_n calls. + 2. Use I, J, K, ... for the lambda function parameters representing SEAL iterators. This is compact and + makes it very clear that the objects in question are SEAL iterators since such variable names should not + be used in SEAL in any other context. + 3. Always pass SEAL iterators by value to the lambda function. + + It is not unusual to have multiple nested for_each_n calls operating on multiple/nested IterTuple objects. + It can become very difficult to keep track of what exactly the different iterators are pointing to, and what + their types are (the above convention of using I, J, K, ... does not reveal the type). Hence we sometimes + annotate the code and check that the types match what we expect them to be using the SEAL_ASSERT_TYPE macro. + For example, the above code snippet would be annotated as follows: + + for_each_n(PolyIter(encrypted), encrypted_size, [&](auto I) { + SEAL_ASSERT_TYPE(I, RNSIter, "encrypted"); + for_each_n( + IterTuple<RNSIter, PtrIter<const Modulus *>>(I, coeff_modulus), coeff_modulus_size, [&](auto J) { + SEAL_ASSERT_TYPE(get<0>(J), CoeffIter, "encrypted"); + SEAL_ASSERT_TYPE(get<1>(J), const Modulus *, "coeff_modulus"); + negate_poly_coeffmod(get<0>(J), coeff_count, *get<1>(J), get<0>(J)); + }); + }); + + Note how SEAL_ASSERT_TYPE makes it explicit what type the different iterators are, and includes a string that + describes what object is iterated over. We use this convention in particularly complex functions to make the + code easier to follow and less error-prone. The code will fail to compile if the type of the object in the first + parameter does not match the type in the second parameter of the macro. + + In the future we hope to use the parallel version of std::for_each_n, introduced in C++17. For this to work, + be mindful of how you use heap allocations in the lambda functions. Specifically, in heavy lambda functions it + is probably a good idea to call seal::util::allocate inside the lambda function for any allocations needed, + rather than using allocations captured from outside the lambda function. + */ +#ifndef SEAL_USE_STD_FOR_EACH_N + // C++14 does not have for_each_n so we define a custom version here. + template <typename ForwardIt, typename Size, typename Func> + ForwardIt for_each_n(ForwardIt first, Size size, Func func) + { + for (; size--; (void)++first) + { + func(*first); + } + return first; + } +#endif + class CoeffIter; + + class ConstCoeffIter; + + class RNSIter; + + class ConstRNSIter; + + class PolyIter; + + class ConstPolyIter; + + class CoeffIter + { + public: + friend class RNSIter; + friend class PolyIter; + + using self_type = CoeffIter; + + // Standard iterator typedefs + using value_type = std::uint64_t *; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + CoeffIter() : ptr_(nullptr) + {} + + CoeffIter(value_type ptr) : ptr_(ptr) + {} + + CoeffIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + CoeffIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return ptr_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + return ptr_ + n; + } + + inline self_type &operator++() noexcept + { + ptr_++; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(ptr_); + ptr_++; + return result; + } + + inline self_type &operator--() noexcept + { + ptr_--; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(ptr_); + ptr_--; + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + ptr_ += n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + return ptr_ + n; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + ptr_ -= n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return ptr_ - n; + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const noexcept + { + return ptr_ - b.ptr_; + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return ptr_ == compare.ptr_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return ptr_ < compare.ptr_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return ptr_ > compare.ptr_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(ptr_ > compare.ptr_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(ptr_ < compare.ptr_); + } + + SEAL_NODISCARD inline operator std::uint64_t *() const noexcept + { + return ptr_; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return nullptr != ptr_; + } + + private: + value_type ptr_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline CoeffIter operator+(SizeT n, const CoeffIter &it) noexcept + { + return it + n; + } + + class ConstCoeffIter + { + public: + friend class ConstRNSIter; + friend class ConstPolyIter; + + using self_type = ConstCoeffIter; + + // Standard iterator typedefs + using value_type = const std::uint64_t *; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + ConstCoeffIter() : ptr_(nullptr) + {} + + ConstCoeffIter(value_type ptr) : ptr_(ptr) + {} + + ConstCoeffIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + ConstCoeffIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + ConstCoeffIter(const CoeffIter &copy) : ptr_(static_cast<const std::uint64_t *>(copy)) + {} + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return ptr_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + return ptr_ + n; + } + + inline self_type &operator++() noexcept + { + ptr_++; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(ptr_); + ptr_++; + return result; + } + + inline self_type &operator--() noexcept + { + ptr_--; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(ptr_); + ptr_--; + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + ptr_ += n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + return ptr_ + n; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + ptr_ -= n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return ptr_ - n; + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const noexcept + { + return ptr_ - b.ptr_; + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return ptr_ == compare.ptr_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return ptr_ < compare.ptr_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return ptr_ > compare.ptr_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(ptr_ > compare.ptr_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(ptr_ < compare.ptr_); + } + + SEAL_NODISCARD inline operator const std::uint64_t *() const noexcept + { + return ptr_; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return nullptr != ptr_; + } + + private: + value_type ptr_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline ConstCoeffIter operator+(SizeT n, const ConstCoeffIter &it) noexcept + { + return it + n; + } + + class RNSIter + { + public: + friend class PolyIter; + + using self_type = RNSIter; + + // Standard iterator typedefs + using value_type = CoeffIter; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + RNSIter() : coeff_it_(nullptr), step_size_(0) + {} + + RNSIter(std::uint64_t *ptr, std::size_t poly_modulus_degree) + : coeff_it_(ptr), step_size_(poly_modulus_degree) + {} + + RNSIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + RNSIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return coeff_it_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + self_type result(*this); + result += static_cast<difference_type>(n); + return *result; + } + + inline self_type &operator++() noexcept + { + coeff_it_ += static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + coeff_it_ += static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + inline self_type &operator--() noexcept + { + coeff_it_ -= static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + coeff_it_ -= static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + coeff_it_ += n * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + self_type result(*this); + result.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + coeff_it_ -= static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return *this + (-static_cast<difference_type>(n)); + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const + { +#ifdef SEAL_DEBUG + if (!step_size_) + { + throw std::logic_error("step_size cannot be zero"); + } + if (step_size_ != b.step_size_) + { + throw std::invalid_argument("incompatible iterators"); + } +#endif + return (coeff_it_ - b.coeff_it_) / static_cast<std::ptrdiff_t>(step_size_); + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return coeff_it_ == compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return coeff_it_ < compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return coeff_it_ > compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(coeff_it_ > compare.coeff_it_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(coeff_it_ < compare.coeff_it_); + } + + SEAL_NODISCARD inline operator std::uint64_t *() const noexcept + { + return static_cast<std::uint64_t *>(coeff_it_); + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(coeff_it_); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return step_size_; + } + + private: + CoeffIter coeff_it_; + + std::size_t step_size_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline RNSIter operator+(SizeT n, RNSIter it) noexcept + { + return it + n; + } + + class ConstRNSIter + { + public: + friend class ConstPolyIter; + + using self_type = ConstRNSIter; + + // Standard iterator typedefs + using value_type = ConstCoeffIter; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + + ConstRNSIter() : coeff_it_(nullptr), step_size_(0) + {} + + ConstRNSIter(const std::uint64_t *ptr, std::size_t poly_modulus_degree) + : coeff_it_(ptr), step_size_(poly_modulus_degree) + {} + + ConstRNSIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + ConstRNSIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + ConstRNSIter(const RNSIter &copy) + : coeff_it_(static_cast<const std::uint64_t *>(copy)), step_size_(copy.poly_modulus_degree()) + {} + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return coeff_it_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + self_type result(*this); + result += static_cast<difference_type>(n); + return *result; + } + + inline self_type &operator++() noexcept + { + coeff_it_ += static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + coeff_it_ += static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + inline self_type &operator--() noexcept + { + coeff_it_ -= static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + coeff_it_ -= static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + self_type result(*this); + result.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + coeff_it_ -= static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return *this + (-static_cast<difference_type>(n)); + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const + { +#ifdef SEAL_DEBUG + if (!step_size_) + { + throw std::logic_error("step_size cannot be zero"); + } + if (step_size_ != b.step_size_) + { + throw std::invalid_argument("incompatible iterators"); + } +#endif + return (coeff_it_ - b.coeff_it_) / static_cast<std::ptrdiff_t>(step_size_); + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return coeff_it_ == compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return coeff_it_ < compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return coeff_it_ > compare.coeff_it_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(coeff_it_ > compare.coeff_it_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(coeff_it_ < compare.coeff_it_); + } + + SEAL_NODISCARD inline operator const std::uint64_t *() const noexcept + { + return static_cast<const std::uint64_t *>(coeff_it_); + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(coeff_it_); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return step_size_; + } + + private: + ConstCoeffIter coeff_it_; + + std::size_t step_size_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline ConstRNSIter operator+(SizeT n, ConstRNSIter it) noexcept + { + return it + n; + } + + class PolyIter + { + public: + using self_type = PolyIter; + + // Standard iterator typedefs + using value_type = RNSIter; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + PolyIter() : rns_it_(nullptr, 0), coeff_modulus_size_(0), step_size_(0) + {} + + PolyIter(std::uint64_t *ptr, std::size_t poly_modulus_degree, std::size_t coeff_modulus_size) + : rns_it_(ptr, poly_modulus_degree), coeff_modulus_size_(coeff_modulus_size), + step_size_(mul_safe(poly_modulus_degree, coeff_modulus_size_)) + {} + + PolyIter(Ciphertext &ct) : self_type(ct.data(), ct.poly_modulus_degree(), ct.coeff_modulus_size()) + {} + + PolyIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + PolyIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return rns_it_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + self_type result(*this); + result += static_cast<difference_type>(n); + return *result; + } + + inline self_type &operator++() noexcept + { + rns_it_.coeff_it_.ptr_ += step_size_; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + rns_it_.coeff_it_.ptr_ += step_size_; + return result; + } + + inline self_type &operator--() noexcept + { + rns_it_.coeff_it_.ptr_ -= step_size_; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + rns_it_.coeff_it_.ptr_ -= step_size_; + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + rns_it_.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + self_type result(*this); + result.rns_it_.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + rns_it_.coeff_it_ -= static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return *this + (-static_cast<difference_type>(n)); + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const + { +#ifdef SEAL_DEBUG + if (!step_size_) + { + throw std::logic_error("step_size cannot be zero"); + } + if (step_size_ != b.step_size_) + { + throw std::invalid_argument("incompatible iterators"); + } + if (coeff_modulus_size_ != b.coeff_modulus_size_) + { + throw std::invalid_argument("incompatible iterators"); + } +#endif + return (rns_it_.coeff_it_ - b.rns_it_.coeff_it_) / static_cast<std::ptrdiff_t>(step_size_); + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return rns_it_ == compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return rns_it_ < compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return rns_it_ > compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(rns_it_ > compare.rns_it_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(rns_it_ < compare.rns_it_); + } + + SEAL_NODISCARD inline operator std::uint64_t *() const noexcept + { + return rns_it_; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(rns_it_); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return rns_it_.step_size_; + } + + SEAL_NODISCARD inline std::size_t coeff_modulus_size() const noexcept + { + return coeff_modulus_size_; + } + + private: + RNSIter rns_it_; + + std::size_t coeff_modulus_size_; + + std::size_t step_size_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline PolyIter operator+(SizeT n, PolyIter it) noexcept + { + return it + n; + } + + class ConstPolyIter + { + public: + using self_type = ConstPolyIter; + + // Standard iterator typedefs + using value_type = ConstRNSIter; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + ConstPolyIter() : rns_it_(nullptr, 0), coeff_modulus_size_(0), step_size_(0) + {} + + ConstPolyIter(const std::uint64_t *ptr, std::size_t poly_modulus_degree, std::size_t coeff_modulus_size) + : rns_it_(ptr, poly_modulus_degree), coeff_modulus_size_(coeff_modulus_size), + step_size_(mul_safe(poly_modulus_degree, coeff_modulus_size_)) + {} + + ConstPolyIter(const Ciphertext &ct) + : self_type(ct.data(), ct.poly_modulus_degree(), ct.coeff_modulus_size()) + {} + + ConstPolyIter(Ciphertext &ct) : self_type(ct.data(), ct.poly_modulus_degree(), ct.coeff_modulus_size()) + {} + + ConstPolyIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + ConstPolyIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + ConstPolyIter(const PolyIter &copy) + : rns_it_(static_cast<const std::uint64_t *>(copy), copy.poly_modulus_degree()), + coeff_modulus_size_(copy.coeff_modulus_size()), + step_size_(mul_safe(rns_it_.step_size_, coeff_modulus_size_)) + {} + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return rns_it_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + self_type result(*this); + result += static_cast<difference_type>(n); + return *result; + } + + inline self_type &operator++() noexcept + { + rns_it_.coeff_it_.ptr_ += step_size_; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + rns_it_.coeff_it_.ptr_ += step_size_; + return result; + } + + inline self_type &operator--() noexcept + { + rns_it_.coeff_it_.ptr_ -= step_size_; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + rns_it_.coeff_it_.ptr_ -= step_size_; + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + rns_it_.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + self_type result(*this); + result.rns_it_.coeff_it_ += static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return result; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + rns_it_.coeff_it_ -= static_cast<difference_type>(n) * static_cast<std::ptrdiff_t>(step_size_); + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return *this + (-static_cast<difference_type>(n)); + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const + { +#ifdef SEAL_DEBUG + if (!step_size_) + { + throw std::logic_error("step_size cannot be zero"); + } + if (step_size_ != b.step_size_) + { + throw std::invalid_argument("incompatible iterators"); + } + if (coeff_modulus_size_ != b.coeff_modulus_size_) + { + throw std::invalid_argument("incompatible iterators"); + } +#endif + return (rns_it_.coeff_it_ - b.rns_it_.coeff_it_) / static_cast<std::ptrdiff_t>(step_size_); + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return rns_it_ == compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return rns_it_ < compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return rns_it_ > compare.rns_it_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(rns_it_ > compare.rns_it_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(rns_it_ < compare.rns_it_); + } + + SEAL_NODISCARD inline operator const std::uint64_t *() const noexcept + { + return rns_it_; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(rns_it_); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept + { + return rns_it_.step_size_; + } + + SEAL_NODISCARD inline std::size_t coeff_modulus_size() const noexcept + { + return coeff_modulus_size_; + } + + private: + ConstRNSIter rns_it_; + + std::size_t coeff_modulus_size_; + + std::size_t step_size_; + }; + + // Out-of-class definitions + template <typename SizeT> + SEAL_NODISCARD inline ConstPolyIter operator+(SizeT n, ConstPolyIter it) noexcept + { + return it + n; + } + + template <typename PtrT> + class PtrIter + { + public: + using self_type = PtrIter<PtrT>; + + // Standard iterator typedefs + using value_type = PtrT; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + + PtrIter() : ptr_(nullptr) + {} + + PtrIter(value_type ptr) : ptr_(ptr) + {} + + PtrIter(const std::vector<std::remove_cv_t<std::remove_pointer_t<PtrT>>> &arr) : PtrIter(arr.data()) + {} + + PtrIter(const Pointer<std::remove_cv_t<std::remove_pointer_t<PtrT>>> &arr) : PtrIter(arr.get()) + {} + + PtrIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + PtrIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline reference operator*() const noexcept + { + return ptr_; + } + + template <typename SizeT> + SEAL_NODISCARD inline value_type operator[](SizeT n) const noexcept + { + return ptr_ + n; + } + + inline self_type &operator++() noexcept + { + ptr_++; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(ptr_); + ptr_++; + return result; + } + + inline self_type &operator--() noexcept + { + ptr_--; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(ptr_); + ptr_--; + return result; + } + + template <typename SizeT> + inline self_type &operator+=(SizeT n) noexcept + { + ptr_ += n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator+(SizeT n) const noexcept + { + return ptr_ + n; + } + + template <typename SizeT> + inline self_type &operator-=(SizeT n) noexcept + { + ptr_ -= n; + return *this; + } + + template <typename SizeT> + SEAL_NODISCARD inline self_type operator-(SizeT n) const noexcept + { + return ptr_ - n; + } + + SEAL_NODISCARD inline difference_type operator-(const self_type &b) const noexcept + { + return std::distance(ptr_, b.ptr_); + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return ptr_ == compare.ptr_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline bool operator<(const self_type &compare) const noexcept + { + return ptr_ < compare.ptr_; + } + + SEAL_NODISCARD inline bool operator>(const self_type &compare) const noexcept + { + return ptr_ > compare.ptr_; + } + + SEAL_NODISCARD inline bool operator<=(const self_type &compare) const noexcept + { + return !(ptr_ > compare.ptr_); + } + + SEAL_NODISCARD inline bool operator>=(const self_type &compare) const noexcept + { + return !(ptr_ < compare.ptr_); + } + + SEAL_NODISCARD inline operator value_type *() const noexcept + { + return ptr_; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return nullptr != ptr_; + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + private: + value_type ptr_; + }; + + // Out-of-class definitions + template <typename PtrT, typename SizeT> + SEAL_NODISCARD inline PtrIter<PtrT> operator+(SizeT n, const PtrIter<PtrT> &it) noexcept + { + return it + n; + } + + template <typename SEALIter> + class ReverseIter : public SEALIter + { + public: + using self_type = ReverseIter<SEALIter>; + + // Standard iterator typedefs + using value_type = typename std::iterator_traits<SEALIter>::value_type; + using pointer = typename std::iterator_traits<SEALIter>::pointer; + using reference = typename std::iterator_traits<SEALIter>::reference; + using iterator_category = typename std::iterator_traits<SEALIter>::iterator_category; + using difference_type = typename std::iterator_traits<SEALIter>::difference_type; + + ReverseIter() : SEALIter() + {} + + ReverseIter(const SEALIter &copy) : SEALIter(copy) + {} + + ReverseIter(SEALIter &&source) : SEALIter(source) + {} + + ReverseIter(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + ReverseIter(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + template <typename SizeT, typename Ignore = value_type> + SEAL_NODISCARD inline auto operator[](SizeT n) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + self_type result(*this); + result += static_cast<difference_type>(n); + return *result; + } + + inline self_type &operator++() noexcept + { + SEALIter::operator--(); + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + SEALIter::operator--(); + return result; + } + + inline self_type &operator--() noexcept + { + SEALIter::operator++(); + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + SEALIter::operator++(); + return result; + } + + template <typename SizeT, typename Ignore = typename std::add_lvalue_reference<self_type>::type> + inline auto operator+=(SizeT n) noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + SEALIter::operator-=(n); + return *this; + } + + template <typename SizeT, typename Ignore = self_type> + SEAL_NODISCARD inline auto operator+(SizeT n) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + self_type result(*this); + result += n; + return result; + } + + template <typename SizeT, typename Ignore = typename std::add_lvalue_reference<self_type>::type> + inline auto operator-=(SizeT n) noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + SEALIter::operator+=(n); + return *this; + } + + template <typename SizeT, typename Ignore = self_type> + SEAL_NODISCARD inline auto operator-(SizeT n) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return *this + (-static_cast<difference_type>(n)); + } + + template <typename Ignore = difference_type> + SEAL_NODISCARD inline auto operator-(const self_type &b) const + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return static_cast<SEALIter>(*this) - static_cast<SEALIter>(*b); + } + + template <typename Ignore = bool> + SEAL_NODISCARD inline auto operator<(const self_type &compare) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return static_cast<SEALIter>(*this) > static_cast<SEALIter>(*compare); + } + + template <typename Ignore = bool> + SEAL_NODISCARD inline auto operator>(const self_type &compare) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return static_cast<SEALIter>(*this) < static_cast<SEALIter>(*compare); + } + + template <typename Ignore = bool> + SEAL_NODISCARD inline auto operator<=(const self_type &compare) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return !(*this > compare); + } + + template <typename Ignore = bool> + SEAL_NODISCARD inline auto operator>=(const self_type &compare) const noexcept + -> std::enable_if_t<std::is_same<iterator_category, std::random_access_iterator_tag>::value, Ignore> + { + return !(*this < compare); + } + }; + + // Out-of-class definitions + template < + typename SizeT, typename SEALIter, + typename = std::enable_if_t<std::is_same< + typename std::iterator_traits<SEALIter>::iterator_category, std::random_access_iterator_tag>::value>> + SEAL_NODISCARD inline ReverseIter<SEALIter> operator+(SizeT n, const ReverseIter<SEALIter> &it) noexcept + { + return it + n; + } + + template <typename... SEALIters> + class IterTuple; + + template <typename SEALIter, typename... Rest> + class IterTuple<SEALIter, Rest...> + { + public: + using self_type = IterTuple<SEALIter, Rest...>; + + // Standard iterator typedefs + using value_type = IterTuple< + typename std::iterator_traits<SEALIter>::value_type, + typename std::iterator_traits<IterTuple<Rest>>::value_type...>; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + + IterTuple() = default; + + IterTuple(SEALIter first, IterTuple<Rest...> rest) : first_(first), rest_(rest){}; + + IterTuple(SEALIter first, Rest... rest) : first_(first), rest_(rest...) + {} + + IterTuple(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + IterTuple(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline value_type operator*() const noexcept + { + return { *first_, *rest_ }; + } + + inline self_type &operator++() noexcept + { + first_++; + rest_++; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + first_++; + rest_++; + return result; + } + + inline self_type &operator--() noexcept + { + first_--; + rest_--; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + first_--; + rest_--; + return result; + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return (first_ == compare.first_) && (rest_ == compare.rest_); + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(first_) && static_cast<bool>(rest_); + } + + SEAL_NODISCARD inline const SEALIter &first() const noexcept + { + return first_; + } + + SEAL_NODISCARD inline const IterTuple<Rest...> &rest() const noexcept + { + return rest_; + } + + private: + SEALIter first_; + + IterTuple<Rest...> rest_; + }; + + template <typename SEALIter> + class IterTuple<SEALIter> + { + public: + using self_type = IterTuple<SEALIter>; + + // Standard iterator typedefs + using value_type = typename std::iterator_traits<SEALIter>::value_type; + using pointer = void; + using reference = const value_type &; + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + + IterTuple(){}; + + IterTuple(SEALIter first) : first_(first) + {} + + IterTuple(const self_type &copy) = default; + + self_type &operator=(const self_type &assign) = default; + + IterTuple(self_type &&source) = default; + + self_type &operator=(self_type &&assign) = default; + + SEAL_NODISCARD inline value_type operator*() const noexcept + { + return *first_; + } + + inline self_type &operator++() noexcept + { + first_++; + return *this; + } + + inline self_type operator++(int) noexcept + { + self_type result(*this); + first_++; + return result; + } + + inline self_type &operator--() noexcept + { + first_--; + return *this; + } + + inline self_type operator--(int) noexcept + { + self_type result(*this); + first_--; + return result; + } + + SEAL_NODISCARD inline bool operator==(const self_type &compare) const noexcept + { + return first_ == compare.first_; + } + + SEAL_NODISCARD inline bool operator!=(const self_type &compare) const noexcept + { + return !(*this == compare); + } + + SEAL_NODISCARD inline value_type operator->() const noexcept + { + return **this; + } + + SEAL_NODISCARD explicit inline operator bool() const noexcept + { + return static_cast<bool>(first_); + } + + SEAL_NODISCARD inline const SEALIter &first() const noexcept + { + return first_; + } + + private: + SEALIter first_; + }; + + namespace iterator_tuple_internal + { + template <std::size_t N> + struct GetHelperStruct + { + template <typename SEALIter, typename... Rest> + static auto apply(const IterTuple<SEALIter, Rest...> &it) + { + return GetHelperStruct<N - 1>::apply(it.rest()); + } + }; + + template <> + struct GetHelperStruct<0> + { + template <typename SEALIter, typename... Rest> + static auto apply(const IterTuple<SEALIter, Rest...> &it) + { + return it.first(); + } + }; + } // namespace iterator_tuple_internal + + template <std::size_t N, typename... SEALIters> + auto get(const IterTuple<SEALIters...> &it) + { + return iterator_tuple_internal::GetHelperStruct<N>::apply(it); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/locks.h b/bigpiseal3.5.1/native/src/seal/util/locks.h new file mode 100644 index 0000000000000000000000000000000000000000..53528c7e34fb813fc5a146d1a9c6ee7abd6ff7f9 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/locks.h @@ -0,0 +1,296 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/defines.h" + +#ifdef SEAL_USE_SHARED_MUTEX +#include <shared_mutex> +/*Building problem with shared_mutex!*/ +#include <mutex> + +namespace seal +{ + namespace util + { + using ReaderLock = std::shared_lock<std::shared_mutex>; + + using WriterLock = std::unique_lock<std::shared_mutex>; + + class SEAL_NODISCARD ReaderWriterLocker + { + public: + ReaderWriterLocker() = default; + + SEAL_NODISCARD inline ReaderLock acquire_read() + { + return ReaderLock(rw_lock_mutex_); + } + + SEAL_NODISCARD inline WriterLock acquire_write() + { + return WriterLock(rw_lock_mutex_); + } + + SEAL_NODISCARD inline ReaderLock try_acquire_read() noexcept + { + return ReaderLock(rw_lock_mutex_, std::try_to_lock); + } + + SEAL_NODISCARD inline WriterLock try_acquire_write() noexcept + { + return WriterLock(rw_lock_mutex_, std::try_to_lock); + } + + private: + ReaderWriterLocker(const ReaderWriterLocker &copy) = delete; + + ReaderWriterLocker &operator=(const ReaderWriterLocker &assign) = delete; + + std::shared_mutex rw_lock_mutex_{}; + }; + } // namespace util +} // namespace seal +#else +#include <atomic> +#include <utility> + +namespace seal +{ + namespace util + { + struct try_to_lock_t + {}; + + constexpr try_to_lock_t try_to_lock{}; + + class ReaderWriterLocker; + + class SEAL_NODISCARD ReaderLock + { + public: + ReaderLock() noexcept : locker_(nullptr) + {} + + ReaderLock(ReaderLock &&move) noexcept : locker_(move.locker_) + { + move.locker_ = nullptr; + } + + ReaderLock(ReaderWriterLocker &locker) noexcept : locker_(nullptr) + { + acquire(locker); + } + + ReaderLock(ReaderWriterLocker &locker, try_to_lock_t) noexcept : locker_(nullptr) + { + try_acquire(locker); + } + + ~ReaderLock() noexcept + { + unlock(); + } + + SEAL_NODISCARD inline bool owns_lock() const noexcept + { + return locker_ != nullptr; + } + + void unlock() noexcept; + + inline void swap_with(ReaderLock &lock) noexcept + { + std::swap(locker_, lock.locker_); + } + + inline ReaderLock &operator=(ReaderLock &&lock) noexcept + { + swap_with(lock); + lock.unlock(); + return *this; + } + + private: + void acquire(ReaderWriterLocker &locker) noexcept; + + bool try_acquire(ReaderWriterLocker &locker) noexcept; + + ReaderWriterLocker *locker_; + }; + + class SEAL_NODISCARD WriterLock + { + public: + WriterLock() noexcept : locker_(nullptr) + {} + + WriterLock(WriterLock &&move) noexcept : locker_(move.locker_) + { + move.locker_ = nullptr; + } + + WriterLock(ReaderWriterLocker &locker) noexcept : locker_(nullptr) + { + acquire(locker); + } + + WriterLock(ReaderWriterLocker &locker, try_to_lock_t) noexcept : locker_(nullptr) + { + try_acquire(locker); + } + + ~WriterLock() noexcept + { + unlock(); + } + + SEAL_NODISCARD inline bool owns_lock() const noexcept + { + return locker_ != nullptr; + } + + void unlock() noexcept; + + inline void swap_with(WriterLock &lock) noexcept + { + std::swap(locker_, lock.locker_); + } + + inline WriterLock &operator=(WriterLock &&lock) noexcept + { + swap_with(lock); + lock.unlock(); + return *this; + } + + private: + void acquire(ReaderWriterLocker &locker) noexcept; + + bool try_acquire(ReaderWriterLocker &locker) noexcept; + + ReaderWriterLocker *locker_; + }; + + class SEAL_NODISCARD ReaderWriterLocker + { + friend class ReaderLock; + + friend class WriterLock; + + public: + ReaderWriterLocker() noexcept : reader_locks_(0), writer_locked_(false) + {} + + SEAL_NODISCARD inline ReaderLock acquire_read() noexcept + { + return ReaderLock(*this); + } + + SEAL_NODISCARD inline WriterLock acquire_write() noexcept + { + return WriterLock(*this); + } + + SEAL_NODISCARD inline ReaderLock try_acquire_read() noexcept + { + return ReaderLock(*this, try_to_lock); + } + + SEAL_NODISCARD inline WriterLock try_acquire_write() noexcept + { + return WriterLock(*this, try_to_lock); + } + + private: + ReaderWriterLocker(const ReaderWriterLocker &copy) = delete; + + ReaderWriterLocker &operator=(const ReaderWriterLocker &assign) = delete; + + std::atomic<int> reader_locks_; + + std::atomic<bool> writer_locked_; + }; + + inline void ReaderLock::unlock() noexcept + { + if (locker_ == nullptr) + { + return; + } + locker_->reader_locks_.fetch_sub(1, std::memory_order_release); + locker_ = nullptr; + } + + inline void ReaderLock::acquire(ReaderWriterLocker &locker) noexcept + { + unlock(); + do + { + locker.reader_locks_.fetch_add(1, std::memory_order_acquire); + locker_ = &locker; + if (locker.writer_locked_.load(std::memory_order_acquire)) + { + unlock(); + while (locker.writer_locked_.load(std::memory_order_acquire)) + ; + } + } while (locker_ == nullptr); + } + + SEAL_NODISCARD inline bool ReaderLock::try_acquire(ReaderWriterLocker &locker) noexcept + { + unlock(); + locker.reader_locks_.fetch_add(1, std::memory_order_acquire); + locker_ = &locker; + if (locker.writer_locked_.load(std::memory_order_acquire)) + { + unlock(); + return false; + } + return true; + } + + inline void WriterLock::acquire(ReaderWriterLocker &locker) noexcept + { + unlock(); + bool expected = false; + while (!locker.writer_locked_.compare_exchange_strong(expected, true, std::memory_order_acquire)) + { + expected = false; + } + locker_ = &locker; + while (locker.reader_locks_.load(std::memory_order_acquire) != 0) + ; + } + + SEAL_NODISCARD inline bool WriterLock::try_acquire(ReaderWriterLocker &locker) noexcept + { + unlock(); + bool expected = false; + if (!locker.writer_locked_.compare_exchange_strong(expected, true, std::memory_order_acquire)) + { + return false; + } + locker_ = &locker; + if (locker.reader_locks_.load(std::memory_order_acquire) != 0) + { + unlock(); + return false; + } + return true; + } + + inline void WriterLock::unlock() noexcept + { + if (locker_ == nullptr) + { + return; + } + locker_->writer_locked_.store(false, std::memory_order_release); + locker_ = nullptr; + } + } // namespace util +} // namespace seal +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/mempool.cpp b/bigpiseal3.5.1/native/src/seal/util/mempool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e4233d04aea646b56abb71fcdba12cf59c160b6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/mempool.cpp @@ -0,0 +1,486 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/mempool.h" +#include "seal/util/uintarith.h" +#include <algorithm> +#include <cmath> +#include <cstring> +#include <numeric> +#include <stdexcept> + +using namespace std; + +namespace seal +{ + namespace util + { + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr double MemoryPool::alloc_size_multiplier; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr std::size_t MemoryPool::max_pool_head_count; + + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr std::size_t MemoryPool::first_alloc_count; + + MemoryPoolHeadMT::MemoryPoolHeadMT(size_t item_byte_count, bool clear_on_destruction) + : clear_on_destruction_(clear_on_destruction), locked_(false), item_byte_count_(item_byte_count), + item_count_(MemoryPool::first_alloc_count), first_item_(nullptr) + { + if ((item_byte_count_ == 0) || (item_byte_count_ > MemoryPool::max_batch_alloc_byte_count) || + (mul_safe(item_byte_count_, MemoryPool::first_alloc_count) > MemoryPool::max_batch_alloc_byte_count)) + { + throw invalid_argument("invalid allocation size"); + } + + // Initial allocation + allocation new_alloc; + try + { + new_alloc.data_ptr = new SEAL_BYTE[mul_safe(MemoryPool::first_alloc_count, item_byte_count_)]; + } + catch (const bad_alloc &) + { + // Allocation failed; rethrow + throw; + } + + new_alloc.size = MemoryPool::first_alloc_count; + new_alloc.free = MemoryPool::first_alloc_count; + new_alloc.head_ptr = new_alloc.data_ptr; + allocs_.clear(); + allocs_.push_back(new_alloc); + } + + MemoryPoolHeadMT::~MemoryPoolHeadMT() noexcept + { + bool expected = false; + while (!locked_.compare_exchange_strong(expected, true, memory_order_acquire)) + { + expected = false; + } + + // Delete the items (but not the memory) + MemoryPoolItem *curr_item = first_item_; + while (curr_item) + { + MemoryPoolItem *next_item = curr_item->next(); + delete curr_item; + curr_item = next_item; + } + first_item_ = nullptr; + + // Do we need to clear the memory? + if (clear_on_destruction_) + { + // Delete the memory + for (auto &alloc : allocs_) + { + size_t curr_alloc_byte_count = mul_safe(item_byte_count_, alloc.size); + volatile SEAL_BYTE *data_ptr = reinterpret_cast<SEAL_BYTE *>(alloc.data_ptr); + while (curr_alloc_byte_count--) + { + *data_ptr++ = static_cast<SEAL_BYTE>(0); + } + + // Delete this allocation + delete[] alloc.data_ptr; + } + } + else + { + // Delete the memory + for (auto &alloc : allocs_) + { + // Delete this allocation + delete[] alloc.data_ptr; + } + } + + allocs_.clear(); + } + + MemoryPoolItem *MemoryPoolHeadMT::get() + { + bool expected = false; + while (!locked_.compare_exchange_strong(expected, true, memory_order_acquire)) + { + expected = false; + } + MemoryPoolItem *old_first = first_item_; + + // Is pool empty? + if (old_first == nullptr) + { + allocation &last_alloc = allocs_.back(); + MemoryPoolItem *new_item = nullptr; + if (last_alloc.free > 0) + { + // Pool is empty; there is memory + new_item = new MemoryPoolItem(last_alloc.head_ptr); + last_alloc.free--; + last_alloc.head_ptr += item_byte_count_; + } + else + { + // Pool is empty; there is no memory + allocation new_alloc; + + // Increase allocation size unless we are already at max + size_t new_size = safe_cast<size_t>( + ceil(MemoryPool::alloc_size_multiplier * static_cast<double>(last_alloc.size))); + size_t new_alloc_byte_count = mul_safe(new_size, item_byte_count_); + if (new_alloc_byte_count > MemoryPool::max_batch_alloc_byte_count) + { + new_size = last_alloc.size; + new_alloc_byte_count = new_size * item_byte_count_; + } + + try + { + new_alloc.data_ptr = new SEAL_BYTE[new_alloc_byte_count]; + } + catch (const bad_alloc &) + { + // Allocation failed; rethrow + throw; + } + + new_alloc.size = new_size; + new_alloc.free = new_size - 1; + new_alloc.head_ptr = new_alloc.data_ptr + item_byte_count_; + allocs_.push_back(new_alloc); + item_count_ += new_size; + new_item = new MemoryPoolItem(new_alloc.data_ptr); + } + + locked_.store(false, memory_order_release); + return new_item; + } + + // Pool is not empty + first_item_ = old_first->next(); + old_first->next() = nullptr; + locked_.store(false, memory_order_release); + return old_first; + } + + MemoryPoolHeadST::MemoryPoolHeadST(size_t item_byte_count, bool clear_on_destruction) + : clear_on_destruction_(clear_on_destruction), item_byte_count_(item_byte_count), + item_count_(MemoryPool::first_alloc_count), first_item_(nullptr) + { + if ((item_byte_count_ == 0) || (item_byte_count_ > MemoryPool::max_batch_alloc_byte_count) || + (mul_safe(item_byte_count_, MemoryPool::first_alloc_count) > MemoryPool::max_batch_alloc_byte_count)) + { + throw invalid_argument("invalid allocation size"); + } + + // Initial allocation + allocation new_alloc; + try + { + new_alloc.data_ptr = new SEAL_BYTE[mul_safe(MemoryPool::first_alloc_count, item_byte_count_)]; + } + catch (const bad_alloc &) + { + // Allocation failed; rethrow + throw; + } + + new_alloc.size = MemoryPool::first_alloc_count; + new_alloc.free = MemoryPool::first_alloc_count; + new_alloc.head_ptr = new_alloc.data_ptr; + allocs_.clear(); + allocs_.push_back(new_alloc); + } + + MemoryPoolHeadST::~MemoryPoolHeadST() noexcept + { + // Delete the items (but not the memory) + MemoryPoolItem *curr_item = first_item_; + while (curr_item) + { + MemoryPoolItem *next_item = curr_item->next(); + delete curr_item; + curr_item = next_item; + } + first_item_ = nullptr; + + // Do we need to clear the memory? + if (clear_on_destruction_) + { + // Delete the memory + for (auto &alloc : allocs_) + { + size_t curr_alloc_byte_count = mul_safe(item_byte_count_, alloc.size); + volatile SEAL_BYTE *data_ptr = reinterpret_cast<SEAL_BYTE *>(alloc.data_ptr); + while (curr_alloc_byte_count--) + { + *data_ptr++ = static_cast<SEAL_BYTE>(0); + } + + // Delete this allocation + delete[] alloc.data_ptr; + } + } + else + { + // Delete the memory + for (auto &alloc : allocs_) + { + // Delete this allocation + delete[] alloc.data_ptr; + } + } + + allocs_.clear(); + } + + MemoryPoolItem *MemoryPoolHeadST::get() + { + MemoryPoolItem *old_first = first_item_; + + // Is pool empty? + if (old_first == nullptr) + { + allocation &last_alloc = allocs_.back(); + MemoryPoolItem *new_item = nullptr; + if (last_alloc.free > 0) + { + // Pool is empty; there is memory + new_item = new MemoryPoolItem(last_alloc.head_ptr); + last_alloc.free--; + last_alloc.head_ptr += item_byte_count_; + } + else + { + // Pool is empty; there is no memory + allocation new_alloc; + + // Increase allocation size unless we are already at max + size_t new_size = safe_cast<size_t>( + ceil(MemoryPool::alloc_size_multiplier * static_cast<double>(last_alloc.size))); + size_t new_alloc_byte_count = mul_safe(new_size, item_byte_count_); + if (new_alloc_byte_count > MemoryPool::max_batch_alloc_byte_count) + { + new_size = last_alloc.size; + new_alloc_byte_count = new_size * item_byte_count_; + } + + try + { + new_alloc.data_ptr = new SEAL_BYTE[new_alloc_byte_count]; + } + catch (const bad_alloc &) + { + // Allocation failed; rethrow + throw; + } + + new_alloc.size = new_size; + new_alloc.free = new_size - 1; + new_alloc.head_ptr = new_alloc.data_ptr + item_byte_count_; + allocs_.push_back(new_alloc); + item_count_ += new_size; + new_item = new MemoryPoolItem(new_alloc.data_ptr); + } + + return new_item; + } + + // Pool is not empty + first_item_ = old_first->next(); + old_first->next() = nullptr; + return old_first; + } + + const size_t MemoryPool::max_single_alloc_byte_count = []() -> size_t { + int bit_shift = static_cast<int>(ceil(log2(MemoryPool::alloc_size_multiplier))); + if (bit_shift < 0 || unsigned_geq(bit_shift, sizeof(size_t) * static_cast<size_t>(bits_per_byte))) + { + throw logic_error("alloc_size_multiplier too large"); + } + return numeric_limits<size_t>::max() >> bit_shift; + }(); + + const size_t MemoryPool::max_batch_alloc_byte_count = []() -> size_t { + int bit_shift = static_cast<int>(ceil(log2(MemoryPool::alloc_size_multiplier))); + if (bit_shift < 0 || unsigned_geq(bit_shift, sizeof(size_t) * static_cast<size_t>(bits_per_byte))) + { + throw logic_error("alloc_size_multiplier too large"); + } + return numeric_limits<size_t>::max() >> bit_shift; + }(); + + MemoryPoolMT::~MemoryPoolMT() noexcept + { + WriterLock lock(pools_locker_.acquire_write()); + for (MemoryPoolHead *head : pools_) + { + delete head; + } + pools_.clear(); + } + + Pointer<SEAL_BYTE> MemoryPoolMT::get_for_byte_count(size_t byte_count) + { + if (byte_count > max_single_alloc_byte_count) + { + throw invalid_argument("invalid allocation size"); + } + else if (byte_count == 0) + { + return Pointer<SEAL_BYTE>(); + } + + // Attempt to find size. + ReaderLock reader_lock(pools_locker_.acquire_read()); + size_t start = 0; + size_t end = pools_.size(); + while (start < end) + { + size_t mid = (start + end) / 2; + MemoryPoolHead *mid_head = pools_[mid]; + size_t mid_byte_count = mid_head->item_byte_count(); + if (byte_count < mid_byte_count) + { + start = mid + 1; + } + else if (byte_count > mid_byte_count) + { + end = mid; + } + else + { + return Pointer<SEAL_BYTE>(mid_head); + } + } + reader_lock.unlock(); + + // Size was not found, so obtain an exclusive lock and search again. + WriterLock writer_lock(pools_locker_.acquire_write()); + start = 0; + end = pools_.size(); + while (start < end) + { + size_t mid = (start + end) / 2; + MemoryPoolHead *mid_head = pools_[mid]; + size_t mid_byte_count = mid_head->item_byte_count(); + if (byte_count < mid_byte_count) + { + start = mid + 1; + } + else if (byte_count > mid_byte_count) + { + end = mid; + } + else + { + return Pointer<SEAL_BYTE>(mid_head); + } + } + + // Size was still not found, but we own an exclusive lock so just add it, + // but first check if we are at maximum pool head count already. + if (pools_.size() >= max_pool_head_count) + { + throw runtime_error("maximum pool head count reached"); + } + + MemoryPoolHead *new_head = new MemoryPoolHeadMT(byte_count, clear_on_destruction_); + if (!pools_.empty()) + { + pools_.insert(pools_.begin() + static_cast<ptrdiff_t>(start), new_head); + } + else + { + pools_.emplace_back(new_head); + } + + return Pointer<SEAL_BYTE>(new_head); + } + + size_t MemoryPoolMT::alloc_byte_count() const + { + ReaderLock lock(pools_locker_.acquire_read()); + + return accumulate(pools_.cbegin(), pools_.cend(), size_t(0), [](size_t byte_count, MemoryPoolHead *head) { + return add_safe(byte_count, mul_safe(head->item_count(), head->item_byte_count())); + }); + } + + MemoryPoolST::~MemoryPoolST() noexcept + { + for (MemoryPoolHead *head : pools_) + { + delete head; + } + pools_.clear(); + } + + Pointer<SEAL_BYTE> MemoryPoolST::get_for_byte_count(size_t byte_count) + { + if (byte_count > MemoryPool::max_single_alloc_byte_count) + { + throw invalid_argument("invalid allocation size"); + } + else if (byte_count == 0) + { + return Pointer<SEAL_BYTE>(); + } + + // Attempt to find size. + size_t start = 0; + size_t end = pools_.size(); + while (start < end) + { + size_t mid = (start + end) / 2; + MemoryPoolHead *mid_head = pools_[mid]; + size_t mid_byte_count = mid_head->item_byte_count(); + if (byte_count < mid_byte_count) + { + start = mid + 1; + } + else if (byte_count > mid_byte_count) + { + end = mid; + } + else + { + return Pointer<SEAL_BYTE>(mid_head); + } + } + + // Size was not found so just add it, but first check if we are at + // maximum pool head count already. + if (pools_.size() >= max_pool_head_count) + { + throw runtime_error("maximum pool head count reached"); + } + + MemoryPoolHead *new_head = new MemoryPoolHeadST(byte_count, clear_on_destruction_); + if (!pools_.empty()) + { + pools_.insert(pools_.begin() + static_cast<ptrdiff_t>(start), new_head); + } + else + { + pools_.emplace_back(new_head); + } + + return Pointer<SEAL_BYTE>(new_head); + } + + size_t MemoryPoolST::alloc_byte_count() const + { + return accumulate(pools_.cbegin(), pools_.cend(), size_t(0), [](size_t byte_count, MemoryPoolHead *head) { + return add_safe(byte_count, mul_safe(head->item_count(), head->item_byte_count())); + }); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/mempool.h b/bigpiseal3.5.1/native/src/seal/util/mempool.h new file mode 100644 index 0000000000000000000000000000000000000000..adf518958da87f6207abbf459caa234dbc4cff3a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/mempool.h @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/globals.h" +#include "seal/util/locks.h" +#include <algorithm> +#include <atomic> +#include <cstdint> +#include <cstring> +#include <limits> +#include <memory> +#include <new> +#include <stdexcept> +#include <type_traits> +#include <vector> + +namespace seal +{ + namespace util + { + template <typename T = void, typename = std::enable_if_t<std::is_standard_layout<T>::value>> + class ConstPointer; + + template <> + class ConstPointer<SEAL_BYTE>; + + template <typename T = void, typename = std::enable_if_t<std::is_standard_layout<T>::value>> + class Pointer; + + class MemoryPoolItem + { + public: + MemoryPoolItem(SEAL_BYTE *data) noexcept : data_(data) + {} + + SEAL_NODISCARD inline SEAL_BYTE *data() noexcept + { + return data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE *data() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline MemoryPoolItem *&next() noexcept + { + return next_; + } + + SEAL_NODISCARD inline const MemoryPoolItem *next() const noexcept + { + return next_; + } + + private: + MemoryPoolItem(const MemoryPoolItem &copy) = delete; + + MemoryPoolItem &operator=(const MemoryPoolItem &assign) = delete; + + SEAL_BYTE *data_ = nullptr; + + MemoryPoolItem *next_ = nullptr; + }; + + class MemoryPoolHead + { + public: + struct allocation + { + allocation() : size(0), data_ptr(nullptr), free(0), head_ptr(nullptr) + {} + + // Size of the allocation (number of items it can hold) + std::size_t size; + + // Pointer to start of the allocation + SEAL_BYTE *data_ptr; + + // How much free space is left (number of items that still fit) + std::size_t free; + + // Pointer to current head of allocation + SEAL_BYTE *head_ptr; + }; + + // The overriding functions are noexcept(false) + virtual ~MemoryPoolHead() = default; + + // Byte size of the allocations (items) owned by this pool + virtual std::size_t item_byte_count() const noexcept = 0; + + // Total number of items allocated + virtual std::size_t item_count() const noexcept = 0; + + virtual MemoryPoolItem *get() = 0; + + // Return item back to this pool + virtual void add(MemoryPoolItem *new_first) noexcept = 0; + }; + + class MemoryPoolHeadMT : public MemoryPoolHead + { + public: + // Creates a new MemoryPoolHeadMT with allocation for one single item. + MemoryPoolHeadMT(std::size_t item_byte_count, bool clear_on_destruction = false); + + ~MemoryPoolHeadMT() noexcept override; + + // Byte size of the allocations (items) owned by this pool + SEAL_NODISCARD inline std::size_t item_byte_count() const noexcept override + { + return item_byte_count_; + } + + // Returns the total number of items allocated + SEAL_NODISCARD inline std::size_t item_count() const noexcept override + { + return item_count_; + } + + MemoryPoolItem *get() override; + + inline void add(MemoryPoolItem *new_first) noexcept override + { + bool expected = false; + while (!locked_.compare_exchange_strong(expected, true, std::memory_order_acquire)) + { + expected = false; + } + MemoryPoolItem *old_first = first_item_; + new_first->next() = old_first; + first_item_ = new_first; + locked_.store(false, std::memory_order_release); + } + + private: + MemoryPoolHeadMT(const MemoryPoolHeadMT &copy) = delete; + + MemoryPoolHeadMT &operator=(const MemoryPoolHeadMT &assign) = delete; + + const bool clear_on_destruction_; + + mutable std::atomic<bool> locked_; + + const std::size_t item_byte_count_; + + volatile std::size_t item_count_; + + std::vector<allocation> allocs_; + + MemoryPoolItem *volatile first_item_; + }; + + class MemoryPoolHeadST : public MemoryPoolHead + { + public: + // Creates a new MemoryPoolHeadST with allocation for one single item. + MemoryPoolHeadST(std::size_t item_byte_count, bool clear_on_destruction = false); + + ~MemoryPoolHeadST() noexcept override; + + // Byte size of the allocations (items) owned by this pool + SEAL_NODISCARD inline std::size_t item_byte_count() const noexcept override + { + return item_byte_count_; + } + + // Returns the total number of items allocated + SEAL_NODISCARD inline std::size_t item_count() const noexcept override + { + return item_count_; + } + + SEAL_NODISCARD MemoryPoolItem *get() override; + + inline void add(MemoryPoolItem *new_first) noexcept override + { + new_first->next() = first_item_; + first_item_ = new_first; + } + + private: + MemoryPoolHeadST(const MemoryPoolHeadST &copy) = delete; + + MemoryPoolHeadST &operator=(const MemoryPoolHeadST &assign) = delete; + + const bool clear_on_destruction_; + + std::size_t item_byte_count_; + + std::size_t item_count_; + + std::vector<allocation> allocs_; + + MemoryPoolItem *first_item_; + }; + + class MemoryPool + { + public: + static constexpr double alloc_size_multiplier = 1.05; + + // Largest size of single allocation that can be requested from memory pool + static const std::size_t max_single_alloc_byte_count; + + // Number of different size allocations allowed by a single memory pool + static constexpr std::size_t max_pool_head_count = std::numeric_limits<std::size_t>::max(); + + // Largest allowed size of batch allocation + static const std::size_t max_batch_alloc_byte_count; + + static constexpr std::size_t first_alloc_count = 1; + + virtual ~MemoryPool() = default; + + virtual Pointer<SEAL_BYTE> get_for_byte_count(std::size_t byte_count) = 0; + + virtual std::size_t pool_count() const = 0; + + virtual std::size_t alloc_byte_count() const = 0; + }; + + class MemoryPoolMT : public MemoryPool + { + public: + MemoryPoolMT(bool clear_on_destruction = false) : clear_on_destruction_(clear_on_destruction){}; + + ~MemoryPoolMT() noexcept override; + + SEAL_NODISCARD Pointer<SEAL_BYTE> get_for_byte_count(std::size_t byte_count) override; + + SEAL_NODISCARD inline std::size_t pool_count() const override + { + ReaderLock lock(pools_locker_.acquire_read()); + return pools_.size(); + } + + SEAL_NODISCARD std::size_t alloc_byte_count() const override; + + protected: + MemoryPoolMT(const MemoryPoolMT &copy) = delete; + + MemoryPoolMT &operator=(const MemoryPoolMT &assign) = delete; + + const bool clear_on_destruction_; + + mutable ReaderWriterLocker pools_locker_; + + std::vector<MemoryPoolHead *> pools_; + }; + + class MemoryPoolST : public MemoryPool + { + public: + MemoryPoolST(bool clear_on_destruction = false) : clear_on_destruction_(clear_on_destruction){}; + + ~MemoryPoolST() noexcept override; + + SEAL_NODISCARD Pointer<SEAL_BYTE> get_for_byte_count(std::size_t byte_count) override; + + SEAL_NODISCARD inline std::size_t pool_count() const override + { + return pools_.size(); + } + + std::size_t alloc_byte_count() const override; + + protected: + MemoryPoolST(const MemoryPoolST &copy) = delete; + + MemoryPoolST &operator=(const MemoryPoolST &assign) = delete; + + const bool clear_on_destruction_; + + std::vector<MemoryPoolHead *> pools_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/msvc.h b/bigpiseal3.5.1/native/src/seal/util/msvc.h new file mode 100644 index 0000000000000000000000000000000000000000..5115b10d434b5b84521b7fd6cbc37e4c0202825a --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/msvc.h @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#if SEAL_COMPILER == SEAL_COMPILER_MSVC + +// Require Visual Studio 2017 version 15.3 or newer +#if (_MSC_VER < 1911) +#error "Microsoft Visual Studio 2017 version 15.3 or newer required" +#endif + +// Read in config.h +#include "seal/util/config.h" + +// Do not throw when Evaluator produces transparent ciphertexts +//#undef SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT + +// In Visual Studio redefine std::byte (SEAL_BYTE) +#undef SEAL_USE_STD_BYTE + +// In Visual Studio for now we disable the use of std::shared_mutex +#undef SEAL_USE_SHARED_MUTEX + +// Are we compiling with C++17 or newer +#if (__cplusplus >= 201703L) + +// Use `if constexpr' +#define SEAL_USE_IF_CONSTEXPR + +// Use [[maybe_unused]] +#define SEAL_USE_MAYBE_UNUSED + +// Use [[nodiscard]] +#define SEAL_USE_NODISCARD + +#else +#undef SEAL_USE_IF_CONSTEXPR +#undef SEAL_USE_MAYBE_UNUSED +#undef SEAL_USE_NODISCARD +#endif + +// X64 +#ifdef _M_X64 + +#ifdef SEAL_USE_INTRIN +#include <intrin.h> + +#ifdef SEAL_USE__UMUL128 +#pragma intrinsic(_umul128) +#define SEAL_MULTIPLY_UINT64_HW64(operand1, operand2, hw64) \ + { \ + _umul128(operand1, operand2, hw64); \ + } + +#define SEAL_MULTIPLY_UINT64(operand1, operand2, result128) \ + { \ + result128[0] = _umul128(operand1, operand2, result128 + 1); \ + } +#endif + +#ifdef SEAL_USE__BITSCANREVERSE64 +#pragma intrinsic(_BitScanReverse64) +#define SEAL_MSB_INDEX_UINT64(result, value) _BitScanReverse64(result, value) +#endif + +#ifdef SEAL_USE__ADDCARRY_U64 +#pragma intrinsic(_addcarry_u64) +#define SEAL_ADD_CARRY_UINT64(operand1, operand2, carry, result) _addcarry_u64(carry, operand1, operand2, result) +#endif + +#ifdef SEAL_USE__SUBBORROW_U64 +#pragma intrinsic(_subborrow_u64) +#define SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result) _subborrow_u64(borrow, operand1, operand2, result) +#endif + +#endif +#else +#undef SEAL_USE_INTRIN + +#endif //_M_X64 + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/ntt.cpp b/bigpiseal3.5.1/native/src/seal/util/ntt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d195ea53ab8df528643d2e1a72598fcaa3fdd3c --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/ntt.cpp @@ -0,0 +1,432 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/defines.h" +#include "seal/util/ntt.h" +#include "seal/util/polyarith.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include <algorithm> + +using namespace std; + +namespace seal +{ + namespace util + { + NTTTables::NTTTables(int coeff_count_power, const Modulus &modulus, MemoryPoolHandle pool) : pool_(move(pool)) + { +#ifdef SEAL_DEBUG + if (!pool_) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + initialize(coeff_count_power, modulus); + } + + void NTTTables::initialize(int coeff_count_power, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if ((coeff_count_power < get_power_of_two(SEAL_POLY_MOD_DEGREE_MIN)) || + coeff_count_power > get_power_of_two(SEAL_POLY_MOD_DEGREE_MAX)) + { + throw invalid_argument("coeff_count_power out of range"); + } +#endif + coeff_count_power_ = coeff_count_power; + coeff_count_ = size_t(1) << coeff_count_power_; + + // Allocate memory for the tables + root_powers_ = allocate_uint(coeff_count_, pool_); + inv_root_powers_ = allocate_uint(coeff_count_, pool_); + scaled_root_powers_ = allocate_uint(coeff_count_, pool_); + scaled_inv_root_powers_ = allocate_uint(coeff_count_, pool_); + modulus_ = modulus; + + // We defer parameter checking to try_minimal_primitive_root(...) + if (!try_minimal_primitive_root(2 * coeff_count_, modulus_, root_)) + { + throw invalid_argument("invalid modulus"); + } + + uint64_t inverse_root; + if (!try_invert_uint_mod(root_, modulus_, inverse_root)) + { + throw invalid_argument("invalid modulus"); + } + + // Populate the tables storing (scaled version of) powers of root + // mod q in bit-scrambled order. + ntt_powers_of_primitive_root(root_, root_powers_.get()); + ntt_scale_powers_of_primitive_root(root_powers_.get(), scaled_root_powers_.get()); + + // Populate the tables storing (scaled version of) powers of + // (root)^{-1} mod q in bit-scrambled order. + ntt_powers_of_primitive_root(inverse_root, inv_root_powers_.get()); + ntt_scale_powers_of_primitive_root(inv_root_powers_.get(), scaled_inv_root_powers_.get()); + + // Reordering inv_root_powers_ so that the access pattern in inverse NTT is sequential. + auto temp = allocate_uint(coeff_count_, pool_); + uint64_t *temp_ptr = temp.get() + 1; + for (size_t m = (coeff_count_ >> 1); m > 0; m >>= 1) + { + for (size_t i = 0; i < m; i++) + { + *temp_ptr++ = inv_root_powers_[m + i]; + } + } + set_uint_uint(temp.get() + 1, coeff_count_ - 1, inv_root_powers_.get() + 1); + + temp_ptr = temp.get() + 1; + for (size_t m = (coeff_count_ >> 1); m > 0; m >>= 1) + { + for (size_t i = 0; i < m; i++) + { + *temp_ptr++ = scaled_inv_root_powers_[m + i]; + } + } + set_uint_uint(temp.get() + 1, coeff_count_ - 1, scaled_inv_root_powers_.get() + 1); + + // Last compute n^(-1) modulo q. + uint64_t degree_uint = static_cast<uint64_t>(coeff_count_); + if (!try_invert_uint_mod(degree_uint, modulus_, inv_degree_modulo_)) + { + throw invalid_argument("invalid modulus"); + } + + return; + } + + void NTTTables::ntt_powers_of_primitive_root(uint64_t root, uint64_t *destination) const + { + uint64_t *destination_start = destination; + *destination_start = 1; + for (size_t i = 1; i < coeff_count_; i++) + { + uint64_t *next_destination = destination_start + reverse_bits(i, coeff_count_power_); + *next_destination = multiply_uint_uint_mod(*destination, root, modulus_); + destination = next_destination; + } + } + + // Compute floor (input * beta /q), where beta is a 64k power of 2 and 0 < q < beta. + void NTTTables::ntt_scale_powers_of_primitive_root(const uint64_t *input, uint64_t *destination) const + { + for (size_t i = 0; i < coeff_count_; i++, input++, destination++) + { + uint64_t wide_quotient[2]{ 0, 0 }; + uint64_t wide_coeff[2]{ 0, *input }; + divide_uint128_uint64_inplace(wide_coeff, modulus_.value(), wide_quotient); + *destination = wide_quotient[0]; + } + } + + class NTTTablesCreateIter + { + public: + using value_type = NTTTables; + using pointer = void; + using reference = value_type; + using difference_type = std::ptrdiff_t; + + // LegacyInputIterator allows reference to be equal to value_type so we can construct + // the return objects on the fly and return by value. + using iterator_category = std::input_iterator_tag; + + // Require default constructor + NTTTablesCreateIter() + {} + + // Other constructors + NTTTablesCreateIter(int coeff_count_power, vector<Modulus> modulus, MemoryPoolHandle pool) + : coeff_count_power_(coeff_count_power), modulus_(modulus), pool_(pool) + {} + + // Require copy and move constructors and assignments + NTTTablesCreateIter(const NTTTablesCreateIter &copy) = default; + + NTTTablesCreateIter(NTTTablesCreateIter &&source) = default; + + NTTTablesCreateIter &operator=(const NTTTablesCreateIter &assign) = default; + + NTTTablesCreateIter &operator=(NTTTablesCreateIter &&assign) = default; + + // Dereferencing creates NTTTables and returns by value + inline value_type operator*() const + { + return { coeff_count_power_, modulus_[index_], pool_ }; + } + + // Pre-increment + inline NTTTablesCreateIter &operator++() noexcept + { + index_++; + return *this; + } + + // Post-increment + inline NTTTablesCreateIter operator++(int) noexcept + { + NTTTablesCreateIter result(*this); + index_++; + return result; + } + + // Must be EqualityComparable + inline bool operator==(const NTTTablesCreateIter &compare) const noexcept + { + return (compare.index_ == index_) && (coeff_count_power_ == compare.coeff_count_power_); + } + + inline bool operator!=(const NTTTablesCreateIter &compare) const noexcept + { + return !operator==(compare); + } + + // Arrow operator must be defined + value_type operator->() const + { + return **this; + } + + private: + size_t index_ = 0; + int coeff_count_power_ = 0; + vector<Modulus> modulus_; + MemoryPoolHandle pool_; + }; + + void CreateNTTTables( + int coeff_count_power, const vector<Modulus> &modulus, Pointer<NTTTables> &tables, MemoryPoolHandle pool) + { + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + if (!modulus.size()) + { + throw invalid_argument("invalid modulus"); + } + // coeff_count_power and modulus will be validated by "allocate" + + NTTTablesCreateIter iter(coeff_count_power, modulus, pool); + tables = allocate(iter, modulus.size(), pool); + } + + /** + This function computes in-place the negacyclic NTT. The input is + a polynomial a of degree n in R_q, where n is assumed to be a power of + 2 and q is a prime such that q = 1 (mod 2n). + + The output is a vector A such that the following hold: + A[j] = a(psi**(2*bit_reverse(j) + 1)), 0 <= j < n. + + For details, see Michael Naehrig and Patrick Longa. + */ + void ntt_negacyclic_harvey_lazy(uint64_t *operand, const NTTTables &tables) + { + uint64_t modulus = tables.modulus().value(); + uint64_t two_times_modulus = modulus << 1; + + // Return the NTT in scrambled order + size_t n = size_t(1) << tables.coeff_count_power(); + size_t t = n >> 1; + for (size_t m = 1; m < n; m <<= 1) + { + size_t j1 = 0; + if (t >= 4) + { + for (size_t i = 0; i < m; i++) + { + size_t j2 = j1 + t; + const uint64_t W = tables.get_from_root_powers(m + i); + const uint64_t Wprime = tables.get_from_scaled_root_powers(m + i); + + uint64_t *X = operand + j1; + uint64_t *Y = X + t; + uint64_t tx; + unsigned long long Q; + for (size_t j = j1; j < j2; j += 4) + { + tx = *X - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(*X >= two_times_modulus))); + multiply_uint64_hw64(Wprime, *Y, &Q); + Q = *Y * W - Q * modulus; + *X++ = tx + Q; + *Y++ = tx + two_times_modulus - Q; + + tx = *X - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(*X >= two_times_modulus))); + multiply_uint64_hw64(Wprime, *Y, &Q); + Q = *Y * W - Q * modulus; + *X++ = tx + Q; + *Y++ = tx + two_times_modulus - Q; + + tx = *X - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(*X >= two_times_modulus))); + multiply_uint64_hw64(Wprime, *Y, &Q); + Q = *Y * W - Q * modulus; + *X++ = tx + Q; + *Y++ = tx + two_times_modulus - Q; + + tx = *X - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(*X >= two_times_modulus))); + multiply_uint64_hw64(Wprime, *Y, &Q); + Q = *Y * W - Q * modulus; + *X++ = tx + Q; + *Y++ = tx + two_times_modulus - Q; + } + j1 += (t << 1); + } + } + else + { + for (size_t i = 0; i < m; i++) + { + size_t j2 = j1 + t; + const uint64_t W = tables.get_from_root_powers(m + i); + const uint64_t Wprime = tables.get_from_scaled_root_powers(m + i); + + uint64_t *X = operand + j1; + uint64_t *Y = X + t; + uint64_t tx; + unsigned long long Q; + for (size_t j = j1; j < j2; j++) + { + // The Harvey butterfly: assume X, Y in [0, 2p), and return X', Y' in [0, 4p). + // X', Y' = X + WY, X - WY (mod p). + tx = *X - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(*X >= two_times_modulus))); + multiply_uint64_hw64(Wprime, *Y, &Q); + Q = W * *Y - Q * modulus; + *X++ = tx + Q; + *Y++ = tx + two_times_modulus - Q; + } + j1 += (t << 1); + } + } + t >>= 1; + } + } + + // Inverse negacyclic NTT using Harvey's butterfly. (See Patrick Longa and Michael Naehrig). + void inverse_ntt_negacyclic_harvey_lazy(uint64_t *operand, const NTTTables &tables) + { + uint64_t modulus = tables.modulus().value(); + uint64_t two_times_modulus = modulus << 1; + + // return the bit-reversed order of NTT. + size_t n = size_t(1) << tables.coeff_count_power(); + size_t t = 1; + size_t root_index = 1; + for (size_t m = (n >> 1); m > 1; m >>= 1) + { + size_t j1 = 0; + if (t >= 4) + { + for (size_t i = 0; i < m; i++, root_index++) + { + size_t j2 = j1 + t; + const uint64_t W = tables.get_from_inv_root_powers(root_index); + const uint64_t Wprime = tables.get_from_scaled_inv_root_powers(root_index); + + uint64_t *X = operand + j1; + uint64_t *Y = X + t; + uint64_t tx; + uint64_t ty; + unsigned long long Q; + for (size_t j = j1; j < j2; j += 4) + { + tx = *X + *Y; + ty = *X + two_times_modulus - *Y; + *X++ = tx - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus))); + multiply_uint64_hw64(Wprime, ty, &Q); + *Y++ = ty * W - Q * modulus; + + tx = *X + *Y; + ty = *X + two_times_modulus - *Y; + *X++ = tx - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus))); + multiply_uint64_hw64(Wprime, ty, &Q); + *Y++ = ty * W - Q * modulus; + + tx = *X + *Y; + ty = *X + two_times_modulus - *Y; + *X++ = tx - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus))); + multiply_uint64_hw64(Wprime, ty, &Q); + *Y++ = ty * W - Q * modulus; + + tx = *X + *Y; + ty = *X + two_times_modulus - *Y; + *X++ = tx - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus))); + multiply_uint64_hw64(Wprime, ty, &Q); + *Y++ = ty * W - Q * modulus; + } + j1 += (t << 1); + } + } + else + { + for (size_t i = 0; i < m; i++, root_index++) + { + size_t j2 = j1 + t; + const uint64_t W = tables.get_from_inv_root_powers(root_index); + const uint64_t Wprime = tables.get_from_scaled_inv_root_powers(root_index); + + uint64_t *X = operand + j1; + uint64_t *Y = X + t; + uint64_t tx; + uint64_t ty; + unsigned long long Q; + for (size_t j = j1; j < j2; j++) + { + tx = *X + *Y; + ty = *X + two_times_modulus - *Y; + *X++ = tx - (two_times_modulus & + static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus))); + multiply_uint64_hw64(Wprime, ty, &Q); + *Y++ = ty * W - Q * modulus; + } + j1 += (t << 1); + } + } + t <<= 1; + } + + const uint64_t inv_N = *(tables.get_inv_degree_modulo()); + const uint64_t W = tables.get_from_inv_root_powers(root_index); + const uint64_t inv_N_W = multiply_uint_uint_mod(inv_N, W, tables.modulus()); + uint64_t wide_quotient[2]{ 0, 0 }; + uint64_t wide_coeff[2]{ 0, inv_N }; + divide_uint128_uint64_inplace(wide_coeff, modulus, wide_quotient); + const uint64_t inv_Nprime = wide_quotient[0]; + wide_quotient[0] = 0; + wide_quotient[1] = 0; + wide_coeff[0] = 0; + wide_coeff[1] = inv_N_W; + divide_uint128_uint64_inplace(wide_coeff, modulus, wide_quotient); + const uint64_t inv_N_Wprime = wide_quotient[0]; + + uint64_t *X = operand; + uint64_t *Y = X + (n >> 1); + uint64_t tx; + uint64_t ty; + unsigned long long Q; + for (size_t j = (n >> 1); j < n; j++) + { + tx = *X + *Y; + tx -= two_times_modulus & static_cast<uint64_t>(-static_cast<int64_t>(tx >= two_times_modulus)); + ty = *X + two_times_modulus - *Y; + multiply_uint64_hw64(inv_Nprime, tx, &Q); + *X++ = inv_N * tx - Q * modulus; + multiply_uint64_hw64(inv_N_Wprime, ty, &Q); + *Y++ = inv_N_W * ty - Q * modulus; + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/ntt.h b/bigpiseal3.5.1/native/src/seal/util/ntt.h new file mode 100644 index 0000000000000000000000000000000000000000..bb0747a6894c1e92984005efc3657d178cbf62d3 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/ntt.h @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/util/pointer.h" +#include "seal/util/uintcore.h" +#include <stdexcept> + +namespace seal +{ + namespace util + { + class NTTTables + { + public: + NTTTables(NTTTables &&source) = default; + + NTTTables(NTTTables &copy) + : pool_(copy.pool_), root_(copy.root_), coeff_count_power_(copy.coeff_count_power_), + coeff_count_(copy.coeff_count_), modulus_(copy.modulus_), inv_degree_modulo_(copy.inv_degree_modulo_) + { + root_powers_ = allocate_uint(coeff_count_, pool_); + inv_root_powers_ = allocate_uint(coeff_count_, pool_); + scaled_root_powers_ = allocate_uint(coeff_count_, pool_); + scaled_inv_root_powers_ = allocate_uint(coeff_count_, pool_); + + set_uint_uint(copy.root_powers_.get(), coeff_count_, root_powers_.get()); + set_uint_uint(copy.inv_root_powers_.get(), coeff_count_, inv_root_powers_.get()); + set_uint_uint(copy.scaled_root_powers_.get(), coeff_count_, scaled_root_powers_.get()); + set_uint_uint(copy.scaled_inv_root_powers_.get(), coeff_count_, scaled_inv_root_powers_.get()); + } + + NTTTables(int coeff_count_power, const Modulus &modulus, MemoryPoolHandle pool = MemoryManager::GetPool()); + + SEAL_NODISCARD inline std::uint64_t get_root() const + { + return root_; + } + + SEAL_NODISCARD inline auto get_from_root_powers(std::size_t index) const -> std::uint64_t + { +#ifdef SEAL_DEBUG + if (index >= coeff_count_) + { + throw std::out_of_range("index"); + } +#endif + return root_powers_[index]; + } + + SEAL_NODISCARD inline auto get_from_scaled_root_powers(std::size_t index) const -> std::uint64_t + { +#ifdef SEAL_DEBUG + if (index >= coeff_count_) + { + throw std::out_of_range("index"); + } +#endif + return scaled_root_powers_[index]; + } + + SEAL_NODISCARD inline auto get_from_inv_root_powers(std::size_t index) const -> std::uint64_t + { +#ifdef SEAL_DEBUG + if (index >= coeff_count_) + { + throw std::out_of_range("index"); + } +#endif + return inv_root_powers_[index]; + } + + SEAL_NODISCARD inline auto get_from_scaled_inv_root_powers(std::size_t index) const -> std::uint64_t + { +#ifdef SEAL_DEBUG + if (index >= coeff_count_) + { + throw std::out_of_range("index"); + } +#endif + return scaled_inv_root_powers_[index]; + } + + SEAL_NODISCARD inline auto get_inv_degree_modulo() const -> const std::uint64_t * + { + return &inv_degree_modulo_; + } + + SEAL_NODISCARD inline const Modulus &modulus() const + { + return modulus_; + } + + SEAL_NODISCARD inline int coeff_count_power() const + { + return coeff_count_power_; + } + + SEAL_NODISCARD inline std::size_t coeff_count() const + { + return coeff_count_; + } + + private: + NTTTables &operator=(const NTTTables &assign) = delete; + + NTTTables &operator=(NTTTables &&assign) = delete; + + void initialize(int coeff_count_power, const Modulus &modulus); + + // Computed bit-scrambled vector of first 1 << coeff_count_power powers + // of a primitive root. + void ntt_powers_of_primitive_root(std::uint64_t root, std::uint64_t *destination) const; + + // Scales the elements of a vector returned by powers_of_primitive_root(...) + // by word_size/modulus and rounds down. + void ntt_scale_powers_of_primitive_root(const std::uint64_t *input, std::uint64_t *destination) const; + + MemoryPoolHandle pool_; + + std::uint64_t root_ = 0; + + // Size coeff_count_ + Pointer<std::uint64_t> root_powers_; + + // Size coeff_count_ + Pointer<std::uint64_t> scaled_root_powers_; + + int coeff_count_power_ = 0; + + std::size_t coeff_count_ = 0; + + Modulus modulus_; + + // Size coeff_count_ + Pointer<std::uint64_t> inv_root_powers_; + + // Size coeff_count_ + Pointer<std::uint64_t> scaled_inv_root_powers_; + + std::uint64_t inv_degree_modulo_ = 0; + }; + + /** + Allocate and construct an array of NTTTables each with different a modulus. + + @throws std::invalid_argument if modulus is empty, modulus does not support NTT, coeff_count_power is invalid, + or pool is uninitialized. + */ + void CreateNTTTables( + int coeff_count_power, const std::vector<Modulus> &modulus, Pointer<NTTTables> &tables, + MemoryPoolHandle pool); + + void ntt_negacyclic_harvey_lazy(std::uint64_t *operand, const NTTTables &tables); + + inline void ntt_negacyclic_harvey(std::uint64_t *operand, const NTTTables &tables) + { + ntt_negacyclic_harvey_lazy(operand, tables); + + // Finally maybe we need to reduce every coefficient modulo q, but we + // know that they are in the range [0, 4q). + // Since word size is controlled this is fast. + std::uint64_t modulus = tables.modulus().value(); + std::uint64_t two_times_modulus = modulus * 2; + std::size_t n = std::size_t(1) << tables.coeff_count_power(); + + for (; n--; operand++) + { + if (*operand >= two_times_modulus) + { + *operand -= two_times_modulus; + } + if (*operand >= modulus) + { + *operand -= modulus; + } + } + } + + void inverse_ntt_negacyclic_harvey_lazy(std::uint64_t *operand, const NTTTables &tables); + + inline void inverse_ntt_negacyclic_harvey(std::uint64_t *operand, const NTTTables &tables) + { + inverse_ntt_negacyclic_harvey_lazy(operand, tables); + + std::uint64_t modulus = tables.modulus().value(); + std::size_t n = std::size_t(1) << tables.coeff_count_power(); + + // Final adjustments; compute a[j] = a[j] * n^{-1} mod q. + // We incorporated the final adjustment in the butterfly. Only need + // to reduce here. + for (; n--; operand++) + { + if (*operand >= modulus) + { + *operand -= modulus; + } + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/numth.cpp b/bigpiseal3.5.1/native/src/seal/util/numth.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fef1fc8923d8835d3e5e313ff043d3c165cbfbd8 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/numth.cpp @@ -0,0 +1,426 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/numth.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <random> + +using namespace std; + +namespace seal +{ + namespace util + { + vector<uint64_t> conjugate_classes(uint64_t modulus, uint64_t subgroup_generator) + { +#ifdef SEAL_DEBUG + if (!product_fits_in(modulus, subgroup_generator) || !fits_in<size_t>(modulus)) + { + throw invalid_argument("inputs too large"); + } +#endif + vector<uint64_t> classes{}; + for (uint64_t i = 0; i < modulus; i++) + { + if (gcd(i, modulus) > 1) + { + classes.push_back(0); + } + else + { + classes.push_back(i); + } + } + for (uint64_t i = 0; i < modulus; i++) + { + if (classes[static_cast<size_t>(i)] == 0) + { + continue; + } + if (classes[static_cast<size_t>(i)] < i) + { + // i is not a pivot, updated its pivot + classes[static_cast<size_t>(i)] = classes[static_cast<size_t>(classes[static_cast<size_t>(i)])]; + continue; + } + // If i is a pivot, update other pivots to point to it + uint64_t j = (i * subgroup_generator) % modulus; + while (classes[static_cast<size_t>(j)] != i) + { + // Merge the equivalence classes of j and i + // Note: if classes[j] != j then classes[j] will be updated later, + // when we get to i = j and use the code for "i not pivot". + classes[static_cast<size_t>(classes[static_cast<size_t>(j)])] = i; + j = (j * subgroup_generator) % modulus; + } + } + return classes; + } + + bool try_invert_uint_mod(uint64_t value, uint64_t modulus, uint64_t &result) + { +#ifdef SEAL_DEBUG + if (modulus <= 1) + { + throw invalid_argument("modulus must be at least 2"); + } +#endif + if (value == 0) + { + return false; + } + auto gcd_tuple = xgcd(value, modulus); + if (get<0>(gcd_tuple) != 1) + { + return false; + } + else if (get<1>(gcd_tuple) < 0) + { + result = static_cast<uint64_t>(get<1>(gcd_tuple)) + modulus; + return true; + } + else + { + result = static_cast<uint64_t>(get<1>(gcd_tuple)); + return true; + } + } + + vector<uint64_t> multiplicative_orders(vector<uint64_t> conjugate_classes, uint64_t modulus) + { +#ifdef SEAL_DEBUG + if (!product_fits_in(modulus, modulus) || !fits_in<size_t>(modulus)) + { + throw invalid_argument("inputs too large"); + } +#endif + vector<uint64_t> orders{}; + orders.push_back(0); + orders.push_back(1); + + for (uint64_t i = 2; i < modulus; i++) + { + if (conjugate_classes[static_cast<size_t>(i)] <= 1) + { + orders.push_back(conjugate_classes[static_cast<size_t>(i)]); + continue; + } + if (conjugate_classes[static_cast<size_t>(i)] < i) + { + orders.push_back(orders[static_cast<size_t>(conjugate_classes[static_cast<size_t>(i)])]); + continue; + } + uint64_t j = (i * i) % modulus; + uint64_t order = 2; + while (conjugate_classes[static_cast<size_t>(j)] != 1) + { + j = (j * i) % modulus; + order++; + } + orders.push_back(order); + } + return orders; + } + + void babystep_giantstep(uint64_t modulus, vector<uint64_t> &baby_steps, vector<uint64_t> &giant_steps) + { + int exponent = get_power_of_two(modulus); + if (exponent < 0) + { + throw invalid_argument("modulus must be a power of 2"); + } + + // Compute square root of modulus (k stores the baby steps) + uint64_t k = uint64_t(1) << (exponent / 2); + uint64_t l = modulus / k; + + baby_steps.clear(); + giant_steps.clear(); + + uint64_t m = mul_safe(modulus, uint64_t(2)); + uint64_t g = 3; // the generator + uint64_t kprime = k >> 1; + uint64_t value = 1; + for (uint64_t i = 0; i < kprime; i++) + { + baby_steps.push_back(value); + baby_steps.push_back(m - value); + value = mul_safe(value, g) % m; + } + + // now value should equal to g**kprime + uint64_t value2 = value; + for (uint64_t j = 0; j < l; j++) + { + giant_steps.push_back(value2); + value2 = mul_safe(value2, value) % m; + } + } + + pair<size_t, size_t> decompose_babystep_giantstep( + uint64_t modulus, uint64_t input, const vector<uint64_t> &baby_steps, const vector<uint64_t> &giant_steps) + { + for (size_t i = 0; i < giant_steps.size(); i++) + { + uint64_t gs = giant_steps[i]; + for (size_t j = 0; j < baby_steps.size(); j++) + { + uint64_t bs = baby_steps[j]; + if (mul_safe(gs, bs) % modulus == input) + { + return { i, j }; + } + } + } + throw logic_error("failed to decompose input"); + } + + bool is_prime(const Modulus &modulus, size_t num_rounds) + { + uint64_t value = modulus.value(); + // First check the simplest cases. + if (value < 2) + { + return false; + } + if (2 == value) + { + return true; + } + if (0 == (value & 0x1)) + { + return false; + } + if (3 == value) + { + return true; + } + if (0 == (value % 3)) + { + return false; + } + if (5 == value) + { + return true; + } + if (0 == (value % 5)) + { + return false; + } + if (7 == value) + { + return true; + } + if (0 == (value % 7)) + { + return false; + } + if (11 == value) + { + return true; + } + if (0 == (value % 11)) + { + return false; + } + if (13 == value) + { + return true; + } + if (0 == (value % 13)) + { + return false; + } + + // Second, Miller-Rabin test. + // Find r and odd d that satisfy value = 2^r * d + 1. + uint64_t d = value - 1; + uint64_t r = 0; + while (0 == (d & 0x1)) + { + d >>= 1; + r++; + } + if (r == 0) + { + return false; + } + + // 1) Pick a = 2, check a^(value - 1). + // 2) Pick a randomly from [3, value - 1], check a^(value - 1). + // 3) Repeat 2) for another num_rounds - 2 times. + random_device rand; + uniform_int_distribution<unsigned long long> dist(3, value - 1); + for (size_t i = 0; i < num_rounds; i++) + { + uint64_t a = i ? dist(rand) : 2; + uint64_t x = exponentiate_uint_mod(a, d, modulus); + if (x == 1 || x == value - 1) + { + continue; + } + uint64_t count = 0; + do + { + x = multiply_uint_uint_mod(x, x, modulus); + count++; + } while (x != value - 1 && count < r - 1); + if (x != value - 1) + { + return false; + } + } + return true; + } + + vector<Modulus> get_primes(size_t ntt_size, int bit_size, size_t count) + { +#ifdef SEAL_DEBUG + if (!count) + { + throw invalid_argument("count must be positive"); + } + if (get_power_of_two(ntt_size) < 0) + { + throw invalid_argument("ntt_size must be a power of two"); + } + if (bit_size >= 63 || bit_size <= 1) + { + throw invalid_argument("bit_size is invalid"); + } +#endif + vector<Modulus> destination; + uint64_t factor = mul_safe(uint64_t(2), safe_cast<uint64_t>(ntt_size)); + + // Start with 2^bit_size - 2 * ntt_size + 1 + uint64_t value = uint64_t(0x1) << bit_size; + try + { + value = sub_safe(value, factor) + 1; + } + catch (const logic_error &) + { + throw logic_error("failed to find enough qualifying primes"); + } + + uint64_t lower_bound = uint64_t(0x1) << (bit_size - 1); + while (count > 0 && value > lower_bound) + { + Modulus new_mod(value); + if (new_mod.is_prime()) + { + destination.emplace_back(move(new_mod)); + count--; + } + value -= factor; + } + if (count > 0) + { + throw logic_error("failed to find enough qualifying primes"); + } + return destination; + } + + bool is_primitive_root(uint64_t root, uint64_t degree, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.bit_count() < 2) + { + throw invalid_argument("modulus"); + } + if (root >= modulus.value()) + { + throw out_of_range("operand"); + } + if (get_power_of_two(degree) < 1) + { + throw invalid_argument("degree must be a power of two and at least two"); + } +#endif + if (root == 0) + { + return false; + } + + // We check if root is a degree-th root of unity in integers modulo modulus, + // where degree is a power of two. It suffices to check that root^(degree/2) + // is -1 modulo modulus. + return exponentiate_uint_mod(root, degree >> 1, modulus) == (modulus.value() - 1); + } + + bool try_primitive_root(uint64_t degree, const Modulus &modulus, uint64_t &destination) + { +#ifdef SEAL_DEBUG + if (modulus.bit_count() < 2) + { + throw invalid_argument("modulus"); + } + if (get_power_of_two(degree) < 1) + { + throw invalid_argument("degree must be a power of two and at least two"); + } +#endif + // We need to divide modulus-1 by degree to get the size of the quotient group + uint64_t size_entire_group = modulus.value() - 1; + + // Compute size of quotient group + uint64_t size_quotient_group = size_entire_group / degree; + + // size_entire_group must be divisible by degree, or otherwise the primitive root does not + // exist in integers modulo modulus + if (size_entire_group - size_quotient_group * degree != 0) + { + return false; + } + + // For randomness + random_device rd; + + int attempt_counter = 0; + int attempt_counter_max = 100; + do + { + attempt_counter++; + + // Set destination to be a random number modulo modulus + destination = (static_cast<uint64_t>(rd()) << 32) | static_cast<uint64_t>(rd()); + destination %= modulus.value(); + + // Raise the random number to power the size of the quotient + // to get rid of irrelevant part + destination = exponentiate_uint_mod(destination, size_quotient_group, modulus); + } while (!is_primitive_root(destination, degree, modulus) && (attempt_counter < attempt_counter_max)); + + return is_primitive_root(destination, degree, modulus); + } + + bool try_minimal_primitive_root(uint64_t degree, const Modulus &modulus, uint64_t &destination) + { + uint64_t root; + if (!try_primitive_root(degree, modulus, root)) + { + return false; + } + uint64_t generator_sq = multiply_uint_uint_mod(root, root, modulus); + uint64_t current_generator = root; + + // destination is going to always contain the smallest generator found + for (size_t i = 0; i < degree; i++) + { + // If our current generator is strictly smaller than destination, + // update + if (current_generator < root) + { + root = current_generator; + } + + // Then move on to the next generator + current_generator = multiply_uint_uint_mod(current_generator, generator_sq, modulus); + } + + destination = root; + return true; + } + } // namespace util +} // namespace seal \ No newline at end of file diff --git a/bigpiseal3.5.1/native/src/seal/util/numth.h b/bigpiseal3.5.1/native/src/seal/util/numth.h new file mode 100644 index 0000000000000000000000000000000000000000..568cebd5f8ead0e85ea5d84150c21b54bdf25c64 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/numth.h @@ -0,0 +1,157 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include <cmath> +#include <cstddef> +#include <cstdint> +#include <stdexcept> +#include <tuple> +#include <vector> + +namespace seal +{ + namespace util + { + SEAL_NODISCARD inline std::vector<int> naf(int value) + { + std::vector<int> res; + + // Record the sign of the original value and compute abs + bool sign = value < 0; + value = std::abs(value); + + // Transform to non-adjacent form (NAF) + for (int i = 0; value; i++) + { + int zi = (value % 2) ? 2 - (value % 4) : 0; + value = (value - zi) / 2; + if (zi) + { + res.push_back((sign ? -zi : zi) * (1 << i)); + } + } + + return res; + } + + SEAL_NODISCARD inline std::uint64_t gcd(std::uint64_t x, std::uint64_t y) + { +#ifdef SEAL_DEBUG + if (x == 0) + { + throw std::invalid_argument("x cannot be zero"); + } + if (y == 0) + { + throw std::invalid_argument("y cannot be zero"); + } +#endif + if (x < y) + { + return gcd(y, x); + } + else if (y == 0) + { + return x; + } + else + { + std::uint64_t f = x % y; + if (f == 0) + { + return y; + } + else + { + return gcd(y, f); + } + } + } + + SEAL_NODISCARD inline auto xgcd(std::uint64_t x, std::uint64_t y) + -> std::tuple<std::uint64_t, std::int64_t, std::int64_t> + { + /* Extended GCD: + Returns (gcd, x, y) where gcd is the greatest common divisor of a and b. + The numbers x, y are such that gcd = ax + by. + */ +#ifdef SEAL_DEBUG + if (x == 0) + { + throw std::invalid_argument("x cannot be zero"); + } + if (y == 0) + { + throw std::invalid_argument("y cannot be zero"); + } +#endif + std::int64_t prev_a = 1; + std::int64_t a = 0; + std::int64_t prev_b = 0; + std::int64_t b = 1; + + while (y != 0) + { + std::int64_t q = util::safe_cast<std::int64_t>(x / y); + std::int64_t temp = util::safe_cast<std::int64_t>(x % y); + x = y; + y = util::safe_cast<std::uint64_t>(temp); + + temp = a; + a = util::sub_safe(prev_a, mul_safe(q, a)); + prev_a = temp; + + temp = b; + b = util::sub_safe(prev_b, mul_safe(q, b)); + prev_b = temp; + } + return std::make_tuple(x, prev_a, prev_b); + } + + SEAL_NODISCARD inline bool are_coprime(std::uint64_t x, std::uint64_t y) noexcept + { + return !(gcd(x, y) > 1); + } + + SEAL_NODISCARD std::vector<std::uint64_t> multiplicative_orders( + std::vector<std::uint64_t> conjugate_classes, std::uint64_t modulus); + + SEAL_NODISCARD std::vector<std::uint64_t> conjugate_classes( + std::uint64_t modulus, std::uint64_t subgroup_generator); + + void babystep_giantstep( + std::uint64_t modulus, std::vector<std::uint64_t> &baby_steps, std::vector<std::uint64_t> &giant_steps); + + SEAL_NODISCARD auto decompose_babystep_giantstep( + std::uint64_t modulus, std::uint64_t input, const std::vector<std::uint64_t> &baby_steps, + const std::vector<std::uint64_t> &giant_steps) -> std::pair<std::size_t, std::size_t>; + + SEAL_NODISCARD bool is_prime(const Modulus &modulus, std::size_t num_rounds = 40); + + SEAL_NODISCARD std::vector<Modulus> get_primes(std::size_t ntt_size, int bit_size, std::size_t count); + + SEAL_NODISCARD inline Modulus get_prime(std::size_t ntt_size, int bit_size) + { + return get_primes(ntt_size, bit_size, 1)[0]; + } + + bool try_invert_uint_mod(std::uint64_t value, std::uint64_t modulus, std::uint64_t &result); + + bool is_primitive_root(std::uint64_t root, std::uint64_t degree, const Modulus &prime_modulus); + + // Try to find a primitive degree-th root of unity modulo small prime + // modulus, where degree must be a power of two. + bool try_primitive_root(std::uint64_t degree, const Modulus &prime_modulus, std::uint64_t &destination); + + // Try to find the smallest (as integer) primitive degree-th root of + // unity modulo small prime modulus, where degree must be a power of two. + bool try_minimal_primitive_root(std::uint64_t degree, const Modulus &prime_modulus, std::uint64_t &destination); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/pointer.h b/bigpiseal3.5.1/native/src/seal/util/pointer.h new file mode 100644 index 0000000000000000000000000000000000000000..b337a0494275f3b6b14aa1fd8198f2cddc7bcc44 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/pointer.h @@ -0,0 +1,1324 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/mempool.h" +#include <iterator> +#include <memory> +#include <type_traits> +#include <utility> + +namespace seal +{ + namespace util + { + // Specialization for SEAL_BYTE + template <> + class SEAL_NODISCARD Pointer<SEAL_BYTE> + { + friend class MemoryPoolST; + friend class MemoryPoolMT; + + public: + template <typename, typename> + friend class Pointer; + template <typename, typename> + friend class ConstPointer; + + Pointer() = default; + + // Move of the same type + Pointer(Pointer<SEAL_BYTE> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move of the same type + Pointer(Pointer<SEAL_BYTE> &&source, SEAL_BYTE value) : Pointer(std::move(source)) + { + std::fill_n(data_, head_->item_byte_count(), value); + } + + // Copy a range of elements + template <typename InputIt> + Pointer(InputIt first, Pointer<SEAL_BYTE> &&source) : Pointer(std::move(source)) + { + std::copy_n(first, head_->item_byte_count(), data_); + } + + SEAL_NODISCARD inline SEAL_BYTE &operator[](std::size_t index) + { + return data_[index]; + } + + SEAL_NODISCARD inline const SEAL_BYTE &operator[](std::size_t index) const + { + return data_[index]; + } + + inline auto &operator=(Pointer<SEAL_BYTE> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + SEAL_NODISCARD inline bool is_set() const noexcept + { + return data_ != nullptr; + } + + SEAL_NODISCARD inline SEAL_BYTE *get() noexcept + { + return data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE *get() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline SEAL_BYTE *operator->() noexcept + { + return data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE *operator->() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline SEAL_BYTE &operator*() + { + return *data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE &operator*() const + { + return *data_; + } + + SEAL_NODISCARD inline bool is_alias() const noexcept + { + return alias_; + } + + inline void release() noexcept + { + if (head_) + { + // Return the memory to pool + head_->add(item_); + } + else if (data_ && !alias_) + { + // Free the memory + delete[] data_; + } + + data_ = nullptr; + head_ = nullptr; + item_ = nullptr; + alias_ = false; + } + + void acquire(Pointer<SEAL_BYTE> &other) noexcept + { + if (this == &other) + { + return; + } + + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<SEAL_BYTE> &&other) noexcept + { + acquire(other); + } + + ~Pointer() noexcept + { + release(); + } + + SEAL_NODISCARD explicit operator bool() const noexcept + { + return (data_ != nullptr); + } + + SEAL_NODISCARD inline static Pointer<SEAL_BYTE> Owning(SEAL_BYTE *pointer) noexcept + { + return { pointer, false }; + } + + SEAL_NODISCARD inline static auto Aliasing(SEAL_BYTE *pointer) noexcept -> Pointer<SEAL_BYTE> + { + return { pointer, true }; + } + + private: + Pointer(const Pointer<SEAL_BYTE> &copy) = delete; + + Pointer<SEAL_BYTE> &operator=(const Pointer<SEAL_BYTE> &assign) = delete; + + Pointer(SEAL_BYTE *pointer, bool alias) noexcept : data_(pointer), alias_(alias) + {} + + Pointer(class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = item_->data(); + } + + SEAL_BYTE *data_ = nullptr; + + MemoryPoolHead *head_ = nullptr; + + MemoryPoolItem *item_ = nullptr; + + bool alias_ = false; + }; + + template <typename T, typename> + class SEAL_NODISCARD Pointer + { + friend class MemoryPoolST; + friend class MemoryPoolMT; + + public: + friend class Pointer<SEAL_BYTE>; + friend class ConstPointer<SEAL_BYTE>; + friend class ConstPointer<T>; + + Pointer() = default; + + // Move of the same type + Pointer(Pointer<T> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + Pointer(Pointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + template <typename... Args> + Pointer(Pointer<SEAL_BYTE> &&source, Args &&... args) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T(std::forward<Args>(args)...); + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Copy a range when T is not SEAL_BYTE + template <typename InputIt> + Pointer(InputIt first, Pointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + std::uninitialized_copy_n(first, count, data_); + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + SEAL_NODISCARD inline T &operator[](std::size_t index) + { + return data_[index]; + } + + SEAL_NODISCARD inline const T &operator[](std::size_t index) const + { + return data_[index]; + } + + inline auto &operator=(Pointer<T> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + inline auto &operator=(Pointer<SEAL_BYTE> &&assign) + { + acquire(std::move(assign)); + return *this; + } + + SEAL_NODISCARD inline bool is_set() const noexcept + { + return data_ != nullptr; + } + + SEAL_NODISCARD inline T *get() noexcept + { + return data_; + } + + SEAL_NODISCARD inline const T *get() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline T *operator->() noexcept + { + return data_; + } + + SEAL_NODISCARD inline const T *operator->() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline T &operator*() + { + return *data_; + } + + SEAL_NODISCARD inline const T &operator*() const + { + return *data_; + } + + SEAL_NODISCARD inline bool is_alias() const noexcept + { + return alias_; + } + + inline void release() noexcept + { + if (head_) + { + SEAL_IF_CONSTEXPR(!std::is_trivially_destructible<T>::value) + { + // Manual destructor calls + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + alloc_ptr->~T(); + } + } + + // Return the memory to pool + head_->add(item_); + } + else if (data_ && !alias_) + { + // Free the memory + delete[] data_; + } + + data_ = nullptr; + head_ = nullptr; + item_ = nullptr; + alias_ = false; + } + + void acquire(Pointer<T> &other) noexcept + { + if (this == &other) + { + return; + } + + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<T> &&other) noexcept + { + acquire(other); + } + + void acquire(Pointer<SEAL_BYTE> &other) + { + // Cannot acquire a non-pool pointer of different type + if (!other.head_ && other.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + release(); + + head_ = other.head_; + item_ = other.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<SEAL_BYTE> &&other) + { + acquire(other); + } + + ~Pointer() noexcept + { + release(); + } + + SEAL_NODISCARD explicit operator bool() const noexcept + { + return (data_ != nullptr); + } + + SEAL_NODISCARD inline static Pointer<T> Owning(T *pointer) noexcept + { + return { pointer, false }; + } + + SEAL_NODISCARD inline static auto Aliasing(T *pointer) noexcept -> Pointer<T> + { + return { pointer, true }; + } + + private: + Pointer(const Pointer<T> &copy) = delete; + + Pointer<T> &operator=(const Pointer<T> &assign) = delete; + + Pointer(T *pointer, bool alias) noexcept : data_(pointer), alias_(alias) + {} + + Pointer(class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + + template <typename... Args> + Pointer(class MemoryPoolHead *head, Args &&... args) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T(std::forward<Args>(args)...); + } + } + + template <typename InputIt> + Pointer(InputIt first, class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + std::uninitialized_copy_n(first, count, data_); + } + + T *data_ = nullptr; + + MemoryPoolHead *head_ = nullptr; + + MemoryPoolItem *item_ = nullptr; + + bool alias_ = false; + }; + + // Specialization for SEAL_BYTE + template <> + class SEAL_NODISCARD ConstPointer<SEAL_BYTE> + { + friend class MemoryPoolST; + friend class MemoryPoolMT; + + public: + template <typename, typename> + friend class ConstPointer; + + ConstPointer() = default; + + // Move of the same type + ConstPointer(Pointer<SEAL_BYTE> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move of the same type + ConstPointer(Pointer<SEAL_BYTE> &&source, SEAL_BYTE value) : ConstPointer(std::move(source)) + { + std::fill_n(data_, head_->item_byte_count(), value); + } + + // Move of the same type + ConstPointer(ConstPointer<SEAL_BYTE> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move of the same type + ConstPointer(ConstPointer<SEAL_BYTE> &&source, SEAL_BYTE value) : ConstPointer(std::move(source)) + { + std::fill_n(data_, head_->item_byte_count(), value); + } + + // Copy a range of elements + template <typename InputIt> + ConstPointer(InputIt first, ConstPointer<SEAL_BYTE> &&source) : ConstPointer(std::move(source)) + { + std::copy_n(first, head_->item_byte_count(), data_); + } + + inline auto &operator=(ConstPointer<SEAL_BYTE> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + inline auto &operator=(Pointer<SEAL_BYTE> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + SEAL_NODISCARD inline const SEAL_BYTE &operator[](std::size_t index) const + { + return data_[index]; + } + + SEAL_NODISCARD inline bool is_set() const noexcept + { + return data_ != nullptr; + } + + SEAL_NODISCARD inline const SEAL_BYTE *get() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE *operator->() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline const SEAL_BYTE &operator*() const + { + return *data_; + } + + inline void release() noexcept + { + if (head_) + { + // Return the memory to pool + head_->add(item_); + } + else if (data_ && !alias_) + { + // Free the memory + delete[] data_; + } + + data_ = nullptr; + head_ = nullptr; + item_ = nullptr; + alias_ = false; + } + + void acquire(Pointer<SEAL_BYTE> &other) noexcept + { + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<SEAL_BYTE> &&other) noexcept + { + acquire(other); + } + + void acquire(ConstPointer<SEAL_BYTE> &other) noexcept + { + if (this == &other) + { + return; + } + + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(ConstPointer<SEAL_BYTE> &&other) noexcept + { + acquire(other); + } + + ~ConstPointer() noexcept + { + release(); + } + + SEAL_NODISCARD explicit operator bool() const + { + return (data_ != nullptr); + } + + SEAL_NODISCARD inline static auto Owning(SEAL_BYTE *pointer) noexcept -> ConstPointer<SEAL_BYTE> + { + return { pointer, false }; + } + + SEAL_NODISCARD inline static auto Aliasing(const SEAL_BYTE *pointer) noexcept -> ConstPointer<SEAL_BYTE> + { + return { const_cast<SEAL_BYTE *>(pointer), true }; + } + + private: + ConstPointer(const ConstPointer<SEAL_BYTE> &copy) = delete; + + ConstPointer &operator=(const ConstPointer<SEAL_BYTE> &assign) = delete; + + ConstPointer(SEAL_BYTE *pointer, bool alias) noexcept : data_(pointer), alias_(alias) + {} + + ConstPointer(class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = item_->data(); + } + + SEAL_BYTE *data_ = nullptr; + + MemoryPoolHead *head_ = nullptr; + + MemoryPoolItem *item_ = nullptr; + + bool alias_ = false; + }; + + template <typename T, typename> + class SEAL_NODISCARD ConstPointer + { + friend class MemoryPoolST; + friend class MemoryPoolMT; + + public: + ConstPointer() = default; + + // Move of the same type + ConstPointer(Pointer<T> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + ConstPointer(Pointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + template <typename... Args> + ConstPointer(Pointer<SEAL_BYTE> &&source, Args &&... args) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T(std::forward<Args>(args)...); + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Copy a range when T is not SEAL_BYTE + template <typename InputIt> + ConstPointer(InputIt first, Pointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + std::uninitialized_copy_n(first, count, data_); + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move of the same type + ConstPointer(ConstPointer<T> &&source) noexcept + : data_(source.data_), head_(source.head_), item_(source.item_), alias_(source.alias_) + { + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + ConstPointer(ConstPointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Move when T is not SEAL_BYTE + template <typename... Args> + ConstPointer(ConstPointer<SEAL_BYTE> &&source, Args &&... args) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T(std::forward<Args>(args)...); + } + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + // Copy a range when T is not SEAL_BYTE + template <typename InputIt> + ConstPointer(InputIt first, ConstPointer<SEAL_BYTE> &&source) + { + // Cannot acquire a non-pool pointer of different type + if (!source.head_ && source.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + head_ = source.head_; + item_ = source.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + std::uninitialized_copy_n(first, count, data_); + } + alias_ = source.alias_; + + source.data_ = nullptr; + source.head_ = nullptr; + source.item_ = nullptr; + source.alias_ = false; + } + + inline auto &operator=(ConstPointer<T> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + inline auto &operator=(ConstPointer<SEAL_BYTE> &&assign) + { + acquire(std::move(assign)); + return *this; + } + + inline auto &operator=(Pointer<T> &&assign) noexcept + { + acquire(std::move(assign)); + return *this; + } + + inline auto &operator=(Pointer<SEAL_BYTE> &&assign) + { + acquire(std::move(assign)); + return *this; + } + + SEAL_NODISCARD inline const T &operator[](std::size_t index) const + { + return data_[index]; + } + + SEAL_NODISCARD inline bool is_set() const noexcept + { + return data_ != nullptr; + } + + SEAL_NODISCARD inline const T *get() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline const T *operator->() const noexcept + { + return data_; + } + + SEAL_NODISCARD inline const T &operator*() const + { + return *data_; + } + + inline void release() noexcept + { + if (head_) + { + SEAL_IF_CONSTEXPR(!std::is_trivially_destructible<T>::value) + { + // Manual destructor calls + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + alloc_ptr->~T(); + } + } + + // Return the memory to pool + head_->add(item_); + } + else if (data_ && !alias_) + { + // Free the memory + delete[] data_; + } + + data_ = nullptr; + head_ = nullptr; + item_ = nullptr; + alias_ = false; + } + + void acquire(ConstPointer<T> &other) noexcept + { + if (this == &other) + { + return; + } + + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(ConstPointer<T> &&other) noexcept + { + acquire(other); + } + + void acquire(ConstPointer<SEAL_BYTE> &other) + { + // Cannot acquire a non-pool pointer of different type + if (!other.head_ && other.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + release(); + + head_ = other.head_; + item_ = other.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(ConstPointer<SEAL_BYTE> &&other) + { + acquire(other); + } + + void acquire(Pointer<T> &other) noexcept + { + release(); + + data_ = other.data_; + head_ = other.head_; + item_ = other.item_; + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<T> &&other) noexcept + { + acquire(other); + } + + void acquire(Pointer<SEAL_BYTE> &other) + { + // Cannot acquire a non-pool pointer of different type + if (!other.head_ && other.data_) + { + throw std::invalid_argument("cannot acquire a non-pool pointer of different type"); + } + + release(); + + head_ = other.head_; + item_ = other.item_; + if (head_) + { + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + alias_ = other.alias_; + other.data_ = nullptr; + other.head_ = nullptr; + other.item_ = nullptr; + other.alias_ = false; + } + + inline void acquire(Pointer<SEAL_BYTE> &&other) + { + acquire(other); + } + + ~ConstPointer() noexcept + { + release(); + } + + SEAL_NODISCARD explicit operator bool() const noexcept + { + return (data_ != nullptr); + } + + SEAL_NODISCARD inline static ConstPointer<T> Owning(T *pointer) noexcept + { + return { pointer, false }; + } + + SEAL_NODISCARD inline static auto Aliasing(const T *pointer) noexcept -> ConstPointer<T> + { + return { const_cast<T *>(pointer), true }; + } + + private: + ConstPointer(const ConstPointer<T> &copy) = delete; + + ConstPointer &operator=(const ConstPointer<T> &assign) = delete; + + ConstPointer(T *pointer, bool alias) noexcept : data_(pointer), alias_(alias) + {} + + ConstPointer(class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + SEAL_IF_CONSTEXPR(!std::is_trivially_constructible<T>::value) + { + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T; + } + } + } + + template <typename... Args> + ConstPointer(class MemoryPoolHead *head, Args &&... args) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + for (auto alloc_ptr = data_; count--; alloc_ptr++) + { + new (alloc_ptr) T(std::forward<Args>(args)...); + } + } + + template <typename InputIt> + ConstPointer(InputIt first, class MemoryPoolHead *head) + { +#ifdef SEAL_DEBUG + if (!head) + { + throw std::invalid_argument("head cannot be null"); + } +#endif + head_ = head; + item_ = head->get(); + data_ = reinterpret_cast<T *>(item_->data()); + auto count = head_->item_byte_count() / sizeof(T); + std::uninitialized_copy_n(first, count, data_); + } + + T *data_ = nullptr; + + MemoryPoolHead *head_ = nullptr; + + MemoryPoolItem *item_ = nullptr; + + bool alias_ = false; + }; + + // Allocate single element + template < + typename T_, typename... Args, + typename = std::enable_if_t<std::is_standard_layout< + typename std::remove_cv<typename std::remove_reference<T_>::type>::type>::value>> + SEAL_NODISCARD inline auto allocate(MemoryPool &pool, Args &&... args) + { + using T = typename std::remove_cv<typename std::remove_reference<T_>::type>::type; + return Pointer<T>(pool.get_for_byte_count(sizeof(T)), std::forward<Args>(args)...); + } + + // Allocate array of elements + template < + typename T_, typename... Args, + typename = std::enable_if_t<std::is_standard_layout< + typename std::remove_cv<typename std::remove_reference<T_>::type>::type>::value>> + SEAL_NODISCARD inline auto allocate(std::size_t count, MemoryPool &pool, Args &&... args) + { + using T = typename std::remove_cv<typename std::remove_reference<T_>::type>::type; + return Pointer<T>(pool.get_for_byte_count(mul_safe(count, sizeof(T))), std::forward<Args>(args)...); + } + + // Allocate and copy a range of elements + template < + typename InputIt, + typename T_ = typename std::iterator_traits<typename std::remove_reference<InputIt>::type>::value_type, + typename = std::enable_if_t<std::is_standard_layout< + typename std::remove_cv<typename std::remove_reference<T_>::type>::type>::value>> + SEAL_NODISCARD inline auto allocate(InputIt &&first, std::size_t count, MemoryPool &pool) + { + using T = typename std::remove_cv<typename std::remove_reference<T_>::type>::type; + return Pointer<T>(std::forward<InputIt>(first), pool.get_for_byte_count(mul_safe(count, sizeof(T)))); + } + + template < + typename T_, typename = std::enable_if_t<std::is_standard_layout< + typename std::remove_cv<typename std::remove_reference<T_>::type>::type>::value>> + SEAL_NODISCARD inline auto duplicate_if_needed( + T_ *original, std::size_t count, bool condition, MemoryPool &pool) + { + using T = typename std::remove_cv<typename std::remove_reference<T_>::type>::type; +#ifdef SEAL_DEBUG + if (original == nullptr && count > 0) + { + throw std::invalid_argument("original"); + } +#endif + if (condition == false) + { + return Pointer<T>::Aliasing(original); + } + auto allocation(allocate<T>(count, pool)); + std::copy_n(original, count, allocation.get()); + return allocation; + } + + template < + typename T_, typename = std::enable_if_t<std::is_standard_layout< + typename std::remove_cv<typename std::remove_reference<T_>::type>::type>::value>> + SEAL_NODISCARD inline auto duplicate_if_needed( + const T_ *original, std::size_t count, bool condition, MemoryPool &pool) + { + using T = typename std::remove_cv<typename std::remove_reference<T_>::type>::type; +#ifdef SEAL_DEBUG + if (original == nullptr && count > 0) + { + throw std::invalid_argument("original"); + } +#endif + if (condition == false) + { + return ConstPointer<T>::Aliasing(original); + } + auto allocation(allocate<T>(count, pool)); + std::copy_n(original, count, allocation.get()); + return ConstPointer<T>(std::move(allocation)); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarith.cpp b/bigpiseal3.5.1/native/src/seal/util/polyarith.cpp new file mode 100644 index 0000000000000000000000000000000000000000..543f5b2907a43ddd5532abc3f9dbf2705a68a12f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarith.cpp @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/polyarith.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" + +using namespace std; + +namespace seal +{ + namespace util + { + void multiply_poly_poly( + const uint64_t *operand1, size_t operand1_coeff_count, size_t operand1_coeff_uint64_count, + const uint64_t *operand2, size_t operand2_coeff_count, size_t operand2_coeff_uint64_count, + size_t result_coeff_count, size_t result_coeff_uint64_count, uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && operand1_coeff_count > 0 && operand1_coeff_uint64_count > 0) + { + throw invalid_argument("operand1"); + } + if (operand2 == nullptr && operand2_coeff_count > 0 && operand2_coeff_uint64_count > 0) + { + throw invalid_argument("operand2"); + } + if (result == nullptr && result_coeff_count > 0 && result_coeff_uint64_count > 0) + { + throw invalid_argument("result"); + } + if (result != nullptr && (operand1 == result || operand2 == result)) + { + throw invalid_argument("result cannot point to the same value as operand1 or operand2"); + } + if (!sum_fits_in(operand1_coeff_count, operand2_coeff_count)) + { + throw invalid_argument("operand1 and operand2 too large"); + } +#endif + auto intermediate(allocate_uint(result_coeff_uint64_count, pool)); + + // Clear product. + set_zero_poly(result_coeff_count, result_coeff_uint64_count, result); + + operand1_coeff_count = + get_significant_coeff_count_poly(operand1, operand1_coeff_count, operand1_coeff_uint64_count); + operand2_coeff_count = + get_significant_coeff_count_poly(operand2, operand2_coeff_count, operand2_coeff_uint64_count); + for (size_t operand1_index = 0; operand1_index < operand1_coeff_count; operand1_index++) + { + const uint64_t *operand1_coeff = get_poly_coeff(operand1, operand1_index, operand1_coeff_uint64_count); + for (size_t operand2_index = 0; operand2_index < operand2_coeff_count; operand2_index++) + { + size_t product_coeff_index = operand1_index + operand2_index; + if (product_coeff_index >= result_coeff_count) + { + break; + } + + const uint64_t *operand2_coeff = + get_poly_coeff(operand2, operand2_index, operand2_coeff_uint64_count); + multiply_uint_uint( + operand1_coeff, operand1_coeff_uint64_count, operand2_coeff, operand2_coeff_uint64_count, + result_coeff_uint64_count, intermediate.get()); + uint64_t *result_coeff = get_poly_coeff(result, product_coeff_index, result_coeff_uint64_count); + add_uint_uint(result_coeff, intermediate.get(), result_coeff_uint64_count, result_coeff); + } + } + } + + void poly_eval_poly( + const uint64_t *poly_to_eval, size_t poly_to_eval_coeff_count, size_t poly_to_eval_coeff_uint64_count, + const uint64_t *value, size_t value_coeff_count, size_t value_coeff_uint64_count, size_t result_coeff_count, + size_t result_coeff_uint64_count, uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (poly_to_eval == nullptr) + { + throw invalid_argument("poly_to_eval"); + } + if (value == nullptr) + { + throw invalid_argument("value"); + } + if (result == nullptr) + { + throw invalid_argument("result"); + } + if (poly_to_eval_coeff_count == 0) + { + throw invalid_argument("poly_to_eval_coeff_count"); + } + if (poly_to_eval_coeff_uint64_count == 0) + { + throw invalid_argument("poly_to_eval_coeff_uint64_count"); + } + if (value_coeff_count == 0) + { + throw invalid_argument("value_coeff_count"); + } + if (value_coeff_uint64_count == 0) + { + throw invalid_argument("value_coeff_uint64_count"); + } + if (result_coeff_count == 0) + { + throw invalid_argument("result_coeff_count"); + } + if (result_coeff_uint64_count == 0) + { + throw invalid_argument("result_coeff_uint64_count"); + } +#endif + // Evaluate poly at value using Horner's method + auto temp1(allocate_poly(result_coeff_count, result_coeff_uint64_count, pool)); + auto temp2(allocate_zero_poly(result_coeff_count, result_coeff_uint64_count, pool)); + uint64_t *productptr = temp1.get(); + uint64_t *intermediateptr = temp2.get(); + + while (poly_to_eval_coeff_count--) + { + multiply_poly_poly( + intermediateptr, result_coeff_count, result_coeff_uint64_count, value, value_coeff_count, + value_coeff_uint64_count, result_coeff_count, result_coeff_uint64_count, productptr, pool); + const uint64_t *curr_coeff = + get_poly_coeff(poly_to_eval, poly_to_eval_coeff_count, poly_to_eval_coeff_uint64_count); + add_uint_uint( + productptr, result_coeff_uint64_count, curr_coeff, poly_to_eval_coeff_uint64_count, false, + result_coeff_uint64_count, productptr); + swap(productptr, intermediateptr); + } + set_poly_poly(intermediateptr, result_coeff_count, result_coeff_uint64_count, result); + } + + void exponentiate_poly( + const std::uint64_t *poly, size_t poly_coeff_count, size_t poly_coeff_uint64_count, + const uint64_t *exponent, size_t exponent_uint64_count, size_t result_coeff_count, + size_t result_coeff_uint64_count, std::uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (poly == nullptr) + { + throw invalid_argument("poly"); + } + if (poly_coeff_count == 0) + { + throw invalid_argument("poly_coeff_count"); + } + if (poly_coeff_uint64_count == 0) + { + throw invalid_argument("poly_coeff_uint64_count"); + } + if (exponent == nullptr) + { + throw invalid_argument("exponent"); + } + if (exponent_uint64_count == 0) + { + throw invalid_argument("exponent_uint64_count"); + } + if (result == nullptr) + { + throw invalid_argument("result"); + } + if (result_coeff_count == 0) + { + throw invalid_argument("result_coeff_count"); + } + if (result_coeff_uint64_count == 0) + { + throw invalid_argument("result_coeff_uint64_count"); + } +#endif + // Fast cases + if (is_zero_uint(exponent, exponent_uint64_count)) + { + set_zero_poly(result_coeff_count, result_coeff_uint64_count, result); + *result = 1; + return; + } + if (is_equal_uint(exponent, exponent_uint64_count, 1)) + { + set_poly_poly( + poly, poly_coeff_count, poly_coeff_uint64_count, result_coeff_count, result_coeff_uint64_count, + result); + return; + } + + // Need to make a copy of exponent + auto exponent_copy(allocate_uint(exponent_uint64_count, pool)); + set_uint_uint(exponent, exponent_uint64_count, exponent_copy.get()); + + // Perform binary exponentiation. + auto big_alloc(allocate_uint( + mul_safe( + add_safe(result_coeff_count, result_coeff_count, result_coeff_count), result_coeff_uint64_count), + pool)); + + uint64_t *powerptr = big_alloc.get(); + uint64_t *productptr = get_poly_coeff(powerptr, result_coeff_count, result_coeff_uint64_count); + uint64_t *intermediateptr = get_poly_coeff(productptr, result_coeff_count, result_coeff_uint64_count); + + set_poly_poly( + poly, poly_coeff_count, poly_coeff_uint64_count, result_coeff_count, result_coeff_uint64_count, + powerptr); + set_zero_poly(result_coeff_count, result_coeff_uint64_count, intermediateptr); + *intermediateptr = 1; + + // Initially: power = operand and intermediate = 1, product is not initialized. + while (true) + { + if ((*exponent_copy.get() % 2) == 1) + { + multiply_poly_poly( + powerptr, result_coeff_count, result_coeff_uint64_count, intermediateptr, result_coeff_count, + result_coeff_uint64_count, result_coeff_count, result_coeff_uint64_count, productptr, pool); + swap(productptr, intermediateptr); + } + right_shift_uint(exponent_copy.get(), 1, exponent_uint64_count, exponent_copy.get()); + if (is_zero_uint(exponent_copy.get(), exponent_uint64_count)) + { + break; + } + multiply_poly_poly( + powerptr, result_coeff_count, result_coeff_uint64_count, powerptr, result_coeff_count, + result_coeff_uint64_count, result_coeff_count, result_coeff_uint64_count, productptr, pool); + swap(productptr, powerptr); + } + set_poly_poly(intermediateptr, result_coeff_count, result_coeff_uint64_count, result); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarith.h b/bigpiseal3.5.1/native/src/seal/util/polyarith.h new file mode 100644 index 0000000000000000000000000000000000000000..590d8db17f7475a3176f78ea34e517af59c00c8f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarith.h @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/pointer.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" +#include <cstdint> + +namespace seal +{ + namespace util + { + inline void right_shift_poly_coeffs( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, int shift_amount, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("poly"); + } +#endif + while (coeff_count--) + { + right_shift_uint(poly, shift_amount, coeff_uint64_count, result); + poly += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + inline void negate_poly( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("poly"); + } + if (result == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + while (coeff_count--) + { + negate_uint(poly, coeff_uint64_count, result); + poly += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + inline void add_poly_poly( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (result == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + while (coeff_count--) + { + add_uint_uint(operand1, operand2, coeff_uint64_count, result); + operand1 += coeff_uint64_count; + operand2 += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + inline void sub_poly_poly( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (result == nullptr && coeff_count > 0 && coeff_uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + while (coeff_count--) + { + sub_uint_uint(operand1, operand2, coeff_uint64_count, result); + operand1 += coeff_uint64_count; + operand2 += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + void multiply_poly_poly( + const std::uint64_t *operand1, std::size_t operand1_coeff_count, std::size_t operand1_coeff_uint64_count, + const std::uint64_t *operand2, std::size_t operand2_coeff_count, std::size_t operand2_coeff_uint64_count, + std::size_t result_coeff_count, std::size_t result_coeff_uint64_count, std::uint64_t *result, + MemoryPool &pool); + + inline void poly_infty_norm( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, std::uint64_t *result) + { + set_zero_uint(coeff_uint64_count, result); + while (coeff_count--) + { + if (is_greater_than_uint_uint(poly, result, coeff_uint64_count)) + { + set_uint_uint(poly, coeff_uint64_count, result); + } + + poly += coeff_uint64_count; + } + } + + void poly_eval_poly( + const std::uint64_t *poly_to_eval, std::size_t poly_to_eval_coeff_count, + std::size_t poly_to_eval_coeff_uint64_count, const std::uint64_t *value, std::size_t value_coeff_count, + std::size_t value_coeff_uint64_count, std::size_t result_coeff_count, std::size_t result_coeff_uint64_count, + std::uint64_t *result, MemoryPool &pool); + + void exponentiate_poly( + const std::uint64_t *poly, std::size_t poly_coeff_count, std::size_t poly_coeff_uint64_count, + const std::uint64_t *exponent, std::size_t exponent_uint64_count, std::size_t result_coeff_count, + std::size_t result_coeff_uint64_count, std::uint64_t *result, MemoryPool &pool); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarithmod.cpp b/bigpiseal3.5.1/native/src/seal/util/polyarithmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59670a98680721a2d7c6444096504a5ccae592ad --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarithmod.cpp @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/polyarith.h" +#include "seal/util/polyarithmod.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" + +using namespace std; + +namespace seal +{ + namespace util + { + void poly_infty_norm_coeffmod( + const uint64_t *poly, size_t coeff_count, size_t coeff_uint64_count, const uint64_t *modulus, + uint64_t *result, MemoryPool &pool) + { + // Construct negative threshold (first negative modulus value) to compute + // absolute values of coeffs. + auto modulus_neg_threshold(allocate_uint(coeff_uint64_count, pool)); + + // Set to value of (modulus + 1) / 2. To prevent overflowing with the +1, just + // add 1 to the result if modulus was odd. + half_round_up_uint(modulus, coeff_uint64_count, modulus_neg_threshold.get()); + + // Mod out the poly coefficients and choose a symmetric representative from + // [-modulus,modulus). Keep track of the max. + set_zero_uint(coeff_uint64_count, result); + auto coeff_abs_value(allocate_uint(coeff_uint64_count, pool)); + for (size_t i = 0; i < coeff_count; i++, poly += coeff_uint64_count) + { + if (is_greater_than_or_equal_uint_uint(poly, modulus_neg_threshold.get(), coeff_uint64_count)) + { + sub_uint_uint(modulus, poly, coeff_uint64_count, coeff_abs_value.get()); + } + else + { + set_uint_uint(poly, coeff_uint64_count, coeff_abs_value.get()); + } + if (is_greater_than_uint_uint(coeff_abs_value.get(), result, coeff_uint64_count)) + { + set_uint_uint(coeff_abs_value.get(), coeff_uint64_count, result); + } + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarithmod.h b/bigpiseal3.5.1/native/src/seal/util/polyarithmod.h new file mode 100644 index 0000000000000000000000000000000000000000..5117b461b9617801b7c1ca83c82017b5fd073e3b --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarithmod.h @@ -0,0 +1,119 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/pointer.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarithmod.h" +#include <cstdint> + +namespace seal +{ + namespace util + { + inline void negate_poly_coeffmod( + const std::uint64_t *poly, std::size_t coeff_count, const std::uint64_t *coeff_modulus, + std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0) + { + throw std::invalid_argument("poly"); + } + if (coeff_modulus == nullptr) + { + throw std::invalid_argument("coeff_modulus"); + } + if (coeff_uint64_count == 0) + { + throw std::invalid_argument("coeff_uint64_count"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (std::size_t i = 0; i < coeff_count; i++) + { + negate_uint_mod(poly, coeff_modulus, coeff_uint64_count, result); + poly += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + inline void add_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const std::uint64_t *coeff_modulus, std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (coeff_modulus == nullptr) + { + throw std::invalid_argument("coeff_modulus"); + } + if (coeff_uint64_count == 0) + { + throw std::invalid_argument("coeff_uint64_count"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (std::size_t i = 0; i < coeff_count; i++) + { + add_uint_uint_mod(operand1, operand2, coeff_modulus, coeff_uint64_count, result); + operand1 += coeff_uint64_count; + operand2 += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + inline void sub_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const std::uint64_t *coeff_modulus, std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (coeff_modulus == nullptr) + { + throw std::invalid_argument("coeff_modulus"); + } + if (coeff_uint64_count == 0) + { + throw std::invalid_argument("coeff_uint64_count"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (std::size_t i = 0; i < coeff_count; i++) + { + sub_uint_uint_mod(operand1, operand2, coeff_modulus, coeff_uint64_count, result); + operand1 += coeff_uint64_count; + operand2 += coeff_uint64_count; + result += coeff_uint64_count; + } + } + + void poly_infty_norm_coeffmod( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, + const std::uint64_t *modulus, std::uint64_t *result, MemoryPool &pool); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.cpp b/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16d752e7ad41d48fb8792c0def89820616248566 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.cpp @@ -0,0 +1,613 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/polyarith.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" + +using namespace std; + +namespace seal +{ + namespace util + { + void multiply_poly_scalar_coeffmod( + const uint64_t *poly, size_t coeff_count, uint64_t scalar, const Modulus &modulus, uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0) + { + throw invalid_argument("poly"); + } + if (result == nullptr && coeff_count > 0) + { + throw invalid_argument("result"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + // Explicit inline + // for (int i = 0; i < coeff_count; i++) + //{ + // *result++ = multiply_uint_uint_mod(*poly++, scalar, modulus); + //} + const uint64_t modulus_value = modulus.value(); + const uint64_t const_ratio_0 = modulus.const_ratio()[0]; + const uint64_t const_ratio_1 = modulus.const_ratio()[1]; + for (; coeff_count--; poly++, result++) + { + unsigned long long z[2], tmp1, tmp2[2], tmp3, carry; + multiply_uint64(*poly, scalar, z); + + // Reduces z using base 2^64 Barrett reduction + + // Multiply input and const_ratio + // Round 1 + multiply_uint64_hw64(z[0], const_ratio_0, &carry); + multiply_uint64(z[0], const_ratio_1, tmp2); + tmp3 = tmp2[1] + add_uint64(tmp2[0], carry, &tmp1); + + // Round 2 + multiply_uint64(z[1], const_ratio_0, tmp2); + carry = tmp2[1] + add_uint64(tmp1, tmp2[0], &tmp1); + + // This is all we care about + tmp1 = z[1] * const_ratio_1 + tmp3 + carry; + + // Barrett subtraction + tmp3 = z[0] - tmp1 * modulus_value; + + // Claim: One more subtraction is enough + *result = tmp3 - (modulus_value & static_cast<uint64_t>(-static_cast<int64_t>(tmp3 >= modulus_value))); + } + } + + void multiply_poly_poly_coeffmod( + const uint64_t *operand1, size_t operand1_coeff_count, const uint64_t *operand2, + size_t operand2_coeff_count, const Modulus &modulus, size_t result_coeff_count, uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && operand1_coeff_count > 0) + { + throw invalid_argument("operand1"); + } + if (operand2 == nullptr && operand2_coeff_count > 0) + { + throw invalid_argument("operand2"); + } + if (result == nullptr && result_coeff_count > 0) + { + throw invalid_argument("result"); + } + if (result != nullptr && (operand1 == result || operand2 == result)) + { + throw invalid_argument("result cannot point to the same value as operand1, operand2, or modulus"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } + if (!sum_fits_in(operand1_coeff_count, operand2_coeff_count)) + { + throw invalid_argument("operand1 and operand2 too large"); + } +#endif + // Clear product. + set_zero_uint(result_coeff_count, result); + + operand1_coeff_count = get_significant_coeff_count_poly(operand1, operand1_coeff_count, 1); + operand2_coeff_count = get_significant_coeff_count_poly(operand2, operand2_coeff_count, 1); + for (size_t operand1_index = 0; operand1_index < operand1_coeff_count; operand1_index++) + { + if (operand1[operand1_index] == 0) + { + // If coefficient is 0, then move on to next coefficient. + continue; + } + // Do expensive add + for (size_t operand2_index = 0; operand2_index < operand2_coeff_count; operand2_index++) + { + size_t product_coeff_index = operand1_index + operand2_index; + if (product_coeff_index >= result_coeff_count) + { + break; + } + + if (operand2[operand2_index] == 0) + { + // If coefficient is 0, then move on to next coefficient. + continue; + } + + // Lazy reduction + unsigned long long temp[2]; + multiply_uint64(operand1[operand1_index], operand2[operand2_index], temp); + temp[1] += add_uint64(temp[0], result[product_coeff_index], 0, temp); + result[product_coeff_index] = barrett_reduce_128(temp, modulus); + } + } + } + + void multiply_poly_poly_coeffmod( + const uint64_t *operand1, const uint64_t *operand2, size_t coeff_count, const Modulus &modulus, + uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0) + { + throw invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0) + { + throw invalid_argument("operand2"); + } + if (result == nullptr && coeff_count > 0) + { + throw invalid_argument("result"); + } + if (result != nullptr && (operand1 == result || operand2 == result)) + { + throw invalid_argument("result cannot point to the same value as operand1, operand2, or modulus"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + size_t result_coeff_count = coeff_count + coeff_count - 1; + + // Clear product. + set_zero_uint(result_coeff_count, result); + + for (size_t operand1_index = 0; operand1_index < coeff_count; operand1_index++) + { + if (operand1[operand1_index] == 0) + { + // If coefficient is 0, then move on to next coefficient. + continue; + } + // Lastly, do more expensive add if other cases don't handle it. + for (size_t operand2_index = 0; operand2_index < coeff_count; operand2_index++) + { + uint64_t operand2_coeff = operand2[operand2_index]; + if (operand2_coeff == 0) + { + // If coefficient is 0, then move on to next coefficient. + continue; + } + + // Lazy reduction + unsigned long long temp[2]; + multiply_uint64(operand1[operand1_index], operand2_coeff, temp); + temp[1] += add_uint64(temp[0], result[operand1_index + operand2_index], 0, temp); + + result[operand1_index + operand2_index] = barrett_reduce_128(temp, modulus); + } + } + } + + void divide_poly_poly_coeffmod_inplace( + uint64_t *numerator, const uint64_t *denominator, size_t coeff_count, const Modulus &modulus, + uint64_t *quotient) + { +#ifdef SEAL_DEBUG + if (numerator == nullptr) + { + throw invalid_argument("numerator"); + } + if (denominator == nullptr) + { + throw invalid_argument("denominator"); + } + if (is_zero_poly(denominator, coeff_count, modulus.uint64_count())) + { + throw invalid_argument("denominator"); + } + if (quotient == nullptr) + { + throw invalid_argument("quotient"); + } + if (numerator == quotient || denominator == quotient) + { + throw invalid_argument("quotient cannot point to same value as numerator or denominator"); + } + if (numerator == denominator) + { + throw invalid_argument("numerator cannot point to same value as denominator"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + // Clear quotient. + set_zero_uint(coeff_count, quotient); + + // Determine most significant coefficients of numerator and denominator. + size_t numerator_coeffs = get_significant_uint64_count_uint(numerator, coeff_count); + size_t denominator_coeffs = get_significant_uint64_count_uint(denominator, coeff_count); + + // If numerator has lesser degree than denominator, then done. + if (numerator_coeffs < denominator_coeffs) + { + return; + } + + // Create scalar to store value that makes denominator monic. + uint64_t monic_denominator_scalar; + + // Create temporary scalars used during calculation of quotient. + // Both are purposely twice as wide to store intermediate product prior to modulo operation. + uint64_t temp_quotient; + uint64_t subtrahend; + + // Determine scalar necessary to make denominator monic. + uint64_t leading_denominator_coeff = denominator[denominator_coeffs - 1]; + if (!try_invert_uint_mod(leading_denominator_coeff, modulus, monic_denominator_scalar)) + { + throw invalid_argument("modulus is not coprime with leading denominator coefficient"); + } + + // Perform coefficient-wise division algorithm. + while (numerator_coeffs >= denominator_coeffs) + { + // Determine leading numerator coefficient. + uint64_t leading_numerator_coeff = numerator[numerator_coeffs - 1]; + + // If leading numerator coefficient is not zero, then need to make zero by subtraction. + if (leading_numerator_coeff) + { + // Determine shift necesarry to bring significant coefficients in alignment. + size_t denominator_shift = numerator_coeffs - denominator_coeffs; + + // Determine quotient's coefficient, which is scalar that makes + // denominator's leading coefficient one multiplied by leading + // coefficient of denominator (which when subtracted will zero + // out the topmost denominator coefficient). + uint64_t &quotient_coeff = quotient[denominator_shift]; + temp_quotient = multiply_uint_uint_mod(monic_denominator_scalar, leading_numerator_coeff, modulus); + quotient_coeff = temp_quotient; + + // Subtract numerator and quotient*denominator (shifted by denominator_shift). + for (size_t denominator_coeff_index = 0; denominator_coeff_index < denominator_coeffs; + denominator_coeff_index++) + { + // Multiply denominator's coefficient by quotient. + uint64_t denominator_coeff = denominator[denominator_coeff_index]; + subtrahend = multiply_uint_uint_mod(temp_quotient, denominator_coeff, modulus); + + // Subtract numerator with resulting product, appropriately shifted by denominator shift. + uint64_t &numerator_coeff = numerator[denominator_coeff_index + denominator_shift]; + numerator_coeff = sub_uint_uint_mod(numerator_coeff, subtrahend, modulus); + } + } + + // Top numerator coefficient must now be zero, so adjust coefficient count. + numerator_coeffs--; + } + } + + void dyadic_product_coeffmod( + const uint64_t *operand1, const uint64_t *operand2, size_t coeff_count, const Modulus &modulus, + uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr) + { + throw invalid_argument("operand1"); + } + if (operand2 == nullptr) + { + throw invalid_argument("operand2"); + } + if (result == nullptr) + { + throw invalid_argument("result"); + } + if (coeff_count == 0) + { + throw invalid_argument("coeff_count"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + // Explicit inline + // for (int i = 0; i < coeff_count; i++) + //{ + // *result++ = multiply_uint_uint_mod(*operand1++, *operand2++, modulus); + //} + const uint64_t modulus_value = modulus.value(); + const uint64_t const_ratio_0 = modulus.const_ratio()[0]; + const uint64_t const_ratio_1 = modulus.const_ratio()[1]; + for (; coeff_count--; operand1++, operand2++, result++) + { + // Reduces z using base 2^64 Barrett reduction + unsigned long long z[2], tmp1, tmp2[2], tmp3, carry; + multiply_uint64(*operand1, *operand2, z); + + // Multiply input and const_ratio + // Round 1 + multiply_uint64_hw64(z[0], const_ratio_0, &carry); + multiply_uint64(z[0], const_ratio_1, tmp2); + tmp3 = tmp2[1] + add_uint64(tmp2[0], carry, &tmp1); + + // Round 2 + multiply_uint64(z[1], const_ratio_0, tmp2); + carry = tmp2[1] + add_uint64(tmp1, tmp2[0], &tmp1); + + // This is all we care about + tmp1 = z[1] * const_ratio_1 + tmp3 + carry; + + // Barrett subtraction + tmp3 = z[0] - tmp1 * modulus_value; + + // Claim: One more subtraction is enough + *result = tmp3 - (modulus_value & static_cast<uint64_t>(-static_cast<int64_t>(tmp3 >= modulus_value))); + } + } + + uint64_t poly_infty_norm_coeffmod(const uint64_t *operand, size_t coeff_count, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (operand == nullptr && coeff_count > 0) + { + throw invalid_argument("operand"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + // Construct negative threshold (first negative modulus value) to compute absolute values of coeffs. + uint64_t modulus_neg_threshold = (modulus.value() + 1) >> 1; + + // Mod out the poly coefficients and choose a symmetric representative from + // [-modulus,modulus). Keep track of the max. + uint64_t result = 0; + for (size_t coeff_index = 0; coeff_index < coeff_count; coeff_index++) + { + uint64_t poly_coeff = operand[coeff_index] % modulus.value(); + if (poly_coeff >= modulus_neg_threshold) + { + poly_coeff = modulus.value() - poly_coeff; + } + if (poly_coeff > result) + { + result = poly_coeff; + } + } + return result; + } + + bool try_invert_poly_coeffmod( + const uint64_t *operand, const uint64_t *poly_modulus, size_t coeff_count, const Modulus &modulus, + uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (operand == nullptr) + { + throw invalid_argument("operand"); + } + if (poly_modulus == nullptr) + { + throw invalid_argument("poly_modulus"); + } + if (coeff_count == 0) + { + throw invalid_argument("coeff_count"); + } + if (result == nullptr) + { + throw invalid_argument("result"); + } + if (get_significant_uint64_count_uint(operand, coeff_count) >= + get_significant_uint64_count_uint(poly_modulus, coeff_count)) + { + throw out_of_range("operand"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } +#endif + // Cannot invert 0 poly. + if (is_zero_poly(operand, coeff_count, size_t(1))) + { + return false; + } + + // Construct a mutable copy of operand and modulus, with numerator being modulus + // and operand being denominator. Notice that degree(numerator) >= degree(denominator). + auto numerator_anchor(allocate_uint(coeff_count, pool)); + uint64_t *numerator = numerator_anchor.get(); + set_uint_uint(poly_modulus, coeff_count, numerator); + auto denominator_anchor(allocate_uint(coeff_count, pool)); + uint64_t *denominator = denominator_anchor.get(); + set_uint_uint(operand, coeff_count, denominator); + + // Determine most significant coefficients of each. + size_t numerator_coeffs = get_significant_coeff_count_poly(numerator, coeff_count, size_t(1)); + size_t denominator_coeffs = get_significant_coeff_count_poly(denominator, coeff_count, size_t(1)); + + // Create poly to store quotient. + auto quotient(allocate_uint(coeff_count, pool)); + + // Create scalar to store value that makes denominator monic. + uint64_t monic_denominator_scalar; + + // Create temporary scalars used during calculation of quotient. + // Both are purposely twice as wide to store intermediate product prior to modulo operation. + uint64_t temp_quotient; + uint64_t subtrahend; + + // Create three polynomials to store inverse. + // Initialize invert_prior to 0 and invert_curr to 1. + auto invert_prior_anchor(allocate_uint(coeff_count, pool)); + uint64_t *invert_prior = invert_prior_anchor.get(); + set_zero_uint(coeff_count, invert_prior); + auto invert_curr_anchor(allocate_uint(coeff_count, pool)); + uint64_t *invert_curr = invert_curr_anchor.get(); + set_zero_uint(coeff_count, invert_curr); + invert_curr[0] = 1; + auto invert_next_anchor(allocate_uint(coeff_count, pool)); + uint64_t *invert_next = invert_next_anchor.get(); + + // Perform extended Euclidean algorithm. + while (true) + { + // NOTE: degree(numerator) >= degree(denominator). + + // Determine scalar necessary to make denominator monic. + uint64_t leading_denominator_coeff = denominator[denominator_coeffs - 1]; + if (!try_invert_uint_mod(leading_denominator_coeff, modulus, monic_denominator_scalar)) + { + throw invalid_argument("modulus is not coprime with leading denominator coefficient"); + } + + // Clear quotient. + set_zero_uint(coeff_count, quotient.get()); + + // Perform coefficient-wise division algorithm. + while (numerator_coeffs >= denominator_coeffs) + { + // Determine leading numerator coefficient. + uint64_t leading_numerator_coeff = numerator[numerator_coeffs - 1]; + + // If leading numerator coefficient is not zero, then need to make zero by subtraction. + if (leading_numerator_coeff) + { + // Determine shift necessary to bring significant coefficients in alignment. + size_t denominator_shift = numerator_coeffs - denominator_coeffs; + + // Determine quotient's coefficient, which is scalar that makes + // denominator's leading coefficient one multiplied by leading + // coefficient of denominator (which when subtracted will zero + // out the topmost denominator coefficient). + uint64_t &quotient_coeff = quotient[denominator_shift]; + temp_quotient = + multiply_uint_uint_mod(monic_denominator_scalar, leading_numerator_coeff, modulus); + quotient_coeff = temp_quotient; + + // Subtract numerator and quotient*denominator (shifted by denominator_shift). + for (size_t denominator_coeff_index = 0; denominator_coeff_index < denominator_coeffs; + denominator_coeff_index++) + { + // Multiply denominator's coefficient by quotient. + uint64_t denominator_coeff = denominator[denominator_coeff_index]; + subtrahend = multiply_uint_uint_mod(temp_quotient, denominator_coeff, modulus); + + // Subtract numerator with resulting product, appropriately shifted by + // denominator shift. + uint64_t &numerator_coeff = numerator[denominator_coeff_index + denominator_shift]; + numerator_coeff = sub_uint_uint_mod(numerator_coeff, subtrahend, modulus); + } + } + + // Top numerator coefficient must now be zero, so adjust coefficient count. + numerator_coeffs--; + } + + // Double check that numerator coefficients is correct because possible + // other coefficients are zero. + numerator_coeffs = get_significant_coeff_count_poly(numerator, coeff_count, size_t(1)); + + // We are done if numerator is zero. + if (numerator_coeffs == 0) + { + break; + } + + // Integrate quotient with invert coefficients. + // Calculate: invert_next = invert_prior + -quotient * invert_curr + multiply_truncate_poly_poly_coeffmod(quotient.get(), invert_curr, coeff_count, modulus, invert_next); + sub_poly_poly_coeffmod(invert_prior, invert_next, coeff_count, modulus, invert_next); + + // Swap prior and curr, and then curr and next. + swap(invert_prior, invert_curr); + swap(invert_curr, invert_next); + + // Swap numerator and denominator. + swap(numerator, denominator); + swap(numerator_coeffs, denominator_coeffs); + } + + // Polynomial is invertible only if denominator is just a scalar. + if (denominator_coeffs != 1) + { + return false; + } + + // Determine scalar necessary to make denominator monic. + uint64_t leading_denominator_coeff = denominator[0]; + if (!try_invert_uint_mod(leading_denominator_coeff, modulus, monic_denominator_scalar)) + { + throw invalid_argument("modulus is not coprime with leading denominator coefficient"); + } + + // Multiply inverse by scalar and done. + multiply_poly_scalar_coeffmod(invert_curr, coeff_count, monic_denominator_scalar, modulus, result); + return true; + } + + void negacyclic_shift_poly_coeffmod( + const uint64_t *operand, size_t coeff_count, size_t shift, const Modulus &modulus, uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand == nullptr) + { + throw invalid_argument("operand"); + } + if (result == nullptr) + { + throw invalid_argument("result"); + } + if (operand == result) + { + throw invalid_argument("result cannot point to the same value as operand"); + } + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } + if (util::get_power_of_two(static_cast<uint64_t>(coeff_count)) < 0) + { + throw invalid_argument("coeff_count"); + } + if (shift >= coeff_count) + { + throw invalid_argument("shift"); + } +#endif + // Nothing to do + if (shift == 0) + { + set_uint_uint(operand, coeff_count, result); + return; + } + + uint64_t index_raw = shift; + uint64_t coeff_count_mod_mask = static_cast<uint64_t>(coeff_count) - 1; + for (size_t i = 0; i < coeff_count; i++, operand++, index_raw++) + { + uint64_t index = index_raw & coeff_count_mod_mask; + if (!(index_raw & static_cast<uint64_t>(coeff_count)) || !*operand) + { + result[index] = *operand; + } + else + { + result[index] = modulus.value() - *operand; + } + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.h b/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.h new file mode 100644 index 0000000000000000000000000000000000000000..13395f911a95c0cd31de40f062f6342f6ca89181 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polyarithsmallmod.h @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/pointer.h" +#include "seal/util/polycore.h" +#include "seal/util/uintarithsmallmod.h" +#include <algorithm> +#include <cstdint> +#include <stdexcept> + +namespace seal +{ + namespace util + { + inline void modulo_poly_coeffs( + const std::uint64_t *poly, std::size_t coeff_count, const Modulus &modulus, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0) + { + throw std::invalid_argument("poly"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } +#endif + std::transform(poly, poly + coeff_count, result, [&](auto coeff) { + uint64_t temp[2]{ coeff, 0 }; + return barrett_reduce_128(temp, modulus); + }); + } + + inline void modulo_poly_coeffs_63( + const std::uint64_t *poly, std::size_t coeff_count, const Modulus &modulus, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0) + { + throw std::invalid_argument("poly"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } +#endif + // This function is the fastest for reducing polynomial coefficients, + // but requires that the input coefficients are at most 63 bits, unlike + // modulo_poly_coeffs that allows also 64-bit coefficients. + std::transform( + poly, poly + coeff_count, result, [&](auto coeff) { return barrett_reduce_63(coeff, modulus); }); + } + + inline void negate_poly_coeffmod( + const std::uint64_t *poly, std::size_t coeff_count, const Modulus &modulus, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (poly == nullptr && coeff_count > 0) + { + throw std::invalid_argument("poly"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + const uint64_t modulus_value = modulus.value(); + for (; coeff_count--; poly++, result++) + { + // Explicit inline + //*result = negate_uint_mod(*poly, modulus); +#ifdef SEAL_DEBUG + if (*poly >= modulus_value) + { + throw std::out_of_range("poly"); + } +#endif + std::int64_t non_zero = (*poly != 0); + *result = (modulus_value - *poly) & static_cast<std::uint64_t>(-non_zero); + } + } + + inline void add_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + const uint64_t modulus_value = modulus.value(); + for (; coeff_count--; result++, operand1++, operand2++) + { + // Explicit inline + // result[i] = add_uint_uint_mod(operand1[i], operand2[i], modulus); +#ifdef SEAL_DEBUG + if (*operand1 >= modulus_value) + { + throw std::invalid_argument("operand1"); + } + if (*operand2 >= modulus_value) + { + throw std::invalid_argument("operand2"); + } +#endif + std::uint64_t sum = *operand1 + *operand2; + *result = sum - (modulus_value & + static_cast<std::uint64_t>(-static_cast<std::int64_t>(sum >= modulus_value))); + } + } + + inline void sub_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (operand1 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (operand2 == nullptr && coeff_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (result == nullptr && coeff_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + const uint64_t modulus_value = modulus.value(); + for (; coeff_count--; result++, operand1++, operand2++) + { +#ifdef SEAL_DEBUG + if (*operand1 >= modulus_value) + { + throw std::out_of_range("operand1"); + } + if (*operand2 >= modulus_value) + { + throw std::out_of_range("operand2"); + } +#endif + unsigned long long temp_result; + std::int64_t borrow = sub_uint64(*operand1, *operand2, &temp_result); + *result = temp_result + (modulus_value & static_cast<std::uint64_t>(-borrow)); + } + } + + void multiply_poly_scalar_coeffmod( + const std::uint64_t *poly, std::size_t coeff_count, std::uint64_t scalar, const Modulus &modulus, + std::uint64_t *result); + + void multiply_poly_poly_coeffmod( + const std::uint64_t *operand1, std::size_t operand1_coeff_count, const std::uint64_t *operand2, + std::size_t operand2_coeff_count, const Modulus &modulus, std::size_t result_coeff_count, + std::uint64_t *result); + + void multiply_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result); + + inline void multiply_truncate_poly_poly_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result) + { + multiply_poly_poly_coeffmod(operand1, coeff_count, operand2, coeff_count, modulus, coeff_count, result); + } + + void divide_poly_poly_coeffmod_inplace( + std::uint64_t *numerator, const std::uint64_t *denominator, std::size_t coeff_count, const Modulus &modulus, + std::uint64_t *quotient); + + inline void divide_poly_poly_coeffmod( + const std::uint64_t *numerator, const std::uint64_t *denominator, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *quotient, std::uint64_t *remainder) + { + set_uint_uint(numerator, coeff_count, remainder); + divide_poly_poly_coeffmod_inplace(remainder, denominator, coeff_count, modulus, quotient); + } + + void dyadic_product_coeffmod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result); + + std::uint64_t poly_infty_norm_coeffmod( + const std::uint64_t *operand, std::size_t coeff_count, const Modulus &modulus); + + bool try_invert_poly_coeffmod( + const std::uint64_t *operand, const std::uint64_t *poly_modulus, std::size_t coeff_count, + const Modulus &modulus, std::uint64_t *result, MemoryPool &pool); + + void negacyclic_shift_poly_coeffmod( + const std::uint64_t *operand, std::size_t coeff_count, std::size_t shift, const Modulus &modulus, + std::uint64_t *result); + + inline void negacyclic_multiply_poly_mono_coeffmod( + const std::uint64_t *operand, std::size_t coeff_count, std::uint64_t mono_coeff, std::size_t mono_exponent, + const Modulus &modulus, std::uint64_t *result, MemoryPool &pool) + { + auto temp(util::allocate_uint(coeff_count, pool)); + multiply_poly_scalar_coeffmod(operand, coeff_count, mono_coeff, modulus, temp.get()); + negacyclic_shift_poly_coeffmod(temp.get(), coeff_count, mono_exponent, modulus, result); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/polycore.h b/bigpiseal3.5.1/native/src/seal/util/polycore.h new file mode 100644 index 0000000000000000000000000000000000000000..3569d2546ccfb84b4be29b8e16dfe99483434f54 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/polycore.h @@ -0,0 +1,361 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/common.h" +#include "seal/util/pointer.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <limits> +#include <sstream> +#include <stdexcept> + +namespace seal +{ + namespace util + { + SEAL_NODISCARD inline std::string poly_to_hex_string( + const std::uint64_t *value, std::size_t coeff_count, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } +#endif + // First check if there is anything to print + if (!coeff_count || !coeff_uint64_count) + { + return "0"; + } + + std::ostringstream result; + bool empty = true; + value += util::mul_safe(coeff_count - 1, coeff_uint64_count); + while (coeff_count--) + { + if (is_zero_uint(value, coeff_uint64_count)) + { + value -= coeff_uint64_count; + continue; + } + if (!empty) + { + result << " + "; + } + result << uint_to_hex_string(value, coeff_uint64_count); + if (coeff_count) + { + result << "x^" << coeff_count; + } + empty = false; + value -= coeff_uint64_count; + } + if (empty) + { + result << "0"; + } + return result.str(); + } + + SEAL_NODISCARD inline std::string poly_to_dec_string( + const std::uint64_t *value, std::size_t coeff_count, std::size_t coeff_uint64_count, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } +#endif + // First check if there is anything to print + if (!coeff_count || !coeff_uint64_count) + { + return "0"; + } + + std::ostringstream result; + bool empty = true; + value += coeff_count - 1; + while (coeff_count--) + { + if (is_zero_uint(value, coeff_uint64_count)) + { + value -= coeff_uint64_count; + continue; + } + if (!empty) + { + result << " + "; + } + result << uint_to_dec_string(value, coeff_uint64_count, pool); + if (coeff_count) + { + result << "x^" << coeff_count; + } + empty = false; + value -= coeff_uint64_count; + } + if (empty) + { + result << "0"; + } + return result.str(); + } + + SEAL_NODISCARD inline auto allocate_poly( + std::size_t coeff_count, std::size_t coeff_uint64_count, MemoryPool &pool) + { + return allocate_uint(util::mul_safe(coeff_count, coeff_uint64_count), pool); + } + + inline void set_zero_poly(std::size_t coeff_count, std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!result && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + set_zero_uint(util::mul_safe(coeff_count, coeff_uint64_count), result); + } + + SEAL_NODISCARD inline auto allocate_zero_poly( + std::size_t coeff_count, std::size_t coeff_uint64_count, MemoryPool &pool) + { + return allocate_zero_uint(util::mul_safe(coeff_count, coeff_uint64_count), pool); + } + + SEAL_NODISCARD inline std::uint64_t *get_poly_coeff( + std::uint64_t *poly, std::size_t coeff_index, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly) + { + throw std::invalid_argument("poly"); + } +#endif + return poly + util::mul_safe(coeff_index, coeff_uint64_count); + } + + SEAL_NODISCARD inline const std::uint64_t *get_poly_coeff( + const std::uint64_t *poly, std::size_t coeff_index, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly) + { + throw std::invalid_argument("poly"); + } +#endif + return poly + util::mul_safe(coeff_index, coeff_uint64_count); + } + + inline void set_poly_poly( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } + if (!result && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + set_uint_uint(poly, util::mul_safe(coeff_count, coeff_uint64_count), result); + } + + SEAL_NODISCARD inline bool is_zero_poly( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } +#endif + return is_zero_uint(poly, util::mul_safe(coeff_count, coeff_uint64_count)); + } + + SEAL_NODISCARD inline bool is_equal_poly_poly( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t coeff_count, + std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!operand1 && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("operand2"); + } +#endif + return is_equal_uint_uint(operand1, operand2, util::mul_safe(coeff_count, coeff_uint64_count)); + } + + inline void set_poly_poly( + const std::uint64_t *poly, std::size_t poly_coeff_count, std::size_t poly_coeff_uint64_count, + std::size_t result_coeff_count, std::size_t result_coeff_uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!poly && poly_coeff_count && poly_coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } + if (!result && result_coeff_count && result_coeff_uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + if (!result_coeff_uint64_count || !result_coeff_count) + { + return; + } + + std::size_t min_coeff_count = std::min(poly_coeff_count, result_coeff_count); + for (std::size_t i = 0; i < min_coeff_count; + i++, poly += poly_coeff_uint64_count, result += result_coeff_uint64_count) + { + set_uint_uint(poly, poly_coeff_uint64_count, result_coeff_uint64_count, result); + } + set_zero_uint(util::mul_safe(result_coeff_count - min_coeff_count, result_coeff_uint64_count), result); + } + + SEAL_NODISCARD inline bool is_one_zero_one_poly( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } +#endif + if (coeff_count == 0 || coeff_uint64_count == 0) + { + return false; + } + if (!is_equal_uint(get_poly_coeff(poly, 0, coeff_uint64_count), coeff_uint64_count, 1)) + { + return false; + } + if (!is_equal_uint(get_poly_coeff(poly, coeff_count - 1, coeff_uint64_count), coeff_uint64_count, 1)) + { + return false; + } + if (coeff_count > 2 && !is_zero_poly(poly + coeff_uint64_count, coeff_count - 2, coeff_uint64_count)) + { + return false; + } + return true; + } + + SEAL_NODISCARD inline std::size_t get_significant_coeff_count_poly( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } +#endif + if (coeff_count == 0) + { + return 0; + } + + poly += util::mul_safe(coeff_count - 1, coeff_uint64_count); + for (std::size_t i = coeff_count; i; i--) + { + if (!is_zero_uint(poly, coeff_uint64_count)) + { + return i; + } + poly -= coeff_uint64_count; + } + return 0; + } + + SEAL_NODISCARD inline auto duplicate_poly_if_needed( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, + std::size_t new_coeff_count, std::size_t new_coeff_uint64_count, bool force, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } +#endif + if (!force && coeff_count >= new_coeff_count && coeff_uint64_count == new_coeff_uint64_count) + { + return ConstPointer<std::uint64_t>::Aliasing(poly); + } + auto allocation(allocate_poly(new_coeff_count, new_coeff_uint64_count, pool)); + set_poly_poly( + poly, coeff_count, coeff_uint64_count, new_coeff_count, new_coeff_uint64_count, allocation.get()); + return ConstPointer<std::uint64_t>(std::move(allocation)); + } + + SEAL_NODISCARD inline bool are_poly_coefficients_less_than( + const std::uint64_t *poly, std::size_t coeff_count, std::size_t coeff_uint64_count, + const std::uint64_t *compare, std::size_t compare_uint64_count) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count && coeff_uint64_count) + { + throw std::invalid_argument("poly"); + } + if (!compare && compare_uint64_count > 0) + { + throw std::invalid_argument("compare"); + } +#endif + if (coeff_count == 0) + { + return true; + } + if (compare_uint64_count == 0) + { + return false; + } + if (coeff_uint64_count == 0) + { + return true; + } + for (; coeff_count--; poly += coeff_uint64_count) + { + if (compare_uint_uint(poly, coeff_uint64_count, compare, compare_uint64_count) >= 0) + { + return false; + } + } + return true; + } + + SEAL_NODISCARD inline bool are_poly_coefficients_less_than( + const std::uint64_t *poly, std::size_t coeff_count, std::uint64_t compare) + { +#ifdef SEAL_DEBUG + if (!poly && coeff_count) + { + throw std::invalid_argument("poly"); + } +#endif + if (coeff_count == 0) + { + return true; + } + for (; coeff_count--; poly++) + { + if (*poly >= compare) + { + return false; + } + } + return true; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/rlwe.cpp b/bigpiseal3.5.1/native/src/seal/util/rlwe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad20a960a1f7d7fe44ee991991518c2006eec3cc --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/rlwe.cpp @@ -0,0 +1,303 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/randomgen.h" +#include "seal/randomtostd.h" +#include "seal/util/clipnormal.h" +#include "seal/util/common.h" +#include "seal/util/globals.h" +#include "seal/util/ntt.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/rlwe.h" + +using namespace std; + +namespace seal +{ + namespace util + { + void sample_poly_ternary( + shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, uint64_t *destination) + { + auto coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + RandomToStandardAdapter engine(rng); + uniform_int_distribution<int> dist(-1, 1); + + for (size_t i = 0; i < coeff_count; i++) + { + int rand_index = dist(engine); + if (rand_index == 1) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = 1; + } + } + else if (rand_index == -1) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = coeff_modulus[j].value() - 1; + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = 0; + } + } + } + } + + void sample_poly_normal( + shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, uint64_t *destination) + { + auto coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + + if (are_close(global_variables::noise_max_deviation, 0.0)) + { + set_zero_poly(coeff_count, coeff_modulus_size, destination); + return; + } + + RandomToStandardAdapter engine(rng); + ClippedNormalDistribution dist( + 0, global_variables::noise_standard_deviation, global_variables::noise_max_deviation); + for (size_t i = 0; i < coeff_count; i++) + { + int64_t noise = static_cast<int64_t>(dist(engine)); + if (noise > 0) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = static_cast<uint64_t>(noise); + } + } + else if (noise < 0) + { + noise = -noise; + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = coeff_modulus[j].value() - static_cast<uint64_t>(noise); + } + } + else + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[i + j * coeff_count] = 0; + } + } + } + } + + void sample_poly_uniform( + shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, uint64_t *destination) + { + // Extract encryption parameters. + auto coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + + // Set up source of randomness that produces 32 bit random things. + RandomToStandardAdapter engine(rng); + + // We sample numbers up to 2^63-1 to use barrett_reduce_63 + constexpr uint64_t max_random = static_cast<uint64_t>(0x7FFFFFFFFFFFFFFFULL); + for (size_t j = 0; j < coeff_modulus_size; j++) + { + auto &modulus = coeff_modulus[j]; + uint64_t max_multiple = max_random - barrett_reduce_63(max_random, modulus) - 1; + for (size_t i = 0; i < coeff_count; i++) + { + // This ensures uniform distribution. + uint64_t rand; + do + { + rand = (static_cast<uint64_t>(engine()) << 31) | (static_cast<uint64_t>(engine() >> 1)); + } while (rand >= max_multiple); + destination[i + j * coeff_count] = barrett_reduce_63(rand, modulus); + } + } + } + + void encrypt_zero_asymmetric( + const PublicKey &public_key, shared_ptr<SEALContext> context, parms_id_type parms_id, bool is_ntt_form, + Ciphertext &destination) + { +#ifdef SEAL_DEBUG + if (!is_valid_for(public_key, context)) + { + throw invalid_argument("public key is not valid for the encryption parameters"); + } +#endif + // We use a fresh memory pool with `clear_on_destruction' enabled. + MemoryPoolHandle pool = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true); + + auto &context_data = *context->get_context_data(parms_id); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + auto small_ntt_tables = context_data.small_ntt_tables(); + size_t encrypted_size = public_key.data().size(); + + // Make destination have right size and parms_id + // Ciphertext (c_0,c_1, ...) + destination.resize(context, parms_id, encrypted_size); + destination.is_ntt_form() = is_ntt_form; + destination.scale() = 1.0; + + // c[j] = public_key[j] * u + e[j] where e[j] <-- chi, u <-- R_3. + + // Create RNG, u and error share one RNG. + auto rng = parms.random_generator()->create(); + + // Generate u <-- R_3 + auto u(allocate_poly(coeff_count, coeff_modulus_size, pool)); + sample_poly_ternary(rng, parms, u.get()); + + // c[j] = u * public_key[j] + for (size_t i = 0; i < coeff_modulus_size; i++) + { + ntt_negacyclic_harvey(u.get() + i * coeff_count, small_ntt_tables[i]); + for (size_t j = 0; j < encrypted_size; j++) + { + dyadic_product_coeffmod( + u.get() + i * coeff_count, public_key.data().data(j) + i * coeff_count, coeff_count, + coeff_modulus[i], destination.data(j) + i * coeff_count); + + // addition with e_0, e_1 is in non-NTT form. + if (!is_ntt_form) + { + inverse_ntt_negacyclic_harvey(destination.data(j) + i * coeff_count, small_ntt_tables[i]); + } + } + } + + // Generate e_j <-- chi. + // c[j] = public_key[j] * u + e[j] + for (size_t j = 0; j < encrypted_size; j++) + { + sample_poly_normal(rng, parms, u.get()); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // addition with e_0, e_1 is in NTT form. + if (is_ntt_form) + { + ntt_negacyclic_harvey(u.get() + i * coeff_count, small_ntt_tables[i]); + } + add_poly_poly_coeffmod( + u.get() + i * coeff_count, destination.data(j) + i * coeff_count, coeff_count, coeff_modulus[i], + destination.data(j) + i * coeff_count); + } + } + } + + void encrypt_zero_symmetric( + const SecretKey &secret_key, shared_ptr<SEALContext> context, parms_id_type parms_id, bool is_ntt_form, + bool save_seed, Ciphertext &destination) + { +#ifdef SEAL_DEBUG + if (!is_valid_for(secret_key, context)) + { + throw invalid_argument("secret key is not valid for the encryption parameters"); + } +#endif + // We use a fresh memory pool with `clear_on_destruction' enabled. + MemoryPoolHandle pool = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true); + + auto &context_data = *context->get_context_data(parms_id); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t coeff_count = parms.poly_modulus_degree(); + auto small_ntt_tables = context_data.small_ntt_tables(); + size_t encrypted_size = 2; + + // If a polynomial is too small to store a seed, disable save_seed. + auto poly_uint64_count = mul_safe(coeff_count, coeff_modulus_size); + if (save_seed && static_cast<uint64_t>(poly_uint64_count) < (random_seed_type().size() + 1)) + { + save_seed = false; + } + + destination.resize(context, parms_id, encrypted_size); + destination.is_ntt_form() = is_ntt_form; + destination.scale() = 1.0; + + auto rng_error = parms.random_generator()->create(); + shared_ptr<UniformRandomGenerator> rng_ciphertext; + rng_ciphertext = BlakePRNGFactory().create(); + + // Generate ciphertext: (c[0], c[1]) = ([-(as+e)]_q, a) + uint64_t *c0 = destination.data(); + uint64_t *c1 = destination.data(1); + + // Sample a uniformly at random + if (is_ntt_form || !save_seed) + { + // sample the NTT form directly + sample_poly_uniform(rng_ciphertext, parms, c1); + } + else if (save_seed) + { + // sample non-NTT form and store the seed + sample_poly_uniform(rng_ciphertext, parms, c1); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Transform the c1 into NTT representation. + ntt_negacyclic_harvey(c1 + i * coeff_count, small_ntt_tables[i]); + } + } + + // Sample e <-- chi + auto noise(allocate_poly(coeff_count, coeff_modulus_size, pool)); + sample_poly_normal(rng_error, parms, noise.get()); + + // calculate -(a*s + e) (mod q) and store in c[0] + for (size_t i = 0; i < coeff_modulus_size; i++) + { + dyadic_product_coeffmod( + secret_key.data().data() + i * coeff_count, c1 + i * coeff_count, coeff_count, coeff_modulus[i], + c0 + i * coeff_count); + if (is_ntt_form) + { + // Transform the noise e into NTT representation. + ntt_negacyclic_harvey(noise.get() + i * coeff_count, small_ntt_tables[i]); + } + else + { + inverse_ntt_negacyclic_harvey(c0 + i * coeff_count, small_ntt_tables[i]); + } + add_poly_poly_coeffmod( + noise.get() + i * coeff_count, c0 + i * coeff_count, coeff_count, coeff_modulus[i], + c0 + i * coeff_count); + negate_poly_coeffmod(c0 + i * coeff_count, coeff_count, coeff_modulus[i], c0 + i * coeff_count); + } + + if (!is_ntt_form && !save_seed) + { + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Transform the c1 into non-NTT representation. + inverse_ntt_negacyclic_harvey(c1 + i * coeff_count, small_ntt_tables[i]); + } + } + + if (save_seed) + { + random_seed_type seed = rng_ciphertext->seed(); + // Write random seed to destination.data(1). + c1[0] = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL); + copy_n(seed.cbegin(), seed.size(), c1 + 1); + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/rlwe.h b/bigpiseal3.5.1/native/src/seal/util/rlwe.h new file mode 100644 index 0000000000000000000000000000000000000000..4aca0975990bf455145ffb0e1836f208ba286a90 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/rlwe.h @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/encryptionparams.h" +#include "seal/publickey.h" +#include "seal/randomgen.h" +#include "seal/secretkey.h" +#include <cstdint> + +namespace seal +{ + namespace util + { + /** + Generate a ternary polynomial uniformlly and store in RNS representation. + + @param[in] rng A uniform random generator. + @param[in] parms EncryptionParameters used to parametize an RNS polynomial. + @param[out] destination Allocated space to store a random polynomia. + */ + void sample_poly_ternary( + std::shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, std::uint64_t *destination); + + /** + Generate a polynomial from a normal distribution and store in RNS representation. + + @param[in] rng A uniform random generator. + @param[in] parms EncryptionParameters used to parametize an RNS polynomial. + @param[out] destination Allocated space to store a random polynomia. + */ + void sample_poly_normal( + std::shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, std::uint64_t *destination); + + /** + Generate a polynomial uniformly from Rq and store in RNS representation. + + @param[in] rng A uniform random generator. + @param[in] parms EncryptionParameters used to parametize an RNS polynomial. + @param[out] destination Allocated space to store a random polynomia. + */ + void sample_poly_uniform( + std::shared_ptr<UniformRandomGenerator> rng, const EncryptionParameters &parms, std::uint64_t *destination); + + /** + Create an encryption of zero with a public key and store in a ciphertext. + + @param[in] public_key The public key used for encryption. + @param[in] context The SEALContext containing a chain of ContextData. + @param[in] parms_id Indicates the level of encryption. + @param[in] is_ntt_form If true, store Ciphertext in NTT form. + @param[out] destination The output ciphertext - an encryption of zero. + */ + void encrypt_zero_asymmetric( + const PublicKey &public_key, std::shared_ptr<SEALContext> context, parms_id_type parms_id, bool is_ntt_form, + Ciphertext &destination); + + /** + Create an encryption of zero with a secret key and store in a ciphertext. + + @param[out] destination The output ciphertext - an encryption of zero. + @param[in] secret_key The secret key used for encryption. + @param[in] context The SEALContext containing a chain of ContextData. + @param[in] parms_id Indicates the level of encryption. + @param[in] is_ntt_form If true, store Ciphertext in NTT form. + @param[in] save_seed If true, The second component of ciphertext is + replaced with the random seed used to sample this component. + */ + void encrypt_zero_symmetric( + const SecretKey &secret_key, std::shared_ptr<SEALContext> context, parms_id_type parms_id, bool is_ntt_form, + bool save_seed, Ciphertext &destination); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/rns.cpp b/bigpiseal3.5.1/native/src/seal/util/rns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9955fb9b8e71562503bbcb39936a0e6d04d970c7 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/rns.cpp @@ -0,0 +1,1110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/numth.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/rns.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintarithsmallmod.h" +#include <algorithm> + +using namespace std; + +namespace seal +{ + namespace util + { + RNSBase::RNSBase(const vector<Modulus> &rnsbase, MemoryPoolHandle pool) + : pool_(move(pool)), size_(rnsbase.size()) + { + if (!size_) + { + throw invalid_argument("rnsbase cannot be empty"); + } + if (!pool_) + { + throw invalid_argument("pool is uninitialized"); + } + + for (size_t i = 0; i < size_; i++) + { + // The base elements cannot be zero + if (rnsbase[i].is_zero()) + { + throw invalid_argument("rnsbase is invalid"); + } + for (size_t j = 0; j < i; j++) + { + // The base must be coprime + if (!are_coprime(rnsbase[i].value(), rnsbase[j].value())) + { + throw invalid_argument("rnsbase is invalid"); + } + } + } + + // Base is good; now copy it over to rnsbase_ + base_ = allocate<Modulus>(size_, pool_); + for (size_t i = 0; i < size_; i++) + { + base_[i] = rnsbase[i]; + } + + // Initialize CRT data + if (!initialize()) + { + throw invalid_argument("rnsbase is invalid"); + } + } + + RNSBase::RNSBase(const RNSBase &copy, MemoryPoolHandle pool) : pool_(move(pool)), size_(copy.size_) + { + if (!pool_) + { + throw invalid_argument("pool is uninitialized"); + } + + // Copy over the base + base_ = allocate<Modulus>(size_, pool_); + copy_n(copy.base_.get(), size_, base_.get()); + + // Copy over CRT data + base_prod_ = allocate_uint(size_, pool_); + copy_n(copy.base_prod_.get(), size_, base_prod_.get()); + + punctured_prod_array_ = allocate_uint(size_ * size_, pool_); + copy_n(copy.punctured_prod_array_.get(), size_ * size_, punctured_prod_array_.get()); + + inv_punctured_prod_mod_base_array_ = allocate_uint(size_, pool_); + copy_n(copy.inv_punctured_prod_mod_base_array_.get(), size_, inv_punctured_prod_mod_base_array_.get()); + } + + bool RNSBase::contains(const Modulus &value) const noexcept + { + for (size_t i = 0; i < size_; i++) + { + if (base_[i] == value) + { + return true; + } + } + return false; + } + + bool RNSBase::is_subbase_of(const RNSBase &superbase) const noexcept + { + for (size_t sub = 0; sub < size_; sub++) + { + if (!superbase.contains(base_[sub])) + { + return false; + } + } + return true; + } + + RNSBase RNSBase::extend(Modulus value) const + { + if (value.is_zero()) + { + throw invalid_argument("value cannot be zero"); + } + + for (size_t i = 0; i < size_; i++) + { + // The base must be coprime + if (!are_coprime(base_[i].value(), value.value())) + { + throw logic_error("cannot extend by given value"); + } + } + + // Copy over this base + RNSBase newbase(pool_); + newbase.size_ = add_safe(size_, size_t(1)); + newbase.base_ = allocate<Modulus>(newbase.size_, newbase.pool_); + for (size_t i = 0; i < size_; i++) + { + newbase.base_[i] = base_[i]; + } + + // Extend with value + newbase.base_[newbase.size_ - 1] = value; + + // Initialize CRT data + if (!newbase.initialize()) + { + throw logic_error("cannot extend by given value"); + } + + return newbase; + } + + RNSBase RNSBase::extend(const RNSBase &other) const + { + for (size_t i = 0; i < size_; i++) + { + // The other base must be coprime to this + for (size_t j = 0; j < other.size_; j++) + { + if (!are_coprime(base_[i].value(), other.base_[j].value())) + { + throw logic_error("cannot extend by given base"); + } + } + } + + // Copy over this base + RNSBase newbase(pool_); + newbase.size_ = add_safe(size_, other.size_); + newbase.base_ = allocate<Modulus>(newbase.size_, newbase.pool_); + for (size_t i = 0; i < size_; i++) + { + newbase.base_[i] = base_[i]; + } + + // Extend with other base + for (size_t i = 0; i < other.size_; i++) + { + newbase.base_[size_ + i] = other.base_[i]; + } + + // Initialize CRT data + if (!newbase.initialize()) + { + throw logic_error("cannot extend by given base"); + } + + return newbase; + } + + RNSBase RNSBase::drop() const + { + if (size_ == 1) + { + throw std::logic_error("cannot drop from base of size 1"); + } + + // Copy over this base + RNSBase newbase(pool_); + newbase.size_ = size_ - 1; + newbase.base_ = allocate<Modulus>(newbase.size_, newbase.pool_); + for (size_t i = 0; i < size_ - 1; i++) + { + newbase.base_[i] = base_[i]; + } + + // Initialize CRT data + newbase.initialize(); + + return newbase; + } + + RNSBase RNSBase::drop(Modulus value) const + { + if (size_ == 1) + { + throw std::logic_error("cannot drop from base of size 1"); + } + if (!contains(value)) + { + throw logic_error("base does not contain value"); + } + + // Copy over this base + RNSBase newbase(pool_); + newbase.size_ = size_ - 1; + newbase.base_ = allocate<Modulus>(newbase.size_, newbase.pool_); + size_t source_index = 0; + size_t dest_index = 0; + while (dest_index < size_ - 1) + { + if (base_[source_index] != value) + { + newbase.base_[dest_index] = base_[source_index]; + dest_index++; + } + source_index++; + } + + // Initialize CRT data + newbase.initialize(); + + return newbase; + } + + bool RNSBase::initialize() + { + // Verify that the size is not too large + if (!product_fits_in(size_, size_)) + { + return false; + } + + base_prod_ = allocate_uint(size_, pool_); + punctured_prod_array_ = allocate_zero_uint(size_ * size_, pool_); + inv_punctured_prod_mod_base_array_ = allocate_uint(size_, pool_); + + if (size_ > 1) + { + auto rnsbase_values = allocate<uint64_t>(size_, pool_); + for (size_t i = 0; i < size_; i++) + { + rnsbase_values[i] = base_[i].value(); + } + + // Create punctured products + for (size_t i = 0; i < size_; i++) + { + multiply_many_uint64_except( + rnsbase_values.get(), size_, i, punctured_prod_array_.get() + (i * size_), pool_); + } + + // Compute the full product + auto temp_mpi(allocate_uint(size_, pool_)); + multiply_uint_uint64(punctured_prod_array_.get(), size_, base_[0].value(), size_, temp_mpi.get()); + set_uint_uint(temp_mpi.get(), size_, base_prod_.get()); + + // Compute inverses of punctured products mod primes + for (size_t i = 0; i < size_; i++) + { + inv_punctured_prod_mod_base_array_[i] = + modulo_uint(punctured_prod_array_.get() + (i * size_), size_, base_[i]); + if (!try_invert_uint_mod( + inv_punctured_prod_mod_base_array_[i], base_[i], inv_punctured_prod_mod_base_array_[i])) + { + return false; + } + } + } + else + { + base_prod_[0] = base_[0].value(); + punctured_prod_array_[0] = 1; + inv_punctured_prod_mod_base_array_[0] = 1; + } + + // Everything went well + return true; + } + + void RNSBase::decompose(uint64_t *value, MemoryPoolHandle pool) const + { + if (!value) + { + throw invalid_argument("value cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + if (size_ > 1) + { + // Copy the value + auto value_copy(allocate_uint(size_, pool)); + set_uint_uint(value, size_, value_copy.get()); + + // Temporary space for 128-bit reductions + for (size_t i = 0; i < size_; i++) + { + // Reduce in blocks + uint64_t temp[2]{ 0, value_copy[size_ - 1] }; + for (size_t k = size_ - 1; k--;) + { + temp[0] = value_copy[k]; + temp[1] = barrett_reduce_128(temp, base_[i]); + } + + // Save the result modulo i-th base element + value[i] = temp[1]; + } + } + } + + void RNSBase::decompose_array(uint64_t *value, size_t count, MemoryPoolHandle pool) const + { + if (!value) + { + throw invalid_argument("value cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + if (size_ > 1) + { + if (!product_fits_in(count, size_)) + { + throw logic_error("invalid parameters"); + } + + // Decompose an array of multi-precision integers into an array of arrays, + // one per each base element + auto value_copy(allocate_uint(count * size_, pool)); + for (size_t i = 0; i < count; i++, value += size_) + { + set_uint_uint(value, size_, value_copy.get()); + + // Temporary space for 128-bit reductions + for (size_t j = 0; j < size_; j++) + { + // Reduce in blocks + uint64_t temp[2]{ 0, value_copy[size_ - 1] }; + for (size_t k = size_ - 1; k--;) + { + temp[0] = value_copy[k]; + temp[1] = barrett_reduce_128(temp, base_[j]); + } + + // Save the result modulo i-th base element + value[i] = temp[1]; + } + } + } + } + + void RNSBase::compose(uint64_t *value, MemoryPoolHandle pool) const + { + if (!value) + { + throw invalid_argument("value cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + if (size_ > 1) + { + // Copy the value + auto temp_value(allocate_uint(size_, pool)); + copy_n(value, size_, temp_value.get()); + + // Clear the result + set_zero_uint(size_, value); + + // Compose an array of integers (one per base element) into a single multi-precision integer + auto temp_mpi(allocate_uint(size_, pool)); + for (size_t i = 0; i < size_; i++) + { + uint64_t temp_prod = + multiply_uint_uint_mod(temp_value[i], inv_punctured_prod_mod_base_array_[i], base_[i]); + multiply_uint_uint64( + punctured_prod_array_.get() + (i * size_), size_, temp_prod, size_, temp_mpi.get()); + add_uint_uint_mod(temp_mpi.get(), value, base_prod_.get(), size_, value); + } + } + } + + void RNSBase::compose_array(uint64_t *value, size_t count, MemoryPoolHandle pool) const + { + if (!value) + { + throw invalid_argument("value cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + if (size_ > 1) + { + if (!product_fits_in(count, size_)) + { + throw logic_error("invalid parameters"); + } + + // Compose an array of arrays of integers (one array per base element) into + // a single array of multi-precision integers + auto temp_array(allocate_uint(count * size_, pool)); + + // Merge the coefficients first + for (size_t i = 0; i < count; i++) + { + for (size_t j = 0; j < size_; j++) + { + temp_array[j + (i * size_)] = value[(j * count) + i]; + } + } + + // Clear the result + set_zero_uint(count * size_, value); + + auto temp_mpi(allocate_uint(size_, pool)); + for (size_t i = 0; i < count; i++) + { + // Do CRT compose for each coefficient + for (size_t j = 0; j < size_; j++) + { + uint64_t temp_prod = multiply_uint_uint_mod( + temp_array[(i * size_) + j], inv_punctured_prod_mod_base_array_[j], base_[j]); + multiply_uint_uint64( + punctured_prod_array_.get() + (j * size_), size_, temp_prod, size_, temp_mpi.get()); + add_uint_uint_mod( + temp_mpi.get(), value + (i * size_), base_prod_.get(), size_, value + (i * size_)); + } + } + } + } + + void BaseConverter::fast_convert(const uint64_t *in, uint64_t *out, MemoryPoolHandle pool) const + { + size_t ibase_size = ibase_.size(); + size_t obase_size = obase_.size(); + + auto temp(allocate_uint(ibase_size, pool)); + for (size_t i = 0; i < ibase_size; i++) + { + temp[i] = multiply_uint_uint_mod(in[i], ibase_.inv_punctured_prod_mod_base_array()[i], ibase_[i]); + } + + for (size_t j = 0; j < obase_size; j++) + { + out[j] = dot_product_mod(temp.get(), base_change_matrix_[j].get(), ibase_size, obase_[j]); + } + } + + void BaseConverter::fast_convert_array( + const uint64_t *in, size_t count, uint64_t *out, MemoryPoolHandle pool) const + { + size_t ibase_size = ibase_.size(); + size_t obase_size = obase_.size(); + + auto temp(allocate_uint(count * ibase_size, pool)); + for (size_t i = 0; i < ibase_size; i++) + { + uint64_t inv_ibase_punctured_prod_mod_ibase_elt = ibase_.inv_punctured_prod_mod_base_array()[i]; + Modulus ibase_elt = ibase_[i]; + uint64_t *temp_ptr = temp.get() + i; + for (size_t k = 0; k < count; k++, in++, temp_ptr += ibase_size) + { + *temp_ptr = multiply_uint_uint_mod(*in, inv_ibase_punctured_prod_mod_ibase_elt, ibase_elt); + } + } + + for (size_t j = 0; j < obase_size; j++) + { + uint64_t *temp_ptr = temp.get(); + Modulus obase_elt = obase_[j]; + for (size_t k = 0; k < count; k++, out++, temp_ptr += ibase_size) + { + *out = dot_product_mod(temp_ptr, base_change_matrix_[j].get(), ibase_size, obase_elt); + } + } + } + + void BaseConverter::initialize() + { + // Verify that the size is not too large + if (!product_fits_in(ibase_.size(), obase_.size())) + { + throw logic_error("invalid parameters"); + } + + auto ibase_values = allocate<uint64_t>(ibase_.size(), pool_); + for (size_t i = 0; i < ibase_.size(); i++) + { + ibase_values[i] = ibase_[i].value(); + } + + // Compute the base-change matrix + base_change_matrix_ = allocate<Pointer<uint64_t>>(obase_.size(), pool_); + for (size_t i = 0; i < obase_.size(); i++) + { + base_change_matrix_[i] = allocate_uint(ibase_.size(), pool_); + for (size_t j = 0; j < ibase_.size(); j++) + { + base_change_matrix_[i][j] = + modulo_uint(ibase_.punctured_prod_array() + (j * ibase_.size()), ibase_.size(), obase_[i]); + } + } + } + + RNSTool::RNSTool( + size_t poly_modulus_degree, const RNSBase &coeff_modulus, const Modulus &plain_modulus, + MemoryPoolHandle pool) + : pool_(move(pool)) + { +#ifdef SEAL_DEBUG + if (!pool_) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + initialize(poly_modulus_degree, coeff_modulus, plain_modulus); + } + + void RNSTool::initialize(size_t poly_modulus_degree, const RNSBase &q, const Modulus &t) + { + // Return if q is out of bounds + if (q.size() < SEAL_COEFF_MOD_COUNT_MIN || q.size() > SEAL_COEFF_MOD_COUNT_MAX) + { + throw invalid_argument("rnsbase is invalid"); + } + + // Return if coeff_count is not a power of two or out of bounds + int coeff_count_power = get_power_of_two(poly_modulus_degree); + if (coeff_count_power < 0 || poly_modulus_degree > SEAL_POLY_MOD_DEGREE_MAX || + poly_modulus_degree < SEAL_POLY_MOD_DEGREE_MIN) + { + throw invalid_argument("poly_modulus_degree is invalid"); + } + + t_ = t; + coeff_count_ = poly_modulus_degree; + + // Allocate memory for the bases q, B, Bsk, Bsk U m_tilde, t_gamma + size_t base_q_size = q.size(); + + // In some cases we might need to increase the size of the base B by one, namely we require + // K * n * t * q^2 < q * prod(B) * m_sk, where K takes into account cross terms when larger size ciphertexts + // are used, and n is the "delta factor" for the ring. We reserve 32 bits for K * n. Here the coeff modulus + // primes q_i are bounded to be SEAL_USER_MOD_BIT_COUNT_MAX (60) bits, and all primes in B and m_sk are + // SEAL_INTERNAL_MOD_BIT_COUNT (61) bits. + int total_coeff_bit_count = get_significant_bit_count_uint(q.base_prod(), q.size()); + + size_t base_B_size = base_q_size; + if (32 + t_.bit_count() + total_coeff_bit_count >= + SEAL_INTERNAL_MOD_BIT_COUNT * safe_cast<int>(base_q_size) + SEAL_INTERNAL_MOD_BIT_COUNT) + { + base_B_size++; + } + + size_t base_Bsk_size = add_safe(base_B_size, size_t(1)); + size_t base_Bsk_m_tilde_size = add_safe(base_Bsk_size, size_t(1)); + + size_t base_t_gamma_size = 0; + + // Size check + if (!product_fits_in(coeff_count_, base_Bsk_m_tilde_size)) + { + throw logic_error("invalid parameters"); + } + + // Sample primes for B and two more primes: m_sk and gamma + auto baseconv_primes = get_primes(coeff_count_, SEAL_USER_MOD_BIT_COUNT_MAX + 1, base_Bsk_m_tilde_size); + auto baseconv_primes_iter = baseconv_primes.cbegin(); + m_sk_ = *baseconv_primes_iter++; + gamma_ = *baseconv_primes_iter++; + vector<Modulus> base_B_primes; + copy_n(baseconv_primes_iter, base_B_size, back_inserter(base_B_primes)); + + // Set m_tilde_ to a non-prime value + m_tilde_ = uint64_t(1) << 32; + + // Populate the base arrays + base_q_ = allocate<RNSBase>(pool_, q, pool_); + base_B_ = allocate<RNSBase>(pool_, base_B_primes, pool_); + base_Bsk_ = allocate<RNSBase>(pool_, base_B_->extend(m_sk_)); + base_Bsk_m_tilde_ = allocate<RNSBase>(pool_, base_Bsk_->extend(m_tilde_)); + + // Set up t-gamma base if t_ is non-zero (using BFV) + if (!t_.is_zero()) + { + base_t_gamma_size = 2; + base_t_gamma_ = allocate<RNSBase>(pool_, vector<Modulus>{ t_, gamma_ }, pool_); + } + + // Generate the Bsk NTTTables; these are used for NTT after base extension to Bsk + try + { + CreateNTTTables( + coeff_count_power, vector<Modulus>(base_Bsk_->base(), base_Bsk_->base() + base_Bsk_size), + base_Bsk_small_ntt_tables_, pool_); + } + catch (const logic_error &) + { + throw logic_error("invalid rns bases"); + } + + // Set up BaseConvTool for q --> Bsk + base_q_to_Bsk_conv_ = allocate<BaseConverter>(pool_, *base_q_, *base_Bsk_, pool_); + + // Set up BaseConvTool for q --> {m_tilde} + base_q_to_m_tilde_conv_ = allocate<BaseConverter>(pool_, *base_q_, RNSBase({ m_tilde_ }, pool_), pool_); + + // Set up BaseConvTool for B --> q + base_B_to_q_conv_ = allocate<BaseConverter>(pool_, *base_B_, *base_q_, pool_); + + // Set up BaseConvTool for B --> {m_sk} + base_B_to_m_sk_conv_ = allocate<BaseConverter>(pool_, *base_B_, RNSBase({ m_sk_ }, pool_), pool_); + + if (base_t_gamma_) + { + // Set up BaseConvTool for q --> {t, gamma} + base_q_to_t_gamma_conv_ = allocate<BaseConverter>(pool_, *base_q_, *base_t_gamma_, pool_); + } + + // Compute prod(B) mod q + prod_B_mod_q_ = allocate_uint(base_q_size, pool_); + for (size_t i = 0; i < base_q_size; i++) + { + prod_B_mod_q_[i] = modulo_uint(base_B_->base_prod(), base_B_size, (*base_q_)[i]); + } + + // Compute prod(q)^(-1) mod Bsk + inv_prod_q_mod_Bsk_ = allocate_uint(base_Bsk_size, pool_); + for (size_t i = 0; i < base_Bsk_size; i++) + { + inv_prod_q_mod_Bsk_[i] = modulo_uint(base_q_->base_prod(), base_q_size, (*base_Bsk_)[i]); + if (!try_invert_uint_mod(inv_prod_q_mod_Bsk_[i], (*base_Bsk_)[i], inv_prod_q_mod_Bsk_[i])) + { + throw logic_error("invalid rns bases"); + } + } + + // Compute prod(B)^(-1) mod m_sk + inv_prod_B_mod_m_sk_ = modulo_uint(base_B_->base_prod(), base_B_size, m_sk_); + if (!try_invert_uint_mod(inv_prod_B_mod_m_sk_, m_sk_, inv_prod_B_mod_m_sk_)) + { + throw logic_error("invalid rns bases"); + } + + // Compute m_tilde^(-1) mod Bsk + inv_m_tilde_mod_Bsk_ = allocate_uint(base_Bsk_size, pool_); + for (size_t i = 0; i < base_Bsk_size; i++) + { + if (!try_invert_uint_mod( + m_tilde_.value() % (*base_Bsk_)[i].value(), (*base_Bsk_)[i], inv_m_tilde_mod_Bsk_[i])) + { + throw logic_error("invalid rns bases"); + } + } + + // Compute prod(q)^(-1) mod m_tilde + inv_prod_q_mod_m_tilde_ = modulo_uint(base_q_->base_prod(), base_q_size, m_tilde_); + if (!try_invert_uint_mod(inv_prod_q_mod_m_tilde_, m_tilde_, inv_prod_q_mod_m_tilde_)) + { + throw logic_error("invalid rns bases"); + } + + // Compute prod(q) mod Bsk + prod_q_mod_Bsk_ = allocate_uint(base_Bsk_size, pool_); + for (size_t i = 0; i < base_Bsk_size; i++) + { + prod_q_mod_Bsk_[i] = modulo_uint(base_q_->base_prod(), base_q_size, (*base_Bsk_)[i]); + } + + if (base_t_gamma_) + { + // Compute gamma^(-1) mod t + if (!try_invert_uint_mod(gamma_.value() % t_.value(), t_, inv_gamma_mod_t_)) + { + throw logic_error("invalid rns bases"); + } + + // Compute prod({t, gamma}) mod q + prod_t_gamma_mod_q_ = allocate_uint(base_q_size, pool_); + for (size_t i = 0; i < base_q_size; i++) + { + prod_t_gamma_mod_q_[i] = + multiply_uint_uint_mod((*base_t_gamma_)[0].value(), (*base_t_gamma_)[1].value(), (*base_q_)[i]); + } + + // Compute -prod(q)^(-1) mod {t, gamma} + neg_inv_q_mod_t_gamma_ = allocate_uint(base_t_gamma_size, pool_); + for (size_t i = 0; i < base_t_gamma_size; i++) + { + neg_inv_q_mod_t_gamma_[i] = modulo_uint(base_q_->base_prod(), base_q_size, (*base_t_gamma_)[i]); + if (!try_invert_uint_mod(neg_inv_q_mod_t_gamma_[i], (*base_t_gamma_)[i], neg_inv_q_mod_t_gamma_[i])) + { + throw logic_error("invalid rns bases"); + } + neg_inv_q_mod_t_gamma_[i] = negate_uint_mod(neg_inv_q_mod_t_gamma_[i], (*base_t_gamma_)[i]); + } + } + + // Compute q[last]^(-1) mod q[i] for i = 0..last-1 + // This is used by modulus switching and rescaling + inv_q_last_mod_q_ = allocate_uint(base_q_size - 1, pool_); + for (size_t i = 0; i < base_q_size - 1; i++) + { + if (!try_invert_uint_mod((*base_q_)[base_q_size - 1].value(), (*base_q_)[i], inv_q_last_mod_q_[i])) + { + throw logic_error("invalid rns bases"); + } + } + } + + void RNSTool::divide_and_round_q_last_inplace(uint64_t *input, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (!input) + { + throw invalid_argument("input cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + auto base_q_size = base_q_->size(); + uint64_t *last_ptr = input + (base_q_size - 1) * coeff_count_; + + // Add (qi-1)/2 to change from flooring to rounding + Modulus last_modulus = (*base_q_)[base_q_size - 1]; + uint64_t half = last_modulus.value() >> 1; + for (size_t j = 0; j < coeff_count_; j++) + { + last_ptr[j] = barrett_reduce_63(last_ptr[j] + half, last_modulus); + } + + auto temp(allocate_uint(coeff_count_, pool)); + uint64_t *temp_ptr = temp.get(); + for (size_t i = 0; i < base_q_size - 1; i++) + { + // (ct mod qk) mod qi + modulo_poly_coeffs_63(last_ptr, coeff_count_, (*base_q_)[i], temp_ptr); + + uint64_t half_mod = barrett_reduce_63(half, (*base_q_)[i]); + for (size_t j = 0; j < coeff_count_; j++) + { + temp_ptr[j] = sub_uint_uint_mod(temp_ptr[j], half_mod, (*base_q_)[i]); + } + + sub_poly_poly_coeffmod( + input + (i * coeff_count_), temp_ptr, coeff_count_, (*base_q_)[i], input + (i * coeff_count_)); + + // qk^(-1) * ((ct mod qi) - (ct mod qk)) mod qi + multiply_poly_scalar_coeffmod( + input + (i * coeff_count_), coeff_count_, inv_q_last_mod_q_[i], (*base_q_)[i], + input + (i * coeff_count_)); + } + } + + void RNSTool::divide_and_round_q_last_ntt_inplace( + uint64_t *input, const NTTTables *rns_ntt_tables, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (!input) + { + throw invalid_argument("input cannot be null"); + } + if (!rns_ntt_tables) + { + throw invalid_argument("rns_ntt_tables cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + auto base_q_size = base_q_->size(); + uint64_t *last_ptr = input + (base_q_size - 1) * coeff_count_; + + // Convert to non-NTT form + inverse_ntt_negacyclic_harvey(last_ptr, rns_ntt_tables[base_q_size - 1]); + + // Add (qi-1)/2 to change from flooring to rounding + Modulus last_modulus = (*base_q_)[base_q_size - 1]; + uint64_t half = last_modulus.value() >> 1; + for (size_t j = 0; j < coeff_count_; j++) + { + last_ptr[j] = barrett_reduce_63(last_ptr[j] + half, last_modulus); + } + + auto temp(allocate_uint(coeff_count_, pool)); + uint64_t *temp_ptr = temp.get(); + for (size_t i = 0; i < base_q_size - 1; i++) + { + // (ct mod qk) mod qi + modulo_poly_coeffs_63(last_ptr, coeff_count_, (*base_q_)[i], temp_ptr); + + uint64_t half_mod = barrett_reduce_63(half, (*base_q_)[i]); + for (size_t j = 0; j < coeff_count_; j++) + { + temp_ptr[j] = sub_uint_uint_mod(temp_ptr[j], half_mod, (*base_q_)[i]); + } + + ntt_negacyclic_harvey(temp_ptr, rns_ntt_tables[i]); + + sub_poly_poly_coeffmod( + input + (i * coeff_count_), temp_ptr, coeff_count_, (*base_q_)[i], input + (i * coeff_count_)); + + // qk^(-1) * ((ct mod qi) - (ct mod qk)) mod qi + multiply_poly_scalar_coeffmod( + input + (i * coeff_count_), coeff_count_, inv_q_last_mod_q_[i], (*base_q_)[i], + input + (i * coeff_count_)); + } + } + + void RNSTool::fastbconv_sk(const uint64_t *input, uint64_t *destination, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (!input) + { + throw invalid_argument("input cannot be null"); + } + if (!destination) + { + throw invalid_argument("destination cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + /* + Require: Input in base Bsk + Ensure: Output in base q + */ + + auto base_q_size = base_q_->size(); + auto base_B_size = base_B_->size(); + + // Fast convert B -> q; input is in Bsk but we only use B + base_B_to_q_conv_->fast_convert_array(input, coeff_count_, destination, pool); + + // Compute alpha_sk + // Fast convert B -> {m_sk}; input is in Bsk but we only use B + auto temp(allocate_uint(coeff_count_, pool)); + base_B_to_m_sk_conv_->fast_convert_array(input, coeff_count_, temp.get(), pool); + + // Take the m_sk part of input, subtract from temp, and multiply by inv_prod_B_mod_m_sk_ + // input_sk is allocated in input + (base_B_size * coeff_count_) + const uint64_t *input_ptr = input + (base_B_size * coeff_count_); + auto alpha_sk(allocate_uint(coeff_count_, pool)); + uint64_t *alpha_sk_ptr = alpha_sk.get(); + uint64_t *temp_ptr = temp.get(); + const uint64_t m_sk_value = m_sk_.value(); + for (size_t i = 0; i < coeff_count_; i++) + { + // It is not necessary for the negation to be reduced modulo the small prime + alpha_sk_ptr[i] = + multiply_uint_uint_mod(temp_ptr[i] + (m_sk_value - input_ptr[i]), inv_prod_B_mod_m_sk_, m_sk_); + } + + // alpha_sk is now ready for the Shenoy-Kumaresan conversion; however, note that our + // alpha_sk here is not a centered reduction, so we need to apply a correction below. + const uint64_t m_sk_div_2 = m_sk_value >> 1; + for (size_t i = 0; i < base_q_size; i++) + { + Modulus base_q_elt = (*base_q_)[i]; + uint64_t prod_B_mod_q_elt = prod_B_mod_q_[i]; + for (size_t k = 0; k < coeff_count_; k++, destination++) + { + // Correcting alpha_sk since it represents a negative value + if (alpha_sk_ptr[k] > m_sk_div_2) + { + *destination = multiply_add_uint_mod( + prod_B_mod_q_elt, m_sk_value - alpha_sk_ptr[k], *destination, base_q_elt); + } + // No correction needed + else + { + // It is not necessary for the negation to be reduced modulo the small prime + *destination = multiply_add_uint_mod( + base_q_elt.value() - prod_B_mod_q_[i], alpha_sk_ptr[k], *destination, base_q_elt); + } + } + } + } + + void RNSTool::sm_mrq(const uint64_t *input, uint64_t *destination, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (input == nullptr) + { + throw invalid_argument("input cannot be null"); + } + if (destination == nullptr) + { + throw invalid_argument("destination cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + /* + Require: Input in base Bsk U {m_tilde} + Ensure: Output in base Bsk + */ + + auto base_Bsk_size = base_Bsk_->size(); + + // The last component of the input is mod m_tilde + const uint64_t *input_m_tilde_ptr = input + (coeff_count_ * base_Bsk_size); + const uint64_t m_tilde_div_2 = m_tilde_.value() >> 1; + + // Compute r_m_tilde + auto r_m_tilde(allocate_uint(coeff_count_, pool)); + for (size_t i = 0; i < coeff_count_; i++) + { + uint64_t temp = multiply_uint_uint_mod(input_m_tilde_ptr[i], inv_prod_q_mod_m_tilde_, m_tilde_); + r_m_tilde[i] = negate_uint_mod(temp, m_tilde_); + } + + for (size_t k = 0; k < base_Bsk_size; k++) + { + Modulus base_Bsk_elt = (*base_Bsk_)[k]; + uint64_t inv_m_tilde_mod_Bsk_elt = inv_m_tilde_mod_Bsk_[k]; + uint64_t prod_q_mod_Bsk_elt = prod_q_mod_Bsk_[k]; + for (size_t i = 0; i < coeff_count_; i++, destination++, input++) + { + // We need centered reduction of r_m_tilde modulo Bsk. Note that m_tilde is chosen + // to be a power of two so we have '>=' below. + uint64_t temp = r_m_tilde[i]; + if (temp >= m_tilde_div_2) + { + temp += base_Bsk_elt.value() - m_tilde_.value(); + } + + // Compute (input + q*r_m_tilde)*m_tilde^(-1) mod Bsk + *destination = multiply_uint_uint_mod( + multiply_add_uint_mod(prod_q_mod_Bsk_elt, temp, *input, base_Bsk_elt), inv_m_tilde_mod_Bsk_elt, + base_Bsk_elt); + } + } + } + + void RNSTool::fast_floor(const uint64_t *input, uint64_t *destination, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (input == nullptr) + { + throw invalid_argument("input cannot be null"); + } + if (destination == nullptr) + { + throw invalid_argument("destination cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + /* + Require: Input in base q U Bsk + Ensure: Output in base Bsk + */ + + auto base_q_size = base_q_->size(); + auto base_Bsk_size = base_Bsk_->size(); + + // Convert q -> Bsk + base_q_to_Bsk_conv_->fast_convert_array(input, coeff_count_, destination, pool); + + // Move input pointer to past the base q components + input += base_q_size * coeff_count_; + for (size_t i = 0; i < base_Bsk_size; i++) + { + Modulus base_Bsk_elt = (*base_Bsk_)[i]; + uint64_t inv_prod_q_mod_Bsk_elt = inv_prod_q_mod_Bsk_[i]; + for (size_t k = 0; k < coeff_count_; k++, input++, destination++) + { + // It is not necessary for the negation to be reduced modulo base_Bsk_elt + *destination = multiply_uint_uint_mod( + *input + (base_Bsk_elt.value() - *destination), inv_prod_q_mod_Bsk_elt, base_Bsk_elt); + } + } + } + + void RNSTool::fastbconv_m_tilde(const uint64_t *input, uint64_t *destination, MemoryPoolHandle pool) const + { +#ifdef SEAL_DEBUG + if (input == nullptr) + { + throw invalid_argument("input cannot be null"); + } + if (destination == nullptr) + { + throw invalid_argument("destination cannot be null"); + } + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } +#endif + /* + Require: Input in q + Ensure: Output in Bsk U {m_tilde} + */ + + auto base_q_size = base_q_->size(); + auto base_Bsk_size = base_Bsk_->size(); + + // We need to multiply first the input with m_tilde mod q + // This is to facilitate Montgomery reduction in the next step of multiplication + // This is NOT an ideal approach: as mentioned in BEHZ16, multiplication by + // m_tilde can be easily merge into the base conversion operation; however, then + // we could not use the BaseConvTool as below without modifications. + auto temp(allocate_poly(coeff_count_, base_q_size, pool)); + for (size_t i = 0; i < base_q_size; i++) + { + multiply_poly_scalar_coeffmod( + input + (i * coeff_count_), coeff_count_, m_tilde_.value(), (*base_q_)[i], + temp.get() + (i * coeff_count_)); + } + + // Now convert to Bsk + base_q_to_Bsk_conv_->fast_convert_array(temp.get(), coeff_count_, destination, pool); + + // Finally convert to {m_tilde} + base_q_to_m_tilde_conv_->fast_convert_array( + temp.get(), coeff_count_, destination + (base_Bsk_size * coeff_count_), pool); + } + + void RNSTool::decrypt_scale_and_round(const uint64_t *input, uint64_t *destination, MemoryPoolHandle pool) const + { + auto base_q_size = base_q_->size(); + auto base_t_gamma_size = base_t_gamma_->size(); + + // Compute |gamma * t|_qi * ct(s) + auto temp(allocate_poly(coeff_count_, base_q_size, pool)); + for (size_t i = 0; i < base_q_size; i++) + { + multiply_poly_scalar_coeffmod( + input + (i * coeff_count_), coeff_count_, prod_t_gamma_mod_q_[i], (*base_q_)[i], + temp.get() + (i * coeff_count_)); + } + + // Make another temp destination to get the poly in mod {t, gamma} + auto temp_t_gamma(allocate_poly(coeff_count_, base_t_gamma_size, pool)); + + // Convert from q to {t, gamma} + base_q_to_t_gamma_conv_->fast_convert_array(temp.get(), coeff_count_, temp_t_gamma.get(), pool); + + // Multiply by -prod(q)^(-1) mod {t, gamma} + for (size_t i = 0; i < base_t_gamma_size; i++) + { + multiply_poly_scalar_coeffmod( + temp_t_gamma.get() + (i * coeff_count_), coeff_count_, neg_inv_q_mod_t_gamma_[i], + (*base_t_gamma_)[i], temp_t_gamma.get() + (i * coeff_count_)); + } + + // Need to correct values in temp_t_gamma (gamma component only) which are + // larger than floor(gamma/2) + uint64_t gamma_div_2 = (*base_t_gamma_)[1].value() >> 1; + + // Now compute the subtraction to remove error and perform final multiplication by + // gamma inverse mod t + for (size_t i = 0; i < coeff_count_; i++) + { + // Need correction because of centered mod + if (temp_t_gamma[i + coeff_count_] > gamma_div_2) + { + // Compute -(gamma - a) instead of (a - gamma) + destination[i] = add_uint_uint_mod( + temp_t_gamma[i], (gamma_.value() - temp_t_gamma[i + coeff_count_]) % t_.value(), t_); + } + // No correction needed + else + { + destination[i] = + sub_uint_uint_mod(temp_t_gamma[i], temp_t_gamma[i + coeff_count_] % t_.value(), t_); + } + + // If this coefficient was non-zero, multiply by t^(-1) + if (0 != destination[i]) + { + // Perform final multiplication by gamma inverse mod t + destination[i] = multiply_uint_uint_mod(destination[i], inv_gamma_mod_t_, t_); + } + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/rns.h b/bigpiseal3.5.1/native/src/seal/util/rns.h new file mode 100644 index 0000000000000000000000000000000000000000..7da68e9f02265ccd8fbdf868acd005b171e53b10 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/rns.h @@ -0,0 +1,368 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/util/ntt.h" +#include "seal/util/pointer.h" +#include <cstddef> +#include <cstdint> +#include <functional> +#include <stdexcept> +#include <vector> + +namespace seal +{ + namespace util + { + class RNSBase + { + public: + RNSBase(const std::vector<Modulus> &rnsbase, MemoryPoolHandle pool); + + RNSBase(RNSBase &&source) = default; + + RNSBase(const RNSBase &copy, MemoryPoolHandle pool); + + RNSBase(const RNSBase &copy) : RNSBase(copy, copy.pool_) + {} + + RNSBase &operator=(const RNSBase &assign) = delete; + + SEAL_NODISCARD inline const Modulus &operator[](std::size_t index) const + { + if (index >= size_) + { + throw std::out_of_range("index is out of range"); + } + return base_[index]; + } + + SEAL_NODISCARD inline std::size_t size() const noexcept + { + return size_; + } + + SEAL_NODISCARD bool contains(const Modulus &value) const noexcept; + + SEAL_NODISCARD bool is_subbase_of(const RNSBase &superbase) const noexcept; + + SEAL_NODISCARD inline bool is_superbase_of(const RNSBase &subbase) const noexcept + { + return subbase.is_subbase_of(*this); + } + + SEAL_NODISCARD inline bool is_proper_subbase_of(const RNSBase &superbase) const noexcept + { + return (size_ < superbase.size_) && is_subbase_of(superbase); + } + + SEAL_NODISCARD inline bool is_proper_superbase_of(const RNSBase &subbase) const noexcept + { + return (size_ > subbase.size_) && !is_subbase_of(subbase); + } + + SEAL_NODISCARD RNSBase extend(Modulus value) const; + + SEAL_NODISCARD RNSBase extend(const RNSBase &other) const; + + SEAL_NODISCARD RNSBase drop() const; + + SEAL_NODISCARD RNSBase drop(Modulus value) const; + + void decompose(std::uint64_t *value, MemoryPoolHandle pool) const; + + void decompose_array(std::uint64_t *value, std::size_t count, MemoryPoolHandle pool) const; + + void compose(std::uint64_t *value, MemoryPoolHandle pool) const; + + void compose_array(std::uint64_t *value, std::size_t count, MemoryPoolHandle pool) const; + + SEAL_NODISCARD inline const Modulus *base() const noexcept + { + return base_.get(); + } + + SEAL_NODISCARD inline const std::uint64_t *base_prod() const noexcept + { + return base_prod_.get(); + } + + SEAL_NODISCARD inline const std::uint64_t *punctured_prod_array() const noexcept + { + return punctured_prod_array_.get(); + } + + SEAL_NODISCARD inline const std::uint64_t *inv_punctured_prod_mod_base_array() const noexcept + { + return inv_punctured_prod_mod_base_array_.get(); + } + + private: + RNSBase(MemoryPoolHandle pool) : pool_(pool), size_(0) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + } + + bool initialize(); + + MemoryPoolHandle pool_; + + std::size_t size_; + + Pointer<Modulus> base_; + + Pointer<std::uint64_t> base_prod_; + + Pointer<std::uint64_t> punctured_prod_array_; + + Pointer<std::uint64_t> inv_punctured_prod_mod_base_array_; + }; + + class BaseConverter + { + public: + BaseConverter(const RNSBase &ibase, const RNSBase &obase, MemoryPoolHandle pool) + : pool_(std::move(pool)), ibase_(ibase, pool_), obase_(obase, pool_) + { + if (!pool_) + { + throw std::invalid_argument("pool is uninitialized"); + } + + initialize(); + } + + SEAL_NODISCARD inline std::size_t ibase_size() const noexcept + { + return ibase_.size(); + } + + SEAL_NODISCARD inline std::size_t obase_size() const noexcept + { + return obase_.size(); + } + + SEAL_NODISCARD inline const RNSBase &ibase() const noexcept + { + return ibase_; + } + + SEAL_NODISCARD inline const RNSBase &obase() const noexcept + { + return obase_; + } + + void fast_convert(const std::uint64_t *in, std::uint64_t *out, MemoryPoolHandle pool) const; + + void fast_convert_array( + const std::uint64_t *in, std::size_t count, std::uint64_t *out, MemoryPoolHandle pool) const; + + private: + BaseConverter(const BaseConverter &copy) = delete; + + BaseConverter(BaseConverter &&source) = delete; + + BaseConverter &operator=(const BaseConverter &assign) = delete; + + BaseConverter &operator=(BaseConverter &&assign) = delete; + + void initialize(); + + MemoryPoolHandle pool_; + + RNSBase ibase_; + + RNSBase obase_; + + Pointer<Pointer<std::uint64_t>> base_change_matrix_; + }; + + class RNSTool + { + public: + /** + @throws std::invalid_argument if poly_modulus_degree is out of range, coeff_modulus is not valid, or pool is + invalid. + @throws std::logic_error if coeff_modulus and extended bases do not support NTT or are not coprime. + */ + RNSTool( + std::size_t poly_modulus_degree, const RNSBase &coeff_modulus, const Modulus &plain_modulus, + MemoryPoolHandle pool); + + void divide_and_round_q_last_inplace(std::uint64_t *input, MemoryPoolHandle pool) const; + + void divide_and_round_q_last_ntt_inplace( + std::uint64_t *input, const NTTTables *rns_ntt_tables, MemoryPoolHandle pool) const; + + /** + Shenoy-Kumaresan conversion from Bsk to q + */ + void fastbconv_sk(const std::uint64_t *input, std::uint64_t *destination, MemoryPoolHandle pool) const; + + /** + Montgomery reduction mod q; changes base from Bsk U {m_tilde} to Bsk + */ + void sm_mrq(const std::uint64_t *input, std::uint64_t *destination, MemoryPoolHandle pool) const; + + /** + Divide by q and fast floor from q U Bsk to Bsk + */ + void fast_floor(const std::uint64_t *input, std::uint64_t *destination, MemoryPoolHandle pool) const; + + /** + Fast base conversion from q to Bsk U {m_tilde} + */ + void fastbconv_m_tilde(const std::uint64_t *input, std::uint64_t *destination, MemoryPoolHandle pool) const; + + /** + Compute round(t/q * |input|_q) mod t exactly + */ + void decrypt_scale_and_round(const uint64_t *phase, uint64_t *destination, MemoryPoolHandle pool) const; + + SEAL_NODISCARD inline auto inv_q_last_mod_q() const noexcept + { + return inv_q_last_mod_q_.get(); + } + + SEAL_NODISCARD inline auto base_Bsk_small_ntt_tables() const noexcept + { + return base_Bsk_small_ntt_tables_.get(); + } + + SEAL_NODISCARD inline auto base_q() const noexcept + { + return base_q_.get(); + } + + SEAL_NODISCARD inline auto base_B() const noexcept + { + return base_B_.get(); + } + + SEAL_NODISCARD inline auto base_Bsk() const noexcept + { + return base_Bsk_.get(); + } + + SEAL_NODISCARD inline auto base_Bsk_m_tilde() const noexcept + { + return base_Bsk_m_tilde_.get(); + } + + SEAL_NODISCARD inline auto base_t_gamma() const noexcept + { + return base_t_gamma_.get(); + } + + SEAL_NODISCARD inline auto &m_tilde() const noexcept + { + return m_tilde_; + } + + SEAL_NODISCARD inline auto &m_sk() const noexcept + { + return m_sk_; + } + + SEAL_NODISCARD inline auto &t() const noexcept + { + return t_; + } + + SEAL_NODISCARD inline auto &gamma() const noexcept + { + return gamma_; + } + + private: + RNSTool(const RNSTool &copy) = delete; + + RNSTool(RNSTool &&source) = delete; + + RNSTool &operator=(const RNSTool &assign) = delete; + + RNSTool &operator=(RNSTool &&assign) = delete; + + /** + Generates the pre-computations for the given parameters. + */ + void initialize(std::size_t poly_modulus_degree, const RNSBase &q, const Modulus &t); + + MemoryPoolHandle pool_; + + std::size_t coeff_count_ = 0; + + Pointer<RNSBase> base_q_; + + Pointer<RNSBase> base_B_; + + Pointer<RNSBase> base_Bsk_; + + Pointer<RNSBase> base_Bsk_m_tilde_; + + Pointer<RNSBase> base_t_gamma_; + + // Base converter: q --> B_sk + Pointer<BaseConverter> base_q_to_Bsk_conv_; + + // Base converter: q --> {m_tilde} + Pointer<BaseConverter> base_q_to_m_tilde_conv_; + + // Base converter: B --> q + Pointer<BaseConverter> base_B_to_q_conv_; + + // Base converter: B --> {m_sk} + Pointer<BaseConverter> base_B_to_m_sk_conv_; + + // Base converter: q --> {t, gamma} + Pointer<BaseConverter> base_q_to_t_gamma_conv_; + + // prod(q)^(-1) mod Bsk + Pointer<std::uint64_t> inv_prod_q_mod_Bsk_; + + // prod(q)^(-1) mod m_tilde + std::uint64_t inv_prod_q_mod_m_tilde_ = 0; + + // prod(B)^(-1) mod m_sk + std::uint64_t inv_prod_B_mod_m_sk_ = 0; + + // gamma^(-1) mod t + std::uint64_t inv_gamma_mod_t_ = 0; + + // prod(B) mod q + Pointer<std::uint64_t> prod_B_mod_q_; + + // m_tilde^(-1) mod Bsk + Pointer<std::uint64_t> inv_m_tilde_mod_Bsk_; + + // prod(q) mod Bsk + Pointer<std::uint64_t> prod_q_mod_Bsk_; + + // -prod(q)^(-1) mod {t, gamma} + Pointer<std::uint64_t> neg_inv_q_mod_t_gamma_; + + // prod({t, gamma}) mod q + Pointer<std::uint64_t> prod_t_gamma_mod_q_; + + // q[last]^(-1) mod q[i] for i = 0..last-1 + Pointer<std::uint64_t> inv_q_last_mod_q_; + + // NTTTables for Bsk + Pointer<NTTTables> base_Bsk_small_ntt_tables_; + + Modulus m_tilde_; + + Modulus m_sk_; + + Modulus t_; + + Modulus gamma_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/scalingvariant.cpp b/bigpiseal3.5.1/native/src/seal/util/scalingvariant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5161ede859f62e0eb8a7e18732952dc4ef89bc18 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/scalingvariant.cpp @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/encryptor.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/scalingvariant.h" +#include "seal/util/uintarith.h" + +using namespace std; + +namespace seal +{ + namespace util + { + void multiply_add_plain_with_scaling_variant( + const Plaintext &plain, const SEALContext::ContextData &context_data, uint64_t *destination) + { + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t plain_coeff_count = plain.coeff_count(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + auto plain_modulus = context_data.parms().plain_modulus(); + auto coeff_div_plain_modulus = context_data.coeff_div_plain_modulus(); + uint64_t plain_upper_half_threshold = context_data.plain_upper_half_threshold(); + uint64_t q_mod_t = context_data.coeff_modulus_mod_plain_modulus(); + + // Coefficients of plain m multiplied by coeff_modulus q, divided by plain_modulus t, + // and rounded to the nearest integer (rounded up in case of a tie). Equivalent to + // floor((q * m + floor((t+1) / 2)) / t). + for (size_t i = 0; i < plain_coeff_count; i++, destination++) + { + // Compute numerator = (q mod t) * m[i] + (t+1)/2 + unsigned long long prod[2]{ 0, 0 }; + uint64_t numerator[2]{ 0, 0 }; + multiply_uint64(plain.data()[i], q_mod_t, prod); + unsigned char carry = add_uint64(*prod, plain_upper_half_threshold, numerator); + numerator[1] = static_cast<uint64_t>(prod[1]) + static_cast<uint64_t>(carry); + + // Compute fix[0] = floor(numerator / t) + uint64_t fix[2] = { 0, 0 }; + divide_uint128_uint64_inplace(numerator, plain_modulus.value(), fix); + + // Add to ciphertext: floor(q / t) * m + increment + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[j * coeff_count] = add_uint_uint_mod( + multiply_add_uint_mod(coeff_div_plain_modulus[j], plain.data()[i], fix[0], coeff_modulus[j]), + destination[j * coeff_count], coeff_modulus[j]); + } + } + } + + void multiply_sub_plain_with_scaling_variant( + const Plaintext &plain, const SEALContext::ContextData &context_data, uint64_t *destination) + { + auto &parms = context_data.parms(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t plain_coeff_count = plain.coeff_count(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + auto plain_modulus = context_data.parms().plain_modulus(); + auto coeff_div_plain_modulus = context_data.coeff_div_plain_modulus(); + uint64_t plain_upper_half_threshold = context_data.plain_upper_half_threshold(); + uint64_t q_mod_t = context_data.coeff_modulus_mod_plain_modulus(); + + // Coefficients of plain m multiplied by coeff_modulus q, divided by plain_modulus t, + // and rounded to the nearest integer (rounded up in case of a tie). Equivalent to + // floor((q * m + floor((t+1) / 2)) / t). + for (size_t i = 0; i < plain_coeff_count; i++, destination++) + { + // Compute numerator = (q mod t) * m[i] + (t+1)/2 + unsigned long long prod[2]{ 0, 0 }; + uint64_t numerator[2]{ 0, 0 }; + multiply_uint64(plain[i], q_mod_t, prod); + unsigned char carry = add_uint64(*prod, plain_upper_half_threshold, numerator); + numerator[1] = static_cast<uint64_t>(prod[1]) + static_cast<uint64_t>(carry); + + // Compute fix[0] = floor(numerator / t) + uint64_t fix[2] = { 0, 0 }; + divide_uint128_uint64_inplace(numerator, plain_modulus.value(), fix); + + // Add to ciphertext: floor(q / t) * m + increment + for (size_t j = 0; j < coeff_modulus_size; j++) + { + destination[j * coeff_count] = sub_uint_uint_mod( + destination[j * coeff_count], + multiply_add_uint_mod(coeff_div_plain_modulus[j], plain.data()[i], fix[0], coeff_modulus[j]), + coeff_modulus[j]); + } + } + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/scalingvariant.h b/bigpiseal3.5.1/native/src/seal/util/scalingvariant.h new file mode 100644 index 0000000000000000000000000000000000000000..3199d879bb77c427685873f5b0d7bef84d743419 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/scalingvariant.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/memorymanager.h" +#include "seal/plaintext.h" +#include <cstdint> + +namespace seal +{ + namespace util + { + void multiply_add_plain_with_scaling_variant( + const Plaintext &plain, const SEALContext::ContextData &context_data, std::uint64_t *destination); + + void multiply_sub_plain_with_scaling_variant( + const Plaintext &plain, const SEALContext::ContextData &context_data, std::uint64_t *destination); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/streambuf.cpp b/bigpiseal3.5.1/native/src/seal/util/streambuf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..342549ee38b134d9e328b3066eb80760e397adde --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/streambuf.cpp @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/streambuf.h" + +namespace seal +{ + namespace util + { + // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to + // ensure symbol is created. + constexpr double SafeByteBuffer::expansion_factor_; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/streambuf.h b/bigpiseal3.5.1/native/src/seal/util/streambuf.h new file mode 100644 index 0000000000000000000000000000000000000000..8f4ab628736b5add8907ce9adac93cf0d98085c1 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/streambuf.h @@ -0,0 +1,475 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include <algorithm> +#include <cstddef> +#include <ios> +#include <iterator> +#include <stdexcept> +#include <streambuf> + +namespace seal +{ + namespace util + { + class SafeByteBuffer final : public std::streambuf + { + public: + SafeByteBuffer(std::streamsize size = 1) : size_(size) + { + if (!fits_in<std::size_t>(add_safe(size_, std::streamsize(1)))) + { + throw std::invalid_argument("size is too large"); + } + buf_.resize(static_cast<std::size_t>(size_ + 1), false); + setp(buf_.begin(), buf_.begin() + size_); + setg(buf_.begin(), buf_.begin(), buf_.begin() + size_); + } + + ~SafeByteBuffer() override = default; + + SafeByteBuffer(const SafeByteBuffer &copy) = delete; + + SafeByteBuffer &operator=(const SafeByteBuffer &assign) = delete; + + SEAL_NODISCARD const SEAL_BYTE *data() const noexcept + { + return reinterpret_cast<const SEAL_BYTE *>(buf_.cbegin()); + } + + SEAL_NODISCARD SEAL_BYTE *data() noexcept + { + return reinterpret_cast<SEAL_BYTE *>(buf_.begin()); + } + + SEAL_NODISCARD std::size_t size() noexcept + { + return buf_.size(); + } + + SEAL_NODISCARD std::size_t capacity() noexcept + { + return buf_.capacity(); + } + + private: + void safe_gbump(std::streamsize count) + { + std::streamsize int_max = static_cast<std::streamsize>(std::numeric_limits<int>::max()); + while (count > int_max) + { + gbump(std::numeric_limits<int>::max()); + count -= int_max; + } + + // This is now safe + gbump(static_cast<int>(count)); + } + + void safe_pbump(std::streamsize count) + { + std::streamsize int_max = static_cast<std::streamsize>(std::numeric_limits<int>::max()); + while (count > int_max) + { + pbump(std::numeric_limits<int>::max()); + count -= int_max; + } + + // This is now safe + pbump(static_cast<int>(count)); + } + + int_type underflow() override + { + if (gptr() == egptr()) + { + return eof_; + } + return traits_type::to_int_type(*gptr()); + } + + int_type pbackfail(int_type ch) override + { + if (gptr() == eback() || traits_type::eq_int_type(eof_, ch) || + (traits_type::not_eof(ch) && ch != gptr()[-1])) + { + return traits_type::eof(); + } + safe_gbump(std::streamsize(-1)); + return traits_type::to_int_type(*gptr()); + } + + std::streamsize showmanyc() override + { + if (gptr() >= egptr()) + { + return -1; + } + return std::distance(gptr(), egptr()); + } + + std::streamsize xsgetn(char_type *s, std::streamsize count) override + { + std::streamsize avail = std::max( + std::streamsize(0), std::min(count, safe_cast<std::streamsize>(std::distance(gptr(), egptr())))); + std::copy_n(gptr(), avail, s); + safe_gbump(avail); + return avail; + } + + pos_type seekpos( + pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override + { + if (pos < 0 || pos > size_) + { + return pos_type(off_type(-1)); + } + if (which & std::ios_base::in) + { + setg(eback(), eback() + static_cast<std::ptrdiff_t>(pos), egptr()); + } + if (which & std::ios_base::out) + { + setp(pbase(), epptr()); + safe_pbump(static_cast<std::streamsize>(pos)); + } + return pos; + } + + pos_type seekoff( + off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override + { + // Cannot seek relative to current position for both input and + // output heads if they are in different positions. + if (which == (std::ios_base::in | std::ios_base::out) && dir == std::ios_base::cur && gptr() != pptr()) + { + return pos_type(off_type(-1)); + } + + // We are guaranteed to have only a single absolute offset + off_type newoff = off; + switch (dir) + { + case std::ios_base::beg: + break; + + case std::ios_base::cur: + if (which == std::ios_base::in) + { + newoff = add_safe(newoff, safe_cast<std::streamoff>(std::distance(eback(), gptr()))); + } + else + { + newoff = add_safe(newoff, safe_cast<std::streamoff>(std::distance(pbase(), pptr()))); + } + break; + + case std::ios_base::end: + newoff = add_safe(newoff, safe_cast<off_type>(size_)); + break; + + default: + return pos_type(off_type(-1)); + } + return seekpos(pos_type(newoff), which); + } + + void expand_size() + { + // Compute expanded size + size_ = safe_cast<std::streamsize>(ceil(safe_cast<double>(buf_.size()) * expansion_factor_)); + + // Store the old offsets for both put and get heads + std::streamsize old_poff = std::distance(pbase(), pptr()); + std::streamsize old_goff = std::distance(eback(), gptr()); + + // Copy entire buffer to new location and reserve extra byte + buf_.resize(safe_cast<std::size_t>(add_safe<std::streamsize>(size_, std::streamsize(1))), false); + + // Set the get and put pointers appropriately + setp(buf_.begin(), buf_.begin() + size_); + safe_pbump(old_poff); + setg(buf_.begin(), buf_.begin() + old_goff, buf_.begin() + size_); + } + + int_type overflow(int_type ch = traits_type::eof()) override + { + if (traits_type::eq_int_type(eof_, ch) || + !fits_in<std::size_t>(ceil(static_cast<double>(buf_.size()) * expansion_factor_) + 1)) + { + return eof_; + } + + // Output ch to the buffer (there is one byte left of space) and overflow + *pptr() = traits_type::to_char_type(ch); + safe_pbump(std::streamsize(1)); + + // Expand the size of the buffer + expand_size(); + + return ch; + } + + std::streamsize xsputn(const char_type *s, std::streamsize count) override + { + std::streamsize remaining = count; + while (remaining) + { + if (pptr() == epptr()) + { + expand_size(); + } + std::streamsize avail = std::max( + std::streamsize(0), + std::min(remaining, safe_cast<std::streamsize>(std::distance(pptr(), epptr())))); + std::copy_n(s, avail, pptr()); + safe_pbump(avail); + remaining -= avail; + s += avail; + } + return count; + } + + IntArray<char> buf_{ MemoryManager::GetPool(mm_prof_opt::FORCE_NEW, true) }; + + std::streamsize size_; + + static constexpr double expansion_factor_ = 1.3; + + int_type eof_ = traits_type::eof(); + }; + + class ArrayGetBuffer final : public std::streambuf + { + public: + ArrayGetBuffer(const char_type *buf, std::streamsize size) : buf_(buf), size_(size) + { + if (!buf) + { + throw std::invalid_argument("buf cannot be null"); + } + if (size <= 0) + { + throw std::invalid_argument("size must be positive"); + } + begin_ = buf_; + end_ = buf_ + size_; + head_ = begin_; + } + + ~ArrayGetBuffer() override = default; + + ArrayGetBuffer(const ArrayGetBuffer &copy) = delete; + + ArrayGetBuffer &operator=(const ArrayGetBuffer &assign) = delete; + + private: + int_type underflow() override + { + if (head_ == end_) + { + return eof_; + } + return traits_type::to_int_type(*head_); + } + + int_type uflow() override + { + if (head_ == end_) + { + return eof_; + } + return traits_type::to_int_type(*head_++); + } + + int_type pbackfail(int_type ch) override + { + if (head_ == begin_ || traits_type::eq_int_type(eof_, ch) || + (traits_type::not_eof(ch) && ch != head_[-1])) + { + return traits_type::eof(); + } + return traits_type::to_int_type(*--head_); + } + + std::streamsize showmanyc() override + { + if (head_ >= end_) + { + return -1; + } + return std::distance(head_, end_); + } + + std::streamsize xsgetn(char_type *s, std::streamsize count) override + { + std::streamsize avail = std::max( + std::streamsize(0), std::min(count, safe_cast<std::streamsize>(std::distance(head_, end_)))); + std::copy_n(head_, avail, s); + std::advance(head_, avail); + return avail; + } + + pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in) override + { + if (which != std::ios_base::in) + { + return pos_type(off_type(-1)); + } + if (pos < 0 || pos > pos_type(size_)) + { + return pos_type(off_type(-1)); + } + + head_ = begin_ + static_cast<std::ptrdiff_t>(pos); + return pos; + } + + pos_type seekoff( + off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override + { + off_type newoff = off; + switch (dir) + { + case std::ios_base::beg: + break; + + case std::ios_base::cur: + newoff = add_safe(newoff, safe_cast<off_type>(std::distance(begin_, head_))); + break; + + case std::ios_base::end: + newoff = add_safe(newoff, off_type(size_)); + break; + + default: + return pos_type(off_type(-1)); + } + return seekpos(pos_type(newoff), which); + } + + const char_type *buf_; + + std::streamsize size_; + + using iterator_type = const char_type *; + + int_type eof_ = traits_type::eof(); + + iterator_type begin_; + + iterator_type end_; + + iterator_type head_; + }; + + class ArrayPutBuffer final : public std::streambuf + { + public: + ArrayPutBuffer(char_type *buf, std::streamsize size) : buf_(buf), size_(size) + { + if (!buf) + { + throw std::invalid_argument("buf cannot be null"); + } + if (size <= 0) + { + throw std::invalid_argument("size must be positive"); + } + begin_ = buf_; + end_ = buf_ + size_; + head_ = begin_; + } + + ~ArrayPutBuffer() override = default; + + ArrayPutBuffer(const ArrayPutBuffer &copy) = delete; + + ArrayPutBuffer &operator=(const ArrayPutBuffer &assign) = delete; + + SEAL_NODISCARD bool at_end() const noexcept + { + return head_ == end_; + } + + private: + int_type overflow(int_type ch = traits_type::eof()) override + { + if (head_ == end_ || traits_type::eq_int_type(eof_, ch)) + { + return eof_; + } + *head_++ = traits_type::to_char_type(ch); + return ch; + } + + std::streamsize xsputn(const char_type *s, std::streamsize count) override + { + std::streamsize avail = std::max( + std::streamsize(0), std::min(count, safe_cast<std::streamsize>(std::distance(head_, end_)))); + std::copy_n(s, avail, head_); + std::advance(head_, avail); + return avail; + } + + pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::out) override + { + if (which != std::ios_base::out) + { + return pos_type(off_type(-1)); + } + if (pos < 0 || pos > pos_type(size_)) + { + return pos_type(off_type(-1)); + } + + head_ = begin_ + static_cast<std::ptrdiff_t>(pos); + return pos; + } + + pos_type seekoff( + off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::out) override + { + off_type newoff = off; + switch (dir) + { + case std::ios_base::beg: + break; + + case std::ios_base::cur: + newoff = add_safe(newoff, safe_cast<off_type>(std::distance(begin_, head_))); + break; + + case std::ios_base::end: + newoff = add_safe(newoff, off_type(size_)); + break; + + default: + return pos_type(off_type(-1)); + } + return seekpos(pos_type(newoff), which); + } + + char_type *buf_; + + std::streamsize size_; + + using iterator_type = char_type *; + + int_type eof_ = traits_type::eof(); + + iterator_type begin_; + + iterator_type end_; + + iterator_type head_; + }; + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarith.cpp b/bigpiseal3.5.1/native/src/seal/util/uintarith.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d5872d79ca2a156ea17509d6c2020d46b97dfd6 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarith.cpp @@ -0,0 +1,698 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <array> + +using namespace std; + +namespace seal +{ + namespace util + { + void multiply_uint_uint( + const uint64_t *operand1, size_t operand1_uint64_count, const uint64_t *operand2, + size_t operand2_uint64_count, size_t result_uint64_count, uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1 && operand1_uint64_count > 0) + { + throw invalid_argument("operand1"); + } + if (!operand2 && operand2_uint64_count > 0) + { + throw invalid_argument("operand2"); + } + if (!result_uint64_count) + { + throw invalid_argument("result_uint64_count"); + } + if (!result) + { + throw invalid_argument("result"); + } + if (result != nullptr && (operand1 == result || operand2 == result)) + { + throw invalid_argument("result cannot point to the same value as operand1 or operand2"); + } +#endif + // Handle fast cases. + if (!operand1_uint64_count || !operand2_uint64_count) + { + // If either operand is 0, then result is 0. + set_zero_uint(result_uint64_count, result); + return; + } + if (result_uint64_count == 1) + { + *result = *operand1 * *operand2; + return; + } + + // In some cases these improve performance. + operand1_uint64_count = get_significant_uint64_count_uint(operand1, operand1_uint64_count); + operand2_uint64_count = get_significant_uint64_count_uint(operand2, operand2_uint64_count); + + // More fast cases + if (operand1_uint64_count == 1) + { + multiply_uint_uint64(operand2, operand2_uint64_count, *operand1, result_uint64_count, result); + return; + } + if (operand2_uint64_count == 1) + { + multiply_uint_uint64(operand1, operand1_uint64_count, *operand2, result_uint64_count, result); + return; + } + + // Clear out result. + set_zero_uint(result_uint64_count, result); + + // Multiply operand1 and operand2. + size_t operand1_index_max = min(operand1_uint64_count, result_uint64_count); + for (size_t operand1_index = 0; operand1_index < operand1_index_max; operand1_index++) + { + const uint64_t *inner_operand2 = operand2; + uint64_t *inner_result = result++; + uint64_t carry = 0; + size_t operand2_index = 0; + size_t operand2_index_max = min(operand2_uint64_count, result_uint64_count - operand1_index); + for (; operand2_index < operand2_index_max; operand2_index++) + { + // Perform 64-bit multiplication of operand1 and operand2 + unsigned long long temp_result[2]; + multiply_uint64(*operand1, *inner_operand2++, temp_result); + carry = temp_result[1] + add_uint64(temp_result[0], carry, 0, temp_result); + unsigned long long temp; + carry += add_uint64(*inner_result, temp_result[0], 0, &temp); + *inner_result++ = temp; + } + + // Write carry if there is room in result + if (operand1_index + operand2_index_max < result_uint64_count) + { + *inner_result = carry; + } + + operand1++; + } + } + + void multiply_uint_uint64( + const uint64_t *operand1, size_t operand1_uint64_count, uint64_t operand2, size_t result_uint64_count, + uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1 && operand1_uint64_count > 0) + { + throw invalid_argument("operand1"); + } + if (!result_uint64_count) + { + throw invalid_argument("result_uint64_count"); + } + if (!result) + { + throw invalid_argument("result"); + } + if (result != nullptr && operand1 == result) + { + throw invalid_argument("result cannot point to the same value as operand1"); + } +#endif + // Handle fast cases. + if (!operand1_uint64_count || !operand2) + { + // If either operand is 0, then result is 0. + set_zero_uint(result_uint64_count, result); + return; + } + if (result_uint64_count == 1) + { + *result = *operand1 * operand2; + return; + } + + // More fast cases + // if (result_uint64_count == 2 && operand1_uint64_count > 1) + //{ + // unsigned long long temp_result; + // multiply_uint64(*operand1, operand2, &temp_result); + // *result = temp_result; + // *(result + 1) += *(operand1 + 1) * operand2; + // return; + //} + + // Clear out result. + set_zero_uint(result_uint64_count, result); + + // Multiply operand1 and operand2. + unsigned long long carry = 0; + size_t operand1_index_max = min(operand1_uint64_count, result_uint64_count); + for (size_t operand1_index = 0; operand1_index < operand1_index_max; operand1_index++) + { + unsigned long long temp_result[2]; + multiply_uint64(*operand1++, operand2, temp_result); + unsigned long long temp; + carry = temp_result[1] + add_uint64(temp_result[0], carry, 0, &temp); + *result++ = temp; + } + + // Write carry if there is room in result + if (operand1_index_max < result_uint64_count) + { + *result = carry; + } + } + + void divide_uint_uint_inplace( + uint64_t *numerator, const uint64_t *denominator, size_t uint64_count, uint64_t *quotient, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!numerator && uint64_count > 0) + { + throw invalid_argument("numerator"); + } + if (!denominator && uint64_count > 0) + { + throw invalid_argument("denominator"); + } + if (!quotient && uint64_count > 0) + { + throw invalid_argument("quotient"); + } + if (is_zero_uint(denominator, uint64_count) && uint64_count > 0) + { + throw invalid_argument("denominator"); + } + if (quotient && (numerator == quotient || denominator == quotient)) + { + throw invalid_argument("quotient cannot point to same value as numerator or denominator"); + } +#endif + if (!uint64_count) + { + return; + } + + // Clear quotient. Set it to zero. + set_zero_uint(uint64_count, quotient); + + // Determine significant bits in numerator and denominator. + int numerator_bits = get_significant_bit_count_uint(numerator, uint64_count); + int denominator_bits = get_significant_bit_count_uint(denominator, uint64_count); + + // If numerator has fewer bits than denominator, then done. + if (numerator_bits < denominator_bits) + { + return; + } + + // Only perform computation up to last non-zero uint64s. + uint64_count = safe_cast<size_t>(divide_round_up(numerator_bits, bits_per_uint64)); + + // Handle fast case. + if (uint64_count == 1) + { + *quotient = *numerator / *denominator; + *numerator -= *quotient * *denominator; + return; + } + + auto alloc_anchor(allocate_uint(uint64_count << 1, pool)); + + // Create temporary space to store mutable copy of denominator. + uint64_t *shifted_denominator = alloc_anchor.get(); + + // Create temporary space to store difference calculation. + uint64_t *difference = shifted_denominator + uint64_count; + + // Shift denominator to bring MSB in alignment with MSB of numerator. + int denominator_shift = numerator_bits - denominator_bits; + left_shift_uint(denominator, denominator_shift, uint64_count, shifted_denominator); + denominator_bits += denominator_shift; + + // Perform bit-wise division algorithm. + int remaining_shifts = denominator_shift; + while (numerator_bits == denominator_bits) + { + // NOTE: MSBs of numerator and denominator are aligned. + + // Even though MSB of numerator and denominator are aligned, + // still possible numerator < shifted_denominator. + if (sub_uint_uint(numerator, shifted_denominator, uint64_count, difference)) + { + // numerator < shifted_denominator and MSBs are aligned, + // so current quotient bit is zero and next one is definitely one. + if (remaining_shifts == 0) + { + // No shifts remain and numerator < denominator so done. + break; + } + + // Effectively shift numerator left by 1 by instead adding + // numerator to difference (to prevent overflow in numerator). + add_uint_uint(difference, numerator, uint64_count, difference); + + // Adjust quotient and remaining shifts as a result of + // shifting numerator. + left_shift_uint(quotient, 1, uint64_count, quotient); + remaining_shifts--; + } + // Difference is the new numerator with denominator subtracted. + + // Update quotient to reflect subtraction. + quotient[0] |= 1; + + // Determine amount to shift numerator to bring MSB in alignment + // with denominator. + numerator_bits = get_significant_bit_count_uint(difference, uint64_count); + int numerator_shift = denominator_bits - numerator_bits; + if (numerator_shift > remaining_shifts) + { + // Clip the maximum shift to determine only the integer + // (as opposed to fractional) bits. + numerator_shift = remaining_shifts; + } + + // Shift and update numerator. + if (numerator_bits > 0) + { + left_shift_uint(difference, numerator_shift, uint64_count, numerator); + numerator_bits += numerator_shift; + } + else + { + // Difference is zero so no need to shift, just set to zero. + set_zero_uint(uint64_count, numerator); + } + + // Adjust quotient and remaining shifts as a result of shifting numerator. + left_shift_uint(quotient, numerator_shift, uint64_count, quotient); + remaining_shifts -= numerator_shift; + } + + // Correct numerator (which is also the remainder) for shifting of + // denominator, unless it is just zero. + if (numerator_bits > 0) + { + right_shift_uint(numerator, denominator_shift, uint64_count, numerator); + } + } + + void divide_uint128_uint64_inplace_generic(uint64_t *numerator, uint64_t denominator, uint64_t *quotient) + { +#ifdef SEAL_DEBUG + if (!numerator) + { + throw invalid_argument("numerator"); + } + if (denominator == 0) + { + throw invalid_argument("denominator"); + } + if (!quotient) + { + throw invalid_argument("quotient"); + } + if (numerator == quotient) + { + throw invalid_argument("quotient cannot point to same value as numerator"); + } +#endif + // We expect 128-bit input + constexpr size_t uint64_count = 2; + + // Clear quotient. Set it to zero. + quotient[0] = 0; + quotient[1] = 0; + + // Determine significant bits in numerator and denominator. + int numerator_bits = get_significant_bit_count_uint(numerator, uint64_count); + int denominator_bits = get_significant_bit_count(denominator); + + // If numerator has fewer bits than denominator, then done. + if (numerator_bits < denominator_bits) + { + return; + } + + // Create temporary space to store mutable copy of denominator. + uint64_t shifted_denominator[uint64_count]{ denominator, 0 }; + + // Create temporary space to store difference calculation. + uint64_t difference[uint64_count]{ 0, 0 }; + + // Shift denominator to bring MSB in alignment with MSB of numerator. + int denominator_shift = numerator_bits - denominator_bits; + + left_shift_uint128(shifted_denominator, denominator_shift, shifted_denominator); + denominator_bits += denominator_shift; + + // Perform bit-wise division algorithm. + int remaining_shifts = denominator_shift; + while (numerator_bits == denominator_bits) + { + // NOTE: MSBs of numerator and denominator are aligned. + + // Even though MSB of numerator and denominator are aligned, + // still possible numerator < shifted_denominator. + if (sub_uint_uint(numerator, shifted_denominator, uint64_count, difference)) + { + // numerator < shifted_denominator and MSBs are aligned, + // so current quotient bit is zero and next one is definitely one. + if (remaining_shifts == 0) + { + // No shifts remain and numerator < denominator so done. + break; + } + + // Effectively shift numerator left by 1 by instead adding + // numerator to difference (to prevent overflow in numerator). + add_uint_uint(difference, numerator, uint64_count, difference); + + // Adjust quotient and remaining shifts as a result of shifting numerator. + quotient[1] = (quotient[1] << 1) | (quotient[0] >> (bits_per_uint64 - 1)); + quotient[0] <<= 1; + remaining_shifts--; + } + // Difference is the new numerator with denominator subtracted. + + // Determine amount to shift numerator to bring MSB in alignment + // with denominator. + numerator_bits = get_significant_bit_count_uint(difference, uint64_count); + + // Clip the maximum shift to determine only the integer + // (as opposed to fractional) bits. + int numerator_shift = min(denominator_bits - numerator_bits, remaining_shifts); + + // Shift and update numerator. + // This may be faster; first set to zero and then update if needed + + // Difference is zero so no need to shift, just set to zero. + numerator[0] = 0; + numerator[1] = 0; + + if (numerator_bits > 0) + { + left_shift_uint128(difference, numerator_shift, numerator); + numerator_bits += numerator_shift; + } + + // Update quotient to reflect subtraction. + quotient[0] |= 1; + + // Adjust quotient and remaining shifts as a result of shifting numerator. + left_shift_uint128(quotient, numerator_shift, quotient); + remaining_shifts -= numerator_shift; + } + + // Correct numerator (which is also the remainder) for shifting of + // denominator, unless it is just zero. + if (numerator_bits > 0) + { + right_shift_uint128(numerator, denominator_shift, numerator); + } + } + + void divide_uint192_uint64_inplace(uint64_t *numerator, uint64_t denominator, uint64_t *quotient) + { +#ifdef SEAL_DEBUG + if (!numerator) + { + throw invalid_argument("numerator"); + } + if (denominator == 0) + { + throw invalid_argument("denominator"); + } + if (!quotient) + { + throw invalid_argument("quotient"); + } + if (numerator == quotient) + { + throw invalid_argument("quotient cannot point to same value as numerator"); + } +#endif + // We expect 192-bit input + size_t uint64_count = 3; + + // Clear quotient. Set it to zero. + quotient[0] = 0; + quotient[1] = 0; + quotient[2] = 0; + + // Determine significant bits in numerator and denominator. + int numerator_bits = get_significant_bit_count_uint(numerator, uint64_count); + int denominator_bits = get_significant_bit_count(denominator); + + // If numerator has fewer bits than denominator, then done. + if (numerator_bits < denominator_bits) + { + return; + } + + // Only perform computation up to last non-zero uint64s. + uint64_count = safe_cast<size_t>(divide_round_up(numerator_bits, bits_per_uint64)); + + // Handle fast case. + if (uint64_count == 1) + { + *quotient = *numerator / denominator; + *numerator -= *quotient * denominator; + return; + } + + // Create temporary space to store mutable copy of denominator. + vector<uint64_t> shifted_denominator(uint64_count, 0); + shifted_denominator[0] = denominator; + + // Create temporary space to store difference calculation. + vector<uint64_t> difference(uint64_count); + + // Shift denominator to bring MSB in alignment with MSB of numerator. + int denominator_shift = numerator_bits - denominator_bits; + + left_shift_uint192(shifted_denominator.data(), denominator_shift, shifted_denominator.data()); + denominator_bits += denominator_shift; + + // Perform bit-wise division algorithm. + int remaining_shifts = denominator_shift; + while (numerator_bits == denominator_bits) + { + // NOTE: MSBs of numerator and denominator are aligned. + + // Even though MSB of numerator and denominator are aligned, + // still possible numerator < shifted_denominator. + if (sub_uint_uint(numerator, shifted_denominator.data(), uint64_count, difference.data())) + { + // numerator < shifted_denominator and MSBs are aligned, + // so current quotient bit is zero and next one is definitely one. + if (remaining_shifts == 0) + { + // No shifts remain and numerator < denominator so done. + break; + } + + // Effectively shift numerator left by 1 by instead adding + // numerator to difference (to prevent overflow in numerator). + add_uint_uint(difference.data(), numerator, uint64_count, difference.data()); + + // Adjust quotient and remaining shifts as a result of shifting numerator. + left_shift_uint192(quotient, 1, quotient); + remaining_shifts--; + } + // Difference is the new numerator with denominator subtracted. + + // Update quotient to reflect subtraction. + quotient[0] |= 1; + + // Determine amount to shift numerator to bring MSB in alignment with denominator. + numerator_bits = get_significant_bit_count_uint(difference.data(), uint64_count); + int numerator_shift = denominator_bits - numerator_bits; + if (numerator_shift > remaining_shifts) + { + // Clip the maximum shift to determine only the integer + // (as opposed to fractional) bits. + numerator_shift = remaining_shifts; + } + + // Shift and update numerator. + if (numerator_bits > 0) + { + left_shift_uint192(difference.data(), numerator_shift, numerator); + numerator_bits += numerator_shift; + } + else + { + // Difference is zero so no need to shift, just set to zero. + set_zero_uint(uint64_count, numerator); + } + + // Adjust quotient and remaining shifts as a result of shifting numerator. + left_shift_uint192(quotient, numerator_shift, quotient); + remaining_shifts -= numerator_shift; + } + + // Correct numerator (which is also the remainder) for shifting of + // denominator, unless it is just zero. + if (numerator_bits > 0) + { + right_shift_uint192(numerator, denominator_shift, numerator); + } + } + + void exponentiate_uint( + const uint64_t *operand, size_t operand_uint64_count, const uint64_t *exponent, + size_t exponent_uint64_count, size_t result_uint64_count, uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw invalid_argument("operand"); + } + if (!operand_uint64_count) + { + throw invalid_argument("operand_uint64_count"); + } + if (!exponent) + { + throw invalid_argument("exponent"); + } + if (!exponent_uint64_count) + { + throw invalid_argument("exponent_uint64_count"); + } + if (!result) + { + throw invalid_argument("result"); + } + if (!result_uint64_count) + { + throw invalid_argument("result_uint64_count"); + } +#endif + // Fast cases + if (is_zero_uint(exponent, exponent_uint64_count)) + { + set_uint(1, result_uint64_count, result); + return; + } + if (is_equal_uint(exponent, exponent_uint64_count, 1)) + { + set_uint_uint(operand, operand_uint64_count, result_uint64_count, result); + return; + } + + // Need to make a copy of exponent + auto exponent_copy(allocate_uint(exponent_uint64_count, pool)); + set_uint_uint(exponent, exponent_uint64_count, exponent_copy.get()); + + // Perform binary exponentiation. + auto big_alloc(allocate_uint(result_uint64_count + result_uint64_count + result_uint64_count, pool)); + + uint64_t *powerptr = big_alloc.get(); + uint64_t *productptr = powerptr + result_uint64_count; + uint64_t *intermediateptr = productptr + result_uint64_count; + + set_uint_uint(operand, operand_uint64_count, result_uint64_count, powerptr); + set_uint(1, result_uint64_count, intermediateptr); + + // Initially: power = operand and intermediate = 1, product is not initialized. + while (true) + { + if ((*exponent_copy.get() % 2) == 1) + { + multiply_truncate_uint_uint(powerptr, intermediateptr, result_uint64_count, productptr); + swap(productptr, intermediateptr); + } + right_shift_uint(exponent_copy.get(), 1, exponent_uint64_count, exponent_copy.get()); + if (is_zero_uint(exponent_copy.get(), exponent_uint64_count)) + { + break; + } + multiply_truncate_uint_uint(powerptr, powerptr, result_uint64_count, productptr); + swap(productptr, powerptr); + } + set_uint_uint(intermediateptr, result_uint64_count, result); + } + + uint64_t exponentiate_uint64_safe(uint64_t operand, uint64_t exponent) + { + // Fast cases + if (exponent == 0) + { + return 1; + } + if (exponent == 1) + { + return operand; + } + + // Perform binary exponentiation. + uint64_t power = operand; + uint64_t product = 0; + uint64_t intermediate = 1; + + // Initially: power = operand and intermediate = 1, product irrelevant. + while (true) + { + if (exponent & 1) + { + product = mul_safe(power, intermediate); + swap(product, intermediate); + } + exponent >>= 1; + if (exponent == 0) + { + break; + } + product = mul_safe(power, power); + swap(product, power); + } + + return intermediate; + } + + uint64_t exponentiate_uint64(uint64_t operand, uint64_t exponent) + { + // Fast cases + if (exponent == 0) + { + return 1; + } + if (exponent == 1) + { + return operand; + } + + // Perform binary exponentiation. + uint64_t power = operand; + uint64_t product = 0; + uint64_t intermediate = 1; + + // Initially: power = operand and intermediate = 1, product irrelevant. + while (true) + { + if (exponent & 1) + { + product = power * intermediate; + swap(product, intermediate); + } + exponent >>= 1; + if (exponent == 0) + { + break; + } + product = power * power; + swap(product, power); + } + + return intermediate; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarith.h b/bigpiseal3.5.1/native/src/seal/util/uintarith.h new file mode 100644 index 0000000000000000000000000000000000000000..14581b4c2f86ad9c76ee1b1f1fa941ebeab03d0b --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarith.h @@ -0,0 +1,1014 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <cstdint> +#include <functional> +#include <set> +#include <stdexcept> +#include <type_traits> + +namespace seal +{ + namespace util + { + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + SEAL_NODISCARD inline unsigned char add_uint64_generic( + T operand1, S operand2, unsigned char carry, unsigned long long *result) + { +#ifdef SEAL_DEBUG + if (!result) + { + throw std::invalid_argument("result cannot be null"); + } +#endif + operand1 += operand2; + *result = operand1 + carry; + return (operand1 < operand2) || (~operand1 < carry); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + SEAL_NODISCARD inline unsigned char add_uint64( + T operand1, S operand2, unsigned char carry, unsigned long long *result) + { + return SEAL_ADD_CARRY_UINT64(operand1, operand2, carry, result); + } + + template <typename T, typename S, typename R, typename = std::enable_if_t<is_uint64_v<T, S, R>>> + SEAL_NODISCARD inline unsigned char add_uint64(T operand1, S operand2, R *result) + { + *result = operand1 + operand2; + return static_cast<unsigned char>(*result < operand1); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + inline unsigned char add_uint128(const T *operand1, const S *operand2, unsigned long long *result) + { +#ifdef SEAL_DEBUG + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + unsigned char carry = add_uint64(operand1[0], operand2[0], result); + return add_uint64(operand1[1], operand2[1], carry, result + 1); + } + + inline unsigned char add_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count, unsigned char carry, std::size_t result_uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1_uint64_count) + { + throw std::invalid_argument("operand1_uint64_count"); + } + if (!operand2_uint64_count) + { + throw std::invalid_argument("operand2_uint64_count"); + } + if (!result_uint64_count) + { + throw std::invalid_argument("result_uint64_count"); + } + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + for (std::size_t i = 0; i < result_uint64_count; i++) + { + unsigned long long temp_result; + carry = add_uint64( + (i < operand1_uint64_count) ? *operand1++ : 0, (i < operand2_uint64_count) ? *operand2++ : 0, carry, + &temp_result); + *result++ = temp_result; + } + return carry; + } + + inline unsigned char add_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // Unroll first iteration of loop. We assume uint64_count > 0. + unsigned char carry = add_uint64(*operand1++, *operand2++, result++); + + // Do the rest + for (; --uint64_count; operand1++, operand2++, result++) + { + unsigned long long temp_result; + carry = add_uint64(*operand1, *operand2, carry, &temp_result); + *result = temp_result; + } + return carry; + } + + inline unsigned char add_uint_uint64( + const std::uint64_t *operand1, std::uint64_t operand2, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // Unroll first iteration of loop. We assume uint64_count > 0. + unsigned char carry = add_uint64(*operand1++, operand2, result++); + + // Do the rest + for (; --uint64_count; operand1++, result++) + { + unsigned long long temp_result; + carry = add_uint64(*operand1, std::uint64_t(0), carry, &temp_result); + *result = temp_result; + } + return carry; + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + SEAL_NODISCARD inline unsigned char sub_uint64_generic( + T operand1, S operand2, unsigned char borrow, unsigned long long *result) + { +#ifdef SEAL_DEBUG + if (!result) + { + throw std::invalid_argument("result cannot be null"); + } +#endif + auto diff = operand1 - operand2; + *result = diff - (borrow != 0); + return (diff > operand1) || (diff < borrow); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + SEAL_NODISCARD inline unsigned char sub_uint64( + T operand1, S operand2, unsigned char borrow, unsigned long long *result) + { + return SEAL_SUB_BORROW_UINT64(operand1, operand2, borrow, result); + } + + template <typename T, typename S, typename R, typename = std::enable_if_t<is_uint64_v<T, S, R>>> + SEAL_NODISCARD inline unsigned char sub_uint64(T operand1, S operand2, R *result) + { + *result = operand1 - operand2; + return static_cast<unsigned char>(operand2 > operand1); + } + + inline unsigned char sub_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count, unsigned char borrow, std::size_t result_uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!result_uint64_count) + { + throw std::invalid_argument("result_uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + for (std::size_t i = 0; i < result_uint64_count; i++, operand1++, operand2++, result++) + { + unsigned long long temp_result; + borrow = sub_uint64( + (i < operand1_uint64_count) ? *operand1 : 0, (i < operand2_uint64_count) ? *operand2 : 0, borrow, + &temp_result); + *result = temp_result; + } + return borrow; + } + + inline unsigned char sub_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // Unroll first iteration of loop. We assume uint64_count > 0. + unsigned char borrow = sub_uint64(*operand1++, *operand2++, result++); + + // Do the rest + for (; --uint64_count; operand1++, operand2++, result++) + { + unsigned long long temp_result; + borrow = sub_uint64(*operand1, *operand2, borrow, &temp_result); + *result = temp_result; + } + return borrow; + } + + inline unsigned char sub_uint_uint64( + const std::uint64_t *operand1, std::uint64_t operand2, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // Unroll first iteration of loop. We assume uint64_count > 0. + unsigned char borrow = sub_uint64(*operand1++, operand2, result++); + + // Do the rest + for (; --uint64_count; operand1++, operand2++, result++) + { + unsigned long long temp_result; + borrow = sub_uint64(*operand1, std::uint64_t(0), borrow, &temp_result); + *result = temp_result; + } + return borrow; + } + + inline unsigned char increment_uint( + const std::uint64_t *operand, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + return add_uint_uint64(operand, 1, uint64_count, result); + } + + inline unsigned char decrement_uint( + const std::uint64_t *operand, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand && uint64_count > 0) + { + throw std::invalid_argument("operand"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + return sub_uint_uint64(operand, 1, uint64_count, result); + } + + inline void negate_uint(const std::uint64_t *operand, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // Negation is equivalent to inverting bits and adding 1. + unsigned char carry = add_uint64(~*operand++, std::uint64_t(1), result++); + for (; --uint64_count; operand++, result++) + { + unsigned long long temp_result; + carry = add_uint64(~*operand, std::uint64_t(0), carry, &temp_result); + *result = temp_result; + } + } + + inline void left_shift_uint( + const std::uint64_t *operand, int shift_amount, std::size_t uint64_count, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, mul_safe(uint64_count, bits_per_uint64_sz))) + { + throw std::invalid_argument("shift_amount"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // How many words to shift + std::size_t uint64_shift_amount = static_cast<std::size_t>(shift_amount) / bits_per_uint64_sz; + + // Shift words + for (std::size_t i = 0; i < uint64_count - uint64_shift_amount; i++) + { + result[uint64_count - i - 1] = operand[uint64_count - i - 1 - uint64_shift_amount]; + } + for (std::size_t i = uint64_count - uint64_shift_amount; i < uint64_count; i++) + { + result[uint64_count - i - 1] = 0; + } + + // How many bits to shift in addition + std::size_t bit_shift_amount = + static_cast<std::size_t>(shift_amount) - (uint64_shift_amount * bits_per_uint64_sz); + + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + for (std::size_t i = uint64_count - 1; i > 0; i--) + { + result[i] = (result[i] << bit_shift_amount) | (result[i - 1] >> neg_bit_shift_amount); + } + result[0] = result[0] << bit_shift_amount; + } + } + + inline void right_shift_uint( + const std::uint64_t *operand, int shift_amount, std::size_t uint64_count, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, mul_safe(uint64_count, bits_per_uint64_sz))) + { + throw std::invalid_argument("shift_amount"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // How many words to shift + std::size_t uint64_shift_amount = static_cast<std::size_t>(shift_amount) / bits_per_uint64_sz; + + // Shift words + for (std::size_t i = 0; i < uint64_count - uint64_shift_amount; i++) + { + result[i] = operand[i + uint64_shift_amount]; + } + for (std::size_t i = uint64_count - uint64_shift_amount; i < uint64_count; i++) + { + result[i] = 0; + } + + // How many bits to shift in addition + std::size_t bit_shift_amount = + static_cast<std::size_t>(shift_amount) - (uint64_shift_amount * bits_per_uint64_sz); + + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + for (std::size_t i = 0; i < uint64_count - 1; i++) + { + result[i] = (result[i] >> bit_shift_amount) | (result[i + 1] << neg_bit_shift_amount); + } + result[uint64_count - 1] = result[uint64_count - 1] >> bit_shift_amount; + } + } + + inline void left_shift_uint128(const std::uint64_t *operand, int shift_amount, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, 2 * bits_per_uint64_sz)) + { + throw std::invalid_argument("shift_amount"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + const std::size_t shift_amount_sz = static_cast<std::size_t>(shift_amount); + + // Early return + if (shift_amount_sz & bits_per_uint64_sz) + { + result[1] = operand[0]; + result[0] = 0; + } + else + { + result[1] = operand[1]; + result[0] = operand[0]; + } + + // How many bits to shift in addition to word shift + std::size_t bit_shift_amount = shift_amount_sz & (bits_per_uint64_sz - 1); + + // Do we have a word shift + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + // Warning: if bit_shift_amount == 0 this is incorrect + result[1] = (result[1] << bit_shift_amount) | (result[0] >> neg_bit_shift_amount); + result[0] = result[0] << bit_shift_amount; + } + } + + inline void right_shift_uint128(const std::uint64_t *operand, int shift_amount, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, 2 * bits_per_uint64_sz)) + { + throw std::invalid_argument("shift_amount"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + const std::size_t shift_amount_sz = static_cast<std::size_t>(shift_amount); + + if (shift_amount_sz & bits_per_uint64_sz) + { + result[0] = operand[1]; + result[1] = 0; + } + else + { + result[1] = operand[1]; + result[0] = operand[0]; + } + + // How many bits to shift in addition to word shift + std::size_t bit_shift_amount = shift_amount_sz & (bits_per_uint64_sz - 1); + + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + // Warning: if bit_shift_amount == 0 this is incorrect + result[0] = (result[0] >> bit_shift_amount) | (result[1] << neg_bit_shift_amount); + result[1] = result[1] >> bit_shift_amount; + } + } + + inline void left_shift_uint192(const std::uint64_t *operand, int shift_amount, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, 3 * bits_per_uint64_sz)) + { + throw std::invalid_argument("shift_amount"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + const std::size_t shift_amount_sz = static_cast<std::size_t>(shift_amount); + + if (shift_amount_sz & (bits_per_uint64_sz << 1)) + { + result[2] = operand[0]; + result[1] = 0; + result[0] = 0; + } + else if (shift_amount_sz & bits_per_uint64_sz) + { + result[2] = operand[1]; + result[1] = operand[0]; + result[0] = 0; + } + else + { + result[2] = operand[2]; + result[1] = operand[1]; + result[0] = operand[0]; + } + + // How many bits to shift in addition to word shift + std::size_t bit_shift_amount = shift_amount_sz & (bits_per_uint64_sz - 1); + + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + // Warning: if bit_shift_amount == 0 this is incorrect + result[2] = (result[2] << bit_shift_amount) | (result[1] >> neg_bit_shift_amount); + result[1] = (result[1] << bit_shift_amount) | (result[0] >> neg_bit_shift_amount); + result[0] = result[0] << bit_shift_amount; + } + } + + inline void right_shift_uint192(const std::uint64_t *operand, int shift_amount, std::uint64_t *result) + { + const std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (shift_amount < 0 || unsigned_geq(shift_amount, 3 * bits_per_uint64_sz)) + { + throw std::invalid_argument("shift_amount"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + const std::size_t shift_amount_sz = static_cast<std::size_t>(shift_amount); + + if (shift_amount_sz & (bits_per_uint64_sz << 1)) + { + result[0] = operand[2]; + result[1] = 0; + result[2] = 0; + } + else if (shift_amount_sz & bits_per_uint64_sz) + { + result[0] = operand[1]; + result[1] = operand[2]; + result[2] = 0; + } + else + { + result[2] = operand[2]; + result[1] = operand[1]; + result[0] = operand[0]; + } + + // How many bits to shift in addition to word shift + std::size_t bit_shift_amount = shift_amount_sz & (bits_per_uint64_sz - 1); + + if (bit_shift_amount) + { + std::size_t neg_bit_shift_amount = bits_per_uint64_sz - bit_shift_amount; + + // Warning: if bit_shift_amount == 0 this is incorrect + result[0] = (result[0] >> bit_shift_amount) | (result[1] << neg_bit_shift_amount); + result[1] = (result[1] >> bit_shift_amount) | (result[2] << neg_bit_shift_amount); + result[2] = result[2] >> bit_shift_amount; + } + } + + inline void half_round_up_uint(const std::uint64_t *operand, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand && uint64_count > 0) + { + throw std::invalid_argument("operand"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + if (!uint64_count) + { + return; + } + // Set result to (operand + 1) / 2. To prevent overflowing operand, right shift + // and then increment result if low-bit of operand was set. + bool low_bit_set = operand[0] & 1; + + for (std::size_t i = 0; i < uint64_count - 1; i++) + { + result[i] = (operand[i] >> 1) | (operand[i + 1] << (bits_per_uint64 - 1)); + } + result[uint64_count - 1] = operand[uint64_count - 1] >> 1; + + if (low_bit_set) + { + increment_uint(result, uint64_count, result); + } + } + + inline void not_uint(const std::uint64_t *operand, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand && uint64_count > 0) + { + throw std::invalid_argument("operand"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (; uint64_count--; result++, operand++) + { + *result = ~*operand; + } + } + + inline void and_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1 && uint64_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && uint64_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (; uint64_count--; result++, operand1++, operand2++) + { + *result = *operand1 & *operand2; + } + } + + inline void or_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1 && uint64_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && uint64_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (; uint64_count--; result++, operand1++, operand2++) + { + *result = *operand1 | *operand2; + } + } + + inline void xor_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1 && uint64_count > 0) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && uint64_count > 0) + { + throw std::invalid_argument("operand2"); + } + if (!result && uint64_count > 0) + { + throw std::invalid_argument("result"); + } +#endif + for (; uint64_count--; result++, operand1++, operand2++) + { + *result = *operand1 ^ *operand2; + } + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + inline void multiply_uint64_generic(T operand1, S operand2, unsigned long long *result128) + { +#ifdef SEAL_DEBUG + if (!result128) + { + throw std::invalid_argument("result128 cannot be null"); + } +#endif + auto operand1_coeff_right = operand1 & 0x00000000FFFFFFFF; + auto operand2_coeff_right = operand2 & 0x00000000FFFFFFFF; + operand1 >>= 32; + operand2 >>= 32; + + auto middle1 = operand1 * operand2_coeff_right; + T middle; + auto left = operand1 * operand2 + + (static_cast<T>(add_uint64(middle1, operand2 * operand1_coeff_right, &middle)) << 32); + auto right = operand1_coeff_right * operand2_coeff_right; + auto temp_sum = (right >> 32) + (middle & 0x00000000FFFFFFFF); + + result128[1] = static_cast<unsigned long long>(left + (middle >> 32) + (temp_sum >> 32)); + result128[0] = static_cast<unsigned long long>((temp_sum << 32) | (right & 0x00000000FFFFFFFF)); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + inline void multiply_uint64(T operand1, S operand2, unsigned long long *result128) + { + SEAL_MULTIPLY_UINT64(operand1, operand2, result128); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + inline void multiply_uint64_hw64_generic(T operand1, S operand2, unsigned long long *hw64) + { +#ifdef SEAL_DEBUG + if (!hw64) + { + throw std::invalid_argument("hw64 cannot be null"); + } +#endif + auto operand1_coeff_right = operand1 & 0x00000000FFFFFFFF; + auto operand2_coeff_right = operand2 & 0x00000000FFFFFFFF; + operand1 >>= 32; + operand2 >>= 32; + + auto middle1 = operand1 * operand2_coeff_right; + T middle; + auto left = operand1 * operand2 + + (static_cast<T>(add_uint64(middle1, operand2 * operand1_coeff_right, &middle)) << 32); + auto right = operand1_coeff_right * operand2_coeff_right; + auto temp_sum = (right >> 32) + (middle & 0x00000000FFFFFFFF); + + *hw64 = static_cast<unsigned long long>(left + (middle >> 32) + (temp_sum >> 32)); + } + + template <typename T, typename S, typename = std::enable_if_t<is_uint64_v<T, S>>> + inline void multiply_uint64_hw64(T operand1, S operand2, unsigned long long *hw64) + { + SEAL_MULTIPLY_UINT64_HW64(operand1, operand2, hw64); + } + + void multiply_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count, std::size_t result_uint64_count, std::uint64_t *result); + + inline void multiply_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { + multiply_uint_uint(operand1, uint64_count, operand2, uint64_count, uint64_count * 2, result); + } + + void multiply_uint_uint64( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, std::uint64_t operand2, + std::size_t result_uint64_count, std::uint64_t *result); + + inline void multiply_truncate_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count, + std::uint64_t *result) + { + multiply_uint_uint(operand1, uint64_count, operand2, uint64_count, uint64_count, result); + } + + template <typename T, typename = std::enable_if_t<is_uint64_v<T>>> + inline void multiply_many_uint64(T *operands, std::size_t count, T *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (operands == result) + { + throw std::invalid_argument("operands cannot point to same value as result"); + } + if (!operands && count) + { + throw std::invalid_argument("operands"); + } + if (!result && count) + { + throw std::invalid_argument("operands"); + } +#endif + // Nothing to do + if (!count) + { + return; + } + + // Set result to operands[0] + set_uint(static_cast<std::uint64_t>(operands[0]), count, result); + + // Compute product + auto temp_mpi(allocate_uint(count, pool)); + for (std::size_t i = 1; i < count; i++) + { + multiply_uint_uint64(result, i, operands[i], i + 1, temp_mpi.get()); + set_uint_uint(temp_mpi.get(), i + 1, result); + } + } + + template <typename T, typename = std::enable_if_t<is_uint64_v<T>>> + inline void multiply_many_uint64_except( + T *operands, std::size_t count, std::size_t except, T *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (operands == result) + { + throw std::invalid_argument("operands cannot point to same value as result"); + } + if (!operands) + { + throw std::invalid_argument("operands"); + } + if (count < 1) + { + throw std::invalid_argument("count"); + } + if (except >= count) + { + throw std::invalid_argument("except"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + // An empty product; return 1 + if (count == 1 && except == 0) + { + set_uint(1, count, result); + return; + } + + // Set result to operands[0] unless except is 0 + set_uint(except == 0 ? std::uint64_t(1) : static_cast<std::uint64_t>(operands[0]), count, result); + + // Compute punctured product + auto temp_mpi(allocate_uint(count, pool)); + for (std::size_t i = 1; i < count; i++) + { + if (i != except) + { + multiply_uint_uint64(result, i, operands[i], i + 1, temp_mpi.get()); + set_uint_uint(temp_mpi.get(), i + 1, result); + } + } + } + + template <std::size_t Count> + inline void multiply_accumulate_uint64( + const std::uint64_t *operand1, const std::uint64_t *operand2, unsigned long long *accumulator) + { + unsigned long long qword[2]; + multiply_uint64(*operand1, *operand2, qword); + multiply_accumulate_uint64<Count - 1>(operand1 + 1, operand2 + 1, accumulator); + add_uint128(qword, accumulator, accumulator); + } + + template <> + inline void multiply_accumulate_uint64<0>( + SEAL_MAYBE_UNUSED const std::uint64_t *operand1, SEAL_MAYBE_UNUSED const std::uint64_t *operand2, + SEAL_MAYBE_UNUSED unsigned long long *accumulator) + { + // Base case; nothing to do + } + + void divide_uint_uint_inplace( + std::uint64_t *numerator, const std::uint64_t *denominator, std::size_t uint64_count, + std::uint64_t *quotient, MemoryPool &pool); + + inline void divide_uint_uint( + const std::uint64_t *numerator, const std::uint64_t *denominator, std::size_t uint64_count, + std::uint64_t *quotient, std::uint64_t *remainder, MemoryPool &pool) + { + set_uint_uint(numerator, uint64_count, remainder); + divide_uint_uint_inplace(remainder, denominator, uint64_count, quotient, pool); + } + + void divide_uint128_uint64_inplace_generic( + std::uint64_t *numerator, std::uint64_t denominator, std::uint64_t *quotient); + + inline void divide_uint128_uint64_inplace( + std::uint64_t *numerator, std::uint64_t denominator, std::uint64_t *quotient) + { +#ifdef SEAL_DEBUG + if (!numerator) + { + throw std::invalid_argument("numerator"); + } + if (denominator == 0) + { + throw std::invalid_argument("denominator"); + } + if (!quotient) + { + throw std::invalid_argument("quotient"); + } + if (numerator == quotient) + { + throw std::invalid_argument("quotient cannot point to same value as numerator"); + } +#endif + SEAL_DIVIDE_UINT128_UINT64(numerator, denominator, quotient); + } + + void divide_uint128_uint64_inplace( + std::uint64_t *numerator, std::uint64_t denominator, std::uint64_t *quotient); + + void divide_uint192_uint64_inplace( + std::uint64_t *numerator, std::uint64_t denominator, std::uint64_t *quotient); + + void exponentiate_uint( + const std::uint64_t *operand, std::size_t operand_uint64_count, const std::uint64_t *exponent, + std::size_t exponent_uint64_count, std::size_t result_uint64_count, std::uint64_t *result, + MemoryPool &pool); + + SEAL_NODISCARD std::uint64_t exponentiate_uint64_safe(std::uint64_t operand, std::uint64_t exponent); + + SEAL_NODISCARD std::uint64_t exponentiate_uint64(std::uint64_t operand, std::uint64_t exponent); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarithmod.cpp b/bigpiseal3.5.1/native/src/seal/util/uintarithmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad1e368bb1891656c5f7ab70ea14ee7915eb662d --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarithmod.cpp @@ -0,0 +1,237 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" + +using namespace std; + +namespace seal +{ + namespace util + { + bool try_invert_uint_mod( + const uint64_t *operand, const uint64_t *modulus, size_t uint64_count, uint64_t *result, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw invalid_argument("operand"); + } + if (!modulus) + { + throw invalid_argument("modulus"); + } + if (!uint64_count) + { + throw invalid_argument("uint64_count"); + } + if (!result) + { + throw invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand, modulus, uint64_count)) + { + throw logic_error("operand"); + } +#endif + // Cannot invert 0. + int bit_count = get_significant_bit_count_uint(operand, uint64_count); + if (bit_count == 0) + { + return false; + } + + // If it is 1, then its invert is itself. + if (bit_count == 1) + { + set_uint(1, uint64_count, result); + return true; + } + + auto alloc_anchor(allocate_uint(7 * uint64_count, pool)); + + // Construct a mutable copy of operand and modulus, with numerator being modulus + // and operand being denominator. Notice that numerator > denominator. + uint64_t *numerator = alloc_anchor.get(); + set_uint_uint(modulus, uint64_count, numerator); + + uint64_t *denominator = numerator + uint64_count; + set_uint_uint(operand, uint64_count, denominator); + + // Create space to store difference. + uint64_t *difference = denominator + uint64_count; + + // Determine highest bit index of each. + int numerator_bits = get_significant_bit_count_uint(numerator, uint64_count); + int denominator_bits = get_significant_bit_count_uint(denominator, uint64_count); + + // Create space to store quotient. + uint64_t *quotient = difference + uint64_count; + + // Create three sign/magnitude values to store coefficients. + // Initialize invert_prior to +0 and invert_curr to +1. + uint64_t *invert_prior = quotient + uint64_count; + set_zero_uint(uint64_count, invert_prior); + bool invert_prior_positive = true; + + uint64_t *invert_curr = invert_prior + uint64_count; + set_uint(1, uint64_count, invert_curr); + bool invert_curr_positive = true; + + uint64_t *invert_next = invert_curr + uint64_count; + bool invert_next_positive = true; + + // Perform extended Euclidean algorithm. + while (true) + { + // NOTE: Numerator is > denominator. + + // Only perform computation up to last non-zero uint64s. + size_t division_uint64_count = static_cast<size_t>(divide_round_up(numerator_bits, bits_per_uint64)); + + // Shift denominator to bring MSB in alignment with MSB of numerator. + int denominator_shift = numerator_bits - denominator_bits; + left_shift_uint(denominator, denominator_shift, division_uint64_count, denominator); + denominator_bits += denominator_shift; + + // Clear quotient. + set_zero_uint(uint64_count, quotient); + + // Perform bit-wise division algorithm. + int remaining_shifts = denominator_shift; + while (numerator_bits == denominator_bits) + { + // NOTE: MSBs of numerator and denominator are aligned. + + // Even though MSB of numerator and denominator are aligned, + // still possible numerator < denominator. + if (sub_uint_uint(numerator, denominator, division_uint64_count, difference)) + { + // numerator < denominator and MSBs are aligned, so current + // quotient bit is zero and next one is definitely one. + if (remaining_shifts == 0) + { + // No shifts remain and numerator < denominator so done. + break; + } + + // Effectively shift numerator left by 1 by instead adding + // numerator to difference (to prevent overflow in numerator). + add_uint_uint(difference, numerator, division_uint64_count, difference); + + // Adjust quotient and remaining shifts as a result of shifting numerator. + left_shift_uint(quotient, 1, division_uint64_count, quotient); + remaining_shifts--; + } + // Difference is the new numerator with denominator subtracted. + + // Update quotient to reflect subtraction. + *quotient |= 1; + + // Determine amount to shift numerator to bring MSB in alignment + // with denominator. + numerator_bits = get_significant_bit_count_uint(difference, division_uint64_count); + int numerator_shift = denominator_bits - numerator_bits; + if (numerator_shift > remaining_shifts) + { + // Clip the maximum shift to determine only the integer + // (as opposed to fractional) bits. + numerator_shift = remaining_shifts; + } + + // Shift and update numerator. + if (numerator_bits > 0) + { + left_shift_uint(difference, numerator_shift, division_uint64_count, numerator); + numerator_bits += numerator_shift; + } + else + { + // Difference is zero so no need to shift, just set to zero. + set_zero_uint(division_uint64_count, numerator); + } + + // Adjust quotient and remaining shifts as a result of + // shifting numerator. + left_shift_uint(quotient, numerator_shift, division_uint64_count, quotient); + remaining_shifts -= numerator_shift; + } + + // Correct for shifting of denominator. + right_shift_uint(denominator, denominator_shift, division_uint64_count, denominator); + denominator_bits -= denominator_shift; + + // We are done if remainder (which is stored in numerator) is zero. + if (numerator_bits == 0) + { + break; + } + + // Correct for shifting of denominator. + right_shift_uint(numerator, denominator_shift, division_uint64_count, numerator); + numerator_bits -= denominator_shift; + + // Integrate quotient with invert coefficients. + // Calculate: invert_prior + -quotient * invert_curr + multiply_truncate_uint_uint(quotient, invert_curr, uint64_count, invert_next); + invert_next_positive = !invert_curr_positive; + if (invert_prior_positive == invert_next_positive) + { + // If both sides of add have same sign, then simple add and + // do not need to worry about overflow due to known limits + // on the coefficients proved in the euclidean algorithm. + add_uint_uint(invert_prior, invert_next, uint64_count, invert_next); + } + else + { + // If both sides of add have opposite sign, then subtract + // and check for overflow. + uint64_t borrow = sub_uint_uint(invert_prior, invert_next, uint64_count, invert_next); + if (borrow == 0) + { + // No borrow means |invert_prior| >= |invert_next|, + // so sign is same as invert_prior. + invert_next_positive = invert_prior_positive; + } + else + { + // Borrow means |invert prior| < |invert_next|, + // so sign is opposite of invert_prior. + invert_next_positive = !invert_prior_positive; + negate_uint(invert_next, uint64_count, invert_next); + } + } + + // Swap prior and curr, and then curr and next. + swap(invert_prior, invert_curr); + swap(invert_prior_positive, invert_curr_positive); + swap(invert_curr, invert_next); + swap(invert_curr_positive, invert_next_positive); + + // Swap numerator and denominator using pointer swings. + swap(numerator, denominator); + swap(numerator_bits, denominator_bits); + } + + if (!is_equal_uint(denominator, uint64_count, 1)) + { + // GCD is not one, so unable to find inverse. + return false; + } + + // Correct coefficient if negative by modulo. + if (!invert_curr_positive && !is_zero_uint(invert_curr, uint64_count)) + { + sub_uint_uint(modulus, invert_curr, uint64_count, invert_curr); + invert_curr_positive = true; + } + + // Set result. + set_uint_uint(invert_curr, uint64_count, result); + return true; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarithmod.h b/bigpiseal3.5.1/native/src/seal/util/uintarithmod.h new file mode 100644 index 0000000000000000000000000000000000000000..d886584d98e2b041feed4fe586d8cac9f03755ba --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarithmod.h @@ -0,0 +1,260 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/pointer.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintcore.h" +#include <cstdint> + +namespace seal +{ + namespace util + { + inline void increment_uint_mod( + const std::uint64_t *operand, const std::uint64_t *modulus, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand, modulus, uint64_count)) + { + throw std::invalid_argument("operand"); + } + if (modulus == result) + { + throw std::invalid_argument("result cannot point to the same value as modulus"); + } +#endif + unsigned char carry = increment_uint(operand, uint64_count, result); + if (carry || is_greater_than_or_equal_uint_uint(result, modulus, uint64_count)) + { + sub_uint_uint(result, modulus, uint64_count, result); + } + } + + inline void decrement_uint_mod( + const std::uint64_t *operand, const std::uint64_t *modulus, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand, modulus, uint64_count)) + { + throw std::invalid_argument("operand"); + } + if (modulus == result) + { + throw std::invalid_argument("result cannot point to the same value as modulus"); + } +#endif + if (decrement_uint(operand, uint64_count, result)) + { + add_uint_uint(result, modulus, uint64_count, result); + } + } + + inline void negate_uint_mod( + const std::uint64_t *operand, const std::uint64_t *modulus, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand, modulus, uint64_count)) + { + throw std::invalid_argument("operand"); + } +#endif + if (is_zero_uint(operand, uint64_count)) + { + // Negation of zero is zero. + set_zero_uint(uint64_count, result); + } + else + { + // Otherwise, we know operand > 0 and < modulus so subtract modulus - operand. + sub_uint_uint(modulus, operand, uint64_count, result); + } + } + + inline void div2_uint_mod( + const std::uint64_t *operand, const std::uint64_t *modulus, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand) + { + throw std::invalid_argument("operand"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (!is_bit_set_uint(modulus, uint64_count, 0)) + { + throw std::invalid_argument("modulus"); + } + if (is_greater_than_or_equal_uint_uint(operand, modulus, uint64_count)) + { + throw std::invalid_argument("operand"); + } +#endif + if (*operand & 1) + { + unsigned char carry = add_uint_uint(operand, modulus, uint64_count, result); + right_shift_uint(result, 1, uint64_count, result); + if (carry) + { + set_bit_uint(result, uint64_count, static_cast<int>(uint64_count) * bits_per_uint64 - 1); + } + } + else + { + right_shift_uint(operand, 1, uint64_count, result); + } + } + + inline void add_uint_uint_mod( + const std::uint64_t *operand1, const std::uint64_t *operand2, const std::uint64_t *modulus, + std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand1, modulus, uint64_count)) + { + throw std::invalid_argument("operand1"); + } + if (is_greater_than_or_equal_uint_uint(operand2, modulus, uint64_count)) + { + throw std::invalid_argument("operand2"); + } + if (modulus == result) + { + throw std::invalid_argument("result cannot point to the same value as modulus"); + } +#endif + unsigned char carry = add_uint_uint(operand1, operand2, uint64_count, result); + if (carry || is_greater_than_or_equal_uint_uint(result, modulus, uint64_count)) + { + sub_uint_uint(result, modulus, uint64_count, result); + } + } + + inline void sub_uint_uint_mod( + const std::uint64_t *operand1, const std::uint64_t *operand2, const std::uint64_t *modulus, + std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!operand1) + { + throw std::invalid_argument("operand1"); + } + if (!operand2) + { + throw std::invalid_argument("operand2"); + } + if (!modulus) + { + throw std::invalid_argument("modulus"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } + if (is_greater_than_or_equal_uint_uint(operand1, modulus, uint64_count)) + { + throw std::invalid_argument("operand1"); + } + if (is_greater_than_or_equal_uint_uint(operand2, modulus, uint64_count)) + { + throw std::invalid_argument("operand2"); + } + if (modulus == result) + { + throw std::invalid_argument("result cannot point to the same value as modulus"); + } +#endif + if (sub_uint_uint(operand1, operand2, uint64_count, result)) + { + add_uint_uint(result, modulus, uint64_count, result); + } + } + + bool try_invert_uint_mod( + const std::uint64_t *operand, const std::uint64_t *modulus, std::size_t uint64_count, std::uint64_t *result, + MemoryPool &pool); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.cpp b/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6ecaa7ca1d44014232f4f7c9a4a522b8611e6e8 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.cpp @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/uintarith.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <numeric> +#include <random> +#include <tuple> + +using namespace std; + +namespace seal +{ + namespace util + { + uint64_t exponentiate_uint_mod(uint64_t operand, uint64_t exponent, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw invalid_argument("modulus"); + } + if (operand >= modulus.value()) + { + throw invalid_argument("operand"); + } +#endif + // Fast cases + if (exponent == 0) + { + // Result is supposed to be only one digit + return 1; + } + + if (exponent == 1) + { + return operand; + } + + // Perform binary exponentiation. + uint64_t power = operand; + uint64_t product = 0; + uint64_t intermediate = 1; + + // Initially: power = operand and intermediate = 1, product is irrelevant. + while (true) + { + if (exponent & 1) + { + product = multiply_uint_uint_mod(power, intermediate, modulus); + swap(product, intermediate); + } + exponent >>= 1; + if (exponent == 0) + { + break; + } + product = multiply_uint_uint_mod(power, power, modulus); + swap(product, power); + } + return intermediate; + } + + void divide_uint_uint_mod_inplace( + uint64_t *numerator, const Modulus &modulus, size_t uint64_count, uint64_t *quotient, MemoryPool &pool) + { + // Handle base cases + if (uint64_count == 2) + { + divide_uint128_uint64_inplace(numerator, modulus.value(), quotient); + return; + } + else if (uint64_count == 1) + { + *numerator = *numerator % modulus.value(); + *quotient = *numerator / modulus.value(); + return; + } + else + { + // If uint64_count > 2. + // x = numerator = x1 * 2^128 + x2. + // 2^128 = A*value + B. + + auto x1_alloc(allocate_uint(uint64_count - 2, pool)); + uint64_t *x1 = x1_alloc.get(); + uint64_t x2[2]; + auto quot_alloc(allocate_uint(uint64_count, pool)); + uint64_t *quot = quot_alloc.get(); + auto rem_alloc(allocate_uint(uint64_count, pool)); + uint64_t *rem = rem_alloc.get(); + set_uint_uint(numerator + 2, uint64_count - 2, x1); + set_uint_uint(numerator, 2, x2); // x2 = (num) % 2^128. + + multiply_uint_uint(x1, uint64_count - 2, &modulus.const_ratio()[0], 2, uint64_count, quot); // x1*A. + multiply_uint_uint64(x1, uint64_count - 2, modulus.const_ratio()[2], uint64_count - 1, rem); // x1*B + add_uint_uint(rem, uint64_count - 1, x2, 2, 0, uint64_count, rem); // x1*B + x2; + + size_t remainder_uint64_count = get_significant_uint64_count_uint(rem, uint64_count); + divide_uint_uint_mod_inplace(rem, modulus, remainder_uint64_count, quotient, pool); + add_uint_uint(quotient, quot, uint64_count, quotient); + *numerator = rem[0]; + + return; + } + } + + uint64_t dot_product_mod( + const uint64_t *operand1, const uint64_t *operand2, size_t count, const Modulus &modulus) + { + static_assert(SEAL_MULTIPLY_ACCUMULATE_MOD_MAX >= 16, "SEAL_MULTIPLY_ACCUMULATE_MOD_MAX"); + unsigned long long accumulator[2]{ 0, 0 }; + switch (count) + { + case 0: + return 0; + case 1: + multiply_accumulate_uint64<1>(operand1, operand2, accumulator); + break; + case 2: + multiply_accumulate_uint64<2>(operand1, operand2, accumulator); + break; + case 3: + multiply_accumulate_uint64<3>(operand1, operand2, accumulator); + break; + case 4: + multiply_accumulate_uint64<4>(operand1, operand2, accumulator); + break; + case 5: + multiply_accumulate_uint64<5>(operand1, operand2, accumulator); + break; + case 6: + multiply_accumulate_uint64<6>(operand1, operand2, accumulator); + break; + case 7: + multiply_accumulate_uint64<7>(operand1, operand2, accumulator); + break; + case 8: + multiply_accumulate_uint64<8>(operand1, operand2, accumulator); + break; + case 9: + multiply_accumulate_uint64<9>(operand1, operand2, accumulator); + break; + case 10: + multiply_accumulate_uint64<10>(operand1, operand2, accumulator); + break; + case 11: + multiply_accumulate_uint64<11>(operand1, operand2, accumulator); + break; + case 12: + multiply_accumulate_uint64<12>(operand1, operand2, accumulator); + break; + case 13: + multiply_accumulate_uint64<13>(operand1, operand2, accumulator); + break; + case 14: + multiply_accumulate_uint64<14>(operand1, operand2, accumulator); + break; + case 15: + multiply_accumulate_uint64<15>(operand1, operand2, accumulator); + break; + case 16: + largest_case: + multiply_accumulate_uint64<16>(operand1, operand2, accumulator); + break; + default: + accumulator[0] = dot_product_mod(operand1 + 16, operand2 + 16, count - 16, modulus); + goto largest_case; + }; + return barrett_reduce_128(accumulator, modulus); + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.h b/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.h new file mode 100644 index 0000000000000000000000000000000000000000..3d3be8b7bd91f862cf3a7d94633f046972dafb90 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintarithsmallmod.h @@ -0,0 +1,307 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/modulus.h" +#include "seal/util/defines.h" +#include "seal/util/numth.h" +#include "seal/util/pointer.h" +#include "seal/util/uintarith.h" +#include <cstdint> +#include <type_traits> + +namespace seal +{ + namespace util + { + SEAL_NODISCARD inline std::uint64_t increment_uint_mod(std::uint64_t operand, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (operand >= modulus.value()) + { + throw std::out_of_range("operand"); + } +#endif + operand++; + return operand - (modulus.value() & + static_cast<std::uint64_t>(-static_cast<std::int64_t>(operand >= modulus.value()))); + } + + SEAL_NODISCARD inline std::uint64_t decrement_uint_mod(std::uint64_t operand, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (operand >= modulus.value()) + { + throw std::out_of_range("operand"); + } +#endif + std::int64_t carry = (operand == 0); + return operand - 1 + (modulus.value() & static_cast<std::uint64_t>(-carry)); + } + + SEAL_NODISCARD inline std::uint64_t negate_uint_mod(std::uint64_t operand, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (operand >= modulus.value()) + { + throw std::out_of_range("operand"); + } +#endif + std::int64_t non_zero = (operand != 0); + return (modulus.value() - operand) & static_cast<std::uint64_t>(-non_zero); + } + + SEAL_NODISCARD inline std::uint64_t div2_uint_mod(std::uint64_t operand, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (operand >= modulus.value()) + { + throw std::out_of_range("operand"); + } +#endif + if (operand & 1) + { + unsigned long long temp; + int64_t carry = add_uint64(operand, modulus.value(), 0, &temp); + operand = temp >> 1; + if (carry) + { + return operand | (std::uint64_t(1) << (bits_per_uint64 - 1)); + } + return operand; + } + return operand >> 1; + } + + SEAL_NODISCARD inline std::uint64_t add_uint_uint_mod( + std::uint64_t operand1, std::uint64_t operand2, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (operand1 >= modulus.value()) + { + throw std::out_of_range("operand1"); + } + if (operand2 >= modulus.value()) + { + throw std::out_of_range("operand2"); + } +#endif + // Sum of operands modulo Modulus can never wrap around 2^64 + operand1 += operand2; + return operand1 - (modulus.value() & + static_cast<std::uint64_t>(-static_cast<std::int64_t>(operand1 >= modulus.value()))); + } + + SEAL_NODISCARD inline std::uint64_t sub_uint_uint_mod( + std::uint64_t operand1, std::uint64_t operand2, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + + if (operand1 >= modulus.value()) + { + throw std::out_of_range("operand1"); + } + if (operand2 >= modulus.value()) + { + throw std::out_of_range("operand2"); + } +#endif + unsigned long long temp; + std::int64_t borrow = SEAL_SUB_BORROW_UINT64(operand1, operand2, 0, &temp); + return static_cast<std::uint64_t>(temp) + (modulus.value() & static_cast<std::uint64_t>(-borrow)); + } + + template <typename T, typename = std::enable_if_t<is_uint64_v<T>>> + SEAL_NODISCARD inline std::uint64_t barrett_reduce_128(const T *input, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (!input) + { + throw std::invalid_argument("input"); + } + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } +#endif + // Reduces input using base 2^64 Barrett reduction + // input allocation size must be 128 bits + + unsigned long long tmp1, tmp2[2], tmp3, carry; + const std::uint64_t *const_ratio = modulus.const_ratio().data(); + + // Multiply input and const_ratio + // Round 1 + multiply_uint64_hw64(input[0], const_ratio[0], &carry); + + multiply_uint64(input[0], const_ratio[1], tmp2); + tmp3 = tmp2[1] + add_uint64(tmp2[0], carry, 0, &tmp1); + + // Round 2 + multiply_uint64(input[1], const_ratio[0], tmp2); + carry = tmp2[1] + add_uint64(tmp1, tmp2[0], 0, &tmp1); + + // This is all we care about + tmp1 = input[1] * const_ratio[1] + tmp3 + carry; + + // Barrett subtraction + tmp3 = input[0] - tmp1 * modulus.value(); + + // One more subtraction is enough + return static_cast<std::uint64_t>(tmp3) - + (modulus.value() & static_cast<std::uint64_t>(-static_cast<std::int64_t>(tmp3 >= modulus.value()))); + } + + template <typename T, typename = std::enable_if_t<is_uint64_v<T>>> + SEAL_NODISCARD inline std::uint64_t barrett_reduce_63(T input, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } + if (input >> 63) + { + throw std::invalid_argument("input"); + } +#endif + // Reduces input using base 2^64 Barrett reduction + // input must be at most 63 bits + + unsigned long long tmp[2]; + const std::uint64_t *const_ratio = modulus.const_ratio().data(); + multiply_uint64(input, const_ratio[1], tmp); + + // Barrett subtraction + tmp[0] = input - tmp[1] * modulus.value(); + + // One more subtraction is enough + return static_cast<std::uint64_t>(tmp[0]) - + (modulus.value() & + static_cast<std::uint64_t>(-static_cast<std::int64_t>(tmp[0] >= modulus.value()))); + } + + SEAL_NODISCARD inline std::uint64_t multiply_uint_uint_mod( + std::uint64_t operand1, std::uint64_t operand2, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (modulus.is_zero()) + { + throw std::invalid_argument("modulus"); + } +#endif + unsigned long long z[2]; + multiply_uint64(operand1, operand2, z); + return barrett_reduce_128(z, modulus); + } + + inline void modulo_uint_inplace(std::uint64_t *value, std::size_t value_uint64_count, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } + if (!value_uint64_count) + { + throw std::invalid_argument("value_uint64_count"); + } +#endif + + if (value_uint64_count == 1) + { + value[0] %= modulus.value(); + return; + } + + // Starting from the top, reduce always 128-bit blocks + for (std::size_t i = value_uint64_count - 1; i--;) + { + value[i] = barrett_reduce_128(value + i, modulus); + value[i + 1] = 0; + } + } + + SEAL_NODISCARD inline std::uint64_t modulo_uint( + const std::uint64_t *value, std::size_t value_uint64_count, const Modulus &modulus) + { +#ifdef SEAL_DEBUG + if (!value && value_uint64_count) + { + throw std::invalid_argument("value"); + } + if (!value_uint64_count) + { + throw std::invalid_argument("value_uint64_count"); + } +#endif + if (value_uint64_count == 1) + { + // If value < modulus no operation is needed + return *value % modulus.value(); + } + + // Temporary space for 128-bit reductions + uint64_t temp[2]{ 0, value[value_uint64_count - 1] }; + for (size_t k = value_uint64_count - 1; k--;) + { + temp[0] = value[k]; + temp[1] = barrett_reduce_128(temp, modulus); + } + + // Save the result modulo i-th prime + return temp[1]; + } + + // Computes (operand1 * operand2) + operand3 mod modulus + inline std::uint64_t multiply_add_uint_mod( + std::uint64_t operand1, std::uint64_t operand2, std::uint64_t operand3, const Modulus &modulus) + { + // Lazy reduction + unsigned long long temp[2]; + multiply_uint64(operand1, operand2, temp); + temp[1] += add_uint64(temp[0], operand3, temp); + return barrett_reduce_128(temp, modulus); + } + + inline bool try_invert_uint_mod(std::uint64_t operand, const Modulus &modulus, std::uint64_t &result) + { + return try_invert_uint_mod(operand, modulus.value(), result); + } + + SEAL_NODISCARD std::uint64_t exponentiate_uint_mod( + std::uint64_t operand, std::uint64_t exponent, const Modulus &modulus); + + void divide_uint_uint_mod_inplace( + std::uint64_t *numerator, const Modulus &modulus, std::size_t uint64_count, std::uint64_t *quotient, + MemoryPool &pool); + + SEAL_NODISCARD std::uint64_t dot_product_mod( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t count, const Modulus &modulus); + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintcore.cpp b/bigpiseal3.5.1/native/src/seal/util/uintcore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c167f8c382e796d591fa2d2b938552065a03be43 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintcore.cpp @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <string> + +using namespace std; + +namespace seal +{ + namespace util + { + string uint_to_hex_string(const uint64_t *value, size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (uint64_count && !value) + { + throw invalid_argument("value"); + } +#endif + // Start with a string with a zero for each nibble in the array. + size_t num_nibbles = mul_safe(uint64_count, static_cast<size_t>(nibbles_per_uint64)); + string output(num_nibbles, '0'); + + // Iterate through each uint64 in array and set string with correct nibbles in hex. + size_t nibble_index = num_nibbles; + size_t leftmost_non_zero_pos = num_nibbles; + for (size_t i = 0; i < uint64_count; i++) + { + uint64_t part = *value++; + + // Iterate through each nibble in the current uint64. + for (size_t j = 0; j < nibbles_per_uint64; j++) + { + size_t nibble = safe_cast<size_t>(part & uint64_t(0x0F)); + size_t pos = --nibble_index; + if (nibble != 0) + { + // If nibble is not zero, then update string and save this pos to determine + // number of leading zeros. + output[pos] = nibble_to_upper_hex(static_cast<int>(nibble)); + leftmost_non_zero_pos = pos; + } + part >>= 4; + } + } + + // Trim string to remove leading zeros. + output.erase(0, leftmost_non_zero_pos); + + // Return 0 if nothing remains. + if (output.empty()) + { + return string("0"); + } + + return output; + } + + string uint_to_dec_string(const uint64_t *value, size_t uint64_count, MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (uint64_count && !value) + { + throw invalid_argument("value"); + } +#endif + if (!uint64_count) + { + return string("0"); + } + auto remainder(allocate_uint(uint64_count, pool)); + auto quotient(allocate_uint(uint64_count, pool)); + auto base(allocate_uint(uint64_count, pool)); + uint64_t *remainderptr = remainder.get(); + uint64_t *quotientptr = quotient.get(); + uint64_t *baseptr = base.get(); + set_uint(10, uint64_count, baseptr); + set_uint_uint(value, uint64_count, remainderptr); + string output; + while (!is_zero_uint(remainderptr, uint64_count)) + { + divide_uint_uint_inplace(remainderptr, baseptr, uint64_count, quotientptr, pool); + char digit = static_cast<char>(remainderptr[0] + static_cast<uint64_t>('0')); + output += digit; + swap(remainderptr, quotientptr); + } + reverse(output.begin(), output.end()); + + // Return 0 if nothing remains. + if (output.empty()) + { + return string("0"); + } + + return output; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/uintcore.h b/bigpiseal3.5.1/native/src/seal/util/uintcore.h new file mode 100644 index 0000000000000000000000000000000000000000..b5788bf4090de26631c0a72421e9d2315d78d14f --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/uintcore.h @@ -0,0 +1,647 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/util/common.h" +#include "seal/util/defines.h" +#include "seal/util/pointer.h" +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <limits> +#include <stdexcept> + +namespace seal +{ + namespace util + { + SEAL_NODISCARD std::string uint_to_hex_string(const std::uint64_t *value, std::size_t uint64_count); + + SEAL_NODISCARD std::string uint_to_dec_string( + const std::uint64_t *value, std::size_t uint64_count, MemoryPool &pool); + + inline void hex_string_to_uint( + const char *hex_string, int char_count, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!hex_string && char_count > 0) + { + throw std::invalid_argument("hex_string"); + } + if (uint64_count && !result) + { + throw std::invalid_argument("result"); + } + if (unsigned_gt( + get_hex_string_bit_count(hex_string, char_count), + mul_safe(uint64_count, static_cast<size_t>(bits_per_uint64)))) + { + throw std::invalid_argument("hex_string"); + } +#endif + const char *hex_string_ptr = hex_string + char_count; + for (std::size_t uint64_index = 0; uint64_index < uint64_count; uint64_index++) + { + std::uint64_t value = 0; + for (int bit_index = 0; bit_index < bits_per_uint64; bit_index += bits_per_nibble) + { + if (hex_string_ptr == hex_string) + { + break; + } + char hex = *--hex_string_ptr; + int nibble = hex_to_nibble(hex); + if (nibble == -1) + { + throw std::invalid_argument("hex_value"); + } + value |= static_cast<std::uint64_t>(nibble) << bit_index; + } + result[uint64_index] = value; + } + } + + SEAL_NODISCARD inline auto allocate_uint(std::size_t uint64_count, MemoryPool &pool) + { + return allocate<std::uint64_t>(uint64_count, pool); + } + + inline void set_zero_uint(std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!result && uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + std::fill_n(result, uint64_count, std::uint64_t(0)); + } + + SEAL_NODISCARD inline auto allocate_zero_uint(std::size_t uint64_count, MemoryPool &pool) + { + auto result(allocate_uint(uint64_count, pool)); + set_zero_uint(uint64_count, result.get()); + return result; + + // The following looks better but seems to yield worse results. + // return allocate<std::uint64_t>(uint64_count, pool, std::uint64_t(0)); + } + + inline void set_uint(std::uint64_t value, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (!result) + { + throw std::invalid_argument("result"); + } +#endif + *result++ = value; + for (; --uint64_count; result++) + { + *result = 0; + } + } + + inline void set_uint_uint(const std::uint64_t *value, std::size_t uint64_count, std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!value && uint64_count) + { + throw std::invalid_argument("value"); + } + if (!result && uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + if ((value == result) || !uint64_count) + { + return; + } + std::copy_n(value, uint64_count, result); + } + + SEAL_NODISCARD inline bool is_zero_uint(const std::uint64_t *value, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!value && uint64_count) + { + throw std::invalid_argument("value"); + } +#endif + return std::all_of(value, value + uint64_count, [](auto coeff) -> bool { return !coeff; }); + } + + SEAL_NODISCARD inline bool is_equal_uint( + const std::uint64_t *value, std::size_t uint64_count, std::uint64_t scalar) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } +#endif + if (*value++ != scalar) + { + return false; + } + return std::all_of(value, value + uint64_count - 1, [](auto coeff) -> bool { return !coeff; }); + } + + SEAL_NODISCARD inline bool is_high_bit_set_uint(const std::uint64_t *value, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } +#endif + return (value[uint64_count - 1] >> (bits_per_uint64 - 1)) != 0; + } +#ifndef SEAL_USE_MAYBE_UNUSED +#if (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif +#endif + SEAL_NODISCARD inline bool is_bit_set_uint( + const std::uint64_t *value, std::size_t uint64_count SEAL_MAYBE_UNUSED, int bit_index) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (bit_index < 0 || + static_cast<std::int64_t>(bit_index) >= static_cast<std::int64_t>(uint64_count) * bits_per_uint64) + { + throw std::invalid_argument("bit_index"); + } +#endif + int uint64_index = bit_index / bits_per_uint64; + int sub_bit_index = bit_index - uint64_index * bits_per_uint64; + return ((value[static_cast<std::size_t>(uint64_index)] >> sub_bit_index) & 1) != 0; + } + + inline void set_bit_uint(std::uint64_t *value, std::size_t uint64_count SEAL_MAYBE_UNUSED, int bit_index) + { +#ifdef SEAL_DEBUG + if (!value) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } + if (bit_index < 0 || + static_cast<std::int64_t>(bit_index) >= static_cast<std::int64_t>(uint64_count) * bits_per_uint64) + { + throw std::invalid_argument("bit_index"); + } +#endif + int uint64_index = bit_index / bits_per_uint64; + int sub_bit_index = bit_index % bits_per_uint64; + value[static_cast<std::size_t>(uint64_index)] |= std::uint64_t(1) << sub_bit_index; + } +#ifndef SEAL_USE_MAYBE_UNUSED +#if (SEAL_COMPILER == SEAL_COMPILER_GCC) +#pragma GCC diagnostic pop +#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG) +#pragma clang diagnostic pop +#endif +#endif + SEAL_NODISCARD inline int get_significant_bit_count_uint(const std::uint64_t *value, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!value && uint64_count) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } +#endif + value += uint64_count - 1; + for (; *value == 0 && uint64_count > 1; uint64_count--) + { + value--; + } + + return static_cast<int>(uint64_count - 1) * bits_per_uint64 + get_significant_bit_count(*value); + } + + SEAL_NODISCARD inline std::size_t get_significant_uint64_count_uint( + const std::uint64_t *value, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!value && uint64_count) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } +#endif + value += uint64_count - 1; + for (; uint64_count && !*value; uint64_count--) + { + value--; + } + + return uint64_count; + } + + SEAL_NODISCARD inline std::size_t get_nonzero_uint64_count_uint( + const std::uint64_t *value, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!value && uint64_count) + { + throw std::invalid_argument("value"); + } + if (!uint64_count) + { + throw std::invalid_argument("uint64_count"); + } +#endif + std::size_t nonzero_count = uint64_count; + + value += uint64_count - 1; + for (; uint64_count; uint64_count--) + { + if (*value-- == 0) + { + nonzero_count--; + } + } + + return nonzero_count; + } + + inline void set_uint_uint( + const std::uint64_t *value, std::size_t value_uint64_count, std::size_t result_uint64_count, + std::uint64_t *result) + { +#ifdef SEAL_DEBUG + if (!value && value_uint64_count) + { + throw std::invalid_argument("value"); + } + if (!result && result_uint64_count) + { + throw std::invalid_argument("result"); + } +#endif + if (value == result || !value_uint64_count) + { + // Fast path to handle self assignment. + std::fill(result + value_uint64_count, result + result_uint64_count, std::uint64_t(0)); + } + else + { + std::size_t min_uint64_count = std::min(value_uint64_count, result_uint64_count); + std::copy_n(value, min_uint64_count, result); + std::fill(result + min_uint64_count, result + result_uint64_count, std::uint64_t(0)); + } + } + + /** + If the value is a power of two, return the power; otherwise, return -1. + */ + SEAL_NODISCARD inline int get_power_of_two(std::uint64_t value) + { + if (value == 0 || (value & (value - 1)) != 0) + { + return -1; + } + + unsigned long result = 0; + SEAL_MSB_INDEX_UINT64(&result, value); + return static_cast<int>(result); + } + + SEAL_NODISCARD inline int get_power_of_two_minus_one(std::uint64_t value) + { + if (value == 0xFFFFFFFFFFFFFFFF) + { + return bits_per_uint64; + } + return get_power_of_two(value + 1); + } + + SEAL_NODISCARD inline int get_power_of_two_uint(const std::uint64_t *operand, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!operand && uint64_count) + { + throw std::invalid_argument("operand"); + } +#endif + operand += uint64_count; + int long_index = safe_cast<int>(uint64_count), local_result = -1; + for (; (long_index >= 1) && (local_result == -1); long_index--) + { + operand--; + local_result = get_power_of_two(*operand); + } + + // If local_result != -1, we've found a power-of-two highest order block, + // in which case need to check that rest are zero. + // If local_result == -1, operand is not power of two. + if (local_result == -1) + { + return -1; + } + + int zeros = 1; + for (int j = long_index; j >= 1; j--) + { + zeros &= (*--operand == 0); + } + + return add_safe(mul_safe(zeros, add_safe(local_result, mul_safe(long_index, bits_per_uint64))), zeros, -1); + } + + SEAL_NODISCARD inline int get_power_of_two_minus_one_uint( + const std::uint64_t *operand, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!operand && uint64_count) + { + throw std::invalid_argument("operand"); + } + if (unsigned_geq(uint64_count, std::numeric_limits<int>::max())) + { + throw std::invalid_argument("uint64_count"); + } +#endif + operand += uint64_count; + int long_index = safe_cast<int>(uint64_count), local_result = 0; + for (; (long_index >= 1) && (local_result == 0); long_index--) + { + operand--; + local_result = get_power_of_two_minus_one(*operand); + } + + // If local_result != -1, we've found a power-of-two-minus-one highest + // order block, in which case need to check that rest are ~0. + // If local_result == -1, operand is not power of two minus one. + if (local_result == -1) + { + return -1; + } + + int ones = 1; + for (int j = long_index; j >= 1; j--) + { + ones &= (~*--operand == 0); + } + + return add_safe(mul_safe(ones, add_safe(local_result, mul_safe(long_index, bits_per_uint64))), ones, -1); + } + + inline void filter_highbits_uint(std::uint64_t *operand, std::size_t uint64_count, int bit_count) + { + std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64); +#ifdef SEAL_DEBUG + if (!operand && uint64_count) + { + throw std::invalid_argument("operand"); + } + if (bit_count < 0 || unsigned_gt(bit_count, mul_safe(uint64_count, bits_per_uint64_sz))) + { + throw std::invalid_argument("bit_count"); + } +#endif + if (unsigned_eq(bit_count, mul_safe(uint64_count, bits_per_uint64_sz))) + { + return; + } + int uint64_index = bit_count / bits_per_uint64; + int subbit_index = bit_count - uint64_index * bits_per_uint64; + operand += uint64_index; + *operand++ &= (std::uint64_t(1) << subbit_index) - 1; + for (int long_index = uint64_index + 1; unsigned_lt(long_index, uint64_count); long_index++) + { + *operand++ = 0; + } + } + + SEAL_NODISCARD inline auto duplicate_uint_if_needed( + const std::uint64_t *input, std::size_t uint64_count, std::size_t new_uint64_count, bool force, + MemoryPool &pool) + { +#ifdef SEAL_DEBUG + if (!input && uint64_count) + { + throw std::invalid_argument("uint"); + } +#endif + if (!force && uint64_count >= new_uint64_count) + { + return ConstPointer<std::uint64_t>::Aliasing(input); + } + + auto allocation(allocate<std::uint64_t>(new_uint64_count, pool)); + set_uint_uint(input, uint64_count, new_uint64_count, allocation.get()); + return ConstPointer<std::uint64_t>(std::move(allocation)); + } + + SEAL_NODISCARD inline int compare_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { +#ifdef SEAL_DEBUG + if (!operand1 && uint64_count) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && uint64_count) + { + throw std::invalid_argument("operand2"); + } +#endif + int result = 0; + operand1 += uint64_count - 1; + operand2 += uint64_count - 1; + + for (; (result == 0) && uint64_count--; operand1--, operand2--) + { + result = (*operand1 > *operand2) - (*operand1 < *operand2); + } + return result; + } + + SEAL_NODISCARD inline int compare_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { +#ifdef SEAL_DEBUG + if (!operand1 && operand1_uint64_count) + { + throw std::invalid_argument("operand1"); + } + if (!operand2 && operand2_uint64_count) + { + throw std::invalid_argument("operand2"); + } +#endif + int result = 0; + operand1 += operand1_uint64_count - 1; + operand2 += operand2_uint64_count - 1; + + std::size_t min_uint64_count = std::min(operand1_uint64_count, operand2_uint64_count); + + operand1_uint64_count -= min_uint64_count; + for (; (result == 0) && operand1_uint64_count--; operand1--) + { + result = (*operand1 > 0); + } + + operand2_uint64_count -= min_uint64_count; + for (; (result == 0) && operand2_uint64_count--; operand2--) + { + result = -(*operand2 > 0); + } + + for (; (result == 0) && min_uint64_count--; operand1--, operand2--) + { + result = (*operand1 > *operand2) - (*operand1 < *operand2); + } + return result; + } + + SEAL_NODISCARD inline bool is_greater_than_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) > 0; + } + + SEAL_NODISCARD inline bool is_greater_than_or_equal_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) >= 0; + } + + SEAL_NODISCARD inline bool is_less_than_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) < 0; + } + + SEAL_NODISCARD inline bool is_less_than_or_equal_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) <= 0; + } + + SEAL_NODISCARD inline bool is_equal_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) == 0; + } + + SEAL_NODISCARD inline bool is_not_equal_uint_uint( + const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count) + { + return compare_uint_uint(operand1, operand2, uint64_count) != 0; + } + + SEAL_NODISCARD inline bool is_greater_than_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) > 0; + } + + SEAL_NODISCARD inline bool is_greater_than_or_equal_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) >= 0; + } + + SEAL_NODISCARD inline bool is_less_than_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) < 0; + } + + SEAL_NODISCARD inline bool is_less_than_or_equal_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) <= 0; + } + + SEAL_NODISCARD inline bool is_equal_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) == 0; + } + + SEAL_NODISCARD inline bool is_not_equal_uint_uint( + const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2, + std::size_t operand2_uint64_count) + { + return compare_uint_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) != 0; + } + + SEAL_NODISCARD inline std::uint64_t hamming_weight(std::uint64_t value) + { + std::uint64_t res = 0; + while (value) + { + res++; + value &= value - 1; + } + return res; + } + + SEAL_NODISCARD inline std::uint64_t hamming_weight_split(std::uint64_t value) + { + std::uint64_t hwx = hamming_weight(value); + std::uint64_t target = (hwx + 1) >> 1; + std::uint64_t now = 0; + std::uint64_t result = 0; + + for (int i = 0; i < bits_per_uint64; i++) + { + std::uint64_t xbit = value & 1; + value = value >> 1; + now += xbit; + result += (xbit << i); + + if (now >= target) + { + break; + } + } + return result; + } + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/util/ztools.cpp b/bigpiseal3.5.1/native/src/seal/util/ztools.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46b0360c7d2f80e137d40bd45e4c1ebe8b034aac --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/ztools.cpp @@ -0,0 +1,505 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/defines.h" + +#ifdef SEAL_USE_ZLIB + +#include "seal/serialization.h" +#include "seal/util/pointer.h" +#include "seal/util/ztools.h" +#include <cmath> +#include <cstddef> +#include <cstring> +#include <limits> +#include <unordered_map> +#include <zlib.h> + +using namespace std; + +namespace seal +{ + namespace util + { + namespace ztools + { + namespace + { + // Size for an internal buffer allocated for inflate and deflate + constexpr size_t buffer_size = 256 * 1024; + + constexpr double deflate_buffer_expansion_factor = 1.3; + + // The output size in a single deflate round cannot exceed 4 GB so we need to invert the deflateBound + // inequality to find an upper bound for the input size. + constexpr size_t process_bytes_out_max = static_cast<size_t>(numeric_limits<uInt>::max()); + + // If input size is at most process_bytes_in_max, we can complete the deflate algorithm in a single call + // to deflate (deflateBound(process_bytes_in_max) is at most 4 GB). + constexpr size_t process_bytes_in_max = process_bytes_out_max - (process_bytes_out_max >> 10) - 17; + + class PointerStorage + { + public: + PointerStorage(MemoryPoolHandle pool) : pool_(pool) + {} + + void *allocate(size_t size) + { + auto ptr = util::allocate<SEAL_BYTE>(size, pool_); + void *addr = reinterpret_cast<void *>(ptr.get()); + ptr_storage_[addr] = move(ptr); + return addr; + } + + void free(void *addr) + { + ptr_storage_.erase(addr); + } + + private: + MemoryPoolHandle pool_; + + unordered_map<void *, Pointer<SEAL_BYTE>> ptr_storage_; + }; + + // Custom implementation for zlib zalloc + void *alloc_impl(voidpf ptr_storage, uInt items, uInt size) + { + try + { + size_t total_size = safe_cast<size_t>(mul_safe(items, size)); + return reinterpret_cast<PointerStorage *>(ptr_storage)->allocate(total_size); + } + catch (const invalid_argument &) + { + // Allocation failed due to too large allocation size + return Z_NULL; + } + catch (const bad_alloc &) + { + // Allocation failed due to out of memory error + return Z_NULL; + } + catch (const logic_error &) + { + // Allocation failed due to data type overflow + return Z_NULL; + } + catch (const runtime_error &) + { + // Allocation failed due to too many pools allocated + return Z_NULL; + } + } + + // Custom implementation for zlib zfree + void free_impl(voidpf ptr_storage, void *addr) + { + reinterpret_cast<PointerStorage *>(ptr_storage)->free(addr); + } + } // namespace + + int deflate_array(const IntArray<SEAL_BYTE> &in, IntArray<SEAL_BYTE> &out, MemoryPoolHandle pool) + { + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + // We need size_t to be at least as large as uInt + static_assert(numeric_limits<uInt>::max() <= numeric_limits<size_t>::max(), ""); + + size_t in_size = in.size(); + int result, flush; + int level = Z_DEFAULT_COMPRESSION; + + int pending_bits; + unsigned pending_bytes; + + z_stream zstream; + zstream.data_type = Z_BINARY; + + PointerStorage ptr_storage(pool); + zstream.zalloc = alloc_impl; + zstream.zfree = free_impl; + zstream.opaque = reinterpret_cast<voidpf>(&ptr_storage); + + result = deflateInit(&zstream, level); + if (result != Z_OK) + { + deflateEnd(&zstream); + return result; + } + + // Set the output buffer size to the deflate size bound; for small input buffers this will guarantee + // deflate to immediately return Z_STREAM_END + size_t out_size = deflate_size_bound(in_size); + out.resize(out_size, false); + + // How much data was finally produced + size_t final_out_size = 0; + + // Set the input and output pointers; deflate moves these automatically + zstream.next_in = reinterpret_cast<unsigned char *>(const_cast<SEAL_BYTE *>(in.cbegin())); + zstream.next_out = reinterpret_cast<unsigned char *>(out.begin()); + + do + { + size_t process_bytes_in = min<size_t>(in_size, process_bytes_in_max); + zstream.avail_in = static_cast<uInt>(process_bytes_in); + + // Number of bytes left after this round; if we are at the end set flush accordingly + in_size -= process_bytes_in; + flush = in_size ? Z_NO_FLUSH : Z_FINISH; + + do + { + // If out_size is zero, then we need to reallocate and increase the size + if (!out_size) + { + out_size = safe_cast<size_t>( + ceil(safe_cast<double>(out.size()) * deflate_buffer_expansion_factor)); + out.resize(out_size, false); + + // Set the next_out pointer correctly to the new allocation and shift by the number of bytes + // already written + zstream.next_out = reinterpret_cast<unsigned char *>(out.begin()) + final_out_size; + out_size -= final_out_size; + } + + size_t process_bytes_out = min<size_t>(out_size, process_bytes_out_max); + zstream.avail_out = static_cast<uInt>(process_bytes_out); + + result = deflate(&zstream, flush); +#ifdef SEAL_DEBUG + // Intermediate rounds should return Z_OK and last should return Z_STREAM_END + if (result != Z_OK && result != Z_STREAM_END) + { + // Something went wrong so finish up here + deflateEnd(&zstream); + return result; + } +#endif + // Update out_size + process_bytes_out -= static_cast<size_t>(zstream.avail_out); + out_size -= process_bytes_out; + final_out_size += process_bytes_out; + + // Is there pending output in the internal buffers? If so, we need to call deflate again + deflatePending(&zstream, &pending_bytes, &pending_bits); + } while (!zstream.avail_out && (pending_bits || pending_bytes)); + } while (in_size); + + // Now resize out to the right size + out.resize(final_out_size); + + deflateEnd(&zstream); + return Z_OK; + } + + int deflate_array_inplace(IntArray<SEAL_BYTE> &in, MemoryPoolHandle pool) + { + if (!pool) + { + throw invalid_argument("pool is uninitialized"); + } + + // We need size_t to be at least as large as uInt + static_assert(numeric_limits<uInt>::max() <= numeric_limits<size_t>::max(), ""); + + int result, flush; + int level = Z_DEFAULT_COMPRESSION; + + int pending_bits; + unsigned pending_bytes; + + z_stream zstream; + zstream.data_type = Z_BINARY; + + PointerStorage ptr_storage(pool); + zstream.zalloc = alloc_impl; + zstream.zfree = free_impl; + zstream.opaque = reinterpret_cast<voidpf>(&ptr_storage); + + result = deflateInit(&zstream, level); + if (result != Z_OK) + { + deflateEnd(&zstream); + return result; + } + + // How much data was finally produced + size_t bytes_written_to_in = 0; + size_t bytes_read_from_in = 0; + + // Allocate a temporary buffer for output + auto temp_out = IntArray<SEAL_BYTE>(buffer_size, pool); + + // Where we are writing output now; start writing to the temporary buffer + SEAL_BYTE *out_head = temp_out.begin(); + + // How much of input do we have left to process + size_t in_size = in.size(); + + // Size of the current output buffer + size_t out_size = buffer_size; + + // Are we overwriting in at this time? + bool out_is_in = false; + + // Set the input and output pointers for the initial block + zstream.next_in = reinterpret_cast<unsigned char *>(const_cast<SEAL_BYTE *>(in.cbegin())); + zstream.next_out = reinterpret_cast<unsigned char *>(out_head); + + do + { + // The number of bytes we can read at a time is capped by process_bytes_in_max + size_t process_bytes_in = min<size_t>(in_size, process_bytes_in_max); + zstream.avail_in = static_cast<uInt>(process_bytes_in); + + // Number of bytes left after this round; if we are at the end set flush accordingly + in_size -= process_bytes_in; + flush = in_size ? Z_NO_FLUSH : Z_FINISH; + + // Loop while we have input left + do + { + // First ensure we have output space + while (!out_size) + { + // We are out of output buffer + if (!out_is_in) + { + // If we have been writing to the temporary buffer, then see if we can copy to in + size_t temp_out_size = temp_out.size(); + if (bytes_read_from_in >= bytes_written_to_in + temp_out_size) + { + // All is good; we can copy over the buffer to in + out_head = in.begin() + bytes_written_to_in; + memcpy(out_head, temp_out.cbegin(), temp_out_size); + out_head += temp_out_size; + bytes_written_to_in += temp_out_size; + + // For next writes, try to write to in + out_is_in = true; + + // Reset out_size + out_size = bytes_read_from_in - bytes_written_to_in; + + // Reset temp_out to have size buffer_size + temp_out.resize(buffer_size, false); + } + else + { + // We don't have enough room to copy to in; instead, resize temp_out and continue + // using it, hoping that the situation will change + out_size = temp_out_size + buffer_size; + temp_out.resize(out_size, false); + out_size = buffer_size; + out_head = temp_out.begin() + temp_out_size; + } + } + else + { + // We are writing to in but are out of space; switch to temp_out for the moment + out_is_in = false; + + // Set size and pointer + out_size = temp_out.size(); + out_head = temp_out.begin(); + } + } + + // Set the stream output + zstream.next_out = reinterpret_cast<unsigned char *>(out_head); + + // Cap the out size to process_bytes_out_max + size_t process_bytes_out = min<size_t>(out_size, process_bytes_out_max); + zstream.avail_out = static_cast<uInt>(process_bytes_out); + + result = deflate(&zstream, flush); +#ifdef SEAL_DEBUG + // Intermediate rounds should return Z_OK and last should return Z_STREAM_END + if (result != Z_OK && result != Z_STREAM_END) + { + // Something went wrong so finish up here + deflateEnd(&zstream); + return result; + } +#endif + // True number of bytes written + process_bytes_out = + static_cast<size_t>(reinterpret_cast<SEAL_BYTE *>(zstream.next_out) - out_head); + out_size -= process_bytes_out; + out_head += process_bytes_out; + + // Number of bytes read + bytes_read_from_in += process_bytes_in - zstream.avail_in; + + if (out_is_in) + { + // Update number of bytes written to in + bytes_written_to_in += process_bytes_out; + } + + // Is there pending output in the internal buffers? If so, we need to call deflate again + deflatePending(&zstream, &pending_bytes, &pending_bits); + } while ((flush == Z_FINISH && result == Z_OK) || + (!zstream.avail_out && (pending_bits || pending_bytes))); + } while (in_size); + + if (!out_is_in) + { + // We are done but the last writes were to temp_out + size_t bytes_in_temp_out = temp_out.size() - out_size; + + // Resize in to fit the remaining data + in.resize(bytes_written_to_in + bytes_in_temp_out); + + // Copy over the buffer to in + out_head = in.begin() + bytes_written_to_in; + memcpy(out_head, temp_out.cbegin(), bytes_in_temp_out); + bytes_written_to_in += bytes_in_temp_out; + } + else + { + // Just resize in to the right size + in.resize(bytes_written_to_in); + } + + deflateEnd(&zstream); + return Z_OK; + } + + int inflate_stream(istream &in_stream, streamoff in_size, ostream &out_stream, MemoryPoolHandle pool) + { + // Clear the exception masks; this function returns an error code + // on failure rather than throws an IO exception. + auto in_stream_except_mask = in_stream.exceptions(); + in_stream.exceptions(ios_base::goodbit); + auto out_stream_except_mask = out_stream.exceptions(); + out_stream.exceptions(ios_base::goodbit); + + auto in_stream_start_pos = in_stream.tellg(); + auto in_stream_end_pos = in_stream_start_pos + in_size; + + int result; + size_t have; + + auto in(allocate<unsigned char>(buffer_size, pool)); + auto out(allocate<unsigned char>(buffer_size, pool)); + + z_stream zstream; + zstream.data_type = Z_BINARY; + + PointerStorage ptr_storage(pool); + zstream.zalloc = alloc_impl; + zstream.zfree = free_impl; + zstream.opaque = reinterpret_cast<voidpf>(&ptr_storage); + + zstream.avail_in = 0; + zstream.next_in = Z_NULL; + result = inflateInit(&zstream); + if (result != Z_OK) + { + in_stream.exceptions(in_stream_except_mask); + out_stream.exceptions(out_stream_except_mask); + return result; + } + + do + { + if (!in_stream.read( + reinterpret_cast<char *>(in.get()), + min(static_cast<streamoff>(buffer_size), in_stream_end_pos - in_stream.tellg()))) + { + inflateEnd(&zstream); + in_stream.exceptions(in_stream_except_mask); + out_stream.exceptions(out_stream_except_mask); + return Z_ERRNO; + } + if (!(zstream.avail_in = static_cast<decltype(zstream.avail_in)>(in_stream.gcount()))) + { + break; + } + zstream.next_in = in.get(); + + do + { + zstream.avail_out = buffer_size; + zstream.next_out = out.get(); + result = inflate(&zstream, Z_NO_FLUSH); + + switch (result) + { + case Z_NEED_DICT: + result = Z_DATA_ERROR; + /* fall through */ + + case Z_DATA_ERROR: + /* fall through */ + + case Z_MEM_ERROR: + inflateEnd(&zstream); + in_stream.exceptions(in_stream_except_mask); + out_stream.exceptions(out_stream_except_mask); + return result; + } + + have = buffer_size - static_cast<size_t>(zstream.avail_out); + + if (!out_stream.write(reinterpret_cast<const char *>(out.get()), static_cast<streamsize>(have))) + { + inflateEnd(&zstream); + in_stream.exceptions(in_stream_except_mask); + out_stream.exceptions(out_stream_except_mask); + return Z_ERRNO; + } + } while (!zstream.avail_out); + } while (result != Z_STREAM_END); + + inflateEnd(&zstream); + in_stream.exceptions(in_stream_except_mask); + out_stream.exceptions(out_stream_except_mask); + return result == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; + } + + void write_header_deflate_buffer( + IntArray<SEAL_BYTE> &in, void *header_ptr, ostream &out_stream, MemoryPoolHandle pool) + { + Serialization::SEALHeader &header = *reinterpret_cast<Serialization::SEALHeader *>(header_ptr); + + auto ret = deflate_array_inplace(in, move(pool)); + if (Z_OK != ret) + { + throw logic_error("deflate failed"); + } + + // Populate the header + header.compr_mode = compr_mode_type::deflate; + header.size = static_cast<uint64_t>(add_safe(sizeof(Serialization::SEALHeader), in.size())); + + auto old_except_mask = out_stream.exceptions(); + try + { + // Throw exceptions on ios_base::badbit and ios_base::failbit + out_stream.exceptions(ios_base::badbit | ios_base::failbit); + + // Write the header and the data + out_stream.write(reinterpret_cast<const char *>(&header), sizeof(Serialization::SEALHeader)); + out_stream.write(reinterpret_cast<const char *>(in.cbegin()), safe_cast<streamsize>(in.size())); + } + catch (...) + { + out_stream.exceptions(old_except_mask); + throw; + } + + out_stream.exceptions(old_except_mask); + } + } // namespace ztools + } // namespace util +} // namespace seal + +#endif diff --git a/bigpiseal3.5.1/native/src/seal/util/ztools.h b/bigpiseal3.5.1/native/src/seal/util/ztools.h new file mode 100644 index 0000000000000000000000000000000000000000..51c79de5396da5526ee008d8aff07007b35236a4 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/util/ztools.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/util/defines.h" +#include <ios> +#include <iostream> + +namespace seal +{ + namespace util + { + namespace ztools + { + /** + Compresses data in the given buffer, completes the given SEALHeader + by writing in the size of the output and setting the compression mode + to compr_mode_type::deflate, and finally writes the SEALHeader followed + by the compressed data in the given stream. + + @param[in] in The buffer to compress + @param[in] in_size The size of the buffer to compress in bytes + @param[out] header A pointer to a SEALHeader instance matching the output + of the compression + @param[out] out_stream The stream to write to + @param[in] pool The MemoryPoolHandle pointing to a valid memory pool + @throws std::invalid_argument if pool is uninitialized + @throws std::logic_error if compression failed + */ + void write_header_deflate_buffer( + IntArray<SEAL_BYTE> &in, void *header_ptr, std::ostream &out_stream, MemoryPoolHandle pool); + + int deflate_array(const IntArray<SEAL_BYTE> &in, IntArray<SEAL_BYTE> &out, MemoryPoolHandle pool); + + int deflate_array_inplace(IntArray<SEAL_BYTE> &in, MemoryPoolHandle pool); + + int inflate_stream( + std::istream &in_stream, std::streamoff in_size, std::ostream &out_stream, MemoryPoolHandle pool); + + template <typename SizeT> + SEAL_NODISCARD SizeT deflate_size_bound(SizeT in_size) + { + return util::add_safe<SizeT>(in_size, in_size >> 12, in_size >> 14, in_size >> 25, SizeT(17)); + } + } // namespace ztools + } // namespace util +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/valcheck.cpp b/bigpiseal3.5.1/native/src/seal/valcheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..982229f5bd243f200a3aeb3e34669ef91b884ca2 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/valcheck.cpp @@ -0,0 +1,424 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ciphertext.h" +#include "seal/galoiskeys.h" +#include "seal/kswitchkeys.h" +#include "seal/plaintext.h" +#include "seal/publickey.h" +#include "seal/relinkeys.h" +#include "seal/secretkey.h" +#include "seal/valcheck.h" +#include "seal/util/common.h" +#include "seal/util/defines.h" + +using namespace std; +using namespace seal::util; + +namespace seal +{ + bool is_metadata_valid_for(const Plaintext &in, shared_ptr<const SEALContext> context, bool allow_pure_key_levels) + { + // Verify parameters + if (!context || !context->parameters_set()) + { + return false; + } + + if (in.is_ntt_form()) + { + // Are the parameters valid for the plaintext? + auto context_data_ptr = context->get_context_data(in.parms_id()); + if (!context_data_ptr) + { + return false; + } + + // Check whether the parms_id is in the pure key range + bool is_parms_pure_key = context_data_ptr->chain_index() > context->first_context_data()->chain_index(); + if (!allow_pure_key_levels && is_parms_pure_key) + { + return false; + } + + auto &parms = context_data_ptr->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + + // Check that coeff_count is appropriately set + if (mul_safe(coeff_modulus.size(), poly_modulus_degree) != in.coeff_count()) + { + return false; + } + } + else + { + auto &parms = context->first_context_data()->parms(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + if (in.coeff_count() > poly_modulus_degree) + { + return false; + } + } + + return true; + } + + bool is_metadata_valid_for(const Ciphertext &in, shared_ptr<const SEALContext> context, bool allow_pure_key_levels) + { + // Verify parameters + if (!context || !context->parameters_set()) + { + return false; + } + + // Are the parameters valid for the ciphertext? + auto context_data_ptr = context->get_context_data(in.parms_id()); + if (!context_data_ptr) + { + return false; + } + + // Check whether the parms_id is in the pure key range + bool is_parms_pure_key = context_data_ptr->chain_index() > context->first_context_data()->chain_index(); + if (!allow_pure_key_levels && is_parms_pure_key) + { + return false; + } + + // Check that the metadata matches + auto &coeff_modulus = context_data_ptr->parms().coeff_modulus(); + size_t poly_modulus_degree = context_data_ptr->parms().poly_modulus_degree(); + if ((coeff_modulus.size() != in.coeff_modulus_size()) || (poly_modulus_degree != in.poly_modulus_degree())) + { + return false; + } + + // Check that size is either 0 or within right bounds + auto size = in.size(); + if ((size < SEAL_CIPHERTEXT_SIZE_MIN && size != 0) || size > SEAL_CIPHERTEXT_SIZE_MAX) + { + return false; + } + + return true; + } + + bool is_metadata_valid_for(const SecretKey &in, shared_ptr<const SEALContext> context) + { + // Note: we check the underlying Plaintext and allow pure key levels in + // this check. Then, also need to check that the parms_id matches the + // key level parms_id; this also means the Plaintext is in NTT form. + auto key_parms_id = context->key_parms_id(); + return is_metadata_valid_for(in.data(), move(context), true) && (in.parms_id() == key_parms_id); + } + + bool is_metadata_valid_for(const PublicKey &in, shared_ptr<const SEALContext> context) + { + // Note: we check the underlying Ciphertext and allow pure key levels in + // this check. Then, also need to check that the parms_id matches the + // key level parms_id, that the Ciphertext is in NTT form, and that the + // size is minimal (i.e., SEAL_CIPHERTEXT_SIZE_MIN). + auto key_parms_id = context->key_parms_id(); + return is_metadata_valid_for(in.data(), move(context), true) && in.data().is_ntt_form() && + (in.parms_id() == key_parms_id) && (in.data().size() == SEAL_CIPHERTEXT_SIZE_MIN); + } + + bool is_metadata_valid_for(const KSwitchKeys &in, shared_ptr<const SEALContext> context) + { + // Verify parameters + if (!context || !context->parameters_set()) + { + return false; + } + + // Are the parameters valid and at key level? + if (in.parms_id() != context->key_parms_id()) + { + return false; + } + + size_t decomp_mod_count = context->first_context_data()->parms().coeff_modulus().size(); + for (auto &a : in.data()) + { + // Check that each highest level component has right size + if (a.size() && (a.size() != decomp_mod_count)) + { + return false; + } + for (auto &b : a) + { + // Check that b is a valid public key (metadata only); this also + // checks that its parms_id matches key_parms_id. + if (!is_metadata_valid_for(b, context)) + { + return false; + } + } + } + + return true; + } + + bool is_metadata_valid_for(const RelinKeys &in, shared_ptr<const SEALContext> context) + { + // Check that the size is within bounds. + bool size_check = + !in.size() || (in.size() <= SEAL_CIPHERTEXT_SIZE_MAX - 2 && in.size() >= SEAL_CIPHERTEXT_SIZE_MIN - 2); + return is_metadata_valid_for(static_cast<const KSwitchKeys &>(in), move(context)) && size_check; + } + + bool is_metadata_valid_for(const GaloisKeys &in, shared_ptr<const SEALContext> context) + { + // Check the metadata; then we know context is OK + bool metadata_check = is_metadata_valid_for(static_cast<const KSwitchKeys &>(in), context); + bool size_check = !in.size() || in.size() <= context->key_context_data()->parms().poly_modulus_degree(); + return metadata_check && size_check; + } + + bool is_buffer_valid(const Plaintext &in) + { + if (in.coeff_count() != in.int_array().size()) + { + return false; + } + + return true; + } + + bool is_buffer_valid(const Ciphertext &in) + { + // Check that the buffer size is correct + if (in.int_array().size() != mul_safe(in.size(), in.coeff_modulus_size(), in.poly_modulus_degree())) + { + return false; + } + + return true; + } + + bool is_buffer_valid(const SecretKey &in) + { + return is_buffer_valid(in.data()); + } + + bool is_buffer_valid(const PublicKey &in) + { + return is_buffer_valid(in.data()); + } + + bool is_buffer_valid(const KSwitchKeys &in) + { + for (auto &a : in.data()) + { + for (auto &b : a) + { + if (!is_buffer_valid(b)) + { + return false; + } + } + } + + return true; + } + + bool is_buffer_valid(const RelinKeys &in) + { + return is_buffer_valid(static_cast<const KSwitchKeys &>(in)); + } + + bool is_buffer_valid(const GaloisKeys &in) + { + return is_buffer_valid(static_cast<const KSwitchKeys &>(in)); + } + + bool is_data_valid_for(const Plaintext &in, shared_ptr<const SEALContext> context) + { + // Check metadata + if (!is_metadata_valid_for(in, context)) + { + return false; + } + + // Check the data + if (in.is_ntt_form()) + { + auto context_data_ptr = context->get_context_data(in.parms_id()); + auto &parms = context_data_ptr->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + + const Plaintext::pt_coeff_type *ptr = in.data(); + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t modulus = coeff_modulus[j].value(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + for (; poly_modulus_degree--; ptr++) + { + if (*ptr >= modulus) + { + return false; + } + } + } + } + else + { + auto &parms = context->first_context_data()->parms(); + uint64_t modulus = parms.plain_modulus().value(); + const Plaintext::pt_coeff_type *ptr = in.data(); + auto size = in.coeff_count(); + for (size_t k = 0; k < size; k++, ptr++) + { + if (*ptr >= modulus) + { + return false; + } + } + } + + return true; + } + + bool is_data_valid_for(const Ciphertext &in, shared_ptr<const SEALContext> context) + { + // Check metadata + if (!is_metadata_valid_for(in, context)) + { + return false; + } + + // Check the data + auto context_data_ptr = context->get_context_data(in.parms_id()); + const auto &coeff_modulus = context_data_ptr->parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + + const Ciphertext::ct_coeff_type *ptr = in.data(); + auto size = in.size(); + + for (size_t i = 0; i < size; i++) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t modulus = coeff_modulus[j].value(); + auto poly_modulus_degree = in.poly_modulus_degree(); + for (; poly_modulus_degree--; ptr++) + { + if (*ptr >= modulus) + { + return false; + } + } + } + } + + return true; + } + + bool is_data_valid_for(const SecretKey &in, shared_ptr<const SEALContext> context) + { + // Check metadata + if (!is_metadata_valid_for(in, context)) + { + return false; + } + + // Check the data + auto context_data_ptr = context->key_context_data(); + auto &parms = context_data_ptr->parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + + const Plaintext::pt_coeff_type *ptr = in.data().data(); + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t modulus = coeff_modulus[j].value(); + size_t poly_modulus_degree = parms.poly_modulus_degree(); + for (; poly_modulus_degree--; ptr++) + { + if (*ptr >= modulus) + { + return false; + } + } + } + + return true; + } + + bool is_data_valid_for(const PublicKey &in, shared_ptr<const SEALContext> context) + { + // Check metadata + if (!is_metadata_valid_for(in, context)) + { + return false; + } + + // Check the data + auto context_data_ptr = context->key_context_data(); + const auto &coeff_modulus = context_data_ptr->parms().coeff_modulus(); + size_t coeff_modulus_size = coeff_modulus.size(); + + const Ciphertext::ct_coeff_type *ptr = in.data().data(); + auto size = in.data().size(); + + for (size_t i = 0; i < size; i++) + { + for (size_t j = 0; j < coeff_modulus_size; j++) + { + uint64_t modulus = coeff_modulus[j].value(); + auto poly_modulus_degree = in.data().poly_modulus_degree(); + for (; poly_modulus_degree--; ptr++) + { + if (*ptr >= modulus) + { + return false; + } + } + } + } + + return true; + } + + bool is_data_valid_for(const KSwitchKeys &in, shared_ptr<const SEALContext> context) + { + // Verify parameters + if (!context || !context->parameters_set()) + { + return false; + } + + // Are the parameters valid for given relinearization keys? + if (in.parms_id() != context->key_parms_id()) + { + return false; + } + + for (auto &a : in.data()) + { + for (auto &b : a) + { + // Check that b is a valid public key; this also checks that its + // parms_id matches key_parms_id. + if (!is_data_valid_for(b, context)) + { + return false; + } + } + } + + return true; + } + + bool is_data_valid_for(const RelinKeys &in, shared_ptr<const SEALContext> context) + { + return is_data_valid_for(static_cast<const KSwitchKeys &>(in), move(context)); + } + + bool is_data_valid_for(const GaloisKeys &in, shared_ptr<const SEALContext> context) + { + return is_data_valid_for(static_cast<const KSwitchKeys &>(in), move(context)); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/src/seal/valcheck.h b/bigpiseal3.5.1/native/src/seal/valcheck.h new file mode 100644 index 0000000000000000000000000000000000000000..2b31aed861c0938c2a37a69414ba8005b9b38b05 --- /dev/null +++ b/bigpiseal3.5.1/native/src/seal/valcheck.h @@ -0,0 +1,375 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "seal/context.h" +#include "seal/util/defines.h" +#include <memory> + +namespace seal +{ + class Plaintext; + class Ciphertext; + class SecretKey; + class PublicKey; + class KSwitchKeys; + class RelinKeys; + class GaloisKeys; + + /** + Check whether the given plaintext is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + plaintext data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + plaintext data itself. + + @param[in] in The plaintext to check + @param[in] context The SEALContext + @param[in] allow_pure_key_levels Determines whether pure key levels (i.e., + non-data levels) should be considered valid + */ + SEAL_NODISCARD bool is_metadata_valid_for( + const Plaintext &in, std::shared_ptr<const SEALContext> context, bool allow_pure_key_levels = false); + + /** + Check whether the given ciphertext is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + ciphertext data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + ciphertext data itself. + + @param[in] in The ciphertext to check + @param[in] context The SEALContext + @param[in] allow_pure_key_levels Determines whether pure key levels (i.e., + non-data levels) should be considered valid + */ + SEAL_NODISCARD bool is_metadata_valid_for( + const Ciphertext &in, std::shared_ptr<const SEALContext> context, bool allow_pure_key_levels = false); + + /** + Check whether the given secret key is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + secret key data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + secret key data itself. + + @param[in] in The secret key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_metadata_valid_for(const SecretKey &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given public key is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + public key data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + public key data itself. + + @param[in] in The public key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_metadata_valid_for(const PublicKey &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given KSwitchKeys is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + KSwitchKeys data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + KSwitchKeys data itself. + + @param[in] in The KSwitchKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_metadata_valid_for(const KSwitchKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given RelinKeys is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + RelinKeys data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + RelinKeys data itself. + + @param[in] in The RelinKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_metadata_valid_for(const RelinKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given GaloisKeys is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + GaloisKeys data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function only checks the metadata and not the + GaloisKeys data itself. + + @param[in] in The GaloisKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_metadata_valid_for(const GaloisKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given plaintext data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the plaintext data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the plaintext data itself. + + @param[in] in The plaintext to check + */ + SEAL_NODISCARD bool is_buffer_valid(const Plaintext &in); + + /** + Check whether the given ciphertext data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the ciphertext data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the ciphertext data itself. + + @param[in] in The ciphertext to check + */ + SEAL_NODISCARD bool is_buffer_valid(const Ciphertext &in); + + /** + Check whether the given secret key data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the secret key data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the secret key data itself. + + @param[in] in The secret key to check + */ + SEAL_NODISCARD bool is_buffer_valid(const SecretKey &in); + + /** + Check whether the given public key data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the public key data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the public key data itself. + + @param[in] in The public key to check + */ + SEAL_NODISCARD bool is_buffer_valid(const PublicKey &in); + + /** + Check whether the given KSwitchKeys data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the KSwitchKeys data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the KSwitchKeys data itself. + + @param[in] in The KSwitchKeys to check + */ + SEAL_NODISCARD bool is_buffer_valid(const KSwitchKeys &in); + + /** + Check whether the given RelinKeys data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the RelinKeys data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the RelinKeys data itself. + + @param[in] in The RelinKeys to check + */ + SEAL_NODISCARD bool is_buffer_valid(const RelinKeys &in); + + /** + Check whether the given GaloisKeys data buffer is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the GaloisKeys data buffer does not match the SEALContext, this function + returns false. Otherwise, returns true. This function only checks the size of + the data buffer and not the GaloisKeys data itself. + + @param[in] in The GaloisKeys to check + */ + SEAL_NODISCARD bool is_buffer_valid(const GaloisKeys &in); + + /** + Check whether the given plaintext data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the plaintext data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire plaintext data buffer. + + @param[in] in The plaintext to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const Plaintext &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given ciphertext data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the ciphertext data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire ciphertext data buffer. + + @param[in] in The ciphertext to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const Ciphertext &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given secret key data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the secret key data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire secret key data buffer. + + @param[in] in The secret key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const SecretKey &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given public key data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the public key data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire public key data buffer. + + @param[in] in The public key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const PublicKey &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given KSwitchKeys data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the KSwitchKeys data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire KSwitchKeys data buffer. + + @param[in] in The KSwitchKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const KSwitchKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given RelinKeys data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the RelinKeys data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire RelinKeys data buffer. + + @param[in] in The RelinKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const RelinKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given GaloisKeys data is valid for a given SEALContext. + If the given SEALContext is not set, the encryption parameters are invalid, + or the GaloisKeys data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow, as it checks the + correctness of the entire GaloisKeys data buffer. + + @param[in] in The GaloisKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD bool is_data_valid_for(const GaloisKeys &in, std::shared_ptr<const SEALContext> context); + + /** + Check whether the given plaintext is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + plaintext data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire plaintext data buffer. + + @param[in] in The plaintext to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const Plaintext &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given ciphertext is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + ciphertext data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire ciphertext data buffer. + + @param[in] in The ciphertext to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const Ciphertext &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given secret key is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + secret key data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire secret key data buffer. + + @param[in] in The secret key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const SecretKey &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given public key is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + public key data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire public key data buffer. + + @param[in] in The public key to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const PublicKey &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given KSwitchKeys is valid for a given SEALContext. If + the given SEALContext is not set, the encryption parameters are invalid, + or the KSwitchKeys data does not match the SEALContext, this function returns + false. Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire KSwitchKeys data buffer. + + @param[in] in The KSwitchKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const KSwitchKeys &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given RelinKeys is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + RelinKeys data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire RelinKeys data buffer. + + @param[in] in The RelinKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const RelinKeys &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } + + /** + Check whether the given GaloisKeys is valid for a given SEALContext. If the + given SEALContext is not set, the encryption parameters are invalid, or the + GaloisKeys data does not match the SEALContext, this function returns false. + Otherwise, returns true. This function can be slow as it checks the validity + of all metadata and of the entire GaloisKeys data buffer. + + @param[in] in The GaloisKeys to check + @param[in] context The SEALContext + */ + SEAL_NODISCARD inline bool is_valid_for(const GaloisKeys &in, std::shared_ptr<const SEALContext> context) + { + return is_metadata_valid_for(in, context) && is_buffer_valid(in) && is_data_valid_for(in, context); + } +} // namespace seal diff --git a/bigpiseal3.5.1/native/tests/SEALTest.vcxproj b/bigpiseal3.5.1/native/tests/SEALTest.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..2e3c6ce71a010b98abb8016af44db2cbc1641a02 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/SEALTest.vcxproj @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + <ProjectName>SEALTest</ProjectName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings" /> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealtest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealtest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealtest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>$(ProjectDir)..\..\bin\$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir> + <TargetName>sealtest</TargetName> + </PropertyGroup> + <ItemGroup> + <ClCompile Include="seal\batchencoder.cpp" /> + <ClCompile Include="seal\biguint.cpp" /> + <ClCompile Include="seal\ciphertext.cpp" /> + <ClCompile Include="seal\ckks.cpp" /> + <ClCompile Include="seal\modulus.cpp" /> + <ClCompile Include="seal\context.cpp" /> + <ClCompile Include="seal\intencoder.cpp" /> + <ClCompile Include="seal\encryptionparams.cpp" /> + <ClCompile Include="seal\encryptor.cpp" /> + <ClCompile Include="seal\evaluator.cpp" /> + <ClCompile Include="seal\galoiskeys.cpp" /> + <ClCompile Include="seal\intarray.cpp" /> + <ClCompile Include="seal\keygenerator.cpp" /> + <ClCompile Include="seal\memorymanager.cpp" /> + <ClCompile Include="seal\plaintext.cpp" /> + <ClCompile Include="seal\publickey.cpp" /> + <ClCompile Include="seal\randomgen.cpp" /> + <ClCompile Include="seal\randomtostd.cpp" /> + <ClCompile Include="seal\relinkeys.cpp" /> + <ClCompile Include="seal\secretkey.cpp" /> + <ClCompile Include="seal\serialization.cpp" /> + <ClCompile Include="seal\testrunner.cpp" /> + <ClCompile Include="seal\util\clipnormal.cpp" /> + <ClCompile Include="seal\util\common.cpp" /> + <ClCompile Include="seal\util\galois.cpp" /> + <ClCompile Include="seal\util\hash.cpp" /> + <ClCompile Include="seal\util\iterator.cpp" /> + <ClCompile Include="seal\util\locks.cpp" /> + <ClCompile Include="seal\util\mempool.cpp" /> + <ClCompile Include="seal\util\numth.cpp" /> + <ClCompile Include="seal\util\polyarith.cpp" /> + <ClCompile Include="seal\util\polyarithmod.cpp" /> + <ClCompile Include="seal\util\polyarithsmallmod.cpp" /> + <ClCompile Include="seal\util\polycore.cpp" /> + <ClCompile Include="seal\util\rns.cpp" /> + <ClCompile Include="seal\util\ntt.cpp" /> + <ClCompile Include="seal\util\stringtouint64.cpp" /> + <ClCompile Include="seal\util\uint64tostring.cpp" /> + <ClCompile Include="seal\util\uintarith.cpp" /> + <ClCompile Include="seal\util\uintarithmod.cpp" /> + <ClCompile Include="seal\util\uintarithsmallmod.cpp" /> + <ClCompile Include="seal\util\uintcore.cpp" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <Text Include="seal\CMakeLists.txt" /> + <Text Include="seal\util\CMakeLists.txt" /> + </ItemGroup> + <ItemDefinitionGroup /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="..\..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets" Condition="Exists('..\..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" /> + </ImportGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <AdditionalIncludeDirectories>$(SolutionDir)/native/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <ControlFlowGuard>Guard</ControlFlowGuard> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <AdditionalIncludeDirectories>$(SolutionDir)/native/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <ControlFlowGuard>Guard</ControlFlowGuard> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <AdditionalIncludeDirectories>$(SolutionDir)/native/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <ControlFlowGuard>Guard</ControlFlowGuard> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <PreprocessorDefinitions>_ENABLE_EXTENDED_ALIGNED_STORAGE</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <AdditionalIncludeDirectories>$(SolutionDir)/native/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <ControlFlowGuard>Guard</ControlFlowGuard> + <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <AdditionalDependencies>seal.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ProjectDir)..\..\lib\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets'))" /> + </Target> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/SEALTest.vcxproj.filters b/bigpiseal3.5.1/native/tests/SEALTest.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..e798d3daedefa8157b39ea1a96de057335dd9b5b --- /dev/null +++ b/bigpiseal3.5.1/native/tests/SEALTest.vcxproj.filters @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Source Files\util"> + <UniqueIdentifier>{6c39d93e-a64a-44b3-95ca-ba22fd03ea17}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Other"> + <UniqueIdentifier>{c2fb4c08-c2b6-492e-872b-05c104d883e6}</UniqueIdentifier> + </Filter> + <Filter Include="Other\seal"> + <UniqueIdentifier>{ba659d9a-0bce-409b-8429-a60c1b9506ee}</UniqueIdentifier> + </Filter> + <Filter Include="Other\seal\util"> + <UniqueIdentifier>{86489695-28b4-44f1-8f0d-2637ecd43cb3}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="seal\biguint.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\intencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\encryptionparams.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\encryptor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\evaluator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\keygenerator.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\randomgen.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\randomtostd.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\util\clipnormal.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\common.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\mempool.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarith.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarithmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polycore.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\stringtouint64.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uint64tostring.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarith.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintcore.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\locks.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\relinkeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\memorymanager.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\context.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\secretkey.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\publickey.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\ciphertext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\util\galois.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\hash.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\numth.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\polyarithsmallmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarithmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\uintarithsmallmod.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\ntt.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\plaintext.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\modulus.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\galoiskeys.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\batchencoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\intarray.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\ckks.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\testrunner.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\serialization.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="seal\util\rns.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + <ClCompile Include="seal\util\iterator.cpp"> + <Filter>Source Files\util</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Text Include="seal\CMakeLists.txt"> + <Filter>Other\seal</Filter> + </Text> + <Text Include="seal\util\CMakeLists.txt"> + <Filter>Other\seal\util</Filter> + </Text> + </ItemGroup> + <ItemGroup> + <None Include="packages.config"> + <Filter>Other</Filter> + </None> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/packages.config b/bigpiseal3.5.1/native/tests/packages.config new file mode 100644 index 0000000000000000000000000000000000000000..3c6fe17f5449b9dc8186d2c8cd1bf12b0d12116c --- /dev/null +++ b/bigpiseal3.5.1/native/tests/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn" version="1.8.1" targetFramework="native" /> +</packages> \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/seal/CMakeLists.txt b/bigpiseal3.5.1/native/tests/seal/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..739525ff6b424c929d92871f773dabaf07929dfb --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +target_sources(sealtest + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/batchencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/biguint.cpp + ${CMAKE_CURRENT_LIST_DIR}/ciphertext.cpp + ${CMAKE_CURRENT_LIST_DIR}/ckks.cpp + ${CMAKE_CURRENT_LIST_DIR}/context.cpp + ${CMAKE_CURRENT_LIST_DIR}/intencoder.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptionparams.cpp + ${CMAKE_CURRENT_LIST_DIR}/encryptor.cpp + ${CMAKE_CURRENT_LIST_DIR}/evaluator.cpp + ${CMAKE_CURRENT_LIST_DIR}/galoiskeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/intarray.cpp + ${CMAKE_CURRENT_LIST_DIR}/keygenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/memorymanager.cpp + ${CMAKE_CURRENT_LIST_DIR}/modulus.cpp + ${CMAKE_CURRENT_LIST_DIR}/plaintext.cpp + ${CMAKE_CURRENT_LIST_DIR}/publickey.cpp + ${CMAKE_CURRENT_LIST_DIR}/randomgen.cpp + ${CMAKE_CURRENT_LIST_DIR}/randomtostd.cpp + ${CMAKE_CURRENT_LIST_DIR}/relinkeys.cpp + ${CMAKE_CURRENT_LIST_DIR}/secretkey.cpp + ${CMAKE_CURRENT_LIST_DIR}/serialization.cpp + ${CMAKE_CURRENT_LIST_DIR}/testrunner.cpp +) + +add_subdirectory(util) diff --git a/bigpiseal3.5.1/native/tests/seal/batchencoder.cpp b/bigpiseal3.5.1/native/tests/seal/batchencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..401afeea9fff11084e9bac004e6078a70831ea27 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/batchencoder.cpp @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/batchencoder.h" +#include "seal/context.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include <ctime> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(BatchEncoderTest, BatchUnbatchUIntVector) + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + parms.set_plain_modulus(257); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_TRUE(context->first_context_data()->qualifiers().using_batching); + + BatchEncoder batch_encoder(context); + ASSERT_EQ(64ULL, batch_encoder.slot_count()); + vector<uint64_t> plain_vec; + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + plain_vec.push_back(i); + } + + Plaintext plain; + batch_encoder.encode(plain_vec, plain); + vector<uint64_t> plain_vec2; + batch_encoder.decode(plain, plain_vec2); + ASSERT_TRUE(plain_vec == plain_vec2); + + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + plain_vec[i] = 5; + } + batch_encoder.encode(plain_vec, plain); + ASSERT_TRUE(plain.to_string() == "5"); + batch_encoder.decode(plain, plain_vec2); + ASSERT_TRUE(plain_vec == plain_vec2); + + vector<uint64_t> short_plain_vec; + for (size_t i = 0; i < 20; i++) + { + short_plain_vec.push_back(i); + } + batch_encoder.encode(short_plain_vec, plain); + vector<uint64_t> short_plain_vec2; + batch_encoder.decode(plain, short_plain_vec2); + ASSERT_EQ(20ULL, short_plain_vec.size()); + ASSERT_EQ(64ULL, short_plain_vec2.size()); + for (size_t i = 0; i < 20; i++) + { + ASSERT_EQ(short_plain_vec[i], short_plain_vec2[i]); + } + for (size_t i = 20; i < batch_encoder.slot_count(); i++) + { + ASSERT_EQ(0ULL, short_plain_vec2[i]); + } + } + + TEST(BatchEncoderTest, BatchUnbatchIntVector) + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + parms.set_plain_modulus(257); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_TRUE(context->first_context_data()->qualifiers().using_batching); + + BatchEncoder batch_encoder(context); + ASSERT_EQ(64ULL, batch_encoder.slot_count()); + vector<int64_t> plain_vec; + for (uint64_t i = 0; i < static_cast<uint64_t>(batch_encoder.slot_count()); i++) + { + plain_vec.push_back(static_cast<int64_t>(i * (1 - (i % 2) * 2))); + } + + Plaintext plain; + batch_encoder.encode(plain_vec, plain); + vector<int64_t> plain_vec2; + batch_encoder.decode(plain, plain_vec2); + ASSERT_TRUE(plain_vec == plain_vec2); + + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + plain_vec[i] = -5; + } + batch_encoder.encode(plain_vec, plain); + ASSERT_TRUE(plain.to_string() == "FC"); + batch_encoder.decode(plain, plain_vec2); + ASSERT_TRUE(plain_vec == plain_vec2); + + vector<int64_t> short_plain_vec; + for (int64_t i = 0; i < 20; i++) + { + short_plain_vec.push_back(i * (int64_t(1) - (i & 1) * 2)); + } + batch_encoder.encode(short_plain_vec, plain); + vector<int64_t> short_plain_vec2; + batch_encoder.decode(plain, short_plain_vec2); + ASSERT_EQ(20ULL, short_plain_vec.size()); + ASSERT_EQ(64ULL, short_plain_vec2.size()); + for (size_t i = 0; i < 20; i++) + { + ASSERT_EQ(short_plain_vec[i], short_plain_vec2[i]); + } + for (size_t i = 20; i < batch_encoder.slot_count(); i++) + { + ASSERT_EQ(0ULL, short_plain_vec2[i]); + } + } + + TEST(BatchEncoderTest, BatchUnbatchPlaintext) + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + parms.set_plain_modulus(257); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_TRUE(context->first_context_data()->qualifiers().using_batching); + + BatchEncoder batch_encoder(context); + ASSERT_EQ(64ULL, batch_encoder.slot_count()); + Plaintext plain(batch_encoder.slot_count()); + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + plain[i] = i; + } + + batch_encoder.encode(plain); + batch_encoder.decode(plain); + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + ASSERT_TRUE(plain[i] == i); + } + + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + plain[i] = 5; + } + batch_encoder.encode(plain); + ASSERT_TRUE(plain.to_string() == "5"); + batch_encoder.decode(plain); + for (size_t i = 0; i < batch_encoder.slot_count(); i++) + { + ASSERT_EQ(5ULL, plain[i]); + } + + Plaintext short_plain(20); + for (size_t i = 0; i < 20; i++) + { + short_plain[i] = i; + } + batch_encoder.encode(short_plain); + batch_encoder.decode(short_plain); + for (size_t i = 0; i < 20; i++) + { + ASSERT_TRUE(short_plain[i] == i); + } + for (size_t i = 20; i < batch_encoder.slot_count(); i++) + { + ASSERT_TRUE(short_plain[i] == 0); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/biguint.cpp b/bigpiseal3.5.1/native/tests/seal/biguint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c8153738671cb215aacc62682d8e09f34ecaa0e --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/biguint.cpp @@ -0,0 +1,378 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/biguint.h" +#include "seal/util/defines.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(BigUnsignedInt, EmptyBigUInt) + { + BigUInt uint; + ASSERT_EQ(0, uint.bit_count()); + ASSERT_TRUE(nullptr == uint.data()); + ASSERT_EQ(0ULL, uint.byte_count()); + ASSERT_EQ(0ULL, uint.uint64_count()); + ASSERT_EQ(0, uint.significant_bit_count()); + ASSERT_TRUE("0" == uint.to_string()); + ASSERT_TRUE(uint.is_zero()); + ASSERT_FALSE(uint.is_alias()); + uint.set_zero(); + + BigUInt uint2; + ASSERT_TRUE(uint == uint2); + ASSERT_FALSE(uint != uint2); + + uint.resize(1); + ASSERT_EQ(1, uint.bit_count()); + ASSERT_TRUE(nullptr != uint.data()); + ASSERT_FALSE(uint.is_alias()); + + uint.resize(0); + ASSERT_EQ(0, uint.bit_count()); + ASSERT_TRUE(nullptr == uint.data()); + ASSERT_FALSE(uint.is_alias()); + } + + TEST(BigUnsignedInt, BigUInt64Bits) + { + BigUInt uint(64); + ASSERT_EQ(64, uint.bit_count()); + ASSERT_TRUE(nullptr != uint.data()); + ASSERT_EQ(8ULL, uint.byte_count()); + ASSERT_EQ(1ULL, uint.uint64_count()); + ASSERT_EQ(0, uint.significant_bit_count()); + ASSERT_TRUE("0" == uint.to_string()); + ASSERT_TRUE(uint.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), *uint.data()); + ASSERT_TRUE(SEAL_BYTE(0) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[7]); + + uint = "1"; + ASSERT_EQ(1, uint.significant_bit_count()); + ASSERT_TRUE("1" == uint.to_string()); + ASSERT_FALSE(uint.is_zero()); + ASSERT_EQ(1ULL, *uint.data()); + ASSERT_TRUE(SEAL_BYTE(1) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[7]); + uint.set_zero(); + ASSERT_TRUE(uint.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), *uint.data()); + + uint = "7FFFFFFFFFFFFFFF"; + ASSERT_EQ(63, uint.significant_bit_count()); + ASSERT_TRUE("7FFFFFFFFFFFFFFF" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF), *uint.data()); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0x7F) == uint[7]); + ASSERT_FALSE(uint.is_zero()); + + uint = "FFFFFFFFFFFFFFFF"; + ASSERT_EQ(64, uint.significant_bit_count()); + ASSERT_TRUE("FFFFFFFFFFFFFFFF" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), *uint.data()); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[7]); + ASSERT_FALSE(uint.is_zero()); + + uint = 0x8001; + ASSERT_EQ(16, uint.significant_bit_count()); + ASSERT_TRUE("8001" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0x8001), *uint.data()); + ASSERT_TRUE(SEAL_BYTE(0x01) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0x80) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[7]); + } + + TEST(BigUnsignedInt, BigUInt99Bits) + { + BigUInt uint(99); + ASSERT_EQ(99, uint.bit_count()); + ASSERT_TRUE(nullptr != uint.data()); + ASSERT_EQ(13ULL, uint.byte_count()); + ASSERT_EQ(2ULL, uint.uint64_count()); + ASSERT_EQ(0, uint.significant_bit_count()); + ASSERT_TRUE("0" == uint.to_string()); + ASSERT_TRUE(uint.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[12]); + + uint = "1"; + ASSERT_EQ(1, uint.significant_bit_count()); + ASSERT_TRUE("1" == uint.to_string()); + ASSERT_FALSE(uint.is_zero()); + ASSERT_EQ(1ULL, uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(1) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0) == uint[12]); + uint.set_zero(); + ASSERT_TRUE(uint.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + + uint = "7FFFFFFFFFFFFFFFFFFFFFFFF"; + ASSERT_EQ(99, uint.significant_bit_count()); + ASSERT_TRUE("7FFFFFFFFFFFFFFFFFFFFFFFF" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0x7FFFFFFFF), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0xFF) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0x07) == uint[12]); + ASSERT_FALSE(uint.is_zero()); + uint.set_zero(); + ASSERT_TRUE(uint.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + + uint = "4000000000000000000000000"; + ASSERT_EQ(99, uint.significant_bit_count()); + ASSERT_TRUE("4000000000000000000000000" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0x0000000000000000), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0x400000000), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0x04) == uint[12]); + ASSERT_FALSE(uint.is_zero()); + + uint = 0x8001; + ASSERT_EQ(16, uint.significant_bit_count()); + ASSERT_TRUE("8001" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0x8001), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(0x01) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0x80) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[12]); + + BigUInt uint2("123"); + ASSERT_FALSE(uint == uint2); + ASSERT_FALSE(uint2 == uint); + ASSERT_TRUE(uint != uint2); + ASSERT_TRUE(uint2 != uint); + + uint = uint2; + ASSERT_TRUE(uint == uint2); + ASSERT_FALSE(uint != uint2); + ASSERT_EQ(9, uint.significant_bit_count()); + ASSERT_TRUE("123" == uint.to_string()); + ASSERT_EQ(static_cast<uint64_t>(0x123), uint.data()[0]); + ASSERT_EQ(static_cast<uint64_t>(0), uint.data()[1]); + ASSERT_TRUE(SEAL_BYTE(0x23) == uint[0]); + ASSERT_TRUE(SEAL_BYTE(0x01) == uint[1]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[2]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[3]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[4]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[5]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[6]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[7]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[8]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[9]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[10]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[11]); + ASSERT_TRUE(SEAL_BYTE(0x00) == uint[12]); + + uint.resize(8); + ASSERT_EQ(8, uint.bit_count()); + ASSERT_EQ(1ULL, uint.uint64_count()); + ASSERT_TRUE("23" == uint.to_string()); + + uint.resize(100); + ASSERT_EQ(100, uint.bit_count()); + ASSERT_EQ(2ULL, uint.uint64_count()); + ASSERT_TRUE("23" == uint.to_string()); + + uint.resize(0); + ASSERT_EQ(0, uint.bit_count()); + ASSERT_EQ(0ULL, uint.uint64_count()); + ASSERT_TRUE(nullptr == uint.data()); + } + + TEST(BigUnsignedInt, SaveLoadUInt) + { + stringstream stream; + + BigUInt value; + BigUInt value2("100"); + value.save(stream); + value2.load(stream); + ASSERT_TRUE(value == value2); + + value = "123"; + value.save(stream); + value2.load(stream); + ASSERT_TRUE(value == value2); + + value = "FFFFFFFFFFFFFFFFFFFFFFFFFF"; + value.save(stream); + value2.load(stream); + ASSERT_TRUE(value == value2); + + value = "0"; + value.save(stream); + value2.load(stream); + ASSERT_TRUE(value == value2); + } + + TEST(BigUnsignedInt, DuplicateTo) + { + BigUInt original(123); + original = 56789; + + BigUInt target; + + original.duplicate_to(target); + ASSERT_EQ(target.bit_count(), original.bit_count()); + ASSERT_TRUE(target == original); + } + + TEST(BigUnsignedInt, DuplicateFrom) + { + BigUInt original(123); + original = 56789; + + BigUInt target; + + target.duplicate_from(original); + ASSERT_EQ(target.bit_count(), original.bit_count()); + ASSERT_TRUE(target == original); + } + + TEST(BigUnsignedInt, BigUIntCopyMoveAssign) + { + { + BigUInt p1("123"); + BigUInt p2("456"); + BigUInt p3; + + p1.operator=(p2); + p3.operator=(p1); + ASSERT_TRUE(p1 == p2); + ASSERT_TRUE(p3 == p1); + } + { + BigUInt p1("123"); + BigUInt p2("456"); + BigUInt p3; + BigUInt p4(p2); + + p1.operator=(move(p2)); + p3.operator=(move(p1)); + ASSERT_TRUE(p3 == p4); + ASSERT_TRUE(p1 == p2); + ASSERT_TRUE(p3 == p1); + } + { + uint64_t p1_anchor = 123; + uint64_t p2_anchor = 456; + BigUInt p1(64, &p1_anchor); + BigUInt p2(64, &p2_anchor); + BigUInt p3; + + p1.operator=(p2); + p3.operator=(p1); + ASSERT_TRUE(p1 == p2); + ASSERT_TRUE(p3 == p1); + } + { + uint64_t p1_anchor = 123; + uint64_t p2_anchor = 456; + BigUInt p1(64, &p1_anchor); + BigUInt p2(64, &p2_anchor); + BigUInt p3; + BigUInt p4(p2); + + p1.operator=(move(p2)); + p3.operator=(move(p1)); + ASSERT_TRUE(p3 == p4); + ASSERT_TRUE(p2 == 456); + ASSERT_TRUE(p1 == 456); + ASSERT_TRUE(p3 == 456); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/ciphertext.cpp b/bigpiseal3.5.1/native/tests/seal/ciphertext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..538db355ab61cfb674d287cd9c373316639736aa --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/ciphertext.cpp @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ciphertext.h" +#include "seal/context.h" +#include "seal/encryptor.h" +#include "seal/keygenerator.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(CiphertextTest, CiphertextBasics) + { + EncryptionParameters parms(scheme_type::BFV); + + parms.set_poly_modulus_degree(2); + parms.set_coeff_modulus(CoeffModulus::Create(2, { 30 })); + parms.set_plain_modulus(2); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + Ciphertext ctxt(context); + ctxt.reserve(10); + ASSERT_EQ(0ULL, ctxt.size()); + ASSERT_EQ(0ULL, ctxt.int_array().size()); + ASSERT_EQ(10ULL * 2 * 1, ctxt.int_array().capacity()); + ASSERT_EQ(2ULL, ctxt.poly_modulus_degree()); + ASSERT_TRUE(ctxt.parms_id() == context->first_parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + const uint64_t *ptr = ctxt.data(); + + ctxt.reserve(5); + ASSERT_EQ(0ULL, ctxt.size()); + ASSERT_EQ(0ULL, ctxt.int_array().size()); + ASSERT_EQ(5ULL * 2 * 1, ctxt.int_array().capacity()); + ASSERT_EQ(2ULL, ctxt.poly_modulus_degree()); + ASSERT_TRUE(ptr != ctxt.data()); + ASSERT_TRUE(ctxt.parms_id() == context->first_parms_id()); + ptr = ctxt.data(); + + ctxt.reserve(10); + ASSERT_EQ(0ULL, ctxt.size()); + ASSERT_EQ(0ULL, ctxt.int_array().size()); + ASSERT_EQ(10ULL * 2 * 1, ctxt.int_array().capacity()); + ASSERT_EQ(2ULL, ctxt.poly_modulus_degree()); + ASSERT_TRUE(ptr != ctxt.data()); + ASSERT_TRUE(ctxt.parms_id() == context->first_parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + ptr = ctxt.data(); + + ctxt.reserve(2); + ASSERT_EQ(0ULL, ctxt.size()); + ASSERT_EQ(2ULL * 2 * 1, ctxt.int_array().capacity()); + ASSERT_EQ(0ULL, ctxt.int_array().size()); + ASSERT_EQ(2ULL, ctxt.poly_modulus_degree()); + ASSERT_TRUE(ptr != ctxt.data()); + ASSERT_TRUE(ctxt.parms_id() == context->first_parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + ptr = ctxt.data(); + + ctxt.reserve(5); + ASSERT_EQ(0ULL, ctxt.size()); + ASSERT_EQ(5ULL * 2 * 1, ctxt.int_array().capacity()); + ASSERT_EQ(0ULL, ctxt.int_array().size()); + ASSERT_EQ(2ULL, ctxt.poly_modulus_degree()); + ASSERT_TRUE(ptr != ctxt.data()); + ASSERT_TRUE(ctxt.parms_id() == context->first_parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + + Ciphertext ctxt2{ ctxt }; + ASSERT_EQ(ctxt.coeff_modulus_size(), ctxt2.coeff_modulus_size()); + ASSERT_EQ(ctxt.is_ntt_form(), ctxt2.is_ntt_form()); + ASSERT_EQ(ctxt.poly_modulus_degree(), ctxt2.poly_modulus_degree()); + ASSERT_TRUE(ctxt.parms_id() == ctxt2.parms_id()); + ASSERT_EQ(ctxt.poly_modulus_degree(), ctxt2.poly_modulus_degree()); + ASSERT_EQ(ctxt.size(), ctxt2.size()); + + Ciphertext ctxt3; + ctxt3 = ctxt; + ASSERT_EQ(ctxt.coeff_modulus_size(), ctxt3.coeff_modulus_size()); + ASSERT_EQ(ctxt.poly_modulus_degree(), ctxt3.poly_modulus_degree()); + ASSERT_EQ(ctxt.is_ntt_form(), ctxt3.is_ntt_form()); + ASSERT_TRUE(ctxt.parms_id() == ctxt3.parms_id()); + ASSERT_EQ(ctxt.poly_modulus_degree(), ctxt3.poly_modulus_degree()); + ASSERT_EQ(ctxt.size(), ctxt3.size()); + } + + TEST(CiphertextTest, SaveLoadCiphertext) + { + stringstream stream; + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(2); + parms.set_coeff_modulus(CoeffModulus::Create(2, { 30 })); + parms.set_plain_modulus(2); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + Ciphertext ctxt(context); + Ciphertext ctxt2; + ctxt.save(stream); + ctxt2.load(context, stream); + ASSERT_TRUE(ctxt.parms_id() == ctxt2.parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + ASSERT_FALSE(ctxt2.is_ntt_form()); + + parms.set_poly_modulus_degree(1024); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(1024)); + parms.set_plain_modulus(0xF0F0); + context = SEALContext::Create(parms, false); + KeyGenerator keygen(context); + Encryptor encryptor(context, keygen.public_key()); + encryptor.encrypt(Plaintext("Ax^10 + 9x^9 + 8x^8 + 7x^7 + 6x^6 + 5x^5 + 4x^4 + 3x^3 + 2x^2 + 1"), ctxt); + ctxt.save(stream); + ctxt2.load(context, stream); + ASSERT_TRUE(ctxt.parms_id() == ctxt2.parms_id()); + ASSERT_FALSE(ctxt.is_ntt_form()); + ASSERT_FALSE(ctxt2.is_ntt_form()); + ASSERT_TRUE(is_equal_uint_uint( + ctxt.data(), ctxt2.data(), parms.poly_modulus_degree() * parms.coeff_modulus().size() * 2)); + ASSERT_TRUE(ctxt.data() != ctxt2.data()); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/ckks.cpp b/bigpiseal3.5.1/native/tests/seal/ckks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a72c73e74479ef151a08978aa5280ce3dee78546 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/ckks.cpp @@ -0,0 +1,344 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ckks.h" +#include "seal/context.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include <ctime> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(CKKSEncoderTest, CKKSEncoderEncodeVectorDecodeTest) + { + EncryptionParameters parms(scheme_type::CKKS); + { + size_t slots = 32; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 40, 40, 40, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(0.0, 0.0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 16); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + size_t slots = 32; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 60, 60, 60, 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 40); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + size_t slots = 64; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 60, 60, 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 40); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + size_t slots = 64; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 30, 30, 30, 30, 30 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 40); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + size_t slots = 32; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 30, 30, 30, 30, 30 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 40); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // Many primes + size_t slots = 32; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create( + 128, { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + double delta = (1ULL << 40); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + size_t slots = 64; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 40, 40, 40, 40, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + std::vector<std::complex<double>> values(slots); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 20); + + for (size_t i = 0; i < slots; i++) + { + std::complex<double> value(static_cast<double>(rand() % data_bound), 0); + values[i] = value; + } + + CKKSEncoder encoder(context); + { + // Use a very large scale + double delta = pow(2.0, 110); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // Use a scale over 128 bits + double delta = pow(2.0, 130); + Plaintext plain; + encoder.encode(values, context->first_parms_id(), delta, plain); + std::vector<std::complex<double>> result; + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(values[i].real() - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(CKKSEncoderTest, CKKSEncoderEncodeSingleDecodeTest) + { + EncryptionParameters parms(scheme_type::CKKS); + { + size_t slots = 16; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40, 40, 40, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + CKKSEncoder encoder(context); + + srand(static_cast<unsigned>(time(NULL))); + int data_bound = (1 << 30); + double delta = (1ULL << 16); + Plaintext plain; + std::vector<std::complex<double>> result; + + for (int iRun = 0; iRun < 50; iRun++) + { + double value = static_cast<double>(rand() % data_bound); + encoder.encode(value, context->first_parms_id(), delta, plain); + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(value - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + size_t slots = 32; + parms.set_poly_modulus_degree(slots << 1); + parms.set_coeff_modulus(CoeffModulus::Create(slots << 1, { 40, 40, 40, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + CKKSEncoder encoder(context); + + srand(static_cast<unsigned>(time(NULL))); + { + int data_bound = (1 << 30); + Plaintext plain; + std::vector<std::complex<double>> result; + + for (int iRun = 0; iRun < 50; iRun++) + { + int value = static_cast<int>(rand() % data_bound); + encoder.encode(value, context->first_parms_id(), plain); + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(value - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // Use a very large scale + int data_bound = (1 << 20); + Plaintext plain; + std::vector<std::complex<double>> result; + + for (int iRun = 0; iRun < 50; iRun++) + { + int value = static_cast<int>(rand() % data_bound); + encoder.encode(value, context->first_parms_id(), plain); + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(value - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // Use a scale over 128 bits + int data_bound = (1 << 20); + Plaintext plain; + std::vector<std::complex<double>> result; + + for (int iRun = 0; iRun < 50; iRun++) + { + int value = static_cast<int>(rand() % data_bound); + encoder.encode(value, context->first_parms_id(), plain); + encoder.decode(plain, result); + + for (size_t i = 0; i < slots; ++i) + { + auto tmp = abs(value - result[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/context.cpp b/bigpiseal3.5.1/native/tests/seal/context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa1b5826050aecba14acfa343f287ead294a5695 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/context.cpp @@ -0,0 +1,415 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/modulus.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +using error_type = EncryptionParameterQualifiers::error_type; + +namespace sealtest +{ + TEST(ContextTest, ContextConstructor) + { + // Nothing set + auto scheme = scheme_type::BFV; + EncryptionParameters parms(scheme); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_coeff_modulus_size); + ASSERT_FALSE(qualifiers.using_fft); + ASSERT_FALSE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Not relatively prime coeff moduli + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 2, 30 }); + parms.set_plain_modulus(2); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::failed_creating_rns_base); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_FALSE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Plain modulus not relatively prime to coeff moduli + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17, 41 }); + parms.set_plain_modulus(34); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_plain_modulus_coprimality); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Plain modulus not smaller than product of coeff moduli + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17 }); + parms.set_plain_modulus(41); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(17ULL, *context->first_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_plain_modulus_too_large); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // FFT poly but not NTT modulus + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 3 }); + parms.set_plain_modulus(2); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(3ULL, *context->first_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_coeff_modulus_no_ntt); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_FALSE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters OK; no fast plain lift + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17, 41 }); + parms.set_plain_modulus(18); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(697ULL, *context->first_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters OK; fast plain lift + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17, 41 }); + parms.set_plain_modulus(16); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(17ULL, *context->first_context_data()->total_coeff_modulus()); + ASSERT_EQ(697ULL, *context->key_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + auto key_qualifiers = context->key_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(key_qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_TRUE(context->using_keyswitching()); + } + + // Parameters OK; no batching due to non-prime plain modulus + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17, 41 }); + parms.set_plain_modulus(49); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(697ULL, *context->first_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters OK; batching enabled + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 17, 41 }); + parms.set_plain_modulus(73); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(697ULL, *context->first_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_TRUE(qualifiers.using_batching); + ASSERT_FALSE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters OK; batching and fast plain lift enabled + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 137, 193 }); + parms.set_plain_modulus(73); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(137ULL, *context->first_context_data()->total_coeff_modulus()); + ASSERT_EQ(26441ULL, *context->key_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + auto key_qualifiers = context->key_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_TRUE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(key_qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_TRUE(context->using_keyswitching()); + } + + // Parameters OK; batching and fast plain lift enabled; nullptr RNG + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 137, 193 }); + parms.set_plain_modulus(73); + parms.set_random_generator(nullptr); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(137ULL, *context->first_context_data()->total_coeff_modulus()); + ASSERT_EQ(26441ULL, *context->key_context_data()->total_coeff_modulus()); + auto qualifiers = context->first_context_data()->qualifiers(); + auto key_qualifiers = context->key_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_TRUE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_FALSE(key_qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_TRUE(context->using_keyswitching()); + } + + // Parameters not OK due to too small poly_modulus_degree and enforce_hes + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 137, 193 }); + parms.set_plain_modulus(73); + parms.set_random_generator(nullptr); + { + auto context = SEALContext::Create(parms, false, sec_level_type::tc128); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_parameters_insecure); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters not OK due to too large coeff_modulus and enforce_hes + parms.set_poly_modulus_degree(2048); + parms.set_coeff_modulus(CoeffModulus::BFVDefault(4096, sec_level_type::tc128)); + parms.set_plain_modulus(73); + parms.set_random_generator(nullptr); + { + auto context = SEALContext::Create(parms, false, sec_level_type::tc128); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_FALSE(qualifiers.parameters_set()); + ASSERT_EQ(qualifiers.parameter_error, error_type::invalid_parameters_insecure); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + + // Parameters OK; descending modulus chain + parms.set_poly_modulus_degree(4096); + parms.set_coeff_modulus({ 0xffffee001, 0xffffc4001 }); + parms.set_plain_modulus(73); + { + auto context = SEALContext::Create(parms, false, sec_level_type::tc128); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_TRUE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::tc128, qualifiers.sec_level); + ASSERT_TRUE(context->using_keyswitching()); + } + + // Parameters OK; no standard security + parms.set_poly_modulus_degree(2048); + parms.set_coeff_modulus({ 0x1ffffe0001, 0xffffee001, 0xffffc4001 }); + parms.set_plain_modulus(73); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + auto key_qualifiers = context->key_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_FALSE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_TRUE(key_qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_TRUE(context->using_keyswitching()); + } + + // Parameters OK; using batching; no keyswitching + parms.set_poly_modulus_degree(2048); + parms.set_coeff_modulus(CoeffModulus::Create(2048, { 40 })); + parms.set_plain_modulus(65537); + { + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + ASSERT_TRUE(qualifiers.parameters_set()); + ASSERT_TRUE(qualifiers.using_fft); + ASSERT_TRUE(qualifiers.using_ntt); + ASSERT_TRUE(qualifiers.using_batching); + ASSERT_TRUE(qualifiers.using_fast_plain_lift); + ASSERT_TRUE(qualifiers.using_descending_modulus_chain); + ASSERT_EQ(sec_level_type::none, qualifiers.sec_level); + ASSERT_FALSE(context->using_keyswitching()); + } + } + + TEST(ContextTest, ModulusChainExpansion) + { + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 41, 137, 193, 65537 }); + parms.set_plain_modulus(73); + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto context_data = context->key_context_data(); + ASSERT_EQ(size_t(2), context_data->chain_index()); + ASSERT_EQ(71047416497ULL, *context_data->total_coeff_modulus()); + ASSERT_FALSE(!!context_data->prev_context_data()); + ASSERT_EQ(context_data->parms_id(), context->key_parms_id()); + auto prev_context_data = context_data; + context_data = context_data->next_context_data(); + ASSERT_EQ(size_t(1), context_data->chain_index()); + ASSERT_EQ(1084081ULL, *context_data->total_coeff_modulus()); + ASSERT_EQ(context_data->prev_context_data()->parms_id(), prev_context_data->parms_id()); + prev_context_data = context_data; + context_data = context_data->next_context_data(); + ASSERT_EQ(size_t(0), context_data->chain_index()); + ASSERT_EQ(5617ULL, *context_data->total_coeff_modulus()); + ASSERT_EQ(context_data->prev_context_data()->parms_id(), prev_context_data->parms_id()); + ASSERT_FALSE(!!context_data->next_context_data()); + ASSERT_EQ(context_data->parms_id(), context->last_parms_id()); + + context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(size_t(1), context->key_context_data()->chain_index()); + ASSERT_EQ(size_t(0), context->first_context_data()->chain_index()); + ASSERT_EQ(71047416497ULL, *context->key_context_data()->total_coeff_modulus()); + ASSERT_EQ(1084081ULL, *context->first_context_data()->total_coeff_modulus()); + ASSERT_FALSE(!!context->first_context_data()->next_context_data()); + ASSERT_TRUE(!!context->first_context_data()->prev_context_data()); + } + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus({ 41, 137, 193, 65537 }); + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto context_data = context->key_context_data(); + ASSERT_EQ(size_t(3), context_data->chain_index()); + ASSERT_EQ(71047416497ULL, *context_data->total_coeff_modulus()); + ASSERT_FALSE(!!context_data->prev_context_data()); + ASSERT_EQ(context_data->parms_id(), context->key_parms_id()); + auto prev_context_data = context_data; + context_data = context_data->next_context_data(); + ASSERT_EQ(size_t(2), context_data->chain_index()); + ASSERT_EQ(1084081ULL, *context_data->total_coeff_modulus()); + ASSERT_EQ(context_data->prev_context_data()->parms_id(), prev_context_data->parms_id()); + prev_context_data = context_data; + context_data = context_data->next_context_data(); + ASSERT_EQ(size_t(1), context_data->chain_index()); + ASSERT_EQ(5617ULL, *context_data->total_coeff_modulus()); + ASSERT_EQ(context_data->prev_context_data()->parms_id(), prev_context_data->parms_id()); + prev_context_data = context_data; + context_data = context_data->next_context_data(); + ASSERT_EQ(size_t(0), context_data->chain_index()); + ASSERT_EQ(41ULL, *context_data->total_coeff_modulus()); + ASSERT_EQ(context_data->prev_context_data()->parms_id(), prev_context_data->parms_id()); + ASSERT_FALSE(!!context_data->next_context_data()); + ASSERT_EQ(context_data->parms_id(), context->last_parms_id()); + + context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_EQ(size_t(1), context->key_context_data()->chain_index()); + ASSERT_EQ(size_t(0), context->first_context_data()->chain_index()); + ASSERT_EQ(71047416497ULL, *context->key_context_data()->total_coeff_modulus()); + ASSERT_EQ(1084081ULL, *context->first_context_data()->total_coeff_modulus()); + ASSERT_FALSE(!!context->first_context_data()->next_context_data()); + ASSERT_TRUE(!!context->first_context_data()->prev_context_data()); + } + } + + TEST(EncryptionParameterQualifiersTest, ParameterError) + { + auto scheme = scheme_type::BFV; + EncryptionParameters parms(scheme); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto qualifiers = context->first_context_data()->qualifiers(); + + qualifiers.parameter_error = error_type::none; + ASSERT_STREQ(qualifiers.parameter_error_name(), "none"); + ASSERT_STREQ(qualifiers.parameter_error_message(), "constructed but not yet validated"); + + qualifiers.parameter_error = error_type::success; + ASSERT_STREQ(qualifiers.parameter_error_name(), "success"); + ASSERT_STREQ(qualifiers.parameter_error_message(), "valid"); + + qualifiers.parameter_error = error_type::invalid_coeff_modulus_bit_count; + ASSERT_STREQ(qualifiers.parameter_error_name(), "invalid_coeff_modulus_bit_count"); + ASSERT_STREQ( + qualifiers.parameter_error_message(), + "coeff_modulus's primes' bit counts are not bounded by SEAL_USER_MOD_BIT_COUNT_MIN(MAX)"); + + parms.set_poly_modulus_degree(127); + parms.set_coeff_modulus({ 17, 73 }); + parms.set_plain_modulus(41); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + context = SEALContext::Create(parms, false, sec_level_type::none); + ASSERT_FALSE(context->parameters_set()); + ASSERT_STREQ(context->parameter_error_name(), "invalid_poly_modulus_degree_non_power_of_two"); + ASSERT_STREQ(context->parameter_error_message(), "poly_modulus_degree is not a power of two"); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/encryptionparams.cpp b/bigpiseal3.5.1/native/tests/seal/encryptionparams.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4efe74d7221d5814d1c4c57d18aec276f72df52d --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/encryptionparams.cpp @@ -0,0 +1,148 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/encryptionparams.h" +#include "seal/modulus.h" +#include "seal/util/numth.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(EncryptionParametersTest, EncryptionParametersSet) + { + auto encryption_parameters_test = [](scheme_type scheme) { + EncryptionParameters parms(scheme); + parms.set_coeff_modulus({ 2, 3 }); + if (scheme == scheme_type::BFV) + parms.set_plain_modulus(2); + parms.set_poly_modulus_degree(2); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + + ASSERT_TRUE(scheme == parms.scheme()); + ASSERT_TRUE(parms.coeff_modulus()[0] == 2); + ASSERT_TRUE(parms.coeff_modulus()[1] == 3); + if (scheme == scheme_type::BFV) + { + ASSERT_TRUE(parms.plain_modulus().value() == 2); + } + else if (scheme == scheme_type::CKKS) + { + ASSERT_TRUE(parms.plain_modulus().value() == 0); + } + ASSERT_TRUE(parms.poly_modulus_degree() == 2); + ASSERT_TRUE(parms.random_generator() == UniformRandomGeneratorFactory::DefaultFactory()); + + parms.set_coeff_modulus(CoeffModulus::Create(2, { 30, 40, 50 })); + if (scheme == scheme_type::BFV) + parms.set_plain_modulus(2); + parms.set_poly_modulus_degree(128); + parms.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + + ASSERT_TRUE(util::is_prime(parms.coeff_modulus()[0])); + ASSERT_TRUE(util::is_prime(parms.coeff_modulus()[1])); + ASSERT_TRUE(util::is_prime(parms.coeff_modulus()[2])); + + if (scheme == scheme_type::BFV) + { + ASSERT_TRUE(parms.plain_modulus().value() == 2); + } + else if (scheme == scheme_type::CKKS) + { + ASSERT_TRUE(parms.plain_modulus().value() == 0); + } + ASSERT_TRUE(parms.poly_modulus_degree() == 128); + ASSERT_TRUE(parms.random_generator() == UniformRandomGeneratorFactory::DefaultFactory()); + }; + encryption_parameters_test(scheme_type::BFV); + encryption_parameters_test(scheme_type::CKKS); + } + + TEST(EncryptionParametersTest, EncryptionParametersCompare) + { + auto scheme = scheme_type::BFV; + EncryptionParameters parms1(scheme); + parms1.set_coeff_modulus(CoeffModulus::Create(64, { 30 })); + if (scheme == scheme_type::BFV) + parms1.set_plain_modulus(1 << 6); + parms1.set_poly_modulus_degree(64); + parms1.set_random_generator(UniformRandomGeneratorFactory::DefaultFactory()); + + EncryptionParameters parms2(parms1); + ASSERT_TRUE(parms1 == parms2); + + EncryptionParameters parms3(scheme); + parms3 = parms2; + ASSERT_TRUE(parms3 == parms2); + parms3.set_coeff_modulus(CoeffModulus::Create(64, { 32 })); + ASSERT_FALSE(parms3 == parms2); + + parms3 = parms2; + ASSERT_TRUE(parms3 == parms2); + parms3.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30 })); + ASSERT_FALSE(parms3 == parms2); + + parms3 = parms2; + parms3.set_poly_modulus_degree(128); + ASSERT_FALSE(parms3 == parms1); + + parms3 = parms2; + if (scheme == scheme_type::BFV) + parms3.set_plain_modulus((1 << 6) + 1); + ASSERT_FALSE(parms3 == parms2); + + parms3 = parms2; + ASSERT_TRUE(parms3 == parms2); + + parms3 = parms2; + parms3.set_random_generator(nullptr); + ASSERT_TRUE(parms3 == parms2); + + parms3 = parms2; + parms3.set_poly_modulus_degree(128); + parms3.set_poly_modulus_degree(64); + ASSERT_TRUE(parms3 == parms1); + + parms3 = parms2; + parms3.set_coeff_modulus({ 2 }); + parms3.set_coeff_modulus(CoeffModulus::Create(64, { 50 })); + parms3.set_coeff_modulus(parms2.coeff_modulus()); + ASSERT_TRUE(parms3 == parms2); + } + + TEST(EncryptionParametersTest, EncryptionParametersSaveLoad) + { + stringstream stream; + + auto scheme = scheme_type::BFV; + EncryptionParameters parms(scheme); + EncryptionParameters parms2(scheme); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30 })); + if (scheme == scheme_type::BFV) + parms.set_plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.save(stream); + parms2.load(stream); + ASSERT_TRUE(parms.scheme() == parms2.scheme()); + ASSERT_TRUE(parms.coeff_modulus() == parms2.coeff_modulus()); + ASSERT_TRUE(parms.plain_modulus() == parms2.plain_modulus()); + ASSERT_TRUE(parms.poly_modulus_degree() == parms2.poly_modulus_degree()); + ASSERT_TRUE(parms == parms2); + + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 60, 60 })); + + if (scheme == scheme_type::BFV) + parms.set_plain_modulus(1 << 30); + parms.set_poly_modulus_degree(256); + + parms.save(stream); + parms2.load(stream); + ASSERT_TRUE(parms.scheme() == parms2.scheme()); + ASSERT_TRUE(parms.coeff_modulus() == parms2.coeff_modulus()); + ASSERT_TRUE(parms.plain_modulus() == parms2.plain_modulus()); + ASSERT_TRUE(parms.poly_modulus_degree() == parms2.poly_modulus_degree()); + ASSERT_TRUE(parms == parms2); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/encryptor.cpp b/bigpiseal3.5.1/native/tests/seal/encryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8680259374862c370606df73109d9f0455512e55 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/encryptor.cpp @@ -0,0 +1,659 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/batchencoder.h" +#include "seal/ckks.h" +#include "seal/context.h" +#include "seal/decryptor.h" +#include "seal/encryptor.h" +#include "seal/intencoder.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include <cstddef> +#include <cstdint> +#include <ctime> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(EncryptorTest, BFVEncryptDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_plain_modulus(plain_modulus); + { + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x12345678ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(1ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(2ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFD)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFDULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFE)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFEULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFFULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(314159265), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(314159265ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x12345678ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(1ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(2ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFD)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFDULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFE)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFEULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFFULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(314159265), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(314159265ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + parms.set_poly_modulus_degree(256); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x12345678ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(1ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(2ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFD)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFDULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFE)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFEULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF)), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x7FFFFFFFFFFFFFFFULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(314159265), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(314159265ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + parms.set_poly_modulus_degree(256); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + + Encryptor encryptor(context, keygen.secret_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + stringstream stream; + + encryptor.encrypt_symmetric(encoder.encode(314159265), encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(314159265ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt_symmetric(encoder.encode(314159265)).save(stream); + encrypted.load(context, stream); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(314159265ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + } + + TEST(EncryptorTest, BFVEncryptZeroDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_plain_modulus(plain_modulus); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40, 40, 40 })); + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + Encryptor encryptor(context, keygen.public_key(), keygen.secret_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext ct; + Plaintext pt; + parms_id_type next_parms = context->first_context_data()->next_context_data()->parms_id(); + { + encryptor.encrypt_zero(ct); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + + encryptor.encrypt_zero(next_parms, ct); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + } + { + encryptor.encrypt_zero_symmetric(ct); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + + encryptor.encrypt_zero_symmetric(next_parms, ct); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + } + { + stringstream stream; + encryptor.encrypt_zero_symmetric().save(stream); + ct.load(context, stream); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + + encryptor.encrypt_zero_symmetric(next_parms).save(stream); + ct.load(context, stream); + ASSERT_FALSE(ct.is_ntt_form()); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_TRUE(pt.is_zero()); + } + } + + TEST(EncryptorTest, CKKSEncryptZeroDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + Encryptor encryptor(context, keygen.public_key(), keygen.secret_key()); + Decryptor decryptor(context, keygen.secret_key()); + CKKSEncoder encoder(context); + + Ciphertext ct; + Plaintext pt; + std::vector<std::complex<double>> res; + parms_id_type next_parms = context->first_context_data()->next_context_data()->parms_id(); + { + encryptor.encrypt_zero(ct); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + decryptor.decrypt(ct, pt); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + + encryptor.encrypt_zero(next_parms, ct); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_EQ(pt.parms_id(), next_parms); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + } + { + encryptor.encrypt_zero_symmetric(ct); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + decryptor.decrypt(ct, pt); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + + encryptor.encrypt_zero_symmetric(next_parms, ct); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_EQ(pt.parms_id(), next_parms); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + } + { + stringstream stream; + encryptor.encrypt_zero_symmetric().save(stream); + ct.load(context, stream); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + decryptor.decrypt(ct, pt); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + + encryptor.encrypt_zero_symmetric(next_parms).save(stream); + ct.load(context, stream); + ASSERT_FALSE(ct.is_transparent()); + ASSERT_TRUE(ct.is_ntt_form()); + ASSERT_DOUBLE_EQ(ct.scale(), 1.0); + ct.scale() = std::pow(2.0, 20); + ASSERT_EQ(ct.parms_id(), next_parms); + decryptor.decrypt(ct, pt); + ASSERT_EQ(pt.parms_id(), next_parms); + encoder.decode(pt, res); + for (auto val : res) + { + ASSERT_NEAR(val.real(), 0.0, 0.01); + ASSERT_NEAR(val.imag(), 0.0, 0.01); + } + } + } + + TEST(EncryptorTest, CKKSEncryptDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // input consists of ones + size_t slot_size = 32; + parms.set_poly_modulus_degree(2 * slot_size); + parms.set_coeff_modulus(CoeffModulus::Create(2 * slot_size, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 1.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // input consists of zeros + size_t slot_size = 32; + parms.set_poly_modulus_degree(2 * slot_size); + parms.set_coeff_modulus(CoeffModulus::Create(2 * slot_size, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // Input is a random mix of positive and negative integers + size_t slot_size = 64; + parms.set_poly_modulus_degree(2 * slot_size); + parms.set_coeff_modulus(CoeffModulus::Create(2 * slot_size, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size); + std::vector<std::complex<double>> output(slot_size); + + srand(static_cast<unsigned>(time(NULL))); + int input_bound = 1 << 30; + const double delta = static_cast<double>(1ULL << 50); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = pow(-1.0, rand() % 2) * static_cast<double>(rand() % input_bound); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // Input is a random mix of positive and negative integers + size_t slot_size = 32; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size); + std::vector<std::complex<double>> output(slot_size); + + srand(static_cast<unsigned>(time(NULL))); + int input_bound = 1 << 30; + const double delta = static_cast<double>(1ULL << 60); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = pow(-1.0, rand() % 2) * static_cast<double>(rand() % input_bound); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plain, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // Encrypt at lower level + size_t slot_size = 32; + parms.set_poly_modulus_degree(2 * slot_size); + parms.set_coeff_modulus(CoeffModulus::Create(2 * slot_size, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 1.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + + auto first_context_data = context->first_context_data(); + ASSERT_NE(nullptr, first_context_data.get()); + auto second_context_data = first_context_data->next_context_data(); + ASSERT_NE(nullptr, second_context_data.get()); + auto second_parms_id = second_context_data->parms_id(); + + encoder.encode(input, second_parms_id, delta, plain); + encryptor.encrypt(plain, encrypted); + + // Check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == second_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // Encrypt at lower level + size_t slot_size = 32; + parms.set_poly_modulus_degree(2 * slot_size); + parms.set_coeff_modulus(CoeffModulus::Create(2 * slot_size, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.secret_key()); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + stringstream stream; + + std::vector<std::complex<double>> input(slot_size, 1.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + + auto first_context_data = context->first_context_data(); + ASSERT_NE(nullptr, first_context_data.get()); + auto second_context_data = first_context_data->next_context_data(); + ASSERT_NE(nullptr, second_context_data.get()); + auto second_parms_id = second_context_data->parms_id(); + + encoder.encode(input, second_parms_id, delta, plain); + encryptor.encrypt_symmetric(plain, encrypted); + // Check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == second_parms_id); + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + + encoder.encode(input, second_parms_id, delta, plain); + encryptor.encrypt_symmetric(plain).save(stream); + encrypted.load(context, stream); + // Check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == second_parms_id); + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/evaluator.cpp b/bigpiseal3.5.1/native/tests/seal/evaluator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e1202c3e31db324a9b4e800df9e15ab560b6fdf --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/evaluator.cpp @@ -0,0 +1,3960 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/batchencoder.h" +#include "seal/ckks.h" +#include "seal/context.h" +#include "seal/decryptor.h" +#include "seal/encryptor.h" +#include "seal/evaluator.h" +#include "seal/intencoder.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include <cstddef> +#include <cstdint> +#include <ctime> +#include <string> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(EvaluatorTest, BFVEncryptNegateDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + evaluator.negate_inplace(encrypted); + Plaintext plain; + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(-0x12345678), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + evaluator.negate_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(0), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted); + evaluator.negate_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(-1), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-1), encrypted); + evaluator.negate_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(1), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted); + evaluator.negate_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(-2), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-5), encrypted); + evaluator.negate_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<int32_t>(5), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptAddDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + Ciphertext encrypted2; + encryptor.encrypt(encoder.encode(0x54321), encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + Plaintext plain; + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x12399999), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(5), encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(5), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(-3), encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(2), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted1); + encryptor.encrypt(encoder.encode(2), encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(-5), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + Plaintext plain1("2x^2 + 1x^1 + 3"); + Plaintext plain2("3x^3 + 4x^2 + 5x^1 + 6"); + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(plain.to_string() == "3x^3 + 6x^2 + 6x^1 + 9"); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + plain1 = "3x^5 + 1x^4 + 4x^3 + 1"; + plain2 = "5x^2 + 9x^1 + 2"; + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(plain.to_string() == "3x^5 + 1x^4 + 4x^3 + 5x^2 + 9x^1 + 3"); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, CKKSEncryptAddDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // adding two zero vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 30, 30, 30, 30, 30 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + evaluator.add_inplace(encrypted, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // adding two random vectors 100 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 30); + const double delta = static_cast<double>(1 << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 100; expCount++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] + input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // adding two random vectors 100 times + size_t slot_size = 8; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 30); + const double delta = static_cast<double>(1 << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 100; expCount++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] + input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.add_inplace(encrypted1, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + TEST(EvaluatorTest, CKKSEncryptAddPlainDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // adding two zero vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 30, 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + evaluator.add_plain_inplace(encrypted, plain); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // adding two random vectors 50 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 8); + const double delta = static_cast<double>(1ULL << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 50; expCount++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] + input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.add_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // adding two random vectors 50 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + double input2; + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 8); + const double delta = static_cast<double>(1ULL << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 50; expCount++) + { + input2 = static_cast<double>(rand() % (data_bound * data_bound)) / data_bound; + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] + input2; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.add_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // adding two random vectors 50 times + size_t slot_size = 8; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + double input2; + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 8); + const double delta = static_cast<double>(1ULL << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 50; expCount++) + { + input2 = static_cast<double>(rand() % (data_bound * data_bound)) / data_bound; + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] + input2; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.add_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptSubPlainDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // adding two zero vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 30, 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 16); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + evaluator.add_plain_inplace(encrypted, plain); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // adding two random vectors 100 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 8); + const double delta = static_cast<double>(1ULL << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 100; expCount++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] - input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.sub_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // adding two random vectors 100 times + size_t slot_size = 8; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 8); + const double delta = static_cast<double>(1ULL << 16); + + srand(static_cast<unsigned>(time(NULL))); + + for (int expCount = 0; expCount < 100; expCount++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] - input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.sub_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, BFVEncryptSubDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + Ciphertext encrypted2; + encryptor.encrypt(encoder.encode(0x54321), encrypted2); + evaluator.sub_inplace(encrypted1, encrypted2); + Plaintext plain; + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(0x122F1357), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + evaluator.sub_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(0), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(5), encrypted2); + evaluator.sub_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(-5), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(-3), encrypted2); + evaluator.sub_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(8), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted1); + encryptor.encrypt(encoder.encode(2), encrypted2); + evaluator.sub_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<int32_t>(-9), encoder.decode_int32(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptAddPlainDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + plain = encoder.encode(0x54321); + evaluator.add_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x12399999), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + plain = encoder.encode(0); + evaluator.add_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + plain = encoder.encode(5); + evaluator.add_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(5), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + plain = encoder.encode(-3); + evaluator.add_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(2), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted1); + plain = encoder.encode(7); + evaluator.add_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptSubPlainDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + plain = encoder.encode(0x54321); + evaluator.sub_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x122F1357), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + plain = encoder.encode(0); + evaluator.sub_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + plain = encoder.encode(5); + evaluator.sub_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(static_cast<int64_t>(-5) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + plain = encoder.encode(-3); + evaluator.sub_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(8), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted1); + plain = encoder.encode(2); + evaluator.sub_plain_inplace(encrypted1, plain); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(static_cast<int64_t>(-9) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptMultiplyPlainDecrypt) + { + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + plain = encoder.encode(0x54321); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5FCBBBB88D78), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + plain = encoder.encode(5); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted); + plain = encoder.encode(4); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(28), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted); + plain = encoder.encode(2); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(14), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted); + plain = encoder.encode(1); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(7), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted); + plain = encoder.encode(-3); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(static_cast<int64_t>(-15) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted); + plain = encoder.encode(2); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(static_cast<int64_t>(-14) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus((1ULL << 20) - 1); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + plain = "1"; + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x12345678), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = "5"; + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5B05B058), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus((1ULL << 40) - 1); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted); + plain = "1"; + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x12345678), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = "5"; + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5B05B058), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(PlainModulus::Batching(64, 20)); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + BatchEncoder batch_encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + vector<int64_t> result; + + batch_encoder.encode(vector<int64_t>(batch_encoder.slot_count(), 7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector<int64_t>(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + batch_encoder.encode(vector<int64_t>(batch_encoder.slot_count(), -7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector<int64_t>(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(PlainModulus::Batching(64, 40)); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + BatchEncoder batch_encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + vector<int64_t> result; + + batch_encoder.encode(vector<int64_t>(batch_encoder.slot_count(), 7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector<int64_t>(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + batch_encoder.encode(vector<int64_t>(batch_encoder.slot_count(), -7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector<int64_t>(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + } + + TEST(EvaluatorTest, BFVEncryptMultiplyDecrypt) + { + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + encryptor.encrypt(encoder.encode(0x54321), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5FCBBBB88D78), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(5), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted1); + encryptor.encrypt(encoder.encode(1), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(7), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(-3), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(static_cast<int64_t>(-15) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0x10000), encrypted1); + encryptor.encrypt(encoder.encode(0x100), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x1000000), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus((1ULL << 60) - 1); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + encryptor.encrypt(encoder.encode(0x54321), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5FCBBBB88D78), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(5), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted1); + encryptor.encrypt(encoder.encode(1), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(7), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(-3), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(static_cast<int64_t>(-15) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0x10000), encrypted1); + encryptor.encrypt(encoder.encode(0x100), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x1000000), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain; + encryptor.encrypt(encoder.encode(0x12345678), encrypted1); + encryptor.encrypt(encoder.encode(0x54321), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x5FCBBBB88D78), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted1); + encryptor.encrypt(encoder.encode(5), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted1); + encryptor.encrypt(encoder.encode(1), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(7), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(-3), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_TRUE(static_cast<int64_t>(-15) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0x10000), encrypted1); + encryptor.encrypt(encoder.encode(0x100), encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(0x1000000), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted2.parms_id() == encrypted1.parms_id()); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 8); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1; + Plaintext plain; + encryptor.encrypt(encoder.encode(123), encrypted1); + evaluator.multiply(encrypted1, encrypted1, encrypted1); + evaluator.multiply(encrypted1, encrypted1, encrypted1); + decryptor.decrypt(encrypted1, plain); + ASSERT_EQ(static_cast<uint64_t>(228886641), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + } + } + +#include "seal/randomgen.h" + TEST(EvaluatorTest, BFVRelinearize) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted(context); + Ciphertext encrypted2(context); + + Plaintext plain; + Plaintext plain2; + + plain = 0; + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain == plain2); + + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain == plain2); + + plain = "1x^10 + 2"; + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain2.to_string() == "1x^20 + 4x^10 + 4"); + + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain2.to_string() == "1x^40 + 8x^30 + 18x^20 + 20x^10 + 10"); + + // Relinearization with modulus switching + plain = "1x^10 + 2"; + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.mod_switch_to_next_inplace(encrypted); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain2.to_string() == "1x^20 + 4x^10 + 4"); + + encryptor.encrypt(plain, encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.mod_switch_to_next_inplace(encrypted); + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.mod_switch_to_next_inplace(encrypted); + decryptor.decrypt(encrypted, plain2); + ASSERT_TRUE(plain2.to_string() == "1x^40 + 8x^30 + 18x^20 + 20x^10 + 10"); + } + + TEST(EvaluatorTest, CKKSEncryptNaiveMultiplyDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // multiplying two zero vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1 << 30); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + evaluator.multiply_inplace(encrypted, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + { + // multiplying two random vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors + size_t slot_size = 16; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + evaluator.multiply_inplace(encrypted1, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptMultiplyByNumberDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // multiplying two random vectors by an integer + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + int64_t input2; + std::vector<std::complex<double>> expected(slot_size, 0.0); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int iExp = 0; iExp < 50; iExp++) + { + input2 = max(rand() % data_bound, 1); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * static_cast<double>(input2); + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.multiply_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors by an integer + size_t slot_size = 8; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + int64_t input2; + std::vector<std::complex<double>> expected(slot_size, 0.0); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int iExp = 0; iExp < 50; iExp++) + { + input2 = max(rand() % data_bound, 1); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * static_cast<double>(input2); + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.multiply_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors by a double + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + double input2; + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int iExp = 0; iExp < 50; iExp++) + { + input2 = static_cast<double>(rand() % (data_bound * data_bound)) / static_cast<double>(data_bound); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2; + } + + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.multiply_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors by a double + size_t slot_size = 16; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + Ciphertext encrypted1; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 2.1); + double input2; + std::vector<std::complex<double>> expected(slot_size, 2.1); + std::vector<std::complex<double>> output(slot_size); + + int data_bound = (1 << 10); + srand(static_cast<unsigned>(time(NULL))); + + for (int iExp = 0; iExp < 50; iExp++) + { + input2 = static_cast<double>(rand() % (data_bound * data_bound)) / static_cast<double>(data_bound); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2; + } + + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + evaluator.multiply_plain_inplace(encrypted1, plain2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + + decryptor.decrypt(encrypted1, plainRes); + + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptMultiplyRelinDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // multiplying two random vectors 50 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + int data_bound = 1 << 10; + + for (int round = 0; round < 50; round++) + { + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors 50 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + int data_bound = 1 << 10; + + for (int round = 0; round < 50; round++) + { + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors 50 times + size_t slot_size = 2; + parms.set_poly_modulus_degree(8); + parms.set_coeff_modulus(CoeffModulus::Create(8, { 60, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + int data_bound = 1 << 10; + const double delta = static_cast<double>(1ULL << 40); + + for (int round = 0; round < 50; round++) + { + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + // evaluator.relinearize_inplace(encrypted1, rlk); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptSquareRelinDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // squaring two random vectors 100 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + expected[i] = input[i] * input[i]; + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + // evaluator.square_inplace(encrypted); + evaluator.multiply_inplace(encrypted, encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // squaring two random vectors 100 times + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + expected[i] = input[i] * input[i]; + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + // evaluator.square_inplace(encrypted); + evaluator.multiply_inplace(encrypted, encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // squaring two random vectors 100 times + size_t slot_size = 16; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + expected[i] = input[i] * input[i]; + } + + std::vector<std::complex<double>> output(slot_size); + const double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + // evaluator.square_inplace(encrypted); + evaluator.multiply_inplace(encrypted, encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptMultiplyRelinRescaleDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // multiplying two random vectors 100 times + size_t slot_size = 64; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 30, 30, 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.rescale_to_next_inplace(encrypted1); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors 100 times + size_t slot_size = 16; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 30, 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.rescale_to_next_inplace(encrypted1); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplying two random vectors 100 times + size_t slot_size = 16; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 60, 60, 60, 60, 60 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encryptedRes; + Plaintext plain1; + Plaintext plain2; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + double delta = static_cast<double>(1ULL << 60); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + + // Scale down by two levels + auto target_parms = context->first_context_data()->next_context_data()->next_context_data()->parms_id(); + evaluator.rescale_to_inplace(encrypted1, target_parms); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted1.parms_id() == target_parms); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + + // Test with inverted order: rescale then relin + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 7; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i] * input2[i]; + } + + std::vector<std::complex<double>> output(slot_size); + double delta = static_cast<double>(1ULL << 50); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.multiply_inplace(encrypted1, encrypted2); + + // Scale down by two levels + auto target_parms = context->first_context_data()->next_context_data()->next_context_data()->parms_id(); + evaluator.rescale_to_inplace(encrypted1, target_parms); + + // Relinearize now + evaluator.relinearize_inplace(encrypted1, rlk); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted1.parms_id() == target_parms); + + decryptor.decrypt(encrypted1, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + + TEST(EvaluatorTest, CKKSEncryptSquareRelinRescaleDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // squaring two random vectors 100 times + size_t slot_size = 64; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 50, 50, 50 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + std::vector<std::complex<double>> expected(slot_size, 0.0); + int data_bound = 1 << 8; + + for (int round = 0; round < 100; round++) + { + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + expected[i] = input[i] * input[i]; + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.rescale_to_next_inplace(encrypted); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // squaring two random vectors 100 times + size_t slot_size = 16; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 50, 50, 50 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + std::vector<std::complex<double>> expected(slot_size, 0.0); + int data_bound = 1 << 8; + + for (int round = 0; round < 100; round++) + { + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + expected[i] = input[i] * input[i]; + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + evaluator.square_inplace(encrypted); + evaluator.relinearize_inplace(encrypted, rlk); + evaluator.rescale_to_next_inplace(encrypted); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + TEST(EvaluatorTest, CKKSEncryptModSwitchDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // modulo switching without rescaling for random vectors + size_t slot_size = 64; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 60, 60, 60, 60, 60 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + int data_bound = 1 << 30; + srand(static_cast<unsigned>(time(NULL))); + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + evaluator.mod_switch_to_next_inplace(encrypted); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // modulo switching without rescaling for random vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 40, 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + int data_bound = 1 << 30; + srand(static_cast<unsigned>(time(NULL))); + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + evaluator.mod_switch_to_next_inplace(encrypted); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // modulo switching without rescaling for random vectors + size_t slot_size = 32; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + + int data_bound = 1 << 30; + srand(static_cast<unsigned>(time(NULL))); + + std::vector<std::complex<double>> input(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + Ciphertext encrypted; + Plaintext plain; + Plaintext plainRes; + + for (int round = 0; round < 100; round++) + { + for (size_t i = 0; i < slot_size; i++) + { + input[i] = static_cast<double>(rand() % data_bound); + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input, context->first_parms_id(), delta, plain); + + encryptor.encrypt(plain, encrypted); + + // check correctness of encryption + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + evaluator.mod_switch_to_next_inplace(encrypted); + + // check correctness of modulo switching + ASSERT_TRUE(encrypted.parms_id() == next_parms_id); + + decryptor.decrypt(encrypted, plainRes); + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(input[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + TEST(EvaluatorTest, CKKSEncryptMultiplyRelinRescaleModSwitchAddDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // multiplication and addition without rescaling for random vectors + size_t slot_size = 64; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 50, 50, 50 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encrypted3; + Plaintext plain1; + Plaintext plain2; + Plaintext plain3; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> input3(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 8; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i] + input3[i]; + } + + std::vector<std::complex<double>> output(slot_size); + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + encoder.encode(input3, context->first_parms_id(), delta * delta, plain3); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + encryptor.encrypt(plain3, encrypted3); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted3.parms_id() == context->first_parms_id()); + + // enc1*enc2 + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.rescale_to_next_inplace(encrypted1); + + // check correctness of modulo switching with rescaling + ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); + + // move enc3 to the level of enc1 * enc2 + evaluator.rescale_to_inplace(encrypted3, next_parms_id); + + // enc1*enc2 + enc3 + evaluator.add_inplace(encrypted1, encrypted3); + + // decryption + decryptor.decrypt(encrypted1, plainRes); + // decoding + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + { + // multiplication and addition without rescaling for random vectors + size_t slot_size = 16; + parms.set_poly_modulus_degree(128); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 50, 50, 50 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + KeyGenerator keygen(context); + + CKKSEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Decryptor decryptor(context, keygen.secret_key()); + Evaluator evaluator(context); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1; + Ciphertext encrypted2; + Ciphertext encrypted3; + Plaintext plain1; + Plaintext plain2; + Plaintext plain3; + Plaintext plainRes; + + std::vector<std::complex<double>> input1(slot_size, 0.0); + std::vector<std::complex<double>> input2(slot_size, 0.0); + std::vector<std::complex<double>> input3(slot_size, 0.0); + std::vector<std::complex<double>> expected(slot_size, 0.0); + std::vector<std::complex<double>> output(slot_size); + + for (int round = 0; round < 100; round++) + { + int data_bound = 1 << 8; + srand(static_cast<unsigned>(time(NULL))); + for (size_t i = 0; i < slot_size; i++) + { + input1[i] = static_cast<double>(rand() % data_bound); + input2[i] = static_cast<double>(rand() % data_bound); + expected[i] = input1[i] * input2[i] + input3[i]; + } + + double delta = static_cast<double>(1ULL << 40); + encoder.encode(input1, context->first_parms_id(), delta, plain1); + encoder.encode(input2, context->first_parms_id(), delta, plain2); + encoder.encode(input3, context->first_parms_id(), delta * delta, plain3); + + encryptor.encrypt(plain1, encrypted1); + encryptor.encrypt(plain2, encrypted2); + encryptor.encrypt(plain3, encrypted3); + + // check correctness of encryption + ASSERT_TRUE(encrypted1.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted2.parms_id() == context->first_parms_id()); + // check correctness of encryption + ASSERT_TRUE(encrypted3.parms_id() == context->first_parms_id()); + + // enc1*enc2 + evaluator.multiply_inplace(encrypted1, encrypted2); + evaluator.relinearize_inplace(encrypted1, rlk); + evaluator.rescale_to_next_inplace(encrypted1); + + // check correctness of modulo switching with rescaling + ASSERT_TRUE(encrypted1.parms_id() == next_parms_id); + + // move enc3 to the level of enc1 * enc2 + evaluator.rescale_to_inplace(encrypted3, next_parms_id); + + // enc1*enc2 + enc3 + evaluator.add_inplace(encrypted1, encrypted3); + + // decryption + decryptor.decrypt(encrypted1, plainRes); + // decoding + encoder.decode(plainRes, output); + + for (size_t i = 0; i < slot_size; i++) + { + auto tmp = abs(expected[i].real() - output[i].real()); + ASSERT_TRUE(tmp < 0.5); + } + } + } + } + TEST(EvaluatorTest, CKKSEncryptRotateDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // maximal number of slots + size_t slot_size = 4; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + CKKSEncoder encoder(context); + const double delta = static_cast<double>(1ULL << 30); + + Ciphertext encrypted; + Plaintext plain; + + vector<std::complex<double>> input{ std::complex<double>(1, 1), std::complex<double>(2, 2), + std::complex<double>(3, 3), std::complex<double>(4, 4) }; + input.resize(slot_size); + + vector<std::complex<double>> output(slot_size, 0); + + encoder.encode(input, context->first_parms_id(), delta, plain); + int shift = 1; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 2; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 3; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + evaluator.complex_conjugate_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[i].real(), round(output[i].real())); + ASSERT_EQ(-input[i].imag(), round(output[i].imag())); + } + } + { + size_t slot_size = 32; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + CKKSEncoder encoder(context); + const double delta = static_cast<double>(1ULL << 30); + + Ciphertext encrypted; + Plaintext plain; + + vector<std::complex<double>> input{ std::complex<double>(1, 1), std::complex<double>(2, 2), + std::complex<double>(3, 3), std::complex<double>(4, 4) }; + input.resize(slot_size); + + vector<std::complex<double>> output(slot_size, 0); + + encoder.encode(input, context->first_parms_id(), delta, plain); + int shift = 1; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < input.size(); i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 2; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 3; + encryptor.encrypt(plain, encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + evaluator.complex_conjugate_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[i].real()), round(output[i].real())); + ASSERT_EQ(round(-input[i].imag()), round(output[i].imag())); + } + } + } + + TEST(EvaluatorTest, CKKSEncryptRescaleRotateDecrypt) + { + EncryptionParameters parms(scheme_type::CKKS); + { + // maximal number of slots + size_t slot_size = 4; + parms.set_poly_modulus_degree(slot_size * 2); + parms.set_coeff_modulus(CoeffModulus::Create(slot_size * 2, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + CKKSEncoder encoder(context); + const double delta = std::pow(2.0, 70); + + Ciphertext encrypted; + Plaintext plain; + + vector<std::complex<double>> input{ std::complex<double>(1, 1), std::complex<double>(2, 2), + std::complex<double>(3, 3), std::complex<double>(4, 4) }; + input.resize(slot_size); + + vector<std::complex<double>> output(slot_size, 0); + + encoder.encode(input, context->first_parms_id(), delta, plain); + int shift = 1; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 2; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 3; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].real(), round(output[i].real())); + ASSERT_EQ(input[(i + static_cast<size_t>(shift)) % slot_size].imag(), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.complex_conjugate_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(input[i].real(), round(output[i].real())); + ASSERT_EQ(-input[i].imag(), round(output[i].imag())); + } + } + { + size_t slot_size = 32; + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 40, 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + CKKSEncoder encoder(context); + const double delta = std::pow(2, 70); + + Ciphertext encrypted; + Plaintext plain; + + vector<std::complex<double>> input{ std::complex<double>(1, 1), std::complex<double>(2, 2), + std::complex<double>(3, 3), std::complex<double>(4, 4) }; + input.resize(slot_size); + + vector<std::complex<double>> output(slot_size, 0); + + encoder.encode(input, context->first_parms_id(), delta, plain); + int shift = 1; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 2; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + shift = 3; + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.rotate_vector_inplace(encrypted, shift, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].real()), round(output[i].real())); + ASSERT_EQ(round(input[(i + static_cast<size_t>(shift)) % slot_size].imag()), round(output[i].imag())); + } + + encoder.encode(input, context->first_parms_id(), delta, plain); + encryptor.encrypt(plain, encrypted); + evaluator.rescale_to_next_inplace(encrypted); + evaluator.complex_conjugate_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + encoder.decode(plain, output); + for (size_t i = 0; i < slot_size; i++) + { + ASSERT_EQ(round(input[i].real()), round(output[i].real())); + ASSERT_EQ(round(-input[i].imag()), round(output[i].imag())); + } + } + } + + TEST(EvaluatorTest, BFVEncryptSquareDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 8); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(1), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(1ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-5), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(25ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-1), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(1ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(123), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(15129ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0x10000), encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(0x100000000ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(123), encrypted); + evaluator.square_inplace(encrypted); + evaluator.square_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(228886641ULL, encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptMultiplyManyDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted1, encrypted2, encrypted3, encrypted4, product; + Plaintext plain; + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(6), encrypted2); + encryptor.encrypt(encoder.encode(7), encrypted3); + vector<Ciphertext> encrypteds{ encrypted1, encrypted2, encrypted3 }; + evaluator.multiply_many(encrypteds, rlk, product); + ASSERT_EQ(3, encrypteds.size()); + decryptor.decrypt(product, plain); + ASSERT_EQ(static_cast<uint64_t>(210), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == product.parms_id()); + ASSERT_TRUE(product.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-9), encrypted1); + encryptor.encrypt(encoder.encode(-17), encrypted2); + encrypteds = { encrypted1, encrypted2 }; + evaluator.multiply_many(encrypteds, rlk, product); + ASSERT_EQ(2, encrypteds.size()); + decryptor.decrypt(product, plain); + ASSERT_EQ(static_cast<uint64_t>(153), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == product.parms_id()); + ASSERT_TRUE(product.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted1); + encryptor.encrypt(encoder.encode(-31), encrypted2); + encryptor.encrypt(encoder.encode(7), encrypted3); + encrypteds = { encrypted1, encrypted2, encrypted3 }; + evaluator.multiply_many(encrypteds, rlk, product); + ASSERT_EQ(3, encrypteds.size()); + decryptor.decrypt(product, plain); + ASSERT_TRUE(static_cast<int64_t>(-434) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == product.parms_id()); + ASSERT_TRUE(product.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted1); + encryptor.encrypt(encoder.encode(-1), encrypted2); + encryptor.encrypt(encoder.encode(1), encrypted3); + encryptor.encrypt(encoder.encode(-1), encrypted4); + encrypteds = { encrypted1, encrypted2, encrypted3, encrypted4 }; + evaluator.multiply_many(encrypteds, rlk, product); + ASSERT_EQ(4, encrypteds.size()); + decryptor.decrypt(product, plain); + ASSERT_EQ(static_cast<uint64_t>(1), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted4.parms_id() == product.parms_id()); + ASSERT_TRUE(product.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(98765), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + encryptor.encrypt(encoder.encode(12345), encrypted3); + encryptor.encrypt(encoder.encode(34567), encrypted4); + encrypteds = { encrypted1, encrypted2, encrypted3, encrypted4 }; + evaluator.multiply_many(encrypteds, rlk, product); + ASSERT_EQ(4, encrypteds.size()); + decryptor.decrypt(product, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == product.parms_id()); + ASSERT_TRUE(encrypted4.parms_id() == product.parms_id()); + ASSERT_TRUE(product.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptExponentiateDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + RelinKeys rlk = keygen.relin_keys_local(); + + Ciphertext encrypted; + Plaintext plain; + encryptor.encrypt(encoder.encode(5), encrypted); + evaluator.exponentiate_inplace(encrypted, 1, rlk); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(5), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(7), encrypted); + evaluator.exponentiate_inplace(encrypted, 2, rlk); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(49), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-7), encrypted); + evaluator.exponentiate_inplace(encrypted, 3, rlk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(static_cast<int64_t>(-343) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(0x100), encrypted); + evaluator.exponentiate_inplace(encrypted, 4, rlk); + decryptor.decrypt(encrypted, plain); + ASSERT_EQ(static_cast<uint64_t>(0x100000000), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptAddManyDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + IntegerEncoder encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted1, encrypted2, encrypted3, encrypted4, sum; + Plaintext plain; + encryptor.encrypt(encoder.encode(5), encrypted1); + encryptor.encrypt(encoder.encode(6), encrypted2); + encryptor.encrypt(encoder.encode(7), encrypted3); + vector<Ciphertext> encrypteds = { encrypted1, encrypted2, encrypted3 }; + evaluator.add_many(encrypteds, sum); + decryptor.decrypt(sum, plain); + ASSERT_EQ(static_cast<uint64_t>(18), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == sum.parms_id()); + ASSERT_TRUE(sum.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(-9), encrypted1); + encryptor.encrypt(encoder.encode(-17), encrypted2); + encrypteds = { + encrypted1, + encrypted2, + }; + evaluator.add_many(encrypteds, sum); + decryptor.decrypt(sum, plain); + ASSERT_TRUE(static_cast<int64_t>(-26) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == sum.parms_id()); + ASSERT_TRUE(sum.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(2), encrypted1); + encryptor.encrypt(encoder.encode(-31), encrypted2); + encryptor.encrypt(encoder.encode(7), encrypted3); + encrypteds = { encrypted1, encrypted2, encrypted3 }; + evaluator.add_many(encrypteds, sum); + decryptor.decrypt(sum, plain); + ASSERT_TRUE(static_cast<int64_t>(-22) == encoder.decode_int64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == sum.parms_id()); + ASSERT_TRUE(sum.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(1), encrypted1); + encryptor.encrypt(encoder.encode(-1), encrypted2); + encryptor.encrypt(encoder.encode(1), encrypted3); + encryptor.encrypt(encoder.encode(-1), encrypted4); + encrypteds = { encrypted1, encrypted2, encrypted3, encrypted4 }; + evaluator.add_many(encrypteds, sum); + decryptor.decrypt(sum, plain); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted4.parms_id() == sum.parms_id()); + ASSERT_TRUE(sum.parms_id() == context->first_parms_id()); + + encryptor.encrypt(encoder.encode(98765), encrypted1); + encryptor.encrypt(encoder.encode(0), encrypted2); + encryptor.encrypt(encoder.encode(12345), encrypted3); + encryptor.encrypt(encoder.encode(34567), encrypted4); + encrypteds = { encrypted1, encrypted2, encrypted3, encrypted4 }; + evaluator.add_many(encrypteds, sum); + decryptor.decrypt(sum, plain); + ASSERT_EQ(static_cast<uint64_t>(145677), encoder.decode_uint64(plain)); + ASSERT_TRUE(encrypted1.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted2.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted3.parms_id() == sum.parms_id()); + ASSERT_TRUE(encrypted4.parms_id() == sum.parms_id()); + ASSERT_TRUE(sum.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, TransformPlainToNTT) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40, 40 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + + Evaluator evaluator(context); + Plaintext plain("0"); + ASSERT_FALSE(plain.is_ntt_form()); + evaluator.transform_to_ntt_inplace(plain, context->first_parms_id()); + ASSERT_TRUE(plain.is_zero()); + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == context->first_parms_id()); + + plain.release(); + plain = "0"; + ASSERT_FALSE(plain.is_ntt_form()); + auto next_parms_id = context->first_context_data()->next_context_data()->parms_id(); + evaluator.transform_to_ntt_inplace(plain, next_parms_id); + ASSERT_TRUE(plain.is_zero()); + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == next_parms_id); + + plain.release(); + plain = "1"; + ASSERT_FALSE(plain.is_ntt_form()); + evaluator.transform_to_ntt_inplace(plain, context->first_parms_id()); + for (size_t i = 0; i < 256; i++) + { + ASSERT_TRUE(plain[i] == uint64_t(1)); + } + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == context->first_parms_id()); + + plain.release(); + plain = "1"; + ASSERT_FALSE(plain.is_ntt_form()); + evaluator.transform_to_ntt_inplace(plain, next_parms_id); + for (size_t i = 0; i < 128; i++) + { + ASSERT_TRUE(plain[i] == uint64_t(1)); + } + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == next_parms_id); + + plain.release(); + plain = "2"; + ASSERT_FALSE(plain.is_ntt_form()); + evaluator.transform_to_ntt_inplace(plain, context->first_parms_id()); + for (size_t i = 0; i < 256; i++) + { + ASSERT_TRUE(plain[i] == uint64_t(2)); + } + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == context->first_parms_id()); + + plain.release(); + plain = "2"; + evaluator.transform_to_ntt_inplace(plain, next_parms_id); + for (size_t i = 0; i < 128; i++) + { + ASSERT_TRUE(plain[i] == uint64_t(2)); + } + ASSERT_TRUE(plain.is_ntt_form()); + ASSERT_TRUE(plain.parms_id() == next_parms_id); + } + + TEST(EvaluatorTest, TransformEncryptedToFromNTT) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Plaintext plain; + Ciphertext encrypted; + plain = "0"; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "0"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = "1"; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "1"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = "Fx^10 + Ex^9 + Dx^8 + Cx^7 + Bx^6 + Ax^5 + 1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "Fx^10 + Ex^9 + Dx^8 + Cx^7 + Bx^6 + Ax^5 + 1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptMultiplyPlainNTTDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(1 << 6); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Plaintext plain; + Plaintext plain_multiplier; + Ciphertext encrypted; + + plain = 0; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + plain_multiplier = 1; + evaluator.transform_to_ntt_inplace(plain_multiplier, context->first_parms_id()); + evaluator.multiply_plain_inplace(encrypted, plain_multiplier); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "0"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = 2; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + plain_multiplier.release(); + plain_multiplier = 3; + evaluator.transform_to_ntt_inplace(plain_multiplier, context->first_parms_id()); + evaluator.multiply_plain_inplace(encrypted, plain_multiplier); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "6"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = 1; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + plain_multiplier.release(); + plain_multiplier = "Fx^10 + Ex^9 + Dx^8 + Cx^7 + Bx^6 + Ax^5 + 1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"; + evaluator.transform_to_ntt_inplace(plain_multiplier, context->first_parms_id()); + evaluator.multiply_plain_inplace(encrypted, plain_multiplier); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(plain.to_string() == "Fx^10 + Ex^9 + Dx^8 + Cx^7 + Bx^6 + Ax^5 + 1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + plain = "1x^20"; + encryptor.encrypt(plain, encrypted); + evaluator.transform_to_ntt_inplace(encrypted); + plain_multiplier.release(); + plain_multiplier = "Fx^10 + Ex^9 + Dx^8 + Cx^7 + Bx^6 + Ax^5 + 1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"; + evaluator.transform_to_ntt_inplace(plain_multiplier, context->first_parms_id()); + evaluator.multiply_plain_inplace(encrypted, plain_multiplier); + evaluator.transform_from_ntt_inplace(encrypted); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE( + plain.to_string() == + "Fx^30 + Ex^29 + Dx^28 + Cx^27 + Bx^26 + Ax^25 + 1x^24 + 2x^23 + 3x^22 + 4x^21 + 5x^20"); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + + TEST(EvaluatorTest, BFVEncryptApplyGaloisDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(257); + parms.set_poly_modulus_degree(8); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(8, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(vector<uint32_t>{ 1, 3, 5, 15 }); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Plaintext plain("1"); + Ciphertext encrypted; + encryptor.encrypt(plain, encrypted); + evaluator.apply_galois_inplace(encrypted, 1, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 3, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 5, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 15, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1" == plain.to_string()); + + plain = "1x^1"; + encryptor.encrypt(plain, encrypted); + evaluator.apply_galois_inplace(encrypted, 1, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 3, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^3" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 5, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("100x^7" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 15, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^1" == plain.to_string()); + + plain = "1x^2"; + encryptor.encrypt(plain, encrypted); + evaluator.apply_galois_inplace(encrypted, 1, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^2" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 3, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^6" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 5, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("100x^6" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 15, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^2" == plain.to_string()); + + plain = "1x^3 + 2x^2 + 1x^1 + 1"; + encryptor.encrypt(plain, encrypted); + evaluator.apply_galois_inplace(encrypted, 1, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^3 + 2x^2 + 1x^1 + 1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 3, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("2x^6 + 1x^3 + 100x^1 + 1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 5, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("100x^7 + FFx^6 + 100x^5 + 1" == plain.to_string()); + evaluator.apply_galois_inplace(encrypted, 15, glk); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE("1x^3 + 2x^2 + 1x^1 + 1" == plain.to_string()); + } + + TEST(EvaluatorTest, BFVEncryptRotateMatrixDecrypt) + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(257); + parms.set_poly_modulus_degree(8); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(8, { 40, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + GaloisKeys glk = keygen.galois_keys_local(); + + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + BatchEncoder batch_encoder(context); + + Plaintext plain; + vector<uint64_t> plain_vec{ 1, 2, 3, 4, 5, 6, 7, 8 }; + batch_encoder.encode(plain_vec, plain); + Ciphertext encrypted; + encryptor.encrypt(plain, encrypted); + + evaluator.rotate_columns_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, plain_vec); + ASSERT_TRUE((plain_vec == vector<uint64_t>{ 5, 6, 7, 8, 1, 2, 3, 4 })); + + evaluator.rotate_rows_inplace(encrypted, -1, glk); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, plain_vec); + ASSERT_TRUE((plain_vec == vector<uint64_t>{ 8, 5, 6, 7, 4, 1, 2, 3 })); + + evaluator.rotate_rows_inplace(encrypted, 2, glk); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, plain_vec); + ASSERT_TRUE((plain_vec == vector<uint64_t>{ 6, 7, 8, 5, 2, 3, 4, 1 })); + + evaluator.rotate_columns_inplace(encrypted, glk); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, plain_vec); + ASSERT_TRUE((plain_vec == vector<uint64_t>{ 2, 3, 4, 1, 6, 7, 8, 5 })); + + evaluator.rotate_rows_inplace(encrypted, 0, glk); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, plain_vec); + ASSERT_TRUE((plain_vec == vector<uint64_t>{ 2, 3, 4, 1, 6, 7, 8, 5 })); + } + TEST(EvaluatorTest, BFVEncryptModSwitchToNextDecrypt) + { + // the common parameters: the plaintext and the polynomial moduli + Modulus plain_modulus(1 << 6); + + // the parameters and the context of the higher level + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + auto parms_id = context->first_parms_id(); + + Ciphertext encrypted(context); + Ciphertext encryptedRes; + Plaintext plain; + + plain = 0; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_next(encrypted, encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + evaluator.mod_switch_to_next_inplace(encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + parms_id = context->first_parms_id(); + plain = 1; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_next(encrypted, encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + evaluator.mod_switch_to_next_inplace(encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + parms_id = context->first_parms_id(); + plain = "1x^127"; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_next(encrypted, encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + evaluator.mod_switch_to_next_inplace(encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + parms_id = context->first_parms_id(); + plain = "5x^64 + Ax^5"; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_next(encrypted, encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + + evaluator.mod_switch_to_next_inplace(encryptedRes); + decryptor.decrypt(encryptedRes, plain); + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + ASSERT_TRUE(encryptedRes.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + } + + TEST(EvaluatorTest, BFVEncryptModSwitchToDecrypt) + { + // the common parameters: the plaintext and the polynomial moduli + Modulus plain_modulus(1 << 6); + + // the parameters and the context of the higher level + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 30, 30, 30, 30 })); + + auto context = SEALContext::Create(parms, true, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + auto parms_id = context->first_parms_id(); + + Ciphertext encrypted(context); + Plaintext plain; + + plain = 0; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + parms_id = context->first_parms_id(); + encryptor.encrypt(plain, encrypted); + parms_id = context->get_context_data(parms_id)->next_context_data()->next_context_data()->parms_id(); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "0"); + + parms_id = context->first_parms_id(); + plain = 1; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + parms_id = context->first_parms_id(); + encryptor.encrypt(plain, encrypted); + parms_id = context->get_context_data(parms_id)->next_context_data()->next_context_data()->parms_id(); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1"); + + parms_id = context->first_parms_id(); + plain = "1x^127"; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + parms_id = context->first_parms_id(); + encryptor.encrypt(plain, encrypted); + parms_id = context->get_context_data(parms_id)->next_context_data()->next_context_data()->parms_id(); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "1x^127"); + + parms_id = context->first_parms_id(); + plain = "5x^64 + Ax^5"; + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + + parms_id = context->get_context_data(parms_id)->next_context_data()->parms_id(); + encryptor.encrypt(plain, encrypted); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + + parms_id = context->first_parms_id(); + encryptor.encrypt(plain, encrypted); + parms_id = context->get_context_data(parms_id)->next_context_data()->next_context_data()->parms_id(); + evaluator.mod_switch_to_inplace(encrypted, parms_id); + decryptor.decrypt(encrypted, plain); + ASSERT_TRUE(encrypted.parms_id() == parms_id); + ASSERT_TRUE(plain.to_string() == "5x^64 + Ax^5"); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/galoiskeys.cpp b/bigpiseal3.5.1/native/tests/seal/galoiskeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b59314f15d9281ebcafe1b58f63803b8dca03c8 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/galoiskeys.cpp @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/galoiskeys.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/uintcore.h" +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(GaloisKeysTest, GaloisKeysSaveLoad) + { + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + GaloisKeys keys; + GaloisKeys test_keys; + keys.save(stream); + test_keys.unsafe_load(context, stream); + ASSERT_EQ(keys.data().size(), test_keys.data().size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + ASSERT_EQ(0ULL, keys.data().size()); + + keys = keygen.galois_keys_local(); + keys.save(stream); + test_keys.load(context, stream); + ASSERT_EQ(keys.data().size(), test_keys.data().size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + for (size_t j = 0; j < test_keys.data().size(); j++) + { + for (size_t i = 0; i < test_keys.data()[j].size(); i++) + { + ASSERT_EQ(keys.data()[j][i].data().size(), test_keys.data()[j][i].data().size()); + ASSERT_EQ( + keys.data()[j][i].data().int_array().size(), test_keys.data()[j][i].data().int_array().size()); + ASSERT_TRUE(is_equal_uint_uint( + keys.data()[j][i].data().data(), test_keys.data()[j][i].data().data(), + keys.data()[j][i].data().int_array().size())); + } + } + ASSERT_EQ(64ULL, keys.data().size()); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 50 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + GaloisKeys keys; + GaloisKeys test_keys; + keys.save(stream); + test_keys.unsafe_load(context, stream); + ASSERT_EQ(keys.data().size(), test_keys.data().size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + ASSERT_EQ(0ULL, keys.data().size()); + + keys = keygen.galois_keys_local(); + keys.save(stream); + test_keys.load(context, stream); + ASSERT_EQ(keys.data().size(), test_keys.data().size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + for (size_t j = 0; j < test_keys.data().size(); j++) + { + for (size_t i = 0; i < test_keys.data()[j].size(); i++) + { + ASSERT_EQ(keys.data()[j][i].data().size(), test_keys.data()[j][i].data().size()); + ASSERT_EQ( + keys.data()[j][i].data().int_array().size(), test_keys.data()[j][i].data().int_array().size()); + ASSERT_TRUE(is_equal_uint_uint( + keys.data()[j][i].data().data(), test_keys.data()[j][i].data().data(), + keys.data()[j][i].data().int_array().size())); + } + } + ASSERT_EQ(256ULL, keys.data().size()); + } + } + TEST(GaloisKeysTest, GaloisKeysSeededSaveLoad) + { + // Returns true if a, b contains the same error. + auto compare_kswitchkeys = [](const KSwitchKeys &a, const KSwitchKeys &b, const SecretKey &sk, + shared_ptr<SEALContext> context) { + auto compare_error = [](const Ciphertext &a_ct, const Ciphertext &b_ct, const SecretKey &sk1, + shared_ptr<SEALContext> ctx) { + auto get_error = [](const Ciphertext &encrypted, const SecretKey &sk2, shared_ptr<SEALContext> ctx2) { + auto pool = MemoryManager::GetPool(); + auto &ctx2_data = *ctx2->get_context_data(encrypted.parms_id()); + auto &parms = ctx2_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t rns_poly_uint64_count = util::mul_safe(coeff_count, coeff_modulus_size); + + IntArray<Ciphertext::ct_coeff_type> error; + error.resize(rns_poly_uint64_count); + auto destination = error.begin(); + + auto copy_operand1(util::allocate_uint(coeff_count, pool)); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Initialize pointers for multiplication + const uint64_t *encrypted_ptr = encrypted.data(1) + (i * coeff_count); + const uint64_t *secret_key_ptr = sk2.data().data() + (i * coeff_count); + uint64_t *destination_ptr = destination + (i * coeff_count); + util::set_zero_uint(coeff_count, destination_ptr); + util::set_uint_uint(encrypted_ptr, coeff_count, copy_operand1.get()); + // compute c_{j+1} * s^{j+1} + util::dyadic_product_coeffmod( + copy_operand1.get(), secret_key_ptr, coeff_count, coeff_modulus[i], copy_operand1.get()); + // add c_{j+1} * s^{j+1} to destination + util::add_poly_poly_coeffmod( + destination_ptr, copy_operand1.get(), coeff_count, coeff_modulus[i], destination_ptr); + // add c_0 into destination + util::add_poly_poly_coeffmod( + destination_ptr, encrypted.data() + (i * coeff_count), coeff_count, coeff_modulus[i], + destination_ptr); + } + return error; + }; + + auto error_a = get_error(a_ct, sk1, ctx); + auto error_b = get_error(b_ct, sk1, ctx); + ASSERT_EQ(error_a.size(), error_b.size()); + ASSERT_TRUE(is_equal_uint_uint(error_a.cbegin(), error_b.cbegin(), error_a.size())); + }; + + ASSERT_EQ(a.size(), b.size()); + auto iter_a = a.data().begin(); + auto iter_b = b.data().begin(); + for (; iter_a != a.data().end(); iter_a++, iter_b++) + { + ASSERT_EQ(iter_a->size(), iter_b->size()); + auto pk_a = iter_a->begin(); + auto pk_b = iter_b->begin(); + for (; pk_a != iter_a->end(); pk_a++, pk_b++) + { + compare_error(pk_a->data(), pk_b->data(), sk, context); + } + } + }; + + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(8); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(8, { 60, 60 })); + random_seed_type seed; + for (auto &i : seed) + { + i = random_uint64(); + } + auto rng = make_shared<BlakePRNGFactory>(BlakePRNGFactory(seed)); + parms.set_random_generator(rng); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + + keygen.galois_keys().save(stream); + GaloisKeys test_keys; + test_keys.load(context, stream); + GaloisKeys keys = keygen.galois_keys_local(); + compare_kswitchkeys(keys, test_keys, secret_key, context); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 50 })); + random_seed_type seed; + for (auto &i : seed) + { + i = random_uint64(); + } + auto rng = make_shared<BlakePRNGFactory>(BlakePRNGFactory(seed)); + parms.set_random_generator(rng); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + + keygen.galois_keys().save(stream); + GaloisKeys test_keys; + test_keys.load(context, stream); + GaloisKeys keys = keygen.galois_keys_local(); + compare_kswitchkeys(keys, test_keys, secret_key, context); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/intarray.cpp b/bigpiseal3.5.1/native/tests/seal/intarray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f565e9ad12eba0904df6bedf794a2053bb99849 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/intarray.cpp @@ -0,0 +1,195 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include <sstream> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(IntArrayTest, IntArrayBasics) + { + { + auto pool = MemoryPoolHandle::New(); + MemoryManager::SwitchProfile(new MMProfFixed(pool)); + IntArray<int32_t> arr; + ASSERT_TRUE(arr.begin() == nullptr); + ASSERT_TRUE(arr.end() == nullptr); + ASSERT_EQ(0ULL, arr.size()); + ASSERT_EQ(0ULL, arr.capacity()); + ASSERT_TRUE(arr.empty()); + + arr.resize(1); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(1, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(1ULL, arr.size()); + ASSERT_EQ(1ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(0, arr[0]); + arr.at(0) = 1; + ASSERT_EQ(1, arr[0]); + ASSERT_EQ(4, static_cast<int>(pool.alloc_byte_count())); + + arr.reserve(6); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(1, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(1ULL, arr.size()); + ASSERT_EQ(6ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(1, arr[0]); + ASSERT_EQ(28, static_cast<int>(pool.alloc_byte_count())); + + arr.resize(4); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(4, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(4ULL, arr.size()); + ASSERT_EQ(6ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + arr.at(0) = 0; + arr.at(1) = 1; + arr.at(2) = 2; + arr.at(3) = 3; + ASSERT_EQ(0, arr[0]); + ASSERT_EQ(1, arr[1]); + ASSERT_EQ(2, arr[2]); + ASSERT_EQ(3, arr[3]); + ASSERT_EQ(28, static_cast<int>(pool.alloc_byte_count())); + + arr.shrink_to_fit(); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(4, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(4ULL, arr.size()); + ASSERT_EQ(4ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(0, arr[0]); + ASSERT_EQ(1, arr[1]); + ASSERT_EQ(2, arr[2]); + ASSERT_EQ(3, arr[3]); + ASSERT_EQ(44, static_cast<int>(pool.alloc_byte_count())); + } + { + auto pool = MemoryPoolHandle::New(); + MemoryManager::SwitchProfile(new MMProfFixed(pool)); + IntArray<uint64_t> arr; + ASSERT_TRUE(arr.begin() == nullptr); + ASSERT_TRUE(arr.end() == nullptr); + ASSERT_EQ(0ULL, arr.size()); + ASSERT_EQ(0ULL, arr.capacity()); + ASSERT_TRUE(arr.empty()); + + arr.resize(1); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(1, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(1ULL, arr.size()); + ASSERT_EQ(1ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(0ULL, arr[0]); + arr.at(0) = 1; + ASSERT_EQ(1ULL, arr[0]); + ASSERT_EQ(8, static_cast<int>(pool.alloc_byte_count())); + + arr.reserve(6); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(1, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(1ULL, arr.size()); + ASSERT_EQ(6ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(1ULL, arr[0]); + ASSERT_EQ(56, static_cast<int>(pool.alloc_byte_count())); + + arr.resize(4); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(4, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(4ULL, arr.size()); + ASSERT_EQ(6ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + arr.at(0) = 0; + arr.at(1) = 1; + arr.at(2) = 2; + arr.at(3) = 3; + ASSERT_EQ(0ULL, arr[0]); + ASSERT_EQ(1ULL, arr[1]); + ASSERT_EQ(2ULL, arr[2]); + ASSERT_EQ(3ULL, arr[3]); + ASSERT_EQ(56, static_cast<int>(pool.alloc_byte_count())); + + arr.shrink_to_fit(); + ASSERT_FALSE(arr.begin() == nullptr); + ASSERT_FALSE(arr.end() == nullptr); + ASSERT_FALSE(arr.begin() == arr.end()); + ASSERT_EQ(4, static_cast<int>(arr.end() - arr.begin())); + ASSERT_EQ(4ULL, arr.size()); + ASSERT_EQ(4ULL, arr.capacity()); + ASSERT_FALSE(arr.empty()); + ASSERT_EQ(0ULL, arr[0]); + ASSERT_EQ(1ULL, arr[1]); + ASSERT_EQ(2ULL, arr[2]); + ASSERT_EQ(3ULL, arr[3]); + ASSERT_EQ(88, static_cast<int>(pool.alloc_byte_count())); + } + } + + TEST(IntArrayTest, SaveLoadIntArray) + { + IntArray<int32_t> arr(6, 4); + arr.at(0) = 0; + arr.at(1) = 1; + arr.at(2) = 2; + arr.at(3) = 3; + stringstream ss; + arr.save(ss); + IntArray<int32_t> arr2; + arr2.load(ss); + + ASSERT_EQ(arr.size(), arr2.size()); + ASSERT_EQ(arr.size(), arr2.capacity()); + ASSERT_EQ(arr[0], arr2[0]); + ASSERT_EQ(arr[1], arr2[1]); + ASSERT_EQ(arr[2], arr2[2]); + ASSERT_EQ(arr[3], arr2[3]); + + arr.resize(2); + arr[0] = 5; + arr[1] = 6; + arr.save(ss); + arr2.load(ss); + + ASSERT_EQ(arr.size(), arr2.size()); + ASSERT_EQ(4ULL, arr2.capacity()); + ASSERT_EQ(arr[0], arr2[0]); + ASSERT_EQ(arr[1], arr2[1]); + } + + TEST(IntArrayTest, Assign) + { + IntArray<char> arr(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW)); + IntArray<char> arr2(MemoryManager::GetPool(mm_prof_opt::FORCE_NEW)); + ASSERT_NE(&static_cast<util::MemoryPool &>(arr.pool()), &static_cast<util::MemoryPool &>(arr2.pool())); + + arr = arr2; + util::MemoryPool *addr = &static_cast<util::MemoryPool &>(arr.pool()); + ASSERT_EQ(&static_cast<util::MemoryPool &>(arr.pool()), addr); + + addr = &static_cast<util::MemoryPool &>(arr2.pool()); + arr = move(arr2); + ASSERT_EQ(&static_cast<util::MemoryPool &>(arr.pool()), addr); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/intencoder.cpp b/bigpiseal3.5.1/native/tests/seal/intencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84995d1950333227b11e33de8fae7305722c7341 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/intencoder.cpp @@ -0,0 +1,442 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/intencoder.h" +#include <cstddef> +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(Encoder, IntEncodeDecodeBigUInt) + { + Modulus modulus(0xFFFFFFFFFFFFFFF); + EncryptionParameters parms(scheme_type::BFV); + parms.set_plain_modulus(modulus); + auto context = SEALContext::Create(parms); + IntegerEncoder encoder(context); + + BigUInt value(64); + value = "0"; + Plaintext poly = encoder.encode(value); + ASSERT_EQ(0ULL, poly.significant_coeff_count()); + ASSERT_TRUE(poly.is_zero()); + ASSERT_TRUE(value == encoder.decode_biguint(poly)); + + value = "1"; + Plaintext poly1 = encoder.encode(value); + ASSERT_EQ(1ULL, poly1.coeff_count()); + ASSERT_TRUE("1" == poly1.to_string()); + ASSERT_TRUE(value == encoder.decode_biguint(poly1)); + + value = "2"; + Plaintext poly2 = encoder.encode(value); + ASSERT_EQ(2ULL, poly2.coeff_count()); + ASSERT_TRUE("1x^1" == poly2.to_string()); + ASSERT_TRUE(value == encoder.decode_biguint(poly2)); + + value = "3"; + Plaintext poly3 = encoder.encode(value); + ASSERT_EQ(2ULL, poly3.coeff_count()); + ASSERT_TRUE("1x^1 + 1" == poly3.to_string()); + ASSERT_TRUE(value == encoder.decode_biguint(poly3)); + + value = "FFFFFFFFFFFFFFFF"; + Plaintext poly4 = encoder.encode(value); + ASSERT_EQ(64ULL, poly4.coeff_count()); + for (size_t i = 0; i < 64; ++i) + { + ASSERT_TRUE(poly4[i] == 1); + } + ASSERT_TRUE(value == encoder.decode_biguint(poly4)); + + value = "80F02"; + Plaintext poly5 = encoder.encode(value); + ASSERT_EQ(20ULL, poly5.coeff_count()); + for (size_t i = 0; i < 20; ++i) + { + if (i == 19 || (i >= 8 && i <= 11) || i == 1) + { + ASSERT_TRUE(poly5[i] == 1); + } + else + { + ASSERT_TRUE(poly5[i] == 0); + } + } + ASSERT_TRUE(value == encoder.decode_biguint(poly5)); + + Plaintext poly6(3); + poly6[0] = 1; + poly6[1] = 500; + poly6[2] = 1023; + value = 1 + 500 * 2 + 1023 * 4; + ASSERT_TRUE(value == encoder.decode_biguint(poly6)); + + modulus = 1024; + parms.set_plain_modulus(modulus); + auto context2 = SEALContext::Create(parms); + IntegerEncoder encoder2(context2); + Plaintext poly7(4); + poly7[0] = 1023; // -1 (*1) + poly7[1] = 512; // -512 (*2) + poly7[2] = 511; // 511 (*4) + poly7[3] = 1; // 1 (*8) + value = -1 + -512 * 2 + 511 * 4 + 1 * 8; + ASSERT_TRUE(value == encoder2.decode_biguint(poly7)); + } + + TEST(Encoder, IntEncodeDecodeUInt64) + { + Modulus modulus(0xFFFFFFFFFFFFFFF); + EncryptionParameters parms(scheme_type::BFV); + parms.set_plain_modulus(modulus); + auto context = SEALContext::Create(parms); + IntegerEncoder encoder(context); + + Plaintext poly = encoder.encode(static_cast<uint64_t>(0)); + ASSERT_EQ(0ULL, poly.significant_coeff_count()); + ASSERT_TRUE(poly.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), encoder.decode_uint64(poly)); + + Plaintext poly1 = encoder.encode(1u); + ASSERT_EQ(1ULL, poly1.coeff_count()); + ASSERT_TRUE("1" == poly1.to_string()); + ASSERT_EQ(1ULL, encoder.decode_uint64(poly1)); + + Plaintext poly2 = encoder.encode(static_cast<uint64_t>(2)); + ASSERT_EQ(2ULL, poly2.coeff_count()); + ASSERT_TRUE("1x^1" == poly2.to_string()); + ASSERT_EQ(static_cast<uint64_t>(2), encoder.decode_uint64(poly2)); + + Plaintext poly3 = encoder.encode(static_cast<uint64_t>(3)); + ASSERT_EQ(2ULL, poly3.coeff_count()); + ASSERT_TRUE("1x^1 + 1" == poly3.to_string()); + ASSERT_EQ(static_cast<uint64_t>(3), encoder.decode_uint64(poly3)); + + Plaintext poly4 = encoder.encode(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF)); + ASSERT_EQ(64ULL, poly4.coeff_count()); + for (size_t i = 0; i < 64; ++i) + { + ASSERT_TRUE(poly4[i] == 1); + } + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), encoder.decode_uint64(poly4)); + + Plaintext poly5 = encoder.encode(static_cast<uint64_t>(0x80F02)); + ASSERT_EQ(20ULL, poly5.coeff_count()); + for (size_t i = 0; i < 20; ++i) + { + if (i == 19 || (i >= 8 && i <= 11) || i == 1) + { + ASSERT_TRUE(poly5[i] == 1); + } + else + { + ASSERT_TRUE(poly5[i] == 0); + } + } + ASSERT_EQ(static_cast<uint64_t>(0x80F02), encoder.decode_uint64(poly5)); + + Plaintext poly6(3); + poly6[0] = 1; + poly6[1] = 500; + poly6[2] = 1023; + ASSERT_EQ(static_cast<uint64_t>(1 + 500 * 2 + 1023 * 4), encoder.decode_uint64(poly6)); + + modulus = 1024; + parms.set_plain_modulus(modulus); + auto context2 = SEALContext::Create(parms); + IntegerEncoder encoder2(context2); + Plaintext poly7(4); + poly7[0] = 1023; // -1 (*1) + poly7[1] = 512; // -512 (*2) + poly7[2] = 511; // 511 (*4) + poly7[3] = 1; // 1 (*8) + ASSERT_EQ(static_cast<uint64_t>(-1 + -512 * 2 + 511 * 4 + 1 * 8), encoder2.decode_uint64(poly7)); + } + + TEST(Encoder, IntEncodeDecodeUInt32) + { + Modulus modulus(0xFFFFFFFFFFFFFFF); + EncryptionParameters parms(scheme_type::BFV); + parms.set_plain_modulus(modulus); + auto context = SEALContext::Create(parms); + IntegerEncoder encoder(context); + + Plaintext poly = encoder.encode(static_cast<uint32_t>(0)); + ASSERT_EQ(0ULL, poly.significant_coeff_count()); + ASSERT_TRUE(poly.is_zero()); + ASSERT_EQ(static_cast<uint32_t>(0), encoder.decode_uint32(poly)); + + Plaintext poly1 = encoder.encode(static_cast<uint32_t>(1)); + ASSERT_EQ(1ULL, poly1.significant_coeff_count()); + ASSERT_TRUE("1" == poly1.to_string()); + ASSERT_EQ(static_cast<uint32_t>(1), encoder.decode_uint32(poly1)); + + Plaintext poly2 = encoder.encode(static_cast<uint32_t>(2)); + ASSERT_EQ(2ULL, poly2.significant_coeff_count()); + ASSERT_TRUE("1x^1" == poly2.to_string()); + ASSERT_EQ(static_cast<uint32_t>(2), encoder.decode_uint32(poly2)); + + Plaintext poly3 = encoder.encode(static_cast<uint32_t>(3)); + ASSERT_EQ(2ULL, poly3.significant_coeff_count()); + ASSERT_TRUE("1x^1 + 1" == poly3.to_string()); + ASSERT_EQ(static_cast<uint32_t>(3), encoder.decode_uint32(poly3)); + + Plaintext poly4 = encoder.encode(static_cast<uint32_t>(0xFFFFFFFF)); + ASSERT_EQ(32ULL, poly4.significant_coeff_count()); + for (size_t i = 0; i < 32; ++i) + { + ASSERT_TRUE(1 == poly4[i]); + } + ASSERT_EQ(static_cast<uint32_t>(0xFFFFFFFF), encoder.decode_uint32(poly4)); + + Plaintext poly5 = encoder.encode(static_cast<uint32_t>(0x80F02)); + ASSERT_EQ(20ULL, poly5.significant_coeff_count()); + for (size_t i = 0; i < 20; ++i) + { + if (i == 19 || (i >= 8 && i <= 11) || i == 1) + { + ASSERT_TRUE(1 == poly5[i]); + } + else + { + ASSERT_TRUE(poly5[i] == 0); + } + } + ASSERT_EQ(static_cast<uint32_t>(0x80F02), encoder.decode_uint32(poly5)); + + Plaintext poly6(3); + poly6[0] = 1; + poly6[1] = 500; + poly6[2] = 1023; + ASSERT_EQ(static_cast<uint32_t>(1 + 500 * 2 + 1023 * 4), encoder.decode_uint32(poly6)); + + modulus = 1024; + parms.set_plain_modulus(modulus); + auto context2 = SEALContext::Create(parms); + IntegerEncoder encoder2(context2); + Plaintext poly7(4); + poly7[0] = 1023; // -1 (*1) + poly7[1] = 512; // -512 (*2) + poly7[2] = 511; // 511 (*4) + poly7[3] = 1; // 1 (*8) + ASSERT_EQ(static_cast<uint32_t>(-1 + -512 * 2 + 511 * 4 + 1 * 8), encoder2.decode_uint32(poly7)); + } + + TEST(Encoder, IntEncodeDecodeInt64) + { + Modulus modulus(0x7FFFFFFFFFFFF); + EncryptionParameters parms(scheme_type::BFV); + parms.set_plain_modulus(modulus); + auto context = SEALContext::Create(parms); + IntegerEncoder encoder(context); + + Plaintext poly = encoder.encode(static_cast<int64_t>(0)); + ASSERT_EQ(0ULL, poly.significant_coeff_count()); + ASSERT_TRUE(poly.is_zero()); + ASSERT_EQ(static_cast<uint64_t>(0), static_cast<uint64_t>(encoder.decode_int64(poly))); + + Plaintext poly1 = encoder.encode(static_cast<int64_t>(1)); + ASSERT_EQ(1ULL, poly1.significant_coeff_count()); + ASSERT_TRUE("1" == poly1.to_string()); + ASSERT_EQ(1ULL, static_cast<uint64_t>(encoder.decode_int64(poly1))); + + Plaintext poly2 = encoder.encode(static_cast<int64_t>(2)); + ASSERT_EQ(2ULL, poly2.significant_coeff_count()); + ASSERT_TRUE("1x^1" == poly2.to_string()); + ASSERT_EQ(static_cast<uint64_t>(2), static_cast<uint64_t>(encoder.decode_int64(poly2))); + + Plaintext poly3 = encoder.encode(static_cast<int64_t>(3)); + ASSERT_EQ(2ULL, poly3.significant_coeff_count()); + ASSERT_TRUE("1x^1 + 1" == poly3.to_string()); + ASSERT_EQ(static_cast<uint64_t>(3), static_cast<uint64_t>(encoder.decode_int64(poly3))); + + Plaintext poly4 = encoder.encode(static_cast<int64_t>(-1)); + ASSERT_EQ(1ULL, poly4.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFE" == poly4.to_string()); + ASSERT_EQ(static_cast<uint64_t>(-1), static_cast<uint64_t>(encoder.decode_int64(poly4))); + + Plaintext poly5 = encoder.encode(static_cast<int64_t>(-2)); + ASSERT_EQ(2ULL, poly5.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFEx^1" == poly5.to_string()); + ASSERT_EQ(static_cast<uint64_t>(-2), static_cast<uint64_t>(encoder.decode_int64(poly5))); + + Plaintext poly6 = encoder.encode(static_cast<int64_t>(-3)); + ASSERT_EQ(2ULL, poly6.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFEx^1 + 7FFFFFFFFFFFE" == poly6.to_string()); + ASSERT_EQ(static_cast<uint64_t>(-3), static_cast<uint64_t>(encoder.decode_int64(poly6))); + + Plaintext poly7 = encoder.encode(static_cast<int64_t>(0x7FFFFFFFFFFFF)); + ASSERT_EQ(51ULL, poly7.significant_coeff_count()); + for (size_t i = 0; i < 51; ++i) + { + ASSERT_TRUE(1 == poly7[i]); + } + ASSERT_EQ(static_cast<uint64_t>(0x7FFFFFFFFFFFF), static_cast<uint64_t>(encoder.decode_int64(poly7))); + + Plaintext poly8 = encoder.encode(static_cast<int64_t>(0x8000000000000)); + ASSERT_EQ(52ULL, poly8.significant_coeff_count()); + ASSERT_TRUE(poly8[51] == 1); + for (size_t i = 0; i < 51; ++i) + { + ASSERT_TRUE(poly8[i] == 0); + } + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000), static_cast<uint64_t>(encoder.decode_int64(poly8))); + + Plaintext poly9 = encoder.encode(static_cast<int64_t>(0x80F02)); + ASSERT_EQ(20ULL, poly9.significant_coeff_count()); + for (size_t i = 0; i < 20; ++i) + { + if (i == 19 || (i >= 8 && i <= 11) || i == 1) + { + ASSERT_TRUE(1 == poly9[i]); + } + else + { + ASSERT_TRUE(poly9[i] == 0); + } + } + ASSERT_EQ(static_cast<uint64_t>(0x80F02), static_cast<uint64_t>(encoder.decode_int64(poly9))); + + Plaintext poly10 = encoder.encode(static_cast<int64_t>(-1073)); + ASSERT_EQ(11ULL, poly10.significant_coeff_count()); + ASSERT_TRUE(0x7FFFFFFFFFFFE == poly10[10]); + ASSERT_TRUE(poly10[9] == 0); + ASSERT_TRUE(poly10[8] == 0); + ASSERT_TRUE(poly10[7] == 0); + ASSERT_TRUE(poly10[6] == 0); + ASSERT_TRUE(0x7FFFFFFFFFFFE == poly10[5]); + ASSERT_TRUE(0x7FFFFFFFFFFFE == poly10[4]); + ASSERT_TRUE(poly10[3] == 0); + ASSERT_TRUE(poly10[2] == 0); + ASSERT_TRUE(poly10[1] == 0); + ASSERT_TRUE(0x7FFFFFFFFFFFE == poly10[0]); + ASSERT_EQ(static_cast<uint64_t>(-1073), static_cast<uint64_t>(encoder.decode_int64(poly10))); + + modulus = 0xFFFF; + parms.set_plain_modulus(modulus); + auto context2 = SEALContext::Create(parms); + IntegerEncoder encoder2(context2); + Plaintext poly11(6); + poly11[0] = 1; + poly11[1] = 0xFFFE; // -1 + poly11[2] = 0xFFFD; // -2 + poly11[3] = 0x8000; // -32767 + poly11[4] = 0x7FFF; // 32767 + poly11[5] = 0x7FFE; // 32766 + ASSERT_EQ( + static_cast<uint64_t>(1 + -1 * 2 + -2 * 4 + -32767 * 8 + 32767 * 16 + 32766 * 32), + static_cast<uint64_t>(encoder2.decode_int64(poly11))); + } + + TEST(Encoder, IntEncodeDecodeInt32) + { + Modulus modulus(0x7FFFFFFFFFFFFF); + EncryptionParameters parms(scheme_type::BFV); + parms.set_plain_modulus(modulus); + auto context = SEALContext::Create(parms); + IntegerEncoder encoder(context); + + Plaintext poly = encoder.encode(static_cast<int32_t>(0)); + ASSERT_EQ(0ULL, poly.significant_coeff_count()); + ASSERT_TRUE(poly.is_zero()); + ASSERT_EQ(static_cast<int32_t>(0), encoder.decode_int32(poly)); + + Plaintext poly1 = encoder.encode(static_cast<int32_t>(1)); + ASSERT_EQ(1ULL, poly1.significant_coeff_count()); + ASSERT_TRUE("1" == poly1.to_string()); + ASSERT_EQ(static_cast<int32_t>(1), encoder.decode_int32(poly1)); + + Plaintext poly2 = encoder.encode(static_cast<int32_t>(2)); + ASSERT_EQ(2ULL, poly2.significant_coeff_count()); + ASSERT_TRUE("1x^1" == poly2.to_string()); + ASSERT_EQ(static_cast<int32_t>(2), encoder.decode_int32(poly2)); + + Plaintext poly3 = encoder.encode(static_cast<int32_t>(3)); + ASSERT_EQ(2ULL, poly3.significant_coeff_count()); + ASSERT_TRUE("1x^1 + 1" == poly3.to_string()); + ASSERT_EQ(static_cast<int32_t>(3), encoder.decode_int32(poly3)); + + Plaintext poly4 = encoder.encode(static_cast<int32_t>(-1)); + ASSERT_EQ(1ULL, poly4.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFFE" == poly4.to_string()); + ASSERT_EQ(static_cast<int32_t>(-1), encoder.decode_int32(poly4)); + + Plaintext poly5 = encoder.encode(static_cast<int32_t>(-2)); + ASSERT_EQ(2ULL, poly5.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFFEx^1" == poly5.to_string()); + ASSERT_EQ(static_cast<int32_t>(-2), encoder.decode_int32(poly5)); + + Plaintext poly6 = encoder.encode(static_cast<int32_t>(-3)); + ASSERT_EQ(2ULL, poly6.significant_coeff_count()); + ASSERT_TRUE("7FFFFFFFFFFFFEx^1 + 7FFFFFFFFFFFFE" == poly6.to_string()); + ASSERT_EQ(static_cast<int32_t>(-3), encoder.decode_int32(poly6)); + + Plaintext poly7 = encoder.encode(static_cast<int32_t>(0x7FFFFFFF)); + ASSERT_EQ(31ULL, poly7.significant_coeff_count()); + for (size_t i = 0; i < 31; ++i) + { + ASSERT_TRUE(1 == poly7[i]); + } + ASSERT_EQ(static_cast<int32_t>(0x7FFFFFFF), encoder.decode_int32(poly7)); + + Plaintext poly8 = encoder.encode(static_cast<int32_t>(0x80000000)); + ASSERT_EQ(32ULL, poly8.significant_coeff_count()); + ASSERT_TRUE(0x7FFFFFFFFFFFFE == poly8[31]); + for (size_t i = 0; i < 31; ++i) + { + ASSERT_TRUE(poly8[i] == 0); + } + ASSERT_EQ(static_cast<int32_t>(0x80000000), encoder.decode_int32(poly8)); + + Plaintext poly9 = encoder.encode(static_cast<int32_t>(0x80F02)); + ASSERT_EQ(20ULL, poly9.significant_coeff_count()); + for (size_t i = 0; i < 20; ++i) + { + if (i == 19 || (i >= 8 && i <= 11) || i == 1) + { + ASSERT_TRUE(1 == poly9[i]); + } + else + { + ASSERT_TRUE(poly9[i] == 0); + } + } + ASSERT_EQ(static_cast<int32_t>(0x80F02), encoder.decode_int32(poly9)); + + Plaintext poly10 = encoder.encode(static_cast<int32_t>(-1073)); + ASSERT_EQ(11ULL, poly10.significant_coeff_count()); + ASSERT_TRUE(0x7FFFFFFFFFFFFE == poly10[10]); + ASSERT_TRUE(poly10[9] == 0); + ASSERT_TRUE(poly10[8] == 0); + ASSERT_TRUE(poly10[7] == 0); + ASSERT_TRUE(poly10[6] == 0); + ASSERT_TRUE(0x7FFFFFFFFFFFFE == poly10[5]); + ASSERT_TRUE(0x7FFFFFFFFFFFFE == poly10[4]); + ASSERT_TRUE(poly10[3] == 0); + ASSERT_TRUE(poly10[2] == 0); + ASSERT_TRUE(poly10[1] == 0); + ASSERT_TRUE(0x7FFFFFFFFFFFFE == poly10[0]); + ASSERT_EQ(static_cast<int32_t>(-1073), encoder.decode_int32(poly10)); + + modulus = 0xFFFF; + parms.set_plain_modulus(modulus); + auto context2 = SEALContext::Create(parms); + IntegerEncoder encoder2(context2); + Plaintext poly11(6); + poly11[0] = 1; + poly11[1] = 0xFFFE; // -1 + poly11[2] = 0xFFFD; // -2 + poly11[3] = 0x8000; // -32767 + poly11[4] = 0x7FFF; // 32767 + poly11[5] = 0x7FFE; // 32766 + ASSERT_EQ( + static_cast<int32_t>(1 + -1 * 2 + -2 * 4 + -32767 * 8 + 32767 * 16 + 32766 * 32), + encoder2.decode_int32(poly11)); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/keygenerator.cpp b/bigpiseal3.5.1/native/tests/seal/keygenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddc0fcc24b8d034dde829e0def87cdd6b4f7c7b9 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/keygenerator.cpp @@ -0,0 +1,355 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/decryptor.h" +#include "seal/encryptor.h" +#include "seal/evaluator.h" +#include "seal/keygenerator.h" +#include "seal/valcheck.h" +#include "seal/util/polycore.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(KeyGeneratorTest, BFVKeyGeneration) + { + EncryptionParameters parms(scheme_type::BFV); + { + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + ASSERT_THROW(RelinKeys evk = keygen.relin_keys_local(), logic_error); + ASSERT_THROW(GaloisKeys galk = keygen.galois_keys_local(), logic_error); + } + { + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys evk = keygen.relin_keys_local(); + ASSERT_TRUE(evk.parms_id() == context->key_parms_id()); + ASSERT_EQ(1ULL, evk.key(2).size()); + for (auto &a : evk.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(evk, context)); + + GaloisKeys galks = keygen.galois_keys_local(); + for (auto &a : galks.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(galks, context)); + + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_EQ(1ULL, galks.key(3).size()); + ASSERT_EQ(10ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1, 3, 5, 7 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(3)); + ASSERT_TRUE(galks.has_key(5)); + ASSERT_TRUE(galks.has_key(7)); + ASSERT_FALSE(galks.has_key(9)); + ASSERT_FALSE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.key(3).size()); + ASSERT_EQ(1ULL, galks.key(5).size()); + ASSERT_EQ(1ULL, galks.key(7).size()); + ASSERT_EQ(4ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_FALSE(galks.has_key(3)); + ASSERT_FALSE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 127 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_FALSE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(127).size()); + ASSERT_EQ(1ULL, galks.size()); + } + { + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys evk = keygen.relin_keys_local(); + ASSERT_TRUE(evk.parms_id() == context->key_parms_id()); + ASSERT_EQ(2ULL, evk.key(2).size()); + + for (auto &a : evk.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(evk, context)); + + GaloisKeys galks = keygen.galois_keys_local(); + for (auto &a : galks.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(galks, context)); + + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_EQ(2ULL, galks.key(3).size()); + ASSERT_EQ(14ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1, 3, 5, 7 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(3)); + ASSERT_TRUE(galks.has_key(5)); + ASSERT_TRUE(galks.has_key(7)); + ASSERT_FALSE(galks.has_key(9)); + ASSERT_FALSE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(1).size()); + ASSERT_EQ(2ULL, galks.key(3).size()); + ASSERT_EQ(2ULL, galks.key(5).size()); + ASSERT_EQ(2ULL, galks.key(7).size()); + ASSERT_EQ(4ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_FALSE(galks.has_key(3)); + ASSERT_FALSE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 511 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_FALSE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(511).size()); + ASSERT_EQ(1ULL, galks.size()); + } + } + + TEST(KeyGeneratorTest, CKKSKeyGeneration) + { + EncryptionParameters parms(scheme_type::CKKS); + { + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + ASSERT_THROW(RelinKeys evk = keygen.relin_keys_local(), logic_error); + ASSERT_THROW(GaloisKeys galk = keygen.galois_keys_local(), logic_error); + } + { + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys evk = keygen.relin_keys_local(); + ASSERT_TRUE(evk.parms_id() == context->key_parms_id()); + ASSERT_EQ(1ULL, evk.key(2).size()); + for (auto &a : evk.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(evk, context)); + + GaloisKeys galks = keygen.galois_keys_local(); + for (auto &a : galks.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(galks, context)); + + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_EQ(1ULL, galks.key(3).size()); + ASSERT_EQ(10ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1, 3, 5, 7 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(3)); + ASSERT_TRUE(galks.has_key(5)); + ASSERT_TRUE(galks.has_key(7)); + ASSERT_FALSE(galks.has_key(9)); + ASSERT_FALSE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.key(3).size()); + ASSERT_EQ(1ULL, galks.key(5).size()); + ASSERT_EQ(1ULL, galks.key(7).size()); + ASSERT_EQ(4ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_FALSE(galks.has_key(3)); + ASSERT_FALSE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 127 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_FALSE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(127)); + ASSERT_EQ(1ULL, galks.key(127).size()); + ASSERT_EQ(1ULL, galks.size()); + } + { + parms.set_poly_modulus_degree(256); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys evk = keygen.relin_keys_local(); + ASSERT_TRUE(evk.parms_id() == context->key_parms_id()); + ASSERT_EQ(2ULL, evk.key(2).size()); + for (auto &a : evk.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(evk, context)); + + GaloisKeys galks = keygen.galois_keys_local(); + for (auto &a : galks.data()) + { + for (auto &b : a) + { + ASSERT_FALSE(b.data().is_transparent()); + } + } + ASSERT_TRUE(is_valid_for(galks, context)); + + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_EQ(2ULL, galks.key(3).size()); + ASSERT_EQ(14ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1, 3, 5, 7 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(3)); + ASSERT_TRUE(galks.has_key(5)); + ASSERT_TRUE(galks.has_key(7)); + ASSERT_FALSE(galks.has_key(9)); + ASSERT_FALSE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(1).size()); + ASSERT_EQ(2ULL, galks.key(3).size()); + ASSERT_EQ(2ULL, galks.key(5).size()); + ASSERT_EQ(2ULL, galks.key(7).size()); + ASSERT_EQ(4ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 1 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_TRUE(galks.has_key(1)); + ASSERT_FALSE(galks.has_key(3)); + ASSERT_FALSE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(1).size()); + ASSERT_EQ(1ULL, galks.size()); + + galks = keygen.galois_keys_local(vector<uint32_t>{ 511 }); + ASSERT_TRUE(galks.parms_id() == context->key_parms_id()); + ASSERT_FALSE(galks.has_key(1)); + ASSERT_TRUE(galks.has_key(511)); + ASSERT_EQ(2ULL, galks.key(511).size()); + ASSERT_EQ(1ULL, galks.size()); + } + } + + TEST(KeyGeneratorTest, Constructors) + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(128); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(128, { 60, 50, 40 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + Evaluator evaluator(context); + + KeyGenerator keygen(context); + auto pk = keygen.public_key(); + auto sk = keygen.secret_key(); + RelinKeys rlk = keygen.relin_keys_local(); + GaloisKeys galk = keygen.galois_keys_local(); + + ASSERT_TRUE(is_valid_for(rlk, context)); + ASSERT_TRUE(is_valid_for(galk, context)); + + Encryptor encryptor(context, pk); + Decryptor decryptor(context, sk); + Plaintext pt("1x^2 + 2"), ptres; + Ciphertext ct; + encryptor.encrypt(pt, ct); + evaluator.square_inplace(ct); + evaluator.relinearize_inplace(ct, rlk); + decryptor.decrypt(ct, ptres); + ASSERT_EQ("1x^4 + 4x^2 + 4", ptres.to_string()); + + KeyGenerator keygen2(context, sk); + auto sk2 = keygen.secret_key(); + auto pk2 = keygen2.public_key(); + ASSERT_EQ(sk2.data(), sk.data()); + + RelinKeys rlk2 = keygen2.relin_keys_local(); + GaloisKeys galk2 = keygen2.galois_keys_local(); + + ASSERT_TRUE(is_valid_for(rlk2, context)); + ASSERT_TRUE(is_valid_for(galk2, context)); + + Encryptor encryptor2(context, pk2); + Decryptor decryptor2(context, sk2); + pt = "1x^2 + 2"; + ptres.set_zero(); + encryptor.encrypt(pt, ct); + evaluator.square_inplace(ct); + evaluator.relinearize_inplace(ct, rlk2); + decryptor.decrypt(ct, ptres); + ASSERT_EQ("1x^4 + 4x^2 + 4", ptres.to_string()); + + auto pk3 = keygen2.public_key(); + + // There is a small random chance for this to fail + for (size_t i = 0; i < pk3.data().int_array().size(); i++) + { + ASSERT_NE(pk3.data().data()[i], pk2.data().data()[i]); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/memorymanager.cpp b/bigpiseal3.5.1/native/tests/seal/memorymanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbd1988282985f7876b4a51e8a6f1cd08343e191 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/memorymanager.cpp @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/intarray.h" +#include "seal/memorymanager.h" +#include "seal/util/pointer.h" +#include "seal/util/uintcore.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(MemoryPoolHandleTest, MemoryPoolHandleConstructAssign) + { + MemoryPoolHandle pool; + ASSERT_FALSE(pool); + pool = MemoryPoolHandle::Global(); + ASSERT_TRUE(&static_cast<MemoryPool &>(pool) == global_variables::global_memory_pool.get()); + pool = MemoryPoolHandle::New(); + ASSERT_FALSE(&pool.operator seal::util::MemoryPool &() == global_variables::global_memory_pool.get()); + MemoryPoolHandle pool2 = MemoryPoolHandle::New(); + ASSERT_FALSE(pool == pool2); + + pool = pool2; + ASSERT_TRUE(pool == pool2); + pool = MemoryPoolHandle::Global(); + ASSERT_FALSE(pool == pool2); + pool2 = MemoryPoolHandle::Global(); + ASSERT_TRUE(pool == pool2); + } + + TEST(MemoryPoolHandleTest, MemoryPoolHandleAllocate) + { + MemoryPoolHandle pool = MemoryPoolHandle::New(); + ASSERT_TRUE(0LL == pool.alloc_byte_count()); + { + auto ptr(allocate_uint(5, pool)); + ASSERT_TRUE(5LL * bytes_per_uint64 == pool.alloc_byte_count()); + } + + pool = MemoryPoolHandle::New(); + ASSERT_TRUE(0LL * bytes_per_uint64 == pool.alloc_byte_count()); + { + auto ptr(allocate_uint(5, pool)); + ASSERT_TRUE(5LL * bytes_per_uint64 == pool.alloc_byte_count()); + + ptr = allocate_uint(8, pool); + ASSERT_TRUE(13LL * bytes_per_uint64 == pool.alloc_byte_count()); + + auto ptr2(allocate_uint(2, pool)); + ASSERT_TRUE(15LL * bytes_per_uint64 == pool.alloc_byte_count()); + } + } + + TEST(MemoryPoolHandleTest, UseCount) + { + MemoryPoolHandle pool = MemoryPoolHandle::New(); + ASSERT_EQ(1L, pool.use_count()); + { + IntArray<int> arr(pool); + ASSERT_EQ(2L, pool.use_count()); + IntArray<int> arr2(pool); + ASSERT_EQ(3L, pool.use_count()); + } + ASSERT_EQ(1L, pool.use_count()); + } +} // namespace sealtest \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/seal/modulus.cpp b/bigpiseal3.5.1/native/tests/seal/modulus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..423629e7a3591564af4350213752a46843e0b0b7 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/modulus.cpp @@ -0,0 +1,209 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/uintcore.h" +#include <stdexcept> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(ModulusTest, CreateModulus) + { + Modulus mod; + ASSERT_TRUE(mod.is_zero()); + ASSERT_EQ(0ULL, mod.value()); + ASSERT_EQ(0, mod.bit_count()); + ASSERT_EQ(1ULL, mod.uint64_count()); + ASSERT_EQ(0ULL, mod.const_ratio()[0]); + ASSERT_EQ(0ULL, mod.const_ratio()[1]); + ASSERT_EQ(0ULL, mod.const_ratio()[2]); + ASSERT_FALSE(mod.is_prime()); + + mod = 3; + ASSERT_FALSE(mod.is_zero()); + ASSERT_EQ(3ULL, mod.value()); + ASSERT_EQ(2, mod.bit_count()); + ASSERT_EQ(1ULL, mod.uint64_count()); + ASSERT_EQ(6148914691236517205ULL, mod.const_ratio()[0]); + ASSERT_EQ(6148914691236517205ULL, mod.const_ratio()[1]); + ASSERT_EQ(1ULL, mod.const_ratio()[2]); + ASSERT_TRUE(mod.is_prime()); + + Modulus mod2(2); + Modulus mod3(3); + ASSERT_TRUE(mod != mod2); + ASSERT_TRUE(mod == mod3); + + mod = 0; + ASSERT_TRUE(mod.is_zero()); + ASSERT_EQ(0ULL, mod.value()); + ASSERT_EQ(0, mod.bit_count()); + ASSERT_EQ(1ULL, mod.uint64_count()); + ASSERT_EQ(0ULL, mod.const_ratio()[0]); + ASSERT_EQ(0ULL, mod.const_ratio()[1]); + ASSERT_EQ(0ULL, mod.const_ratio()[2]); + + mod = 0xF00000F00000F; + ASSERT_FALSE(mod.is_zero()); + ASSERT_EQ(0xF00000F00000FULL, mod.value()); + ASSERT_EQ(52, mod.bit_count()); + ASSERT_EQ(1ULL, mod.uint64_count()); + ASSERT_EQ(1224979098644774929ULL, mod.const_ratio()[0]); + ASSERT_EQ(4369ULL, mod.const_ratio()[1]); + ASSERT_EQ(281470698520321ULL, mod.const_ratio()[2]); + ASSERT_FALSE(mod.is_prime()); + + mod = 0xF00000F000079; + ASSERT_FALSE(mod.is_zero()); + ASSERT_EQ(0xF00000F000079ULL, mod.value()); + ASSERT_EQ(52, mod.bit_count()); + ASSERT_EQ(1ULL, mod.uint64_count()); + ASSERT_EQ(1224979096621368355ULL, mod.const_ratio()[0]); + ASSERT_EQ(4369ULL, mod.const_ratio()[1]); + ASSERT_EQ(1144844808538997ULL, mod.const_ratio()[2]); + ASSERT_TRUE(mod.is_prime()); + } + + TEST(ModulusTest, CompareModulus) + { + Modulus sm0; + Modulus sm2(2); + Modulus sm5(5); + ASSERT_FALSE(sm0 < sm0); + ASSERT_TRUE(sm0 == sm0); + ASSERT_TRUE(sm0 <= sm0); + ASSERT_TRUE(sm0 >= sm0); + ASSERT_FALSE(sm0 > sm0); + + ASSERT_FALSE(sm5 < sm5); + ASSERT_TRUE(sm5 == sm5); + ASSERT_TRUE(sm5 <= sm5); + ASSERT_TRUE(sm5 >= sm5); + ASSERT_FALSE(sm5 > sm5); + + ASSERT_FALSE(sm5 < sm2); + ASSERT_FALSE(sm5 == sm2); + ASSERT_FALSE(sm5 <= sm2); + ASSERT_TRUE(sm5 >= sm2); + ASSERT_TRUE(sm5 > sm2); + + ASSERT_TRUE(sm5 < 6); + ASSERT_FALSE(sm5 == 6); + ASSERT_TRUE(sm5 <= 6); + ASSERT_FALSE(sm5 >= 6); + ASSERT_FALSE(sm5 > 6); + } + + TEST(ModulusTest, SaveLoadModulus) + { + stringstream stream; + + Modulus mod; + mod.save(stream); + + Modulus mod2; + mod2.load(stream); + ASSERT_EQ(mod2.value(), mod.value()); + ASSERT_EQ(mod2.bit_count(), mod.bit_count()); + ASSERT_EQ(mod2.uint64_count(), mod.uint64_count()); + ASSERT_EQ(mod2.const_ratio()[0], mod.const_ratio()[0]); + ASSERT_EQ(mod2.const_ratio()[1], mod.const_ratio()[1]); + ASSERT_EQ(mod2.const_ratio()[2], mod.const_ratio()[2]); + ASSERT_EQ(mod2.is_prime(), mod.is_prime()); + + mod = 3; + mod.save(stream); + mod2.load(stream); + ASSERT_EQ(mod2.value(), mod.value()); + ASSERT_EQ(mod2.bit_count(), mod.bit_count()); + ASSERT_EQ(mod2.uint64_count(), mod.uint64_count()); + ASSERT_EQ(mod2.const_ratio()[0], mod.const_ratio()[0]); + ASSERT_EQ(mod2.const_ratio()[1], mod.const_ratio()[1]); + ASSERT_EQ(mod2.const_ratio()[2], mod.const_ratio()[2]); + ASSERT_EQ(mod2.is_prime(), mod.is_prime()); + + mod = 0xF00000F00000F; + mod.save(stream); + mod2.load(stream); + ASSERT_EQ(mod2.value(), mod.value()); + ASSERT_EQ(mod2.bit_count(), mod.bit_count()); + ASSERT_EQ(mod2.uint64_count(), mod.uint64_count()); + ASSERT_EQ(mod2.const_ratio()[0], mod.const_ratio()[0]); + ASSERT_EQ(mod2.const_ratio()[1], mod.const_ratio()[1]); + ASSERT_EQ(mod2.const_ratio()[2], mod.const_ratio()[2]); + ASSERT_EQ(mod2.is_prime(), mod.is_prime()); + + mod = 0xF00000F000079; + mod.save(stream); + mod2.load(stream); + ASSERT_EQ(mod2.value(), mod.value()); + ASSERT_EQ(mod2.bit_count(), mod.bit_count()); + ASSERT_EQ(mod2.uint64_count(), mod.uint64_count()); + ASSERT_EQ(mod2.const_ratio()[0], mod.const_ratio()[0]); + ASSERT_EQ(mod2.const_ratio()[1], mod.const_ratio()[1]); + ASSERT_EQ(mod2.const_ratio()[2], mod.const_ratio()[2]); + ASSERT_EQ(mod2.is_prime(), mod.is_prime()); + } + + TEST(CoeffModTest, CustomExceptionTest) + { + // Too small poly_modulus_degree + ASSERT_THROW(auto modulus = CoeffModulus::Create(1, { 2 }), invalid_argument); + + // Too large poly_modulus_degree + ASSERT_THROW(auto modulus = CoeffModulus::Create(262144, { 30 }), invalid_argument); + + // Invalid poly_modulus_degree + ASSERT_THROW(auto modulus = CoeffModulus::Create(1023, { 20 }), invalid_argument); + + // Invalid bit-size + ASSERT_THROW(auto modulus = CoeffModulus::Create(2048, { 0 }), invalid_argument); + ASSERT_THROW(auto modulus = CoeffModulus::Create(2048, { -30 }), invalid_argument); + ASSERT_THROW(auto modulus = CoeffModulus::Create(2048, { 30, -30 }), invalid_argument); + + // Too small primes requested + ASSERT_THROW(auto modulus = CoeffModulus::Create(2, { 2 }), logic_error); + ASSERT_THROW(auto modulus = CoeffModulus::Create(2, { 3, 3, 3 }), logic_error); + ASSERT_THROW(auto modulus = CoeffModulus::Create(1024, { 8 }), logic_error); + } + + TEST(CoeffModTest, CustomTest) + { + auto cm = CoeffModulus::Create(2, {}); + ASSERT_EQ(0, cm.size()); + + cm = CoeffModulus::Create(2, { 3 }); + ASSERT_EQ(1, cm.size()); + ASSERT_EQ(uint64_t(5), cm[0].value()); + + cm = CoeffModulus::Create(2, { 3, 4 }); + ASSERT_EQ(2, cm.size()); + ASSERT_EQ(uint64_t(5), cm[0].value()); + ASSERT_EQ(uint64_t(13), cm[1].value()); + + cm = CoeffModulus::Create(2, { 3, 5, 4, 5 }); + ASSERT_EQ(4, cm.size()); + ASSERT_EQ(uint64_t(5), cm[0].value()); + ASSERT_EQ(uint64_t(17), cm[1].value()); + ASSERT_EQ(uint64_t(13), cm[2].value()); + ASSERT_EQ(uint64_t(29), cm[3].value()); + + cm = CoeffModulus::Create(32, { 30, 40, 30, 30, 40 }); + ASSERT_EQ(5, cm.size()); + ASSERT_EQ(30, get_significant_bit_count(cm[0].value())); + ASSERT_EQ(40, get_significant_bit_count(cm[1].value())); + ASSERT_EQ(30, get_significant_bit_count(cm[2].value())); + ASSERT_EQ(30, get_significant_bit_count(cm[3].value())); + ASSERT_EQ(40, get_significant_bit_count(cm[4].value())); + ASSERT_EQ(1ULL, cm[0].value() % 64); + ASSERT_EQ(1ULL, cm[1].value() % 64); + ASSERT_EQ(1ULL, cm[2].value() % 64); + ASSERT_EQ(1ULL, cm[3].value() % 64); + ASSERT_EQ(1ULL, cm[4].value() % 64); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/plaintext.cpp b/bigpiseal3.5.1/native/tests/seal/plaintext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d70a6d59c79738c031e4e1c1203eb3a3d958a8d6 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/plaintext.cpp @@ -0,0 +1,164 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/ckks.h" +#include "seal/context.h" +#include "seal/evaluator.h" +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/plaintext.h" +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(PlaintextTest, PlaintextBasics) + { + Plaintext plain(2); + ASSERT_EQ(2ULL, plain.capacity()); + ASSERT_EQ(2ULL, plain.coeff_count()); + ASSERT_EQ(0ULL, plain.significant_coeff_count()); + ASSERT_EQ(0ULL, plain.nonzero_coeff_count()); + ASSERT_FALSE(plain.is_ntt_form()); + + plain[0] = 1; + plain[1] = 2; + + plain.reserve(10); + ASSERT_EQ(10ULL, plain.capacity()); + ASSERT_EQ(2ULL, plain.coeff_count()); + ASSERT_EQ(2ULL, plain.significant_coeff_count()); + ASSERT_EQ(2ULL, plain.nonzero_coeff_count()); + ASSERT_EQ(1ULL, plain[0]); + ASSERT_EQ(2ULL, plain[1]); + ASSERT_FALSE(plain.is_ntt_form()); + + plain.resize(5); + ASSERT_EQ(10ULL, plain.capacity()); + ASSERT_EQ(5ULL, plain.coeff_count()); + ASSERT_EQ(2ULL, plain.significant_coeff_count()); + ASSERT_EQ(2ULL, plain.nonzero_coeff_count()); + ASSERT_EQ(1ULL, plain[0]); + ASSERT_EQ(2ULL, plain[1]); + ASSERT_EQ(0ULL, plain[2]); + ASSERT_EQ(0ULL, plain[3]); + ASSERT_EQ(0ULL, plain[4]); + ASSERT_FALSE(plain.is_ntt_form()); + + Plaintext plain2; + plain2.resize(15); + ASSERT_EQ(15ULL, plain2.capacity()); + ASSERT_EQ(15ULL, plain2.coeff_count()); + ASSERT_EQ(0ULL, plain2.significant_coeff_count()); + ASSERT_EQ(0ULL, plain2.nonzero_coeff_count()); + ASSERT_FALSE(plain.is_ntt_form()); + + plain2 = plain; + ASSERT_EQ(15ULL, plain2.capacity()); + ASSERT_EQ(5ULL, plain2.coeff_count()); + ASSERT_EQ(2ULL, plain2.significant_coeff_count()); + ASSERT_EQ(2ULL, plain2.nonzero_coeff_count()); + ASSERT_EQ(1ULL, plain2[0]); + ASSERT_EQ(2ULL, plain2[1]); + ASSERT_EQ(0ULL, plain2[2]); + ASSERT_EQ(0ULL, plain2[3]); + ASSERT_EQ(0ULL, plain2[4]); + ASSERT_FALSE(plain.is_ntt_form()); + + plain.parms_id() = { 1ULL, 2ULL, 3ULL, 4ULL }; + ASSERT_TRUE(plain.is_ntt_form()); + plain2 = plain; + ASSERT_TRUE(plain == plain2); + plain2.parms_id() = parms_id_zero; + ASSERT_FALSE(plain2.is_ntt_form()); + ASSERT_FALSE(plain == plain2); + plain2.parms_id() = { 1ULL, 2ULL, 3ULL, 5ULL }; + ASSERT_FALSE(plain == plain2); + } + + TEST(PlaintextTest, SaveLoadPlaintext) + { + stringstream stream; + Plaintext plain; + Plaintext plain2; + + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(4); + parms.set_coeff_modulus(CoeffModulus::Create(4, { 20 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + plain.save(stream); + plain2.unsafe_load(context, stream); + ASSERT_TRUE(plain.data() == plain2.data()); + ASSERT_TRUE(plain2.data() == nullptr); + ASSERT_EQ(0ULL, plain2.capacity()); + ASSERT_EQ(0ULL, plain2.coeff_count()); + ASSERT_FALSE(plain2.is_ntt_form()); + + plain.reserve(20); + plain.resize(4); + plain[0] = 1; + plain[1] = 2; + plain[2] = 3; + plain.save(stream); + plain2.unsafe_load(context, stream); + ASSERT_TRUE(plain.data() != plain2.data()); + ASSERT_EQ(4ULL, plain2.capacity()); + ASSERT_EQ(4ULL, plain2.coeff_count()); + ASSERT_EQ(1ULL, plain2[0]); + ASSERT_EQ(2ULL, plain2[1]); + ASSERT_EQ(3ULL, plain2[2]); + ASSERT_EQ(0ULL, plain2[3]); + ASSERT_FALSE(plain2.is_ntt_form()); + + plain.parms_id() = context->first_parms_id(); + plain.save(stream); + plain2.unsafe_load(context, stream); + ASSERT_TRUE(plain2.is_ntt_form()); + ASSERT_TRUE(plain2.parms_id() == plain.parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30 })); + parms.set_plain_modulus(65537); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + + plain.parms_id() = parms_id_zero; + plain = "1x^63 + 2x^62 + Fx^32 + Ax^9 + 1x^1 + 1"; + plain.save(stream); + plain2.load(context, stream); + ASSERT_TRUE(plain.data() != plain2.data()); + ASSERT_FALSE(plain2.is_ntt_form()); + + Evaluator evaluator(context); + evaluator.transform_to_ntt_inplace(plain, context->first_parms_id()); + plain.save(stream); + plain2.load(context, stream); + ASSERT_TRUE(plain.data() != plain2.data()); + ASSERT_TRUE(plain2.is_ntt_form()); + } + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(64); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + CKKSEncoder encoder(context); + + encoder.encode(vector<double>{ 0.1, 2.3, 34.4 }, pow(2.0, 20), plain); + ASSERT_TRUE(plain.is_ntt_form()); + plain.save(stream); + plain2.load(context, stream); + ASSERT_TRUE(plain.data() != plain2.data()); + ASSERT_TRUE(plain2.is_ntt_form()); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/publickey.cpp b/bigpiseal3.5.1/native/tests/seal/publickey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24511dc6273cad70f3effc39730ebaa663d43f2b --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/publickey.cpp @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include "seal/publickey.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(PublicKeyTest, SaveLoadPublicKey) + { + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(1 << 6); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + PublicKey pk = keygen.public_key(); + ASSERT_TRUE(pk.parms_id() == context->key_parms_id()); + pk.save(stream); + + PublicKey pk2; + pk2.load(context, stream); + + ASSERT_EQ(pk.data().int_array().size(), pk2.data().int_array().size()); + for (size_t i = 0; i < pk.data().int_array().size(); i++) + { + ASSERT_EQ(pk.data().data()[i], pk2.data().data()[i]); + } + ASSERT_TRUE(pk.parms_id() == pk2.parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(1 << 20); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 30, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + PublicKey pk = keygen.public_key(); + ASSERT_TRUE(pk.parms_id() == context->key_parms_id()); + pk.save(stream); + + PublicKey pk2; + pk2.load(context, stream); + + ASSERT_EQ(pk.data().int_array().size(), pk2.data().int_array().size()); + for (size_t i = 0; i < pk.data().int_array().size(); i++) + { + ASSERT_EQ(pk.data().data()[i], pk2.data().data()[i]); + } + ASSERT_TRUE(pk.parms_id() == pk2.parms_id()); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/randomgen.cpp b/bigpiseal3.5.1/native/tests/seal/randomgen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a61a84f72091637bbcf73ff3415c1b945b716b91 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/randomgen.cpp @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/keygenerator.h" +#include "seal/randomgen.h" +#include <algorithm> +#include <cstdint> +#include <memory> +#include <numeric> +#include <set> +#include <thread> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + namespace + { + class SequentialRandomGenerator : public UniformRandomGenerator + { + public: + SequentialRandomGenerator() : UniformRandomGenerator({}) + {} + + ~SequentialRandomGenerator() override = default; + + protected: + void refill_buffer() override + { + iota(reinterpret_cast<uint8_t *>(buffer_begin_), reinterpret_cast<uint8_t *>(buffer_end_), value); + + value = static_cast<uint8_t>(static_cast<size_t>(value) + buffer_size_); + } + + private: + uint8_t value = 0; + }; + + class SequentialRandomGeneratorFactory : public UniformRandomGeneratorFactory + { + private: + SEAL_NODISCARD auto create_impl(SEAL_MAYBE_UNUSED random_seed_type seed) + -> shared_ptr<UniformRandomGenerator> override + { + return make_shared<SequentialRandomGenerator>(); + } + }; + } // namespace + + TEST(RandomGenerator, UniformRandomCreateDefault) + { + shared_ptr<UniformRandomGenerator> generator(UniformRandomGeneratorFactory::DefaultFactory()->create()); + bool lower_half = false; + bool upper_half = false; + bool even = false; + bool odd = false; + for (int i = 0; i < 10; ++i) + { + uint32_t value = generator->generate(); + if (value < UINT32_MAX / 2) + { + lower_half = true; + } + else + { + upper_half = true; + } + if ((value % 2) == 0) + { + even = true; + } + else + { + odd = true; + } + } + ASSERT_TRUE(lower_half); + ASSERT_TRUE(upper_half); + ASSERT_TRUE(even); + ASSERT_TRUE(odd); + } + + TEST(RandomGenerator, SequentialRandomGenerator) + { + unique_ptr<UniformRandomGenerator> sgen = make_unique<SequentialRandomGenerator>(); + array<uint8_t, 4096> value_list; + iota(value_list.begin(), value_list.end(), 0); + + array<uint8_t, 4096> compare_list; + sgen->generate(4096, reinterpret_cast<SEAL_BYTE *>(compare_list.data())); + + ASSERT_TRUE(equal(value_list.cbegin(), value_list.cend(), compare_list.cbegin())); + } + + TEST(RandomGenerator, RandomUInt64) + { + set<uint64_t> values; + size_t count = 100; + for (size_t i = 0; i < count; i++) + { + values.emplace(random_uint64()); + } + ASSERT_EQ(count, values.size()); + } + + TEST(RandomGenerator, SeededRNG) + { + auto generator1(UniformRandomGeneratorFactory::DefaultFactory()->create({})); + array<uint32_t, 20> values1; + generator1->generate(sizeof(values1), reinterpret_cast<SEAL_BYTE *>(values1.data())); + + auto generator2(UniformRandomGeneratorFactory::DefaultFactory()->create({ 1 })); + array<uint32_t, 20> values2; + generator2->generate(sizeof(values2), reinterpret_cast<SEAL_BYTE *>(values2.data())); + + auto generator3(UniformRandomGeneratorFactory::DefaultFactory()->create({ 1 })); + array<uint32_t, 20> values3; + generator3->generate(sizeof(values3), reinterpret_cast<SEAL_BYTE *>(values3.data())); + + for (size_t i = 0; i < values1.size(); i++) + { + ASSERT_NE(values1[i], values2[i]); + ASSERT_EQ(values2[i], values3[i]); + } + + uint32_t val1, val2, val3; + val1 = generator1->generate(); + val2 = generator2->generate(); + val3 = generator3->generate(); + ASSERT_NE(val1, val2); + ASSERT_EQ(val2, val3); + } + + TEST(RandomGenerator, RandomSeededRNG) + { + auto generator1(UniformRandomGeneratorFactory::DefaultFactory()->create()); + array<uint32_t, 20> values1; + generator1->generate(sizeof(values1), reinterpret_cast<SEAL_BYTE *>(values1.data())); + + auto generator2(UniformRandomGeneratorFactory::DefaultFactory()->create()); + array<uint32_t, 20> values2; + generator2->generate(sizeof(values2), reinterpret_cast<SEAL_BYTE *>(values2.data())); + + auto seed3 = generator2->seed(); + auto generator3(UniformRandomGeneratorFactory::DefaultFactory()->create(seed3)); + array<uint32_t, 20> values3; + generator3->generate(sizeof(values3), reinterpret_cast<SEAL_BYTE *>(values3.data())); + + for (size_t i = 0; i < values1.size(); i++) + { + ASSERT_NE(values1[i], values2[i]); + ASSERT_EQ(values2[i], values3[i]); + } + + uint32_t val1, val2, val3; + val1 = generator1->generate(); + val2 = generator2->generate(); + val3 = generator3->generate(); + ASSERT_NE(val1, val2); + ASSERT_EQ(val2, val3); + } + + TEST(RandomGenerator, MultiThreaded) + { + constexpr size_t thread_count = 2; + constexpr size_t numbers_per_thread = 50; + array<uint64_t, thread_count * numbers_per_thread> results; + + auto generator(UniformRandomGeneratorFactory::DefaultFactory()->create()); + + vector<thread> th_vec; + for (size_t i = 0; i < thread_count; i++) + { + auto th_func = [&, generator, i]() { + generator->generate( + sizeof(uint64_t) * numbers_per_thread, + reinterpret_cast<SEAL_BYTE *>(results.data() + numbers_per_thread * i)); + }; + th_vec.emplace_back(th_func); + } + + for (auto &th : th_vec) + { + th.join(); + } + + auto seed = generator->seed(); + auto generator2(UniformRandomGeneratorFactory::DefaultFactory()->create(seed)); + for (size_t i = 0; i < thread_count * numbers_per_thread; i++) + { + uint64_t value = 0; + generator2->generate(sizeof(value), reinterpret_cast<SEAL_BYTE *>(&value)); + ASSERT_TRUE(find(results.begin(), results.end(), value) != results.end()); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/randomtostd.cpp b/bigpiseal3.5.1/native/tests/seal/randomtostd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f974ebc34812f2052bb0356960d72ffb924f4dc3 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/randomtostd.cpp @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/randomgen.h" +#include "seal/randomtostd.h" +#include <cstdint> +#include <memory> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(RandomToStandard, RandomToStandardGenerate) + { + shared_ptr<UniformRandomGenerator> generator(UniformRandomGeneratorFactory::DefaultFactory()->create()); + RandomToStandardAdapter rand(generator); + ASSERT_TRUE(rand.generator() == generator); + ASSERT_EQ(static_cast<uint32_t>(0), rand.min()); + ASSERT_EQ(static_cast<uint32_t>(UINT32_MAX), rand.max()); + bool lower_half = false; + bool upper_half = false; + bool even = false; + bool odd = false; + for (int i = 0; i < 50; i++) + { + uint32_t value = rand(); + if (value < UINT32_MAX / 2) + { + lower_half = true; + } + else + { + upper_half = true; + } + if ((value % 2) == 0) + { + even = true; + } + else + { + odd = true; + } + } + ASSERT_TRUE(lower_half); + ASSERT_TRUE(upper_half); + ASSERT_TRUE(even); + ASSERT_TRUE(odd); + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/relinkeys.cpp b/bigpiseal3.5.1/native/tests/seal/relinkeys.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d42ebec7b4b775792215e1d3b7b2227b4cc9687d --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/relinkeys.cpp @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include "seal/relinkeys.h" +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/uintcore.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + TEST(RelinKeysTest, RelinKeysSaveLoad) + { + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(1 << 6); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60, 60 })); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys keys; + RelinKeys test_keys; + keys = keygen.relin_keys_local(); + keys.save(stream); + test_keys.load(context, stream); + ASSERT_EQ(keys.size(), test_keys.size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + for (size_t j = 0; j < test_keys.size(); j++) + { + for (size_t i = 0; i < test_keys.key(j + 2).size(); i++) + { + ASSERT_EQ(keys.key(j + 2)[i].data().size(), test_keys.key(j + 2)[i].data().size()); + ASSERT_EQ( + keys.key(j + 2)[i].data().int_array().size(), + test_keys.key(j + 2)[i].data().int_array().size()); + ASSERT_TRUE(is_equal_uint_uint( + keys.key(j + 2)[i].data().data(), test_keys.key(j + 2)[i].data().data(), + keys.key(j + 2)[i].data().int_array().size())); + } + } + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(1 << 6); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 50 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + RelinKeys keys; + RelinKeys test_keys; + keys = keygen.relin_keys_local(); + keys.save(stream); + test_keys.load(context, stream); + ASSERT_EQ(keys.size(), test_keys.size()); + ASSERT_TRUE(keys.parms_id() == test_keys.parms_id()); + for (size_t j = 0; j < test_keys.size(); j++) + { + for (size_t i = 0; i < test_keys.key(j + 2).size(); i++) + { + ASSERT_EQ(keys.key(j + 2)[i].data().size(), test_keys.key(j + 2)[i].data().size()); + ASSERT_EQ( + keys.key(j + 2)[i].data().int_array().size(), + test_keys.key(j + 2)[i].data().int_array().size()); + ASSERT_TRUE(is_equal_uint_uint( + keys.key(j + 2)[i].data().data(), test_keys.key(j + 2)[i].data().data(), + keys.key(j + 2)[i].data().int_array().size())); + } + } + } + } + TEST(RelinKeysTest, RelinKeysSeededSaveLoad) + { + // Returns true if a, b contains the same error. + auto compare_kswitchkeys = [](const KSwitchKeys &a, const KSwitchKeys &b, const SecretKey &sk, + shared_ptr<SEALContext> context) { + auto compare_error = [](const Ciphertext &a_ct, const Ciphertext &b_ct, const SecretKey &sk1, + shared_ptr<SEALContext> context1) { + auto get_error = [](const Ciphertext &encrypted, const SecretKey &sk2, + shared_ptr<SEALContext> context2) { + auto pool = MemoryManager::GetPool(); + auto &context_data = *context2->get_context_data(encrypted.parms_id()); + auto &parms = context_data.parms(); + auto &coeff_modulus = parms.coeff_modulus(); + size_t coeff_count = parms.poly_modulus_degree(); + size_t coeff_modulus_size = coeff_modulus.size(); + size_t rns_poly_uint64_count = util::mul_safe(coeff_count, coeff_modulus_size); + + IntArray<Ciphertext::ct_coeff_type> error; + error.resize(rns_poly_uint64_count); + auto destination = error.begin(); + + auto copy_operand1(util::allocate_uint(coeff_count, pool)); + for (size_t i = 0; i < coeff_modulus_size; i++) + { + // Initialize pointers for multiplication + const uint64_t *encrypted_ptr = encrypted.data(1) + (i * coeff_count); + const uint64_t *secret_key_ptr = sk2.data().data() + (i * coeff_count); + uint64_t *destination_ptr = destination + (i * coeff_count); + util::set_zero_uint(coeff_count, destination_ptr); + util::set_uint_uint(encrypted_ptr, coeff_count, copy_operand1.get()); + // compute c_{j+1} * s^{j+1} + util::dyadic_product_coeffmod( + copy_operand1.get(), secret_key_ptr, coeff_count, coeff_modulus[i], copy_operand1.get()); + // add c_{j+1} * s^{j+1} to destination + util::add_poly_poly_coeffmod( + destination_ptr, copy_operand1.get(), coeff_count, coeff_modulus[i], destination_ptr); + // add c_0 into destination + util::add_poly_poly_coeffmod( + destination_ptr, encrypted.data() + (i * coeff_count), coeff_count, coeff_modulus[i], + destination_ptr); + } + return error; + }; + + auto error_a = get_error(a_ct, sk1, context1); + auto error_b = get_error(b_ct, sk1, context1); + ASSERT_EQ(error_a.size(), error_b.size()); + ASSERT_TRUE(is_equal_uint_uint(error_a.cbegin(), error_b.cbegin(), error_a.size())); + }; + + ASSERT_EQ(a.size(), b.size()); + auto iter_a = a.data().begin(); + auto iter_b = b.data().begin(); + for (; iter_a != a.data().end(); iter_a++, iter_b++) + { + ASSERT_EQ(iter_a->size(), iter_b->size()); + auto pk_a = iter_a->begin(); + auto pk_b = iter_b->begin(); + for (; pk_a != iter_a->end(); pk_a++, pk_b++) + { + compare_error(pk_a->data(), pk_b->data(), sk, context); + } + } + }; + + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(8); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(8, { 60, 60 })); + random_seed_type seed; + for (auto &i : seed) + { + i = random_uint64(); + } + auto rng = make_shared<BlakePRNGFactory>(BlakePRNGFactory(seed)); + parms.set_random_generator(rng); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + + keygen.relin_keys().save(stream); + RelinKeys test_keys; + test_keys.load(context, stream); + RelinKeys keys = keygen.relin_keys_local(); + compare_kswitchkeys(keys, test_keys, secret_key, context); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(65537); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 60, 50 })); + random_seed_type seed; + for (auto &i : seed) + { + i = random_uint64(); + } + auto rng = make_shared<BlakePRNGFactory>(BlakePRNGFactory(seed)); + parms.set_random_generator(rng); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + SecretKey secret_key = keygen.secret_key(); + + keygen.relin_keys().save(stream); + RelinKeys test_keys; + test_keys.load(context, stream); + RelinKeys keys = keygen.relin_keys_local(); + compare_kswitchkeys(keys, test_keys, secret_key, context); + } + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/secretkey.cpp b/bigpiseal3.5.1/native/tests/seal/secretkey.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1e937d7aa65a80de997d5ea52e7c8f8b398a055 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/secretkey.cpp @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/keygenerator.h" +#include "seal/modulus.h" +#include "seal/secretkey.h" +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + TEST(SecretKeyTest, SaveLoadSecretKey) + { + stringstream stream; + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(1 << 6); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 60 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + SecretKey sk = keygen.secret_key(); + ASSERT_TRUE(sk.parms_id() == context->key_parms_id()); + sk.save(stream); + + SecretKey sk2; + sk2.load(context, stream); + + ASSERT_TRUE(sk.data() == sk2.data()); + ASSERT_TRUE(sk.parms_id() == sk2.parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + parms.set_poly_modulus_degree(256); + parms.set_plain_modulus(1 << 20); + parms.set_coeff_modulus(CoeffModulus::Create(256, { 30, 40 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + SecretKey sk = keygen.secret_key(); + ASSERT_TRUE(sk.parms_id() == context->key_parms_id()); + sk.save(stream); + + SecretKey sk2; + sk2.load(context, stream); + + ASSERT_TRUE(sk.data() == sk2.data()); + ASSERT_TRUE(sk.parms_id() == sk2.parms_id()); + } + } +} // namespace sealtest \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/seal/serialization.cpp b/bigpiseal3.5.1/native/tests/seal/serialization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee00ed566f1850dd826e545e0c0abfb3487fcb83 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/serialization.cpp @@ -0,0 +1,210 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/serialization.h" +#include "seal/util/defines.h" +#include <fstream> +#include <functional> +#include <sstream> +#include <string> +#include "gtest/gtest.h" + +using namespace seal; +using namespace std; + +namespace sealtest +{ + namespace + { + struct test_struct + { + int a; + int b; + double c; + + void save_members(ostream &stream) + { + stream.write(reinterpret_cast<const char *>(&a), sizeof(int)); + stream.write(reinterpret_cast<const char *>(&b), sizeof(int)); + stream.write(reinterpret_cast<const char *>(&c), sizeof(double)); + } + + void load_members(istream &stream) + { + stream.read(reinterpret_cast<char *>(&a), sizeof(int)); + stream.read(reinterpret_cast<char *>(&b), sizeof(int)); + stream.read(reinterpret_cast<char *>(&c), sizeof(double)); + } + + streamoff save_size(compr_mode_type compr_mode) const + { + size_t members_size = Serialization::ComprSizeEstimate(sizeof(test_struct), compr_mode); + + return static_cast<streamoff>(sizeof(Serialization::SEALHeader) + members_size); + } + }; + } // namespace + + TEST(SerializationTest, IsValidHeader) + { + ASSERT_EQ(sizeof(Serialization::SEALHeader), Serialization::seal_header_size); + + Serialization::SEALHeader header; + ASSERT_TRUE(Serialization::IsValidHeader(header)); + + Serialization::SEALHeader invalid_header; + invalid_header.magic = 0x1212; + ASSERT_FALSE(Serialization::IsValidHeader(invalid_header)); + invalid_header.magic = Serialization::seal_magic; + ASSERT_EQ(invalid_header.header_size, Serialization::seal_header_size); + invalid_header.version_major = 0x02; + ASSERT_FALSE(Serialization::IsValidHeader(invalid_header)); + invalid_header.version_major = SEAL_VERSION_MAJOR; + invalid_header.compr_mode = (compr_mode_type)0x02; + ASSERT_FALSE(Serialization::IsValidHeader(invalid_header)); + } + + TEST(SerializationTest, SEALHeaderSaveLoad) + { + { + // Serialize to stream + Serialization::SEALHeader header, loaded_header; + header.compr_mode = Serialization::compr_mode_default; + header.size = 256; + + stringstream stream; + Serialization::SaveHeader(header, stream); + ASSERT_TRUE(Serialization::IsValidHeader(header)); + Serialization::LoadHeader(stream, loaded_header); + ASSERT_EQ(Serialization::seal_magic, loaded_header.magic); + ASSERT_EQ(Serialization::seal_header_size, loaded_header.header_size); + ASSERT_EQ(SEAL_VERSION_MAJOR, loaded_header.version_major); + ASSERT_EQ(SEAL_VERSION_MINOR, loaded_header.version_minor); + ASSERT_EQ(Serialization::compr_mode_default, loaded_header.compr_mode); + ASSERT_EQ(0x00, loaded_header.reserved); + ASSERT_EQ(256, loaded_header.size); + } + { + // Serialize to buffer + Serialization::SEALHeader header, loaded_header; + header.compr_mode = Serialization::compr_mode_default; + header.size = 256; + + vector<SEAL_BYTE> buffer(16); + Serialization::SaveHeader(header, buffer.data(), buffer.size()); + ASSERT_TRUE(Serialization::IsValidHeader(header)); + Serialization::LoadHeader(buffer.data(), buffer.size(), loaded_header); + ASSERT_EQ(Serialization::seal_magic, loaded_header.magic); + ASSERT_EQ(Serialization::seal_header_size, loaded_header.header_size); + ASSERT_EQ(SEAL_VERSION_MAJOR, loaded_header.version_major); + ASSERT_EQ(SEAL_VERSION_MINOR, loaded_header.version_minor); + ASSERT_EQ(Serialization::compr_mode_default, loaded_header.compr_mode); + ASSERT_EQ(0x00, loaded_header.reserved); + ASSERT_EQ(256, loaded_header.size); + } + } + + TEST(SerializationTest, SEALHeaderUpgrade) + { + legacy_headers::SEALHeader_3_4 header_3_4; + header_3_4.compr_mode = Serialization::compr_mode_default; + header_3_4.size = 0xF3F3; + + { + Serialization::SEALHeader header; + Serialization::LoadHeader( + reinterpret_cast<const SEAL_BYTE *>(&header_3_4), sizeof(legacy_headers::SEALHeader_3_4), header); + ASSERT_TRUE(Serialization::IsValidHeader(header)); + ASSERT_EQ(header_3_4.compr_mode, header.compr_mode); + ASSERT_EQ(header_3_4.size, header.size); + } + { + Serialization::SEALHeader header; + Serialization::LoadHeader( + reinterpret_cast<const SEAL_BYTE *>(&header_3_4), sizeof(legacy_headers::SEALHeader_3_4), header, + false); + + // No upgrade requested + ASSERT_FALSE(Serialization::IsValidHeader(header)); + } + } + + TEST(SerializationTest, SaveLoadToStream) + { + test_struct st{ 3, ~0, 3.14159 }, st2; + using namespace std::placeholders; + stringstream stream; + + auto out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(compr_mode_type::none), stream, + compr_mode_type::none); + auto in_size = Serialization::Load(bind(&test_struct::load_members, &st2, _1), stream); + ASSERT_EQ(out_size, in_size); + ASSERT_EQ(st.a, st2.a); + ASSERT_EQ(st.b, st2.b); + ASSERT_EQ(st.c, st2.c); +#ifdef SEAL_USE_ZLIB + test_struct st3; + out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(compr_mode_type::deflate), stream, + compr_mode_type::deflate); + in_size = Serialization::Load(bind(&test_struct::load_members, &st3, _1), stream); + ASSERT_EQ(out_size, in_size); + ASSERT_EQ(st.a, st3.a); + ASSERT_EQ(st.b, st3.b); + ASSERT_EQ(st.c, st3.c); +#endif + } + + TEST(SerializationTest, SaveLoadToBuffer) + { + test_struct st{ 3, ~0, 3.14159 }, st2; + using namespace std::placeholders; + + constexpr size_t arr_size = 1024; + SEAL_BYTE buffer[arr_size]{}; + + stringstream ss; + auto test_out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(Serialization::compr_mode_default), ss, + Serialization::compr_mode_default); + auto out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(Serialization::compr_mode_default), buffer, + arr_size, Serialization::compr_mode_default); + ASSERT_EQ(test_out_size, out_size); + for (size_t i = static_cast<size_t>(out_size); i < arr_size; i++) + { + ASSERT_TRUE(SEAL_BYTE(0) == buffer[i]); + } + + auto in_size = Serialization::Load(bind(&test_struct::load_members, &st2, _1), buffer, arr_size); + ASSERT_EQ(out_size, in_size); + ASSERT_EQ(st.a, st2.a); + ASSERT_EQ(st.b, st2.b); + ASSERT_EQ(st.c, st2.c); +#ifdef SEAL_USE_ZLIB + // Reset buffer back to zero + memset(buffer, 0, arr_size); + + test_struct st3; + ss.seekp(0); + test_out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(compr_mode_type::deflate), ss, + compr_mode_type::deflate); + out_size = Serialization::Save( + bind(&test_struct::save_members, &st, _1), st.save_size(compr_mode_type::deflate), buffer, arr_size, + compr_mode_type::deflate); + ASSERT_EQ(test_out_size, out_size); + for (size_t i = static_cast<size_t>(out_size); i < arr_size; i++) + { + ASSERT_EQ(SEAL_BYTE(0), buffer[i]); + } + + in_size = Serialization::Load(bind(&test_struct::load_members, &st3, _1), buffer, arr_size); + ASSERT_EQ(out_size, in_size); + ASSERT_EQ(st.a, st3.a); + ASSERT_EQ(st.b, st3.b); + ASSERT_EQ(st.c, st3.c); +#endif + } +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/testrunner.cpp b/bigpiseal3.5.1/native/tests/seal/testrunner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7524d29d0451c391b8d5d57bd7571ce48b0d44e --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/testrunner.cpp @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "gtest/gtest.h" + +/** +Main entry point for Google Test unit tests. +*/ +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/bigpiseal3.5.1/native/tests/seal/util/CMakeLists.txt b/bigpiseal3.5.1/native/tests/seal/util/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1da0a3866683af9c8df8bf9b72c47fe6192f807d --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +target_sources(sealtest + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/clipnormal.cpp + ${CMAKE_CURRENT_LIST_DIR}/common.cpp + ${CMAKE_CURRENT_LIST_DIR}/galois.cpp + ${CMAKE_CURRENT_LIST_DIR}/hash.cpp + ${CMAKE_CURRENT_LIST_DIR}/iterator.cpp + ${CMAKE_CURRENT_LIST_DIR}/locks.cpp + ${CMAKE_CURRENT_LIST_DIR}/mempool.cpp + ${CMAKE_CURRENT_LIST_DIR}/numth.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarith.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarithmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/polyarithsmallmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/polycore.cpp + ${CMAKE_CURRENT_LIST_DIR}/rns.cpp + ${CMAKE_CURRENT_LIST_DIR}/ntt.cpp + ${CMAKE_CURRENT_LIST_DIR}/stringtouint64.cpp + ${CMAKE_CURRENT_LIST_DIR}/uint64tostring.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarith.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarithmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintarithsmallmod.cpp + ${CMAKE_CURRENT_LIST_DIR}/uintcore.cpp +) diff --git a/bigpiseal3.5.1/native/tests/seal/util/clipnormal.cpp b/bigpiseal3.5.1/native/tests/seal/util/clipnormal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db56ef2a1da3b37be74d6add0af20f80b787bb16 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/clipnormal.cpp @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/randomgen.h" +#include "seal/randomtostd.h" +#include "seal/util/clipnormal.h" +#include <cmath> +#include <memory> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace seal; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(ClipNormal, ClipNormalGenerate) + { + shared_ptr<UniformRandomGenerator> generator(UniformRandomGeneratorFactory::DefaultFactory()->create()); + RandomToStandardAdapter rand(generator); + ClippedNormalDistribution dist(50.0, 10.0, 20.0); + + ASSERT_EQ(50.0, dist.mean()); + ASSERT_EQ(10.0, dist.standard_deviation()); + ASSERT_EQ(20.0, dist.max_deviation()); + ASSERT_EQ(30.0, dist.min()); + ASSERT_EQ(70.0, dist.max()); + double average = 0; + double stddev = 0; + for (int i = 0; i < 100; ++i) + { + double value = dist(rand); + average += value; + stddev += (value - 50.0) * (value - 50.0); + ASSERT_TRUE(value >= 30.0 && value <= 70.0); + } + average /= 100; + stddev /= 100; + stddev = sqrt(stddev); + ASSERT_TRUE(average >= 40.0 && average <= 60.0); + ASSERT_TRUE(stddev >= 5.0 && stddev <= 15.0); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/common.cpp b/bigpiseal3.5.1/native/tests/seal/util/common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bcb9cc5212098a6606927cdec4e43f5c1a5e6b10 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/common.cpp @@ -0,0 +1,327 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(Common, Constants) + { + ASSERT_EQ(4, bits_per_nibble); + ASSERT_EQ(8, bits_per_byte); + ASSERT_EQ(4, bytes_per_uint32); + ASSERT_EQ(8, bytes_per_uint64); + ASSERT_EQ(32, bits_per_uint32); + ASSERT_EQ(64, bits_per_uint64); + ASSERT_EQ(2, nibbles_per_byte); + ASSERT_EQ(2, uint32_per_uint64); + ASSERT_EQ(16, nibbles_per_uint64); + ASSERT_EQ(static_cast<uint64_t>(INT64_MAX) + 1, uint64_high_bit); + } + + TEST(Common, UnsignedComparisons) + { + int pos_i = 5; + int neg_i = -5; + unsigned pos_u = 6; + signed pos_s = 6; + unsigned char pos_uc = 1; + char neg_c = -1; + char pos_c = 1; + unsigned char pos_uc_max = 0xFF; + unsigned long long pos_ull = 1; + unsigned long long pos_ull_max = 0xFFFFFFFFFFFFFFFF; + long long neg_ull = -1; + + ASSERT_TRUE(unsigned_eq(pos_i, pos_i)); + ASSERT_FALSE(unsigned_eq(pos_i, neg_i)); + ASSERT_TRUE(unsigned_gt(pos_u, pos_i)); + ASSERT_TRUE(unsigned_lt(pos_i, neg_i)); + ASSERT_TRUE(unsigned_geq(pos_u, pos_s)); + ASSERT_TRUE(unsigned_gt(neg_c, pos_c)); + ASSERT_TRUE(unsigned_geq(neg_c, pos_c)); + ASSERT_FALSE(unsigned_eq(neg_c, pos_c)); + ASSERT_FALSE(unsigned_gt(pos_u, neg_c)); + ASSERT_TRUE(unsigned_eq(pos_uc, pos_c)); + ASSERT_TRUE(unsigned_geq(pos_uc, pos_c)); + ASSERT_TRUE(unsigned_leq(pos_uc, pos_c)); + ASSERT_TRUE(unsigned_lt(pos_uc_max, neg_c)); + ASSERT_TRUE(unsigned_eq(neg_c, pos_ull_max)); + ASSERT_TRUE(unsigned_eq(neg_ull, pos_ull_max)); + ASSERT_FALSE(unsigned_lt(neg_ull, pos_ull_max)); + ASSERT_TRUE(unsigned_lt(pos_ull, pos_ull_max)); + } + + TEST(Common, SafeArithmetic) + { + int pos_i = 5; + int neg_i = -5; + unsigned pos_u = 6; + unsigned char pos_uc_max = 0xFF; + unsigned long long pos_ull_max = 0xFFFFFFFFFFFFFFFF; + long long neg_ull = -1; + SEAL_MAYBE_UNUSED unsigned long long res_ul; + SEAL_MAYBE_UNUSED long long res_l; + + ASSERT_EQ(25, mul_safe(pos_i, pos_i)); + ASSERT_EQ(25, mul_safe(neg_i, neg_i)); + ASSERT_EQ(10, add_safe(pos_i, pos_i)); + ASSERT_EQ(-10, add_safe(neg_i, neg_i)); + ASSERT_EQ(0, add_safe(pos_i, neg_i)); + ASSERT_EQ(0, add_safe(neg_i, pos_i)); + ASSERT_EQ(10, sub_safe(pos_i, neg_i)); + ASSERT_EQ(-10, sub_safe(neg_i, pos_i)); + ASSERT_EQ(unsigned(0), sub_safe(pos_u, pos_u)); + ASSERT_THROW(res_ul = sub_safe(unsigned(0), pos_u), logic_error); + ASSERT_THROW(res_ul = sub_safe(unsigned(4), pos_u), logic_error); + ASSERT_THROW(res_ul = add_safe(pos_uc_max, (unsigned char)1), logic_error); + ASSERT_TRUE(pos_uc_max == add_safe(pos_uc_max, (unsigned char)0)); + ASSERT_THROW(res_ul = mul_safe(pos_ull_max, pos_ull_max), logic_error); + ASSERT_EQ(0ULL, mul_safe(0ULL, pos_ull_max)); + ASSERT_TRUE((long long)1 == mul_safe(neg_ull, neg_ull)); + ASSERT_THROW(res_ul = mul_safe(pos_uc_max, pos_uc_max), logic_error); + ASSERT_EQ(15, add_safe(pos_i, -pos_i, pos_i, pos_i, pos_i)); + ASSERT_EQ(6, add_safe(0, -pos_i, pos_i, 1, pos_i)); + ASSERT_EQ(0, mul_safe(pos_i, pos_i, pos_i, 0, pos_i)); + ASSERT_EQ(625, mul_safe(pos_i, pos_i, pos_i, pos_i)); + ASSERT_THROW( + res_l = mul_safe( + pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i, pos_i), + logic_error); + } + + TEST(Common, FitsIn) + { + int neg_i = -5; + signed pos_s = 6; + unsigned char pos_uc = 1; + unsigned char pos_uc_max = 0xFF; + float f = 1.234f; + double d = -1234; + + ASSERT_TRUE(fits_in<unsigned>(pos_s)); + ASSERT_TRUE(fits_in<char>(pos_uc)); + ASSERT_FALSE(fits_in<unsigned>(neg_i)); + ASSERT_FALSE(fits_in<char>(pos_uc_max)); + ASSERT_TRUE(fits_in<float>(d)); + ASSERT_TRUE(fits_in<double>(f)); + ASSERT_TRUE(fits_in<int>(d)); + ASSERT_TRUE(fits_in<unsigned>(f)); + ASSERT_FALSE(fits_in<unsigned>(d)); + } + + TEST(Common, DivideRoundUp) + { + ASSERT_EQ(0, divide_round_up(0, 4)); + ASSERT_EQ(1, divide_round_up(1, 4)); + ASSERT_EQ(1, divide_round_up(2, 4)); + ASSERT_EQ(1, divide_round_up(3, 4)); + ASSERT_EQ(1, divide_round_up(4, 4)); + ASSERT_EQ(2, divide_round_up(5, 4)); + ASSERT_EQ(2, divide_round_up(6, 4)); + ASSERT_EQ(2, divide_round_up(7, 4)); + ASSERT_EQ(2, divide_round_up(8, 4)); + ASSERT_EQ(3, divide_round_up(9, 4)); + ASSERT_EQ(3, divide_round_up(12, 4)); + ASSERT_EQ(4, divide_round_up(13, 4)); + } + + TEST(Common, GetUInt64Byte) + { + uint64_t number[2]; + number[0] = 0x3456789ABCDEF121; + number[1] = 0x23456789ABCDEF12; + ASSERT_TRUE(SEAL_BYTE(0x21) == *get_uint64_byte(number, 0)); + ASSERT_TRUE(SEAL_BYTE(0xF1) == *get_uint64_byte(number, 1)); + ASSERT_TRUE(SEAL_BYTE(0xDE) == *get_uint64_byte(number, 2)); + ASSERT_TRUE(SEAL_BYTE(0xBC) == *get_uint64_byte(number, 3)); + ASSERT_TRUE(SEAL_BYTE(0x9A) == *get_uint64_byte(number, 4)); + ASSERT_TRUE(SEAL_BYTE(0x78) == *get_uint64_byte(number, 5)); + ASSERT_TRUE(SEAL_BYTE(0x56) == *get_uint64_byte(number, 6)); + ASSERT_TRUE(SEAL_BYTE(0x34) == *get_uint64_byte(number, 7)); + ASSERT_TRUE(SEAL_BYTE(0x12) == *get_uint64_byte(number, 8)); + ASSERT_TRUE(SEAL_BYTE(0xEF) == *get_uint64_byte(number, 9)); + ASSERT_TRUE(SEAL_BYTE(0xCD) == *get_uint64_byte(number, 10)); + ASSERT_TRUE(SEAL_BYTE(0xAB) == *get_uint64_byte(number, 11)); + ASSERT_TRUE(SEAL_BYTE(0x89) == *get_uint64_byte(number, 12)); + ASSERT_TRUE(SEAL_BYTE(0x67) == *get_uint64_byte(number, 13)); + ASSERT_TRUE(SEAL_BYTE(0x45) == *get_uint64_byte(number, 14)); + ASSERT_TRUE(SEAL_BYTE(0x23) == *get_uint64_byte(number, 15)); + } + + template <typename T> + void ReverseBits32Helper() + { + ASSERT_EQ(static_cast<T>(0), reverse_bits(static_cast<T>(0))); + ASSERT_EQ(static_cast<T>(0x80000000), reverse_bits(static_cast<T>(1))); + ASSERT_EQ(static_cast<T>(0x40000000), reverse_bits(static_cast<T>(2))); + ASSERT_EQ(static_cast<T>(0xC0000000), reverse_bits(static_cast<T>(3))); + ASSERT_EQ(static_cast<T>(0x00010000), reverse_bits(static_cast<T>(0x00008000))); + ASSERT_EQ(static_cast<T>(0xFFFF0000), reverse_bits(static_cast<T>(0x0000FFFF))); + ASSERT_EQ(static_cast<T>(0x0000FFFF), reverse_bits(static_cast<T>(0xFFFF0000))); + ASSERT_EQ(static_cast<T>(0x00008000), reverse_bits(static_cast<T>(0x00010000))); + ASSERT_EQ(static_cast<T>(3), reverse_bits(static_cast<T>(0xC0000000))); + ASSERT_EQ(static_cast<T>(2), reverse_bits(static_cast<T>(0x40000000))); + ASSERT_EQ(static_cast<T>(1), reverse_bits(static_cast<T>(0x80000000))); + ASSERT_EQ(static_cast<T>(0xFFFFFFFF), reverse_bits(static_cast<T>(0xFFFFFFFF))); + + // Reversing a 0-bit item should return 0 + ASSERT_EQ(static_cast<T>(0), reverse_bits(static_cast<T>(0xFFFFFFFF), 0)); + + // Reversing a 32-bit item returns is same as normal reverse + ASSERT_EQ(static_cast<T>(0), reverse_bits(static_cast<T>(0), 32)); + ASSERT_EQ(static_cast<T>(0x80000000), reverse_bits(static_cast<T>(1), 32)); + ASSERT_EQ(static_cast<T>(0x40000000), reverse_bits(static_cast<T>(2), 32)); + ASSERT_EQ(static_cast<T>(0xC0000000), reverse_bits(static_cast<T>(3), 32)); + ASSERT_EQ(static_cast<T>(0x00010000), reverse_bits(static_cast<T>(0x00008000), 32)); + ASSERT_EQ(static_cast<T>(0xFFFF0000), reverse_bits(static_cast<T>(0x0000FFFF), 32)); + ASSERT_EQ(static_cast<T>(0x0000FFFF), reverse_bits(static_cast<T>(0xFFFF0000), 32)); + ASSERT_EQ(static_cast<T>(0x00008000), reverse_bits(static_cast<T>(0x00010000), 32)); + ASSERT_EQ(static_cast<T>(3), reverse_bits(static_cast<T>(0xC0000000), 32)); + ASSERT_EQ(static_cast<T>(2), reverse_bits(static_cast<T>(0x40000000), 32)); + ASSERT_EQ(static_cast<T>(1), reverse_bits(static_cast<T>(0x80000000), 32)); + ASSERT_EQ(static_cast<T>(0xFFFFFFFF), reverse_bits(static_cast<T>(0xFFFFFFFF), 32)); + + // 16-bit reversal + ASSERT_EQ(static_cast<T>(0), reverse_bits(static_cast<T>(0), 16)); + ASSERT_EQ(static_cast<T>(0x00008000), reverse_bits(static_cast<T>(1), 16)); + ASSERT_EQ(static_cast<T>(0x00004000), reverse_bits(static_cast<T>(2), 16)); + ASSERT_EQ(static_cast<T>(0x0000C000), reverse_bits(static_cast<T>(3), 16)); + ASSERT_EQ(static_cast<T>(0x00000001), reverse_bits(static_cast<T>(0x00008000), 16)); + ASSERT_EQ(static_cast<T>(0x0000FFFF), reverse_bits(static_cast<T>(0x0000FFFF), 16)); + ASSERT_EQ(static_cast<T>(0x00000000), reverse_bits(static_cast<T>(0xFFFF0000), 16)); + ASSERT_EQ(static_cast<T>(0x00000000), reverse_bits(static_cast<T>(0x00010000), 16)); + ASSERT_EQ(static_cast<T>(3), reverse_bits(static_cast<T>(0x0000C000), 16)); + ASSERT_EQ(static_cast<T>(2), reverse_bits(static_cast<T>(0x00004000), 16)); + ASSERT_EQ(static_cast<T>(1), reverse_bits(static_cast<T>(0x00008000), 16)); + ASSERT_EQ(static_cast<T>(0x0000FFFF), reverse_bits(static_cast<T>(0xFFFFFFFF), 16)); + } + + TEST(Common, ReverseBits32) + { + ReverseBits32Helper<uint32_t>(); + + // Other types +#ifdef SEAL_USE_IF_CONSTEXPR + SEAL_IF_CONSTEXPR(sizeof(unsigned) == 4) + ReverseBits32Helper<unsigned>(); + + SEAL_IF_CONSTEXPR(sizeof(unsigned long) == 4) + ReverseBits32Helper<unsigned long>(); + + SEAL_IF_CONSTEXPR(sizeof(unsigned long long) == 4) + ReverseBits32Helper<unsigned long long>(); + + SEAL_IF_CONSTEXPR(sizeof(size_t) == 4) + ReverseBits32Helper<size_t>(); +#endif + } + + template <typename T> + void ReverseBits64Helper() + { + ASSERT_EQ(0ULL, reverse_bits<T>(0ULL)); + ASSERT_EQ(1ULL << 63, reverse_bits<T>(1ULL)); + ASSERT_EQ(1ULL << 32, reverse_bits<T>(1ULL << 31)); + ASSERT_EQ(0xFFFFULL << 32, reverse_bits<T>(0xFFFFULL << 16)); + ASSERT_EQ(0x0000FFFFFFFF0000ULL, reverse_bits<T>(0x0000FFFFFFFF0000ULL)); + ASSERT_EQ(0x0000FFFF0000FFFFULL, reverse_bits<T>(0xFFFF0000FFFF0000ULL)); + + ASSERT_EQ(0ULL, reverse_bits<T>(0ULL, 0)); + ASSERT_EQ(0ULL, reverse_bits<T>(0ULL, 1)); + ASSERT_EQ(0ULL, reverse_bits<T>(0ULL, 32)); + ASSERT_EQ(0ULL, reverse_bits<T>(0ULL, 64)); + + ASSERT_EQ(0ULL, reverse_bits<T>(1ULL, 0)); + ASSERT_EQ(1ULL, reverse_bits<T>(1ULL, 1)); + ASSERT_EQ(1ULL << 31, reverse_bits<T>(1ULL, 32)); + ASSERT_EQ(1ULL << 63, reverse_bits<T>(1ULL, 64)); + + ASSERT_EQ(0ULL, reverse_bits<T>(1ULL << 31, 0)); + ASSERT_EQ(0ULL, reverse_bits<T>(1ULL << 31, 1)); + ASSERT_EQ(1ULL, reverse_bits<T>(1ULL << 31, 32)); + ASSERT_EQ(1ULL << 32, reverse_bits<T>(1ULL << 31, 64)); + + ASSERT_EQ(0ULL, reverse_bits<T>(0xFFFFULL << 16, 0)); + ASSERT_EQ(0ULL, reverse_bits<T>(0xFFFFULL << 16, 1)); + ASSERT_EQ(0xFFFFULL, reverse_bits<T>(0xFFFFULL << 16, 32)); + ASSERT_EQ(0xFFFFULL << 32, reverse_bits<T>(0xFFFFULL << 16, 64)); + + ASSERT_EQ(0ULL, reverse_bits<T>(0x0000FFFFFFFF0000ULL, 0)); + ASSERT_EQ(0ULL, reverse_bits<T>(0x0000FFFFFFFF0000ULL, 1)); + ASSERT_EQ(0xFFFFULL, reverse_bits<T>(0x0000FFFFFFFF0000ULL, 32)); + ASSERT_EQ(0x0000FFFFFFFF0000ULL, reverse_bits<T>(0x0000FFFFFFFF0000ULL, 64)); + + ASSERT_EQ(0ULL, reverse_bits<T>(0xFFFF0000FFFF0000ULL, 0)); + ASSERT_EQ(0ULL, reverse_bits<T>(0xFFFF0000FFFF0000ULL, 1)); + ASSERT_EQ(0xFFFFULL, reverse_bits<T>(0xFFFF0000FFFF0000ULL, 32)); + ASSERT_EQ(0x0000FFFF0000FFFFULL, reverse_bits<T>(0xFFFF0000FFFF0000ULL, 64)); + } + + TEST(Common, ReverseBits64) + { + ReverseBits64Helper<uint64_t>(); + + // Other types +#ifdef SEAL_USE_IF_CONSTEXPR + SEAL_IF_CONSTEXPR(sizeof(unsigned) == 8) + ReverseBits64Helper<unsigned>(); + + SEAL_IF_CONSTEXPR(sizeof(unsigned long) == 8) + ReverseBits64Helper<unsigned long>(); + + SEAL_IF_CONSTEXPR(sizeof(unsigned long long) == 8) + ReverseBits64Helper<unsigned long long>(); + + SEAL_IF_CONSTEXPR(sizeof(size_t) == 8) + ReverseBits64Helper<size_t>(); +#endif + } + + TEST(Common, GetSignificantBitCount) + { + ASSERT_EQ(0, get_significant_bit_count(0)); + ASSERT_EQ(1, get_significant_bit_count(1)); + ASSERT_EQ(2, get_significant_bit_count(2)); + ASSERT_EQ(2, get_significant_bit_count(3)); + ASSERT_EQ(3, get_significant_bit_count(4)); + ASSERT_EQ(3, get_significant_bit_count(5)); + ASSERT_EQ(3, get_significant_bit_count(6)); + ASSERT_EQ(3, get_significant_bit_count(7)); + ASSERT_EQ(4, get_significant_bit_count(8)); + ASSERT_EQ(63, get_significant_bit_count(0x7000000000000000)); + ASSERT_EQ(63, get_significant_bit_count(0x7FFFFFFFFFFFFFFF)); + ASSERT_EQ(64, get_significant_bit_count(0x8000000000000000)); + ASSERT_EQ(64, get_significant_bit_count(0xFFFFFFFFFFFFFFFF)); + } + + TEST(Common, GetMSBIndexGeneric) + { + unsigned long result; + get_msb_index_generic(&result, 1); + ASSERT_EQ(static_cast<unsigned long>(0), result); + get_msb_index_generic(&result, 2); + ASSERT_EQ(static_cast<unsigned long>(1), result); + get_msb_index_generic(&result, 3); + ASSERT_EQ(static_cast<unsigned long>(1), result); + get_msb_index_generic(&result, 4); + ASSERT_EQ(static_cast<unsigned long>(2), result); + get_msb_index_generic(&result, 16); + ASSERT_EQ(static_cast<unsigned long>(4), result); + get_msb_index_generic(&result, 0xFFFFFFFF); + ASSERT_EQ(static_cast<unsigned long>(31), result); + get_msb_index_generic(&result, 0x100000000); + ASSERT_EQ(static_cast<unsigned long>(32), result); + get_msb_index_generic(&result, 0xFFFFFFFFFFFFFFFF); + ASSERT_EQ(static_cast<unsigned long>(63), result); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/galois.cpp b/bigpiseal3.5.1/native/tests/seal/util/galois.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffe5a6ca446fee61766b166732c2b231e9272f98 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/galois.cpp @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/context.h" +#include "seal/memorymanager.h" +#include "seal/util/galois.h" +#include <stdexcept> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(GaloisToolTest, Create) + { + auto pool = MemoryManager::GetPool(); + ASSERT_THROW(GaloisTool galois_tool(0, pool), invalid_argument); + ASSERT_THROW(GaloisTool galois_tool(18, pool), invalid_argument); + ASSERT_NO_THROW(GaloisTool galois_tool(1, pool)); + ASSERT_NO_THROW(GaloisTool galois_tool(17, pool)); + } + + TEST(GaloisToolTest, EltFromStep) + { + auto pool = MemoryManager::GetPool(); + { + GaloisTool galois_tool(3, pool); + ASSERT_EQ(15, galois_tool.get_elt_from_step(0)); + ASSERT_EQ(3, galois_tool.get_elt_from_step(1)); + ASSERT_EQ(3, galois_tool.get_elt_from_step(-3)); + ASSERT_EQ(9, galois_tool.get_elt_from_step(2)); + ASSERT_EQ(9, galois_tool.get_elt_from_step(-2)); + ASSERT_EQ(11, galois_tool.get_elt_from_step(3)); + ASSERT_EQ(11, galois_tool.get_elt_from_step(-1)); + } + } + + TEST(GaloisToolTest, EltsFromSteps) + { + auto pool = MemoryManager::GetPool(); + { + GaloisTool galois_tool(3, pool); + auto elts = galois_tool.get_elts_from_steps({ 0, 1, -3, 2, -2, 3, -1 }); + uint32_t elts_true[7]{ 15, 3, 3, 9, 9, 11, 11 }; + for (size_t i = 0; i < elts.size(); i++) + { + ASSERT_EQ(elts_true[i], elts[i]); + } + } + } + + TEST(GaloisToolTest, EltsAll) + { + auto pool = MemoryManager::GetPool(); + { + GaloisTool galois_tool(3, pool); + auto elts = galois_tool.get_elts_all(); + uint32_t elts_true[5]{ 15, 3, 11, 9, 9 }; + for (size_t i = 0; i < elts.size(); i++) + { + ASSERT_EQ(elts_true[i], elts[i]); + } + } + } + + TEST(GaloisToolTest, IndexFromElt) + { + ASSERT_EQ(7, GaloisTool::GetIndexFromElt(15)); + ASSERT_EQ(1, GaloisTool::GetIndexFromElt(3)); + ASSERT_EQ(4, GaloisTool::GetIndexFromElt(9)); + ASSERT_EQ(5, GaloisTool::GetIndexFromElt(11)); + } + + TEST(GaloisToolTest, ApplyGalois) + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(8); + parms.set_coeff_modulus({ 17 }); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto context_data = context->key_context_data(); + auto galois_tool = context_data->galois_tool(); + uint64_t in[8]{ 0, 1, 2, 3, 4, 5, 6, 7 }; + uint64_t out[8]; + uint64_t out_true[8]{ 0, 14, 6, 1, 13, 7, 2, 12 }; + galois_tool->apply_galois(in, 3, Modulus(17), out); + for (size_t i = 0; i < 8; i++) + { + ASSERT_EQ(out_true[i], out[i]); + } + } + + TEST(GaloisToolTest, ApplyGaloisNTT) + { + EncryptionParameters parms(scheme_type::CKKS); + parms.set_poly_modulus_degree(8); + parms.set_coeff_modulus({ 17 }); + auto context = SEALContext::Create(parms, false, sec_level_type::none); + auto context_data = context->key_context_data(); + auto galois_tool = context_data->galois_tool(); + uint64_t in[8]{ 0, 1, 2, 3, 4, 5, 6, 7 }; + uint64_t out[8]; + uint64_t out_true[8]{ 4, 5, 7, 6, 1, 0, 2, 3 }; + const_cast<GaloisTool *>(galois_tool)->apply_galois_ntt(in, 3, out); + for (size_t i = 0; i < 8; i++) + { + ASSERT_EQ(out_true[i], out[i]); + } + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/hash.cpp b/bigpiseal3.5.1/native/tests/seal/util/hash.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d81110807e5d6a18bcdde6ef14698eb22a619b8b --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/hash.cpp @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/hash.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + namespace + { + void hash(uint64_t value, HashFunction::hash_block_type &destination) + { + HashFunction::hash(&value, 1, destination); + } + } // namespace + + TEST(HashTest, Hash) + { + uint64_t input[3]{ 0, 0, 0 }; + HashFunction::hash_block_type hash1, hash2; + hash(0, hash1); + + HashFunction::hash(input, 0, hash2); + ASSERT_TRUE(hash1 != hash2); + + HashFunction::hash(input, 1, hash2); + ASSERT_TRUE(hash1 == hash2); + + HashFunction::hash(input, 2, hash2); + ASSERT_TRUE(hash1 != hash2); + + hash(0x123456, hash1); + hash(0x023456, hash2); + ASSERT_TRUE(hash1 != hash2); + + input[0] = 0x123456; + input[1] = 1; + hash(0x123456, hash1); + HashFunction::hash(input, 2, hash2); + ASSERT_TRUE(hash1 != hash2); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/iterator.cpp b/bigpiseal3.5.1/native/tests/seal/util/iterator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b29f773158d50f7dce624f855e9f6e5f73b4d16 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/iterator.cpp @@ -0,0 +1,257 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/memorymanager.h" +#include "seal/util/iterator.h" +#include <algorithm> +#include <array> +#include <cstdint> +#include <stdexcept> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(IteratorTest, CoeffIter) + { + array<uint64_t, 10> arr{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + CoeffIter ci(arr.data()); + ConstCoeffIter cci(arr.data()); + + for_each(arr.begin(), arr.end(), [ci](auto a) mutable { ASSERT_EQ(a, **ci++); }); + for_each(arr.begin(), arr.end(), [cci](auto a) mutable { ASSERT_EQ(a, **cci++); }); + + ASSERT_EQ(arr.data(), static_cast<uint64_t *>(ci)); + ASSERT_EQ(arr.data(), static_cast<const uint64_t *>(cci)); + + auto ci2 = ci++; + auto cci2 = cci++; + ASSERT_EQ(arr[1], **ci); + ASSERT_EQ(arr[1], **cci); + ASSERT_EQ(arr[0], **ci2); + ASSERT_EQ(arr[0], **cci2); + + ci2 = ++ci; + cci2 = ++cci; + ASSERT_EQ(arr[2], **ci); + ASSERT_EQ(arr[2], **cci); + ASSERT_EQ(arr[2], **ci2); + ASSERT_EQ(arr[2], **cci2); + + ASSERT_TRUE(ci == ci2); + ASSERT_TRUE(cci == cci2); + } + + TEST(IteratorTest, RNSIter) + { + array<uint64_t, 12> arr{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + RNSIter ri(arr.data(), 4); + ConstRNSIter cri(arr.data(), 4); + + { + vector<uint64_t> values; + for_each_n(ri, arr.size() / ri.poly_modulus_degree(), [&](auto ci) { + for_each_n(ci, ri.poly_modulus_degree(), [&](auto c) { values.push_back(*c); }); + }); + ASSERT_TRUE(equal(arr.begin(), arr.end(), values.begin())); + } + { + vector<uint64_t> values; + for_each_n(cri, arr.size() / cri.poly_modulus_degree(), [&](auto cci) { + for_each_n(cci, cri.poly_modulus_degree(), [&](auto c) { values.push_back(*c); }); + }); + ASSERT_TRUE(equal(arr.begin(), arr.end(), values.begin())); + } + + ASSERT_EQ(arr[0], ***ri++); + ASSERT_EQ(arr[4], ***ri++); + ASSERT_EQ(arr[8], ***ri); + ASSERT_EQ(arr[0], ***cri++); + ASSERT_EQ(arr[4], ***cri++); + ASSERT_EQ(arr[8], ***cri); + + ASSERT_EQ(arr.data() + 8, static_cast<uint64_t *>(ri)); + ASSERT_EQ(arr.data() + 8, static_cast<const uint64_t *>(cri)); + + ASSERT_EQ(arr[4], ***--ri); + ASSERT_EQ(arr[0], ***--ri); + ASSERT_EQ(arr[4], ***--cri); + ASSERT_EQ(arr[0], ***--cri); + + ASSERT_TRUE(ri == cri); + ASSERT_TRUE(ri == arr.data()); + } + + TEST(IteratorTest, PolyIter) + { + array<uint64_t, 12> arr{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + PolyIter pi(arr.data(), 3, 2); + ConstPolyIter cpi(arr.data(), 3, 2); + + { + vector<uint64_t> values; + for_each_n(pi, arr.size() / (pi.poly_modulus_degree() * pi.coeff_modulus_size()), [&](auto ri) { + for_each_n(ri, pi.coeff_modulus_size(), [&](auto ci) { + for_each_n(ci, pi.poly_modulus_degree(), [&](auto c) { values.push_back(*c); }); + }); + }); + ASSERT_TRUE(equal(arr.begin(), arr.end(), values.begin())); + } + { + vector<uint64_t> values; + for_each_n(cpi, arr.size() / (cpi.poly_modulus_degree() * cpi.coeff_modulus_size()), [&](auto cri) { + for_each_n(cri, cpi.coeff_modulus_size(), [&](auto cci) { + for_each_n(cci, cpi.poly_modulus_degree(), [&](auto c) { values.push_back(*c); }); + }); + }); + ASSERT_TRUE(equal(arr.begin(), arr.end(), values.begin())); + } + + ASSERT_EQ(arr[0], ****pi++); + ASSERT_EQ(arr[6], ****pi++); + ASSERT_EQ(arr[0], ****cpi++); + ASSERT_EQ(arr[6], ****cpi++); + + ASSERT_EQ(arr[6], ****--pi); + ASSERT_EQ(arr[0], ****--pi); + ASSERT_EQ(arr[6], ****--cpi); + ASSERT_EQ(arr[0], ****--cpi); + + ASSERT_TRUE(pi == cpi); + ASSERT_TRUE(pi == arr.data()); + } + + TEST(IteratorTest, PtrIter) + { + array<int32_t, 5> int_arr{ 0, 1, 2, 3, 4 }; + array<char, 5> char_arr{ 'a', 'b', 'c', 'd', 'e' }; + + PtrIter<int32_t *> int_iter(int_arr.data()); + PtrIter<char *> char_iter(char_arr.data()); + + { + vector<int32_t> values; + for_each_n(int_iter, int_arr.size(), [&](auto int_ptr) { values.push_back(*int_ptr); }); + ASSERT_TRUE(equal(int_arr.begin(), int_arr.end(), values.begin())); + } + { + vector<char> values; + for_each_n(char_iter, char_arr.size(), [&](auto char_ptr) { values.push_back(*char_ptr); }); + ASSERT_TRUE(equal(char_arr.begin(), char_arr.end(), values.begin())); + } + + ASSERT_EQ(*int_iter, int_arr.data()); + ASSERT_EQ(*char_iter, char_arr.data()); + } + + TEST(IteratorTest, ReverseIter) + { + array<uint64_t, 10> arr{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + CoeffIter ci(arr.data()); + advance(ci, arr.size() - 1); + ReverseIter<CoeffIter> rci(ci); + ConstCoeffIter cci(arr.data()); + advance(cci, arr.size() - 1); + ReverseIter<ConstCoeffIter> rcci(cci); + + for_each(arr.rbegin(), arr.rend(), [rci](auto a) mutable { ASSERT_EQ(a, **rci++); }); + for_each(arr.rbegin(), arr.rend(), [rcci](auto a) mutable { ASSERT_EQ(a, **rcci++); }); + + ASSERT_EQ(arr.data() + arr.size() - 1, static_cast<uint64_t *>(rci)); + ASSERT_EQ(arr.data() + arr.size() - 1, static_cast<const uint64_t *>(rcci)); + + ++rci; + ASSERT_EQ(**rci, arr[8]); + --rci; + ASSERT_EQ(**rci, arr[9]); + rci++; + ASSERT_EQ(**rci, arr[8]); + rci--; + ASSERT_EQ(**rci, arr[9]); + + array<int32_t, 5> int_arr{ 0, 1, 2, 3, 4 }; + array<char, 5> char_arr{ 'a', 'b', 'c', 'd', 'e' }; + + PtrIter<int32_t *> int_iter(int_arr.data() + int_arr.size() - 1); + PtrIter<char *> char_iter(char_arr.data() + char_arr.size() - 1); + + { + vector<int32_t> values; + for_each_n(ReverseIter<PtrIter<int32_t *>>(int_iter), int_arr.size(), [&](auto int_ptr) { + values.push_back(*int_ptr); + }); + + auto values_it = values.begin(); + for_each( + int_arr.rbegin(), int_arr.rend(), [&values_it](auto a) mutable { ASSERT_EQ(a, *values_it++); }); + } + { + vector<char> values; + for_each_n(ReverseIter<PtrIter<char *>>(char_iter), char_arr.size(), [&](auto char_ptr) { + values.push_back(*char_ptr); + }); + + auto values_it = values.begin(); + for_each( + char_arr.rbegin(), char_arr.rend(), [&values_it](auto a) mutable { ASSERT_EQ(a, *values_it++); }); + } + } + + TEST(IteratorTest, IterTuple) + { + array<uint64_t, 12> arr{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + CoeffIter ci(arr.data()); + RNSIter ri(arr.data(), 3); + PolyIter pi(arr.data(), 3, 2); + + IterTuple<CoeffIter, PolyIter> it1(ci, pi); + IterTuple<RNSIter, PolyIter> it2(ri, pi); + + ASSERT_EQ(0, *get<0>(*it1)); + ASSERT_EQ(0, ***get<1>(*it1)); + ASSERT_EQ(0, **get<0>(*it2)); + ASSERT_EQ(0, ***get<1>(*it2)); + + ++it1; + ++it2; + ASSERT_EQ(1, *get<0>(*it1)); + ASSERT_EQ(6, ***get<1>(*it1)); + ASSERT_EQ(3, **get<0>(*it2)); + ASSERT_EQ(6, ***get<1>(*it2)); + + --it1; + --it2; + ASSERT_EQ(0, *get<0>(*it1)); + ASSERT_EQ(0, ***get<1>(*it1)); + ASSERT_EQ(0, **get<0>(*it2)); + ASSERT_EQ(0, ***get<1>(*it2)); + + IterTuple<CoeffIter, RNSIter, PolyIter> it3(ci, ri, pi); + ASSERT_EQ(0, *get<0>(*it3)); + ASSERT_EQ(0, **get<1>(*it3)); + ASSERT_EQ(0, ***get<2>(*it3)); + + ++it3; + ASSERT_EQ(1, *get<0>(*it3)); + ASSERT_EQ(3, **get<1>(*it3)); + ASSERT_EQ(6, ***get<2>(*it3)); + + --it3; + ASSERT_EQ(0, *get<0>(*it3)); + ASSERT_EQ(0, **get<1>(*it3)); + ASSERT_EQ(0, ***get<2>(*it3)); + + IterTuple<IterTuple<CoeffIter, RNSIter, PolyIter>, IterTuple<RNSIter, PolyIter>> it4(it3, it2); + auto it5 = it4; + it5++; + it5--; + ASSERT_TRUE(it5 == it4); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/locks.cpp b/bigpiseal3.5.1/native/tests/seal/util/locks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..130a4d8d73ca283fe529baa8cd2ce08c868c6c20 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/locks.cpp @@ -0,0 +1,313 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/locks.h" +#include <atomic> +#include <thread> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + class Reader + { + public: + Reader(ReaderWriterLocker &locker) : locker_(locker), locked_(false), trying_(false) + {} + + bool is_locked() const + { + return locked_; + } + + bool is_trying_to_lock() const + { + return trying_; + } + + void acquire_read() + { + trying_ = true; + lock_ = locker_.acquire_read(); + locked_ = true; + trying_ = false; + } + + void release() + { + lock_.unlock(); + locked_ = false; + } + + void wait_until_trying() + { + while (!trying_) + ; + } + + void wait_until_locked() + { + while (!locked_) + ; + } + + private: + ReaderWriterLocker &locker_; + + ReaderLock lock_; + + volatile bool locked_; + + volatile bool trying_; + }; + + class Writer + { + public: + Writer(ReaderWriterLocker &locker) : locker_(locker), locked_(false), trying_(false) + {} + + bool is_locked() const + { + return locked_; + } + + bool is_trying_to_lock() const + { + return trying_; + } + + void acquire_write() + { + trying_ = true; + lock_ = locker_.acquire_write(); + locked_ = true; + trying_ = false; + } + + void release() + { + lock_.unlock(); + locked_ = false; + } + + void wait_until_trying() + { + while (!trying_) + ; + } + + void wait_until_locked() + { + while (!locked_) + ; + } + + void wait_until_unlocked() + { + while (locked_) + ; + } + + private: + ReaderWriterLocker &locker_; + + WriterLock lock_; + + volatile bool locked_; + + volatile bool trying_; + }; + + TEST(ReaderWriterLockerTests, ReaderWriterLockNonBlocking) + { + ReaderWriterLocker locker; + + WriterLock writeLock = locker.acquire_write(); + ASSERT_TRUE(writeLock.owns_lock()); + writeLock.unlock(); + ASSERT_FALSE(writeLock.owns_lock()); + + ReaderLock readLock = locker.acquire_read(); + ASSERT_TRUE(readLock.owns_lock()); + readLock.unlock(); + + ReaderLock readLock2 = locker.acquire_read(); + ASSERT_TRUE(readLock2.owns_lock()); + ASSERT_FALSE(readLock.owns_lock()); + readLock2.unlock(); + ASSERT_FALSE(readLock2.owns_lock()); + + readLock = locker.try_acquire_read(); + ASSERT_TRUE(readLock.owns_lock()); + writeLock = locker.try_acquire_write(); + ASSERT_FALSE(writeLock.owns_lock()); + + readLock2 = locker.try_acquire_read(); + ASSERT_TRUE(readLock2.owns_lock()); + writeLock = locker.try_acquire_write(); + ASSERT_FALSE(writeLock.owns_lock()); + + readLock.unlock(); + writeLock = locker.try_acquire_write(); + ASSERT_FALSE(writeLock.owns_lock()); + + readLock2.unlock(); + writeLock = locker.try_acquire_write(); + ASSERT_TRUE(writeLock.owns_lock()); + + WriterLock writeLock2 = locker.try_acquire_write(); + + ASSERT_FALSE(writeLock2.owns_lock()); + readLock2 = locker.try_acquire_read(); + ASSERT_FALSE(readLock2.owns_lock()); + + writeLock.unlock(); + + writeLock2 = locker.try_acquire_write(); + ASSERT_TRUE(writeLock2.owns_lock()); + readLock2 = locker.try_acquire_read(); + ASSERT_FALSE(readLock2.owns_lock()); + + writeLock2.unlock(); + } + + TEST(ReaderWriterLockerTests, ReaderWriterLockBlocking) + { + ReaderWriterLocker locker; + + Reader *reader1 = new Reader(locker); + Reader *reader2 = new Reader(locker); + Writer *writer1 = new Writer(locker); + Writer *writer2 = new Writer(locker); + + ASSERT_FALSE(reader1->is_locked()); + ASSERT_FALSE(reader2->is_locked()); + ASSERT_FALSE(writer1->is_locked()); + ASSERT_FALSE(writer2->is_locked()); + + reader1->acquire_read(); + ASSERT_TRUE(reader1->is_locked()); + ASSERT_FALSE(reader2->is_locked()); + reader2->acquire_read(); + ASSERT_TRUE(reader1->is_locked()); + ASSERT_TRUE(reader2->is_locked()); + + atomic<bool> should_unlock1{ false }; + atomic<bool> should_unlock2{ false }; + + thread writer1_thread([&] { + writer1->acquire_write(); + while (!should_unlock1) + { + this_thread::sleep_for(10ms); + } + writer1->release(); + }); + + writer1->wait_until_trying(); + ASSERT_TRUE(writer1->is_trying_to_lock()); + ASSERT_FALSE(writer1->is_locked()); + + reader2->release(); + ASSERT_TRUE(reader1->is_locked()); + ASSERT_FALSE(reader2->is_locked()); + ASSERT_TRUE(writer1->is_trying_to_lock()); + ASSERT_FALSE(writer1->is_locked()); + + thread writer2_thread([&] { + writer2->acquire_write(); + while (!should_unlock2) + { + this_thread::sleep_for(10ms); + } + writer2->release(); + }); + + writer2->wait_until_trying(); + ASSERT_TRUE(writer1->is_trying_to_lock()); + ASSERT_FALSE(writer1->is_locked()); + ASSERT_TRUE(writer2->is_trying_to_lock()); + ASSERT_FALSE(writer2->is_locked()); + + reader1->release(); + ASSERT_FALSE(reader1->is_locked()); + + while (writer1->is_trying_to_lock() && writer2->is_trying_to_lock()) + ; + + Writer *winner; + Writer *waiting; + atomic<bool> *should_unlock_winner; + atomic<bool> *should_unlock_waiting; + + if (writer1->is_locked()) + { + winner = writer1; + waiting = writer2; + should_unlock_winner = &should_unlock1; + should_unlock_waiting = &should_unlock2; + } + else + { + winner = writer2; + waiting = writer1; + should_unlock_winner = &should_unlock2; + should_unlock_waiting = &should_unlock1; + } + + ASSERT_TRUE(winner->is_locked()); + ASSERT_FALSE(waiting->is_locked()); + + *should_unlock_winner = true; + winner->wait_until_unlocked(); + ASSERT_FALSE(winner->is_locked()); + + waiting->wait_until_locked(); + ASSERT_TRUE(waiting->is_locked()); + + thread reader1_thread(&Reader::acquire_read, reader1); + reader1->wait_until_trying(); + ASSERT_TRUE(reader1->is_trying_to_lock()); + ASSERT_FALSE(reader1->is_locked()); + + thread reader2_thread(&Reader::acquire_read, reader2); + reader2->wait_until_trying(); + ASSERT_TRUE(reader2->is_trying_to_lock()); + ASSERT_FALSE(reader2->is_locked()); + + *should_unlock_waiting = true; + + reader1->wait_until_locked(); + reader2->wait_until_locked(); + ASSERT_TRUE(reader1->is_locked()); + ASSERT_TRUE(reader2->is_locked()); + + reader1->release(); + reader2->release(); + + ASSERT_FALSE(reader1->is_locked()); + ASSERT_FALSE(reader2->is_locked()); + ASSERT_FALSE(writer1->is_locked()); + ASSERT_FALSE(reader2->is_locked()); + ASSERT_FALSE(reader1->is_trying_to_lock()); + ASSERT_FALSE(reader2->is_trying_to_lock()); + ASSERT_FALSE(writer1->is_trying_to_lock()); + ASSERT_FALSE(reader2->is_trying_to_lock()); + + writer1_thread.join(); + writer2_thread.join(); + reader1_thread.join(); + reader2_thread.join(); + + delete reader1; + delete reader2; + delete writer1; + delete writer2; + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/mempool.cpp b/bigpiseal3.5.1/native/tests/seal/util/mempool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3832d1da4b1a58be765e23889e1098c2d4141d7 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/mempool.cpp @@ -0,0 +1,687 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/common.h" +#include "seal/util/mempool.h" +#include "seal/util/ntt.h" +#include "seal/util/pointer.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <memory> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(MemoryPoolTest, TestMemoryPoolMT) + { + { + MemoryPoolMT pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<uint64_t> pointer{ pool.get_for_byte_count(bytes_per_uint64 * 0) }; + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + uint64_t *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<uint64_t> pointer2 = pool.get_for_byte_count(bytes_per_uint64 * 2); + uint64_t *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<uint64_t> pointer3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer4 = pool.get_for_byte_count(1); + Pointer<SEAL_BYTE> pointer5 = pool.get_for_byte_count(2); + Pointer<SEAL_BYTE> pointer6 = pool.get_for_byte_count(1); + pointer4.release(); + pointer5.release(); + pointer6.release(); + ASSERT_TRUE(4LL == pool.pool_count()); + } + { + MemoryPoolMT pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<int> pointer{ pool.get_for_byte_count(4 * 0) }; + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + int *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<int> pointer2 = pool.get_for_byte_count(4 * 2); + int *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<int> pointer3 = pool.get_for_byte_count(4 * 1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer4 = pool.get_for_byte_count(1); + Pointer<SEAL_BYTE> pointer5 = pool.get_for_byte_count(2); + Pointer<SEAL_BYTE> pointer6 = pool.get_for_byte_count(1); + pointer4.release(); + pointer5.release(); + pointer6.release(); + ASSERT_TRUE(4LL == pool.pool_count()); + } + { + MemoryPoolMT pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer = pool.get_for_byte_count(0); + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + SEAL_BYTE *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<SEAL_BYTE> pointer2 = pool.get_for_byte_count(2); + SEAL_BYTE *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<SEAL_BYTE> pointer3 = pool.get_for_byte_count(1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + } + } + + TEST(MemoryPoolTests, PointerTestsMT) + { + MemoryPool &pool = *global_variables::global_memory_pool; + { + Pointer<uint64_t> p1; + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + uint64_t *allocation1 = p1.get(); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() != nullptr); + + p1.release(); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation1); + + Pointer<uint64_t> p2; + p2.acquire(p1); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p2.is_set()); + ASSERT_TRUE(p2.get() == allocation1); + + ConstPointer<uint64_t> cp2; + cp2.acquire(p2); + ASSERT_FALSE(p2.is_set()); + ASSERT_TRUE(cp2.is_set()); + ASSERT_TRUE(cp2.get() == allocation1); + cp2.release(); + + Pointer<uint64_t> p3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation1); + + Pointer<uint64_t> p4 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(p4.is_set()); + uint64_t *allocation2 = p4.get(); + swap(p3, p4); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation2); + ASSERT_TRUE(p4.is_set()); + ASSERT_TRUE(p4.get() == allocation1); + p3.release(); + p4.release(); + } + { + Pointer<SEAL_BYTE> p1; + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + SEAL_BYTE *allocation1 = p1.get(); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() != nullptr); + + p1.release(); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation1); + + Pointer<SEAL_BYTE> p2; + p2.acquire(p1); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p2.is_set()); + ASSERT_TRUE(p2.get() == allocation1); + + ConstPointer<SEAL_BYTE> cp2; + cp2.acquire(p2); + ASSERT_FALSE(p2.is_set()); + ASSERT_TRUE(cp2.is_set()); + ASSERT_TRUE(cp2.get() == allocation1); + cp2.release(); + + Pointer<SEAL_BYTE> p3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation1); + + Pointer<SEAL_BYTE> p4 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(p4.is_set()); + SEAL_BYTE *allocation2 = p4.get(); + swap(p3, p4); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation2); + ASSERT_TRUE(p4.is_set()); + ASSERT_TRUE(p4.get() == allocation1); + p3.release(); + p4.release(); + } + } + + TEST(MemoryPoolTests, DuplicateIfNeededMT) + { + { + unique_ptr<uint64_t[]> allocation(new uint64_t[2]); + allocation[0] = 0x1234567812345678; + allocation[1] = 0x8765432187654321; + + MemoryPoolMT pool; + Pointer<uint64_t> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x1234567812345678); + ASSERT_TRUE(p1.get()[1] == 0x8765432187654321); + p1.release(); + } + { + unique_ptr<int64_t[]> allocation(new int64_t[2]); + allocation[0] = 0x234567812345678; + allocation[1] = 0x765432187654321; + + MemoryPoolMT pool; + Pointer<int64_t> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x234567812345678); + ASSERT_TRUE(p1.get()[1] == 0x765432187654321); + p1.release(); + } + { + unique_ptr<int[]> allocation(new int[2]); + allocation[0] = 0x123; + allocation[1] = 0x876; + + MemoryPoolMT pool; + Pointer<int> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x123); + ASSERT_TRUE(p1.get()[1] == 0x876); + p1.release(); + } + } + + TEST(MemoryPoolTests, TestMemoryPoolST) + { + { + MemoryPoolST pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<uint64_t> pointer{ pool.get_for_byte_count(bytes_per_uint64 * 0) }; + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + uint64_t *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<uint64_t> pointer2 = pool.get_for_byte_count(bytes_per_uint64 * 2); + uint64_t *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<uint64_t> pointer3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer4 = pool.get_for_byte_count(1); + Pointer<SEAL_BYTE> pointer5 = pool.get_for_byte_count(2); + Pointer<SEAL_BYTE> pointer6 = pool.get_for_byte_count(1); + pointer4.release(); + pointer5.release(); + pointer6.release(); + ASSERT_TRUE(4LL == pool.pool_count()); + } + { + MemoryPoolST pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<int> pointer{ pool.get_for_byte_count(4 * 0) }; + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + int *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<int> pointer2 = pool.get_for_byte_count(4 * 2); + int *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(4 * 2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<int> pointer3 = pool.get_for_byte_count(4 * 1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer4 = pool.get_for_byte_count(1); + Pointer<SEAL_BYTE> pointer5 = pool.get_for_byte_count(2); + Pointer<SEAL_BYTE> pointer6 = pool.get_for_byte_count(1); + pointer4.release(); + pointer5.release(); + pointer6.release(); + ASSERT_TRUE(4LL == pool.pool_count()); + } + { + MemoryPoolST pool; + ASSERT_TRUE(0LL == pool.pool_count()); + + Pointer<SEAL_BYTE> pointer = pool.get_for_byte_count(0); + ASSERT_FALSE(pointer.is_set()); + pointer.release(); + ASSERT_TRUE(0LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + SEAL_BYTE *allocation1 = pointer.get(); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(1LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(1); + ASSERT_FALSE(allocation1 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + ASSERT_FALSE(pointer.is_set()); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer.get()); + Pointer<SEAL_BYTE> pointer2 = pool.get_for_byte_count(2); + SEAL_BYTE *allocation2 = pointer2.get(); + ASSERT_FALSE(allocation2 == pointer.get()); + ASSERT_TRUE(pointer.is_set()); + pointer.release(); + pointer2.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + + pointer = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation2 == pointer.get()); + pointer2 = pool.get_for_byte_count(2); + ASSERT_TRUE(allocation1 == pointer2.get()); + Pointer<SEAL_BYTE> pointer3 = pool.get_for_byte_count(1); + pointer.release(); + pointer2.release(); + pointer3.release(); + ASSERT_TRUE(2LL == pool.pool_count()); + } + } + + TEST(MemoryPoolTests, PointerTestsST) + { + MemoryPoolST pool; + { + Pointer<uint64_t> p1; + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + uint64_t *allocation1 = p1.get(); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() != nullptr); + + p1.release(); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation1); + + Pointer<uint64_t> p2; + p2.acquire(p1); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p2.is_set()); + ASSERT_TRUE(p2.get() == allocation1); + + ConstPointer<uint64_t> cp2; + cp2.acquire(p2); + ASSERT_FALSE(p2.is_set()); + ASSERT_TRUE(cp2.is_set()); + ASSERT_TRUE(cp2.get() == allocation1); + cp2.release(); + + Pointer<uint64_t> p3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation1); + + Pointer<uint64_t> p4 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(p4.is_set()); + uint64_t *allocation2 = p4.get(); + swap(p3, p4); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation2); + ASSERT_TRUE(p4.is_set()); + ASSERT_TRUE(p4.get() == allocation1); + p3.release(); + p4.release(); + } + { + Pointer<SEAL_BYTE> p1; + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + SEAL_BYTE *allocation1 = p1.get(); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() != nullptr); + + p1.release(); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p1.get() == nullptr); + + p1 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation1); + + Pointer<SEAL_BYTE> p2; + p2.acquire(p1); + ASSERT_FALSE(p1.is_set()); + ASSERT_TRUE(p2.is_set()); + ASSERT_TRUE(p2.get() == allocation1); + + ConstPointer<SEAL_BYTE> cp2; + cp2.acquire(p2); + ASSERT_FALSE(p2.is_set()); + ASSERT_TRUE(cp2.is_set()); + ASSERT_TRUE(cp2.get() == allocation1); + cp2.release(); + + Pointer<SEAL_BYTE> p3 = pool.get_for_byte_count(bytes_per_uint64 * 1); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation1); + + Pointer<SEAL_BYTE> p4 = pool.get_for_byte_count(bytes_per_uint64 * 2); + ASSERT_TRUE(p4.is_set()); + SEAL_BYTE *allocation2 = p4.get(); + swap(p3, p4); + ASSERT_TRUE(p3.is_set()); + ASSERT_TRUE(p3.get() == allocation2); + ASSERT_TRUE(p4.is_set()); + ASSERT_TRUE(p4.get() == allocation1); + p3.release(); + p4.release(); + } + } + + TEST(MemoryPoolTests, DuplicateIfNeededST) + { + { + unique_ptr<uint64_t[]> allocation(new uint64_t[2]); + allocation[0] = 0x1234567812345678; + allocation[1] = 0x8765432187654321; + + MemoryPoolST pool; + Pointer<uint64_t> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x1234567812345678); + ASSERT_TRUE(p1.get()[1] == 0x8765432187654321); + p1.release(); + } + { + unique_ptr<int64_t[]> allocation(new int64_t[2]); + allocation[0] = 0x234567812345678; + allocation[1] = 0x765432187654321; + + MemoryPoolST pool; + Pointer<int64_t> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x234567812345678); + ASSERT_TRUE(p1.get()[1] == 0x765432187654321); + p1.release(); + } + { + unique_ptr<int[]> allocation(new int[2]); + allocation[0] = 0x123; + allocation[1] = 0x876; + + MemoryPoolST pool; + Pointer<int> p1 = duplicate_if_needed(allocation.get(), 2, false, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_TRUE(p1.get() == allocation.get()); + ASSERT_TRUE(0LL == pool.pool_count()); + + p1 = duplicate_if_needed(allocation.get(), 2, true, pool); + ASSERT_TRUE(p1.is_set()); + ASSERT_FALSE(p1.get() == allocation.get()); + ASSERT_TRUE(1LL == pool.pool_count()); + ASSERT_TRUE(p1.get()[0] == 0x123); + ASSERT_TRUE(p1.get()[1] == 0x876); + p1.release(); + } + } + + TEST(MemoryPoolTests, Allocate) + { + MemoryPool &pool = *global_variables::global_memory_pool; + vector<SEAL_BYTE> bytes{ SEAL_BYTE(0), SEAL_BYTE(1), SEAL_BYTE(2), SEAL_BYTE(3), SEAL_BYTE(4) }; + auto ptr = allocate(bytes.begin(), bytes.size(), pool); + ASSERT_TRUE(equal(bytes.begin(), bytes.end(), ptr.get())); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/ntt.cpp b/bigpiseal3.5.1/native/tests/seal/util/ntt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..763040c5411944e7642cfeffc41caa5a238e88bd --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/ntt.cpp @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/modulus.h" +#include "seal/util/mempool.h" +#include "seal/util/ntt.h" +#include "seal/util/numth.h" +#include "seal/util/polycore.h" +#include "seal/util/uintcore.h" +#include <cstddef> +#include <cstdint> +#include <random> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(NTTTablesTest, NTTBasics) + { + MemoryPoolHandle pool = MemoryPoolHandle::Global(); + Pointer<NTTTables> tables; + int coeff_count_power = 1; + Modulus modulus(get_prime(uint64_t(1) << coeff_count_power, 60)); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + ASSERT_EQ(2ULL, tables->coeff_count()); + ASSERT_EQ(1, tables->coeff_count_power()); + + coeff_count_power = 2; + modulus = get_prime(uint64_t(1) << coeff_count_power, 50); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + ASSERT_EQ(4ULL, tables->coeff_count()); + ASSERT_EQ(2, tables->coeff_count_power()); + + coeff_count_power = 10; + modulus = get_prime(uint64_t(1) << coeff_count_power, 40); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + ASSERT_EQ(1024ULL, tables->coeff_count()); + ASSERT_EQ(10, tables->coeff_count_power()); + + ASSERT_NO_THROW(CreateNTTTables( + coeff_count_power, CoeffModulus::Create(uint64_t(1) << coeff_count_power, { 20, 20, 20, 20, 20 }), + tables, pool)); + for (size_t i = 0; i < 5; i++) + { + ASSERT_EQ(1024ULL, tables[i].coeff_count()); + ASSERT_EQ(10, tables[i].coeff_count_power()); + } + } + + TEST(NTTTablesTest, NTTPrimitiveRootsTest) + { + MemoryPoolHandle pool = MemoryPoolHandle::Global(); + Pointer<NTTTables> tables; + + int coeff_count_power = 1; + Modulus modulus(0xffffffffffc0001ULL); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + ASSERT_EQ(1ULL, tables->get_from_root_powers(0)); + ASSERT_EQ(288794978602139552ULL, tables->get_from_root_powers(1)); + uint64_t inv; + try_invert_uint_mod(tables->get_from_root_powers(1), modulus.value(), inv); + ASSERT_EQ(inv, tables->get_from_inv_root_powers(1)); + + coeff_count_power = 2; + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + ASSERT_EQ(1ULL, tables->get_from_root_powers(0)); + ASSERT_EQ(288794978602139552ULL, tables->get_from_root_powers(1)); + ASSERT_EQ(178930308976060547ULL, tables->get_from_root_powers(2)); + ASSERT_EQ(748001537669050592ULL, tables->get_from_root_powers(3)); + } + + TEST(NTTTablesTest, NegacyclicNTTTest) + { + MemoryPoolHandle pool = MemoryPoolHandle::Global(); + Pointer<NTTTables> tables; + + int coeff_count_power = 1; + Modulus modulus(0xffffffffffc0001ULL); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + auto poly(allocate_poly(2, 1, pool)); + poly[0] = 0; + poly[1] = 0; + ntt_negacyclic_harvey(poly.get(), *tables); + ASSERT_EQ(0ULL, poly[0]); + ASSERT_EQ(0ULL, poly[1]); + + poly[0] = 1; + poly[1] = 0; + ntt_negacyclic_harvey(poly.get(), *tables); + ASSERT_EQ(1ULL, poly[0]); + ASSERT_EQ(1ULL, poly[1]); + + poly[0] = 1; + poly[1] = 1; + ntt_negacyclic_harvey(poly.get(), *tables); + ASSERT_EQ(288794978602139553ULL, poly[0]); + ASSERT_EQ(864126526004445282ULL, poly[1]); + } + + TEST(NTTTablesTest, InverseNegacyclicNTTTest) + { + MemoryPoolHandle pool = MemoryPoolHandle::Global(); + Pointer<NTTTables> tables; + + int coeff_count_power = 3; + Modulus modulus(0xffffffffffc0001ULL); + ASSERT_NO_THROW(tables = allocate<NTTTables>(pool, coeff_count_power, modulus, pool)); + auto poly(allocate_zero_poly(800, 1, pool)); + auto temp(allocate_zero_poly(800, 1, pool)); + + inverse_ntt_negacyclic_harvey(poly.get(), *tables); + for (size_t i = 0; i < 800; i++) + { + ASSERT_EQ(0ULL, poly[i]); + } + + random_device rd; + for (size_t i = 0; i < 800; i++) + { + poly[i] = static_cast<uint64_t>(rd()) % modulus.value(); + temp[i] = poly[i]; + } + + ntt_negacyclic_harvey(poly.get(), *tables); + inverse_ntt_negacyclic_harvey(poly.get(), *tables); + for (size_t i = 0; i < 800; i++) + { + ASSERT_EQ(temp[i], poly[i]); + } + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/numth.cpp b/bigpiseal3.5.1/native/tests/seal/util/numth.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30d32295be4a0938b16490046e0968ab2d72b8c9 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/numth.cpp @@ -0,0 +1,222 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/intarray.h" +#include "seal/util/numth.h" +#include "seal/util/uintarith.h" +#include "seal/util/uintarithsmallmod.h" +#include <cstdint> +#include <numeric> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(NumberTheory, GCD) + { + ASSERT_EQ(1ULL, gcd(1, 1)); + ASSERT_EQ(1ULL, gcd(2, 1)); + ASSERT_EQ(1ULL, gcd(1, 2)); + ASSERT_EQ(2ULL, gcd(2, 2)); + ASSERT_EQ(3ULL, gcd(6, 15)); + ASSERT_EQ(3ULL, gcd(15, 6)); + ASSERT_EQ(1ULL, gcd(7, 15)); + ASSERT_EQ(1ULL, gcd(15, 7)); + ASSERT_EQ(1ULL, gcd(7, 15)); + ASSERT_EQ(3ULL, gcd(11112, 44445)); + } + + TEST(NumberTheory, ExtendedGCD) + { + tuple<uint64_t, int64_t, int64_t> result; + + // Corner case behavior + result = xgcd(7, 7); + ASSERT_TRUE(result == make_tuple<>(7, 0, 1)); + result = xgcd(2, 2); + ASSERT_TRUE(result == make_tuple<>(2, 0, 1)); + + result = xgcd(1, 1); + ASSERT_TRUE(result == make_tuple<>(1, 0, 1)); + result = xgcd(1, 2); + ASSERT_TRUE(result == make_tuple<>(1, 1, 0)); + result = xgcd(5, 6); + ASSERT_TRUE(result == make_tuple<>(1, -1, 1)); + result = xgcd(13, 19); + ASSERT_TRUE(result == make_tuple<>(1, 3, -2)); + result = xgcd(14, 21); + ASSERT_TRUE(result == make_tuple<>(7, -1, 1)); + + result = xgcd(2, 1); + ASSERT_TRUE(result == make_tuple<>(1, 0, 1)); + result = xgcd(6, 5); + ASSERT_TRUE(result == make_tuple<>(1, 1, -1)); + result = xgcd(19, 13); + ASSERT_TRUE(result == make_tuple<>(1, -2, 3)); + result = xgcd(21, 14); + ASSERT_TRUE(result == make_tuple<>(7, 1, -1)); + } + + TEST(NumberTheory, TryInvertUIntMod) + { + uint64_t input, modulus, result; + + input = 1, modulus = 2; + ASSERT_TRUE(try_invert_uint_mod(input, modulus, result)); + ASSERT_EQ(result, 1ULL); + + input = 2, modulus = 2; + ASSERT_FALSE(try_invert_uint_mod(input, modulus, result)); + + input = 3, modulus = 2; + ASSERT_TRUE(try_invert_uint_mod(input, modulus, result)); + ASSERT_EQ(result, 1ULL); + + input = 0xFFFFFF, modulus = 2; + ASSERT_TRUE(try_invert_uint_mod(input, modulus, result)); + ASSERT_EQ(result, 1ULL); + + input = 0xFFFFFE, modulus = 2; + ASSERT_FALSE(try_invert_uint_mod(input, modulus, result)); + + input = 12345, modulus = 3; + ASSERT_FALSE(try_invert_uint_mod(input, modulus, result)); + + input = 5, modulus = 19; + ASSERT_TRUE(try_invert_uint_mod(input, modulus, result)); + ASSERT_EQ(result, 4ULL); + + input = 4, modulus = 19; + ASSERT_TRUE(try_invert_uint_mod(input, modulus, result)); + ASSERT_EQ(result, 5ULL); + } + + TEST(NumberTheory, IsPrime) + { + ASSERT_FALSE(is_prime(0)); + ASSERT_TRUE(is_prime(2)); + ASSERT_TRUE(is_prime(3)); + ASSERT_FALSE(is_prime(4)); + ASSERT_TRUE(is_prime(5)); + ASSERT_FALSE(is_prime(221)); + ASSERT_TRUE(is_prime(65537)); + ASSERT_FALSE(is_prime(65536)); + ASSERT_TRUE(is_prime(59399)); + ASSERT_TRUE(is_prime(72307)); + ASSERT_FALSE(is_prime(72307ULL * 59399ULL)); + ASSERT_TRUE(is_prime(36893488147419103ULL)); + ASSERT_FALSE(is_prime(36893488147419107ULL)); + } + + TEST(NumberTheory, NAF) + { + auto naf_vec = naf(0); + ASSERT_EQ(0, naf_vec.size()); + + naf_vec = naf(1); + ASSERT_EQ(1, naf_vec.size()); + ASSERT_EQ(1, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + naf_vec = naf(-1); + ASSERT_EQ(1, naf_vec.size()); + ASSERT_EQ(-1, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + + naf_vec = naf(2); + ASSERT_EQ(1, naf_vec.size()); + ASSERT_EQ(2, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + naf_vec = naf(-2); + ASSERT_EQ(1, naf_vec.size()); + ASSERT_EQ(-2, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + + naf_vec = naf(3); + ASSERT_EQ(2, naf_vec.size()); + ASSERT_EQ(3, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + naf_vec = naf(-3); + ASSERT_EQ(2, naf_vec.size()); + ASSERT_EQ(-3, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + + naf_vec = naf(127); + ASSERT_EQ(2, naf_vec.size()); + ASSERT_EQ(127, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + naf_vec = naf(-127); + ASSERT_EQ(2, naf_vec.size()); + ASSERT_EQ(-127, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + + naf_vec = naf(123); + ASSERT_EQ(123, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + naf_vec = naf(-123); + ASSERT_EQ(-123, accumulate(naf_vec.begin(), naf_vec.end(), 0)); + } + + TEST(NumberTheory, TryPrimitiveRootMod) + { + uint64_t result; + Modulus mod(11); + + ASSERT_TRUE(try_primitive_root(2, mod, result)); + ASSERT_EQ(10ULL, result); + + mod = 29; + ASSERT_TRUE(try_primitive_root(2, mod, result)); + ASSERT_EQ(28ULL, result); + + vector<uint64_t> corrects{ 12, 17 }; + ASSERT_TRUE(try_primitive_root(4, mod, result)); + ASSERT_TRUE(std::find(corrects.begin(), corrects.end(), result) != corrects.end()); + + mod = 1234565441; + ASSERT_TRUE(try_primitive_root(2, mod, result)); + ASSERT_EQ(1234565440ULL, result); + corrects = { 984839708, 273658408, 249725733, 960907033 }; + ASSERT_TRUE(try_primitive_root(8, mod, result)); + ASSERT_TRUE(std::find(corrects.begin(), corrects.end(), result) != corrects.end()); + } + + TEST(NumberTheory, IsPrimitiveRootMod) + { + Modulus mod(11); + ASSERT_TRUE(is_primitive_root(10, 2, mod)); + ASSERT_FALSE(is_primitive_root(9, 2, mod)); + ASSERT_FALSE(is_primitive_root(10, 4, mod)); + + mod = 29; + ASSERT_TRUE(is_primitive_root(28, 2, mod)); + ASSERT_TRUE(is_primitive_root(12, 4, mod)); + ASSERT_FALSE(is_primitive_root(12, 2, mod)); + ASSERT_FALSE(is_primitive_root(12, 8, mod)); + + mod = 1234565441ULL; + ASSERT_TRUE(is_primitive_root(1234565440ULL, 2, mod)); + ASSERT_TRUE(is_primitive_root(960907033ULL, 8, mod)); + ASSERT_TRUE(is_primitive_root(1180581915ULL, 16, mod)); + ASSERT_FALSE(is_primitive_root(1180581915ULL, 32, mod)); + ASSERT_FALSE(is_primitive_root(1180581915ULL, 8, mod)); + ASSERT_FALSE(is_primitive_root(1180581915ULL, 2, mod)); + } + + TEST(NumberTheory, TryMinimalPrimitiveRootMod) + { + Modulus mod(11); + + uint64_t result; + ASSERT_TRUE(try_minimal_primitive_root(2, mod, result)); + ASSERT_EQ(10ULL, result); + + mod = 29; + ASSERT_TRUE(try_minimal_primitive_root(2, mod, result)); + ASSERT_EQ(28ULL, result); + ASSERT_TRUE(try_minimal_primitive_root(4, mod, result)); + ASSERT_EQ(12ULL, result); + + mod = 1234565441; + ASSERT_TRUE(try_minimal_primitive_root(2, mod, result)); + ASSERT_EQ(1234565440ULL, result); + ASSERT_TRUE(try_minimal_primitive_root(8, mod, result)); + ASSERT_EQ(249725733ULL, result); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/polyarith.cpp b/bigpiseal3.5.1/native/tests/seal/util/polyarith.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0da10db8fd39ad952ce147a8cacad4ecb12acea6 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/polyarith.cpp @@ -0,0 +1,505 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/polyarith.h" +#include "seal/util/uintcore.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; +using namespace seal; + +namespace sealtest +{ + namespace util + { + TEST(PolyArith, RightShiftPolyCoeffs) + { + right_shift_poly_coeffs(nullptr, 0, 0, 0, nullptr); + right_shift_poly_coeffs(nullptr, 0, 0, 1, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_poly(3, 2, pool)); + ptr[0] = 2; + ptr[1] = 4; + ptr[2] = 8; + right_shift_poly_coeffs(ptr.get(), 3, 1, 0, ptr.get()); + ASSERT_EQ(2ULL, ptr[0]); + ASSERT_EQ(4ULL, ptr[1]); + ASSERT_EQ(8ULL, ptr[2]); + + right_shift_poly_coeffs(ptr.get(), 3, 1, 1, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(2ULL, ptr[1]); + ASSERT_EQ(4ULL, ptr[2]); + + right_shift_poly_coeffs(ptr.get(), 3, 1, 1, ptr.get()); + ASSERT_EQ(0ULL, ptr[0]); + ASSERT_EQ(1ULL, ptr[1]); + ASSERT_EQ(2ULL, ptr[2]); + + ptr[0] = 3; + ptr[1] = 5; + ptr[2] = 9; + right_shift_poly_coeffs(ptr.get(), 3, 1, 2, ptr.get()); + ASSERT_EQ(0ULL, ptr[0]); + ASSERT_EQ(1ULL, ptr[1]); + ASSERT_EQ(2ULL, ptr[2]); + + ptr[0] = 3; + ptr[1] = 5; + ptr[2] = 9; + right_shift_poly_coeffs(ptr.get(), 3, 1, 4, ptr.get()); + ASSERT_EQ(0ULL, ptr[0]); + ASSERT_EQ(0ULL, ptr[1]); + ASSERT_EQ(0ULL, ptr[2]); + + ptr[0] = 1; + ptr[1] = 1; + ptr[2] = 1; + right_shift_poly_coeffs(ptr.get(), 1, 2, 64, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(0ULL, ptr[1]); + ASSERT_EQ(1ULL, ptr[2]); + + ptr[0] = 3; + ptr[1] = 5; + ptr[2] = 9; + right_shift_poly_coeffs(ptr.get(), 1, 3, 128, ptr.get()); + ASSERT_EQ(9ULL, ptr[0]); + ASSERT_EQ(0ULL, ptr[1]); + ASSERT_EQ(0ULL, ptr[2]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr[2] = 0xFFFFFFFFFFFFFFFF; + right_shift_poly_coeffs(ptr.get(), 1, 3, 191, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(0ULL, ptr[1]); + ASSERT_EQ(0ULL, ptr[2]); + } + + TEST(PolyArith, NegatePoly) + { + negate_poly(nullptr, 0, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_poly(3, 2, pool)); + ptr[0] = 2; + ptr[2] = 3; + ptr[4] = 4; + negate_poly(ptr.get(), 3, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFD), ptr[2]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[3]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFC), ptr[4]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[5]); + } + + TEST(PolyArith, AddPolyPoly) + { + add_poly_poly(nullptr, nullptr, 0, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 2, pool)); + auto poly2(allocate_zero_poly(3, 2, pool)); + + poly1[0] = 0; + poly1[1] = 0xFFFFFFFFFFFFFFFF; + poly1[2] = 1; + poly1[3] = 0; + poly1[4] = 0xFFFFFFFFFFFFFFFF; + poly1[5] = 1; + poly2[0] = 1; + poly2[1] = 1; + poly2[2] = 1; + poly2[3] = 1; + poly2[4] = 0xFFFFFFFFFFFFFFFF; + poly2[5] = 1; + add_poly_poly(poly1.get(), poly2.get(), 3, 2, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(1), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(2), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(1), poly1[3]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(3), poly1[5]); + + poly1[0] = 2; + poly1[1] = 0; + poly1[2] = 3; + poly1[3] = 0; + poly1[4] = 0xFFFFFFFFFFFFFFFF; + poly1[5] = 0xFFFFFFFFFFFFFFFF; + poly2[0] = 5; + poly2[1] = 0; + poly2[2] = 6; + poly2[3] = 0; + poly2[4] = 0xFFFFFFFFFFFFFFFF; + poly2[5] = 0xFFFFFFFFFFFFFFFF; + add_poly_poly(poly1.get(), poly2.get(), 3, 2, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(7), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(9), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[3]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly1[5]); + } + + TEST(PolyArith, SubPolyPoly) + { + sub_poly_poly(nullptr, nullptr, 0, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 2, pool)); + auto poly2(allocate_zero_poly(3, 2, pool)); + + poly1[0] = 0; + poly1[1] = 0xFFFFFFFFFFFFFFFF; + poly1[2] = 1; + poly1[3] = 0; + poly1[4] = 0xFFFFFFFFFFFFFFFF; + poly1[5] = 1; + poly2[0] = 1; + poly2[1] = 1; + poly2[2] = 1; + poly2[3] = 1; + poly2[4] = 0xFFFFFFFFFFFFFFFF; + poly2[5] = 1; + sub_poly_poly(poly1.get(), poly2.get(), 6, 1, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly1[3]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[5]); + + poly1[0] = 5; + poly1[1] = 0; + poly1[2] = 6; + poly1[3] = 0; + poly1[4] = 0xFFFFFFFFFFFFFFFF; + poly1[5] = 0xFFFFFFFFFFFFFFFF; + poly2[0] = 2; + poly2[1] = 0; + poly2[2] = 8; + poly2[3] = 0; + poly2[4] = 0xFFFFFFFFFFFFFFFE; + poly2[5] = 0xFFFFFFFFFFFFFFFF; + sub_poly_poly(poly1.get(), poly2.get(), 3, 2, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(3), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly1[3]); + ASSERT_EQ(1ULL, poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[5]); + } + + TEST(PolyArith, MultiplyPolyPoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 2, pool)); + auto poly2(allocate_zero_poly(3, 2, pool)); + auto result(allocate_zero_poly(5, 2, pool)); + poly1[0] = 1; + poly1[2] = 2; + poly1[4] = 3; + poly2[0] = 2; + poly2[2] = 3; + poly2[4] = 4; + multiply_poly_poly(poly1.get(), 3, 2, poly2.get(), 3, 2, 5, 2, result.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), result[0]); + ASSERT_EQ(static_cast<uint64_t>(0), result[1]); + ASSERT_EQ(static_cast<uint64_t>(7), result[2]); + ASSERT_EQ(static_cast<uint64_t>(0), result[3]); + ASSERT_EQ(static_cast<uint64_t>(16), result[4]); + ASSERT_EQ(static_cast<uint64_t>(0), result[5]); + ASSERT_EQ(static_cast<uint64_t>(17), result[6]); + ASSERT_EQ(static_cast<uint64_t>(0), result[7]); + ASSERT_EQ(static_cast<uint64_t>(12), result[8]); + ASSERT_EQ(static_cast<uint64_t>(0), result[9]); + + poly2[0] = 2; + poly2[1] = 3; + multiply_poly_poly(poly1.get(), 3, 2, poly2.get(), 2, 1, 5, 2, result.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), result[0]); + ASSERT_EQ(static_cast<uint64_t>(0), result[1]); + ASSERT_EQ(static_cast<uint64_t>(7), result[2]); + ASSERT_EQ(static_cast<uint64_t>(0), result[3]); + ASSERT_EQ(static_cast<uint64_t>(12), result[4]); + ASSERT_EQ(static_cast<uint64_t>(0), result[5]); + ASSERT_EQ(static_cast<uint64_t>(9), result[6]); + ASSERT_EQ(static_cast<uint64_t>(0), result[7]); + ASSERT_EQ(static_cast<uint64_t>(0), result[8]); + ASSERT_EQ(static_cast<uint64_t>(0), result[9]); + + multiply_poly_poly(poly1.get(), 3, 2, poly2.get(), 2, 1, 5, 1, result.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), result[0]); + ASSERT_EQ(static_cast<uint64_t>(7), result[1]); + ASSERT_EQ(static_cast<uint64_t>(12), result[2]); + ASSERT_EQ(static_cast<uint64_t>(9), result[3]); + ASSERT_EQ(static_cast<uint64_t>(0), result[4]); + } + + TEST(PolyArith, PolyInftyNorm) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(10, 1, pool)); + uint64_t result[2]; + + poly[0] = 1, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 4, poly[6] = 0xB, poly[7] = 0xA, poly[8] = 5, poly[9] = 2; + poly_infty_norm(poly.get(), 10, 1, result); + ASSERT_EQ(result[0], 0xBULL); + + poly[0] = 2, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 0xF7, poly[6] = 0xFE, poly[7] = 0xCF, poly[8] = 0xCA, poly[9] = 0xAB; + poly_infty_norm(poly.get(), 10, 1, result); + ASSERT_EQ(result[0], 0xFEULL); + + poly[0] = 2, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 0xABCDEF, poly[6] = 0xABCDE, poly[7] = 0xABCD, poly[8] = 0xABC, poly[9] = 0xAB; + poly_infty_norm(poly.get(), 10, 1, result); + ASSERT_EQ(result[0], 0xABCDEFULL); + + poly[0] = 6, poly[1] = 5, poly[2] = 4, poly[3] = 3, poly[4] = 2; + poly[5] = 1, poly[6] = 0; + poly_infty_norm(poly.get(), 6, 1, result); + ASSERT_EQ(result[0], 6ULL); + + poly[0] = 1, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 4, poly[6] = 0xB, poly[7] = 0xA, poly[8] = 5, poly[9] = 2; + poly_infty_norm(poly.get(), 5, 2, result); + ASSERT_EQ(result[0], 0xBULL); + ASSERT_EQ(result[1], 0xAULL); + + poly[0] = 2, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 0xF7, poly[6] = 0xFE, poly[7] = 0xCF, poly[8] = 0xCA, poly[9] = 0xAB; + poly_infty_norm(poly.get(), 5, 2, result); + ASSERT_EQ(result[0], 0x0ULL); + ASSERT_EQ(result[1], 0xF7ULL); + + poly[0] = 2, poly[1] = 0, poly[2] = 1, poly[3] = 0, poly[4] = 0; + poly[5] = 0xABCDEF, poly[6] = 0xABCDE, poly[7] = 0xABCD, poly[8] = 0xABC, poly[9] = 0xAB; + poly_infty_norm(poly.get(), 5, 2, result); + ASSERT_EQ(result[0], 0ULL); + ASSERT_EQ(result[1], 0xABCDEFULL); + + poly[0] = 6, poly[1] = 5, poly[2] = 4, poly[3] = 3, poly[4] = 2; + poly[5] = 1, poly[6] = 0; + poly_infty_norm(poly.get(), 3, 2, result); + ASSERT_EQ(result[0], 6ULL); + ASSERT_EQ(result[1], 5ULL); + } + + TEST(PolyArith, PolyEvalPoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(4, 1, pool)); + auto poly2(allocate_zero_poly(4, 1, pool)); + auto poly3(allocate_zero_poly(8, 1, pool)); + + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 0ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 1; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 1ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 2; + poly2[0] = 1; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 2ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 1; + poly1[1] = 1; + poly2[0] = 1; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 2ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 1; + poly1[1] = 1; + poly2[0] = 2; + poly2[1] = 0; + poly2[2] = 1; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 3ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 1ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 2; + poly1[1] = 0; + poly1[2] = 1; + poly2[0] = 1; + poly2[1] = 1; + poly2[2] = 0; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 3ULL); + ASSERT_EQ(poly3[1], 2ULL); + ASSERT_EQ(poly3[2], 1ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 0; + poly1[1] = 0; + poly1[2] = 0; + poly1[3] = 1; + poly2[0] = 2; + poly2[1] = 0; + poly2[2] = 0; + poly2[3] = 0; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 8ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 0ULL); + ASSERT_EQ(poly3[7], 0ULL); + + poly1[0] = 0; + poly1[1] = 0; + poly1[2] = 0; + poly1[3] = 1; + poly2[0] = 0; + poly2[1] = 0; + poly2[2] = 2; + poly2[3] = 0; + poly_eval_poly(poly1.get(), 4, 1, poly2.get(), 4, 1, 8, 1, poly3.get(), pool); + ASSERT_EQ(poly3[0], 0ULL); + ASSERT_EQ(poly3[1], 0ULL); + ASSERT_EQ(poly3[2], 0ULL); + ASSERT_EQ(poly3[3], 0ULL); + ASSERT_EQ(poly3[4], 0ULL); + ASSERT_EQ(poly3[5], 0ULL); + ASSERT_EQ(poly3[6], 8ULL); + ASSERT_EQ(poly3[7], 0ULL); + } + + TEST(PolyArith, ExponentiatePoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(4, 1, pool)); + auto poly2(allocate_zero_poly(12, 1, pool)); + + uint64_t exponent = 1; + exponentiate_poly(poly1.get(), 4, 1, &exponent, 1, 12, 1, poly2.get(), pool); + ASSERT_EQ(poly2[0], 0ULL); + ASSERT_EQ(poly2[1], 0ULL); + ASSERT_EQ(poly2[2], 0ULL); + ASSERT_EQ(poly2[3], 0ULL); + ASSERT_EQ(poly2[4], 0ULL); + ASSERT_EQ(poly2[5], 0ULL); + ASSERT_EQ(poly2[6], 0ULL); + ASSERT_EQ(poly2[7], 0ULL); + ASSERT_EQ(poly2[8], 0ULL); + ASSERT_EQ(poly2[9], 0ULL); + ASSERT_EQ(poly2[10], 0ULL); + ASSERT_EQ(poly2[11], 0ULL); + + exponent = 0; + exponentiate_poly(poly1.get(), 4, 1, &exponent, 1, 12, 1, poly2.get(), pool); + ASSERT_EQ(poly2[0], 1ULL); + ASSERT_EQ(poly2[1], 0ULL); + ASSERT_EQ(poly2[2], 0ULL); + ASSERT_EQ(poly2[3], 0ULL); + ASSERT_EQ(poly2[4], 0ULL); + ASSERT_EQ(poly2[5], 0ULL); + ASSERT_EQ(poly2[6], 0ULL); + ASSERT_EQ(poly2[7], 0ULL); + ASSERT_EQ(poly2[8], 0ULL); + ASSERT_EQ(poly2[9], 0ULL); + ASSERT_EQ(poly2[10], 0ULL); + ASSERT_EQ(poly2[11], 0ULL); + + exponent = 3; + poly1[1] = 2; + exponentiate_poly(poly1.get(), 4, 1, &exponent, 1, 12, 1, poly2.get(), pool); + ASSERT_EQ(poly2[0], 0ULL); + ASSERT_EQ(poly2[1], 0ULL); + ASSERT_EQ(poly2[2], 0ULL); + ASSERT_EQ(poly2[3], 8ULL); + ASSERT_EQ(poly2[4], 0ULL); + ASSERT_EQ(poly2[5], 0ULL); + ASSERT_EQ(poly2[6], 0ULL); + ASSERT_EQ(poly2[7], 0ULL); + ASSERT_EQ(poly2[8], 0ULL); + ASSERT_EQ(poly2[9], 0ULL); + ASSERT_EQ(poly2[10], 0ULL); + ASSERT_EQ(poly2[11], 0ULL); + + exponent = 3; + poly1[0] = 1; + poly1[1] = 1; + exponentiate_poly(poly1.get(), 4, 1, &exponent, 1, 12, 1, poly2.get(), pool); + ASSERT_EQ(poly2[0], 1ULL); + ASSERT_EQ(poly2[1], 3ULL); + ASSERT_EQ(poly2[2], 3ULL); + ASSERT_EQ(poly2[3], 1ULL); + ASSERT_EQ(poly2[4], 0ULL); + ASSERT_EQ(poly2[5], 0ULL); + ASSERT_EQ(poly2[6], 0ULL); + ASSERT_EQ(poly2[7], 0ULL); + ASSERT_EQ(poly2[8], 0ULL); + ASSERT_EQ(poly2[9], 0ULL); + ASSERT_EQ(poly2[10], 0ULL); + ASSERT_EQ(poly2[11], 0ULL); + + exponent = 5; + poly1[0] = 0; + poly1[1] = 0; + poly1[2] = 2; + exponentiate_poly(poly1.get(), 4, 1, &exponent, 1, 12, 1, poly2.get(), pool); + ASSERT_EQ(poly2[0], 0ULL); + ASSERT_EQ(poly2[1], 0ULL); + ASSERT_EQ(poly2[2], 0ULL); + ASSERT_EQ(poly2[3], 0ULL); + ASSERT_EQ(poly2[4], 0ULL); + ASSERT_EQ(poly2[5], 0ULL); + ASSERT_EQ(poly2[6], 0ULL); + ASSERT_EQ(poly2[7], 0ULL); + ASSERT_EQ(poly2[8], 0ULL); + ASSERT_EQ(poly2[9], 0ULL); + ASSERT_EQ(poly2[10], 32ULL); + ASSERT_EQ(poly2[11], 0ULL); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/polyarithmod.cpp b/bigpiseal3.5.1/native/tests/seal/util/polyarithmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccc982761e10f2797989b3092504556766331cf2 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/polyarithmod.cpp @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/polyarithmod.h" +#include "seal/util/polycore.h" +#include "seal/util/uintcore.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(PolyArithMod, NegatePolyCoeffMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(3, 2, pool)); + auto modulus(allocate_uint(2, pool)); + poly[0] = 2; + poly[2] = 3; + poly[4] = 4; + modulus[0] = 15; + modulus[1] = 0; + negate_poly_coeffmod(poly.get(), 3, modulus.get(), 2, poly.get()); + ASSERT_EQ(static_cast<uint64_t>(13), poly[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly[1]); + ASSERT_EQ(static_cast<uint64_t>(12), poly[2]); + ASSERT_EQ(static_cast<uint64_t>(0), poly[3]); + ASSERT_EQ(static_cast<uint64_t>(11), poly[4]); + ASSERT_EQ(static_cast<uint64_t>(0), poly[5]); + + poly[0] = 2; + poly[2] = 3; + poly[4] = 4; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + negate_poly_coeffmod(poly.get(), 3, modulus.get(), 2, poly.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFD), poly[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFC), poly[2]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly[3]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFB), poly[4]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), poly[5]); + } + + TEST(PolyArithMod, AddPolyPolyCoeffMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 2, pool)); + auto poly2(allocate_zero_poly(3, 2, pool)); + auto modulus(allocate_uint(2, pool)); + poly1[0] = 1; + poly1[2] = 3; + poly1[4] = 4; + poly2[0] = 1; + poly2[2] = 2; + poly2[4] = 4; + modulus[0] = 5; + modulus[1] = 0; + add_poly_poly_coeffmod(poly1.get(), poly2.get(), 3, modulus.get(), 2, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(2), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[3]); + ASSERT_EQ(static_cast<uint64_t>(3), poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[5]); + } + + TEST(PolyArithMod, SubPolyPolyCoeffMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 2, pool)); + auto poly2(allocate_zero_poly(3, 2, pool)); + auto modulus(allocate_uint(2, pool)); + poly1[0] = 4; + poly1[2] = 3; + poly1[4] = 2; + poly2[0] = 2; + poly2[2] = 3; + poly2[4] = 4; + modulus[0] = 5; + modulus[1] = 0; + sub_poly_poly_coeffmod(poly1.get(), poly2.get(), 3, modulus.get(), 2, poly1.get()); + ASSERT_EQ(static_cast<uint64_t>(2), poly1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[1]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[2]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[3]); + ASSERT_EQ(static_cast<uint64_t>(3), poly1[4]); + ASSERT_EQ(static_cast<uint64_t>(0), poly1[5]); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/polyarithsmallmod.cpp b/bigpiseal3.5.1/native/tests/seal/util/polyarithsmallmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23cfa7bd04812bf3d1b9173f97000804554cd95b --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/polyarithsmallmod.cpp @@ -0,0 +1,413 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/polyarithsmallmod.h" +#include "seal/util/polycore.h" +#include "seal/util/uintcore.h" +#include <cstddef> +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(PolyArithSmallMod, SmallModuloPolyCoeffs) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(3, 1, pool)); + auto modulus(allocate_uint(2, pool)); + poly[0] = 2; + poly[1] = 15; + poly[2] = 77; + Modulus mod(15); + modulo_poly_coeffs(poly.get(), 3, mod, poly.get()); + ASSERT_EQ(2ULL, poly[0]); + ASSERT_EQ(0ULL, poly[1]); + ASSERT_EQ(2ULL, poly[2]); + } + + TEST(PolyArithSmallMod, NegatePolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(3, 1, pool)); + poly[0] = 2; + poly[1] = 3; + poly[2] = 4; + Modulus mod(15); + negate_poly_coeffmod(poly.get(), 3, mod, poly.get()); + ASSERT_EQ(static_cast<uint64_t>(13), poly[0]); + ASSERT_EQ(static_cast<uint64_t>(12), poly[1]); + ASSERT_EQ(static_cast<uint64_t>(11), poly[2]); + + poly[0] = 2; + poly[1] = 3; + poly[2] = 4; + mod = 0xFFFFFFFFFFFFFFULL; + negate_poly_coeffmod(poly.get(), 3, mod, poly.get()); + ASSERT_EQ(0xFFFFFFFFFFFFFDULL, poly[0]); + ASSERT_EQ(0xFFFFFFFFFFFFFCULL, poly[1]); + ASSERT_EQ(0xFFFFFFFFFFFFFBULL, poly[2]); + } + + TEST(PolyArithSmallMod, AddPolyPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 1, pool)); + auto poly2(allocate_zero_poly(3, 1, pool)); + poly1[0] = 1; + poly1[1] = 3; + poly1[2] = 4; + poly2[0] = 1; + poly2[1] = 2; + poly2[2] = 4; + Modulus mod(5); + add_poly_poly_coeffmod(poly1.get(), poly2.get(), 3, mod, poly1.get()); + ASSERT_EQ(2ULL, poly1[0]); + ASSERT_EQ(0ULL, poly1[1]); + ASSERT_EQ(3ULL, poly1[2]); + } + + TEST(PolyArithSmallMod, SubPolyPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 1, pool)); + auto poly2(allocate_zero_poly(3, 1, pool)); + poly1[0] = 4; + poly1[1] = 3; + poly1[2] = 2; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + Modulus mod(5); + sub_poly_poly_coeffmod(poly1.get(), poly2.get(), 3, mod, poly1.get()); + ASSERT_EQ(2ULL, poly1[0]); + ASSERT_EQ(0ULL, poly1[1]); + ASSERT_EQ(3ULL, poly1[2]); + } + + TEST(PolyArithSmallMod, MultiplyPolyScalarCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(3, 1, pool)); + poly[0] = 1; + poly[1] = 3; + poly[2] = 4; + uint64_t scalar = 3; + Modulus mod(5); + multiply_poly_scalar_coeffmod(poly.get(), 3, scalar, mod, poly.get()); + ASSERT_EQ(3ULL, poly[0]); + ASSERT_EQ(4ULL, poly[1]); + ASSERT_EQ(2ULL, poly[2]); + } + + TEST(PolyArithSmallMod, MultiplyPolyMonoCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(4, 1, pool)); + poly1[0] = 1; + poly1[1] = 3; + poly1[2] = 4; + poly1[3] = 2; + uint64_t mono_coeff = 3; + auto result(allocate_zero_poly(4, 1, pool)); + Modulus mod(5); + + size_t mono_exponent = 0; + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 1, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(3ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 2, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(3ULL, result[0]); + ASSERT_EQ(4ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + mono_exponent = 1; + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 2, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(3ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 4, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(4ULL, result[0]); + ASSERT_EQ(3ULL, result[1]); + ASSERT_EQ(4ULL, result[2]); + ASSERT_EQ(2ULL, result[3]); + + mono_coeff = 1; + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 4, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(3ULL, result[0]); + ASSERT_EQ(1ULL, result[1]); + ASSERT_EQ(3ULL, result[2]); + ASSERT_EQ(4ULL, result[3]); + + mono_coeff = 4; + mono_exponent = 3; + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 4, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(3ULL, result[0]); + ASSERT_EQ(4ULL, result[1]); + ASSERT_EQ(2ULL, result[2]); + ASSERT_EQ(4ULL, result[3]); + + mono_coeff = 1; + mono_exponent = 0; + negacyclic_multiply_poly_mono_coeffmod(poly1.get(), 4, mono_coeff, mono_exponent, mod, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(3ULL, result[1]); + ASSERT_EQ(4ULL, result[2]); + ASSERT_EQ(2ULL, result[3]); + } + + TEST(PolyArithSmallMod, MultiplyPolyPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 1, pool)); + auto poly2(allocate_zero_poly(3, 1, pool)); + auto result(allocate_zero_poly(5, 1, pool)); + poly1[0] = 1; + poly1[1] = 2; + poly1[2] = 3; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + Modulus mod(5); + multiply_poly_poly_coeffmod(poly1.get(), 3, poly2.get(), 3, mod, 5, result.get()); + ASSERT_EQ(2ULL, result[0]); + ASSERT_EQ(2ULL, result[1]); + ASSERT_EQ(1ULL, result[2]); + ASSERT_EQ(2ULL, result[3]); + ASSERT_EQ(2ULL, result[4]); + + poly2[0] = 2; + poly2[1] = 3; + multiply_poly_poly_coeffmod(poly1.get(), 3, poly2.get(), 2, mod, 5, result.get()); + ASSERT_EQ(2ULL, result[0]); + ASSERT_EQ(2ULL, result[1]); + ASSERT_EQ(2ULL, result[2]); + ASSERT_EQ(4ULL, result[3]); + ASSERT_EQ(0ULL, result[4]); + } + + TEST(PolyArithSmallMod, DividePolyPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(5, 1, pool)); + auto poly2(allocate_zero_poly(5, 1, pool)); + auto result(allocate_zero_poly(5, 1, pool)); + auto quotient(allocate_zero_poly(5, 1, pool)); + Modulus mod(5); + + poly1[0] = 2; + poly1[1] = 2; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + + divide_poly_poly_coeffmod_inplace(poly1.get(), poly2.get(), 5, mod, result.get()); + ASSERT_EQ(2ULL, poly1[0]); + ASSERT_EQ(2ULL, poly1[1]); + ASSERT_EQ(0ULL, poly1[2]); + ASSERT_EQ(0ULL, poly1[3]); + ASSERT_EQ(0ULL, poly1[4]); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + ASSERT_EQ(0ULL, result[4]); + + poly1[0] = 2; + poly1[1] = 2; + poly1[2] = 1; + poly1[3] = 2; + poly1[4] = 2; + poly2[0] = 4; + poly2[1] = 3; + poly2[2] = 2; + + divide_poly_poly_coeffmod(poly1.get(), poly2.get(), 5, mod, quotient.get(), result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + ASSERT_EQ(0ULL, result[4]); + ASSERT_EQ(3ULL, quotient[0]); + ASSERT_EQ(2ULL, quotient[1]); + ASSERT_EQ(1ULL, quotient[2]); + ASSERT_EQ(0ULL, quotient[3]); + ASSERT_EQ(0ULL, quotient[4]); + } + + TEST(PolyArithSmallMod, DyadicProductCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly1(allocate_zero_poly(3, 1, pool)); + auto poly2(allocate_zero_poly(3, 1, pool)); + auto result(allocate_zero_poly(3, 1, pool)); + Modulus mod(13); + + poly1[0] = 1; + poly1[1] = 1; + poly1[2] = 1; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + + dyadic_product_coeffmod(poly1.get(), poly2.get(), 3, mod, result.get()); + ASSERT_EQ(2ULL, result[0]); + ASSERT_EQ(3ULL, result[1]); + ASSERT_EQ(4ULL, result[2]); + + poly1[0] = 0; + poly1[1] = 0; + poly1[2] = 0; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + + dyadic_product_coeffmod(poly1.get(), poly2.get(), 3, mod, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + + poly1[0] = 3; + poly1[1] = 5; + poly1[2] = 8; + poly2[0] = 2; + poly2[1] = 3; + poly2[2] = 4; + + dyadic_product_coeffmod(poly1.get(), poly2.get(), 3, mod, result.get()); + ASSERT_EQ(6ULL, result[0]); + ASSERT_EQ(2ULL, result[1]); + ASSERT_EQ(6ULL, result[2]); + } + + TEST(PolyArithSmallMod, TryInvertPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(4, 1, pool)); + auto polymod(allocate_zero_poly(4, 1, pool)); + auto result(allocate_zero_poly(4, 1, pool)); + Modulus mod(5); + + polymod[0] = 4; + polymod[1] = 3; + polymod[2] = 0; + polymod[3] = 2; + + ASSERT_FALSE(try_invert_poly_coeffmod(poly.get(), polymod.get(), 4, mod, result.get(), pool)); + + poly[0] = 1; + ASSERT_TRUE(try_invert_poly_coeffmod(poly.get(), polymod.get(), 4, mod, result.get(), pool)); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + poly[0] = 1; + poly[1] = 2; + poly[2] = 3; + ASSERT_TRUE(try_invert_poly_coeffmod(poly.get(), polymod.get(), 4, mod, result.get(), pool)); + ASSERT_EQ(4ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(2ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + } + + TEST(PolyArithSmallMod, PolyInftyNormCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(4, 1, pool)); + Modulus mod(10); + + poly[0] = 0; + poly[1] = 1; + poly[2] = 2; + poly[3] = 3; + ASSERT_EQ(0x3ULL, poly_infty_norm_coeffmod(poly.get(), 4, mod)); + + poly[0] = 0; + poly[1] = 1; + poly[2] = 2; + poly[3] = 8; + ASSERT_EQ(0x2ULL, poly_infty_norm_coeffmod(poly.get(), 4, mod)); + } + + TEST(PolyArithSmallMod, NegacyclicShiftPolyCoeffSmallMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(4, 1, pool)); + auto result(allocate_zero_poly(4, 1, pool)); + + Modulus mod(10); + size_t coeff_count = 4; + + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 0, mod, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 1, mod, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 2, mod, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 3, mod, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + poly[0] = 1; + poly[1] = 2; + poly[2] = 3; + poly[3] = 4; + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 0, mod, result.get()); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(2ULL, result[1]); + ASSERT_EQ(3ULL, result[2]); + ASSERT_EQ(4ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 1, mod, result.get()); + ASSERT_EQ(6ULL, result[0]); + ASSERT_EQ(1ULL, result[1]); + ASSERT_EQ(2ULL, result[2]); + ASSERT_EQ(3ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 2, mod, result.get()); + ASSERT_EQ(7ULL, result[0]); + ASSERT_EQ(6ULL, result[1]); + ASSERT_EQ(1ULL, result[2]); + ASSERT_EQ(2ULL, result[3]); + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 3, mod, result.get()); + ASSERT_EQ(8ULL, result[0]); + ASSERT_EQ(7ULL, result[1]); + ASSERT_EQ(6ULL, result[2]); + ASSERT_EQ(1ULL, result[3]); + + poly[0] = 1; + poly[1] = 2; + poly[2] = 3; + poly[3] = 4; + coeff_count = 2; + negacyclic_shift_poly_coeffmod(poly.get(), coeff_count, 1, mod, result.get()); + negacyclic_shift_poly_coeffmod(poly.get() + 2, coeff_count, 1, mod, result.get() + 2); + ASSERT_EQ(8ULL, result[0]); + ASSERT_EQ(1ULL, result[1]); + ASSERT_EQ(6ULL, result[2]); + ASSERT_EQ(3ULL, result[3]); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/polycore.cpp b/bigpiseal3.5.1/native/tests/seal/util/polycore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f0333d8ee0c6364c194fe5507b864a3a6068226 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/polycore.cpp @@ -0,0 +1,296 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/polycore.h" +#include "seal/util/uintarith.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(PolyCore, AllocatePoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_poly(0, 0, pool)); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_poly(1, 0, pool); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_poly(0, 1, pool); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_poly(1, 1, pool); + ASSERT_TRUE(nullptr != ptr.get()); + + ptr = allocate_poly(2, 1, pool); + ASSERT_TRUE(nullptr != ptr.get()); + } + + TEST(PolyCore, SetZeroPoly) + { + set_zero_poly(0, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_poly(1, 1, pool)); + ptr[0] = 0x1234567812345678; + set_zero_poly(1, 1, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + + ptr = allocate_poly(2, 3, pool); + for (size_t i = 0; i < 6; ++i) + { + ptr[i] = 0x1234567812345678; + } + set_zero_poly(2, 3, ptr.get()); + for (size_t i = 0; i < 6; ++i) + { + ASSERT_EQ(static_cast<uint64_t>(0), ptr[i]); + } + } + + TEST(PolyCore, AllocateZeroPoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_poly(0, 0, pool)); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_zero_poly(1, 1, pool); + ASSERT_TRUE(nullptr != ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + + ptr = allocate_zero_poly(2, 3, pool); + ASSERT_TRUE(nullptr != ptr.get()); + for (size_t i = 0; i < 6; ++i) + { + ASSERT_EQ(static_cast<uint64_t>(0), ptr[i]); + } + } + + TEST(PolyCore, GetPolyCoeff) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_poly(2, 3, pool)); + *get_poly_coeff(ptr.get(), 0, 3) = 1; + *get_poly_coeff(ptr.get(), 1, 3) = 2; + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[3]); + ASSERT_EQ(1ULL, *get_poly_coeff(ptr.get(), 0, 3)); + ASSERT_EQ(static_cast<uint64_t>(2), *get_poly_coeff(ptr.get(), 1, 3)); + } + + TEST(PolyCore, SetPolyPoly) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_poly(2, 3, pool)); + auto ptr2(allocate_zero_poly(2, 3, pool)); + for (size_t i = 0; i < 6; ++i) + { + ptr1[i] = static_cast<uint64_t>(i + 1); + } + set_poly_poly(ptr1.get(), 2, 3, ptr2.get()); + for (size_t i = 0; i < 6; ++i) + { + ASSERT_EQ(static_cast<uint64_t>(i + 1), ptr2[i]); + } + + set_poly_poly(ptr1.get(), 2, 3, ptr1.get()); + for (size_t i = 0; i < 6; ++i) + { + ASSERT_EQ(static_cast<uint64_t>(i + 1), ptr2[i]); + } + + ptr2 = allocate_poly(3, 4, pool); + for (size_t i = 0; i < 12; ++i) + { + ptr2[i] = 1ULL; + } + set_poly_poly(ptr1.get(), 2, 3, 3, 4, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(3), ptr2[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[3]); + ASSERT_EQ(static_cast<uint64_t>(4), ptr2[4]); + ASSERT_EQ(static_cast<uint64_t>(5), ptr2[5]); + ASSERT_EQ(static_cast<uint64_t>(6), ptr2[6]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[7]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[8]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[9]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[10]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[11]); + + ptr2 = allocate_poly(2, 2, pool); + ptr2[1] = 1; + ptr2[2] = 1; + + // Canary + ptr2[0] = 0xDEADBEEFDEADBEEF; + ptr2[3] = 0xDEADBEEFDEADBEEF; + + set_poly_poly(ptr1.get(), 2, 3, 1, 2, ptr2.get() + 1); + ASSERT_EQ(1ULL, ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[2]); + + ASSERT_EQ(0xDEADBEEFDEADBEEF, ptr2[0]); + ASSERT_EQ(0xDEADBEEFDEADBEEF, ptr2[3]); + } + + TEST(PolyCore, IsZeroPoly) + { + ASSERT_TRUE(is_zero_poly(nullptr, 0, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_poly(2, 3, pool)); + for (size_t i = 0; i < 6; ++i) + { + ptr[i] = 0; + } + ASSERT_TRUE(is_zero_poly(ptr.get(), 2, 3)); + for (size_t i = 0; i < 6; ++i) + { + ptr[i] = 1; + ASSERT_FALSE(is_zero_poly(ptr.get(), 2, 3)); + ptr[i] = 0; + } + } + + TEST(PolyCore, IsEqualPolyPoly) + { + ASSERT_TRUE(is_equal_poly_poly(nullptr, nullptr, 0, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_poly(2, 3, pool)); + auto ptr2(allocate_poly(2, 3, pool)); + for (size_t i = 0; i < 6; ++i) + { + ptr2[i] = ptr1[i] = static_cast<uint64_t>(i + 1); + } + ASSERT_TRUE(is_equal_poly_poly(ptr1.get(), ptr2.get(), 2, 3)); + for (size_t i = 0; i < 6; ++i) + { + ptr2[i]--; + ASSERT_FALSE(is_equal_poly_poly(ptr1.get(), ptr2.get(), 2, 3)); + ptr2[i]++; + } + } + + TEST(PolyCore, IsOneZeroOnePoly) + { + ASSERT_FALSE(is_one_zero_one_poly(nullptr, 0, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(4, 2, pool)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 0, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 1, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 2, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 3, 2)); + + poly[0] = 2; + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 1, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 2, 2)); + + poly[0] = 1; + ASSERT_TRUE(is_one_zero_one_poly(poly.get(), 1, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 2, 2)); + + poly[2] = 2; + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 2, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 3, 2)); + + poly[2] = 1; + ASSERT_TRUE(is_one_zero_one_poly(poly.get(), 2, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 3, 2)); + + poly[4] = 1; + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 3, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 4, 2)); + + poly[2] = 0; + ASSERT_TRUE(is_one_zero_one_poly(poly.get(), 3, 2)); + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 4, 2)); + + poly[6] = 2; + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 4, 2)); + + poly[6] = 1; + ASSERT_FALSE(is_one_zero_one_poly(poly.get(), 4, 2)); + + poly[4] = 0; + ASSERT_TRUE(is_one_zero_one_poly(poly.get(), 4, 2)); + } + + TEST(PolyCore, GetSignificantCoeffCountPoly) + { + ASSERT_EQ(0ULL, get_significant_coeff_count_poly(nullptr, 0, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_poly(3, 2, pool)); + ASSERT_EQ(0ULL, get_significant_coeff_count_poly(ptr.get(), 3, 2)); + ptr[0] = 1; + ASSERT_EQ(1ULL, get_significant_coeff_count_poly(ptr.get(), 3, 2)); + ptr[1] = 1; + ASSERT_EQ(1ULL, get_significant_coeff_count_poly(ptr.get(), 3, 2)); + ptr[4] = 1; + ASSERT_EQ(3ULL, get_significant_coeff_count_poly(ptr.get(), 3, 2)); + ptr[4] = 0; + ptr[5] = 1; + ASSERT_EQ(3ULL, get_significant_coeff_count_poly(ptr.get(), 3, 2)); + } + + TEST(PolyCore, DuplicatePolyIfNeeded) + { + ASSERT_EQ(0ULL, get_significant_coeff_count_poly(nullptr, 0, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_poly(3, 2, pool)); + for (size_t i = 0; i < 6; i++) + { + poly[i] = i + 1; + } + + auto ptr = duplicate_poly_if_needed(poly.get(), 3, 2, 3, 2, false, pool); + ASSERT_TRUE(ptr.get() == poly.get()); + ptr = duplicate_poly_if_needed(poly.get(), 3, 2, 2, 2, false, pool); + ASSERT_TRUE(ptr.get() == poly.get()); + ptr = duplicate_poly_if_needed(poly.get(), 3, 2, 2, 3, false, pool); + ASSERT_TRUE(ptr.get() != poly.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[2]); + ASSERT_EQ(static_cast<uint64_t>(3), ptr[3]); + ASSERT_EQ(static_cast<uint64_t>(4), ptr[4]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[5]); + + ptr = duplicate_poly_if_needed(poly.get(), 3, 2, 3, 2, true, pool); + ASSERT_TRUE(ptr.get() != poly.get()); + for (size_t i = 0; i < 6; i++) + { + ASSERT_EQ(static_cast<uint64_t>(i + 1), ptr[i]); + } + } + + TEST(PolyCore, ArePolyCoeffsLessThan) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto poly(allocate_zero_poly(3, 2, pool)); + poly[0] = 3; + poly[2] = 5; + poly[4] = 4; + + auto max(allocate_uint(1, pool)); + max[0] = 1; + ASSERT_FALSE(are_poly_coefficients_less_than(poly.get(), 3, 2, max.get(), 1)); + max[0] = 5; + ASSERT_FALSE(are_poly_coefficients_less_than(poly.get(), 3, 2, max.get(), 1)); + max[0] = 6; + ASSERT_TRUE(are_poly_coefficients_less_than(poly.get(), 3, 2, max.get(), 1)); + max[0] = 10; + ASSERT_TRUE(are_poly_coefficients_less_than(poly.get(), 3, 2, max.get(), 1)); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/rns.cpp b/bigpiseal3.5.1/native/tests/seal/util/rns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b74aa8d2f295940650bdeec42674451a737f3b41 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/rns.cpp @@ -0,0 +1,994 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/memorymanager.h" +#include "seal/util/numth.h" +#include "seal/util/rns.h" +#include "seal/util/uintarithmod.h" +#include "seal/util/uintarithsmallmod.h" +#include <stdexcept> +#include <vector> +#include "gtest/gtest.h" + +using namespace seal; +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(RNSBaseTest, Create) + { + auto pool = MemoryManager::GetPool(); + ASSERT_THROW(RNSBase base({ 0 }, pool), invalid_argument); + ASSERT_THROW(RNSBase base({ 0, 3 }, pool), invalid_argument); + ASSERT_THROW(RNSBase base({ 2, 2 }, pool), invalid_argument); + ASSERT_THROW(RNSBase base({ 2, 3, 4 }, pool), invalid_argument); + ASSERT_THROW(RNSBase base({ 3, 4, 5, 6 }, pool), invalid_argument); + ASSERT_NO_THROW(RNSBase base({ 3, 4, 5, 7 }, pool)); + ASSERT_NO_THROW(RNSBase base({ 2 }, pool)); + ASSERT_NO_THROW(RNSBase base({ 3 }, pool)); + ASSERT_NO_THROW(RNSBase base({ 4 }, pool)); + } + + TEST(RNSBaseTest, ArrayAccess) + { + auto pool = MemoryManager::GetPool(); + { + RNSBase base({ 2 }, pool); + ASSERT_EQ(size_t(1), base.size()); + ASSERT_EQ(Modulus(2), base[0]); + ASSERT_THROW( + [&]() { + return base[1].value(); + }(), + out_of_range); + } + { + RNSBase base({ 2, 3, 5 }, pool); + ASSERT_EQ(size_t(3), base.size()); + ASSERT_EQ(Modulus(2), base[0]); + ASSERT_EQ(Modulus(3), base[1]); + ASSERT_EQ(Modulus(5), base[2]); + ASSERT_THROW( + [&]() { + return base[3].value(); + }(), + out_of_range); + } + } + + TEST(RNSBaseTest, Copy) + { + auto pool = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW); + RNSBase base({ 3, 4 }, pool); + ASSERT_EQ(2l, pool.use_count()); + { + RNSBase base2(base); + ASSERT_EQ(3l, pool.use_count()); + ASSERT_EQ(base.size(), base2.size()); + ASSERT_EQ(base[0], base2[0]); + ASSERT_EQ(base[1], base2[1]); + } + + ASSERT_EQ(2l, pool.use_count()); + { + RNSBase base2(base, MemoryManager::GetPool()); + ASSERT_EQ(2l, pool.use_count()); + ASSERT_EQ(base.size(), base2.size()); + ASSERT_EQ(base[0], base2[0]); + ASSERT_EQ(base[1], base2[1]); + } + } + + TEST(RNSBaseTest, Contains) + { + RNSBase base({ 2, 3, 5, 13 }, MemoryManager::GetPool()); + ASSERT_TRUE(base.contains(2)); + ASSERT_TRUE(base.contains(3)); + ASSERT_TRUE(base.contains(5)); + ASSERT_TRUE(base.contains(13)); + ASSERT_FALSE(base.contains(7)); + ASSERT_FALSE(base.contains(4)); + ASSERT_FALSE(base.contains(0)); + } + + TEST(RNSBaseTest, IsSubbaseOf) + { + { + RNSBase base({ 2 }, MemoryManager::GetPool()); + RNSBase base2({ 2 }, MemoryManager::GetPool()); + ASSERT_TRUE(base.is_subbase_of(base2)); + ASSERT_TRUE(base2.is_subbase_of(base)); + ASSERT_TRUE(base.is_superbase_of(base2)); + ASSERT_TRUE(base2.is_superbase_of(base)); + } + { + RNSBase base({ 2 }, MemoryManager::GetPool()); + RNSBase base2({ 2, 3 }, MemoryManager::GetPool()); + ASSERT_TRUE(base.is_subbase_of(base2)); + ASSERT_FALSE(base2.is_subbase_of(base)); + ASSERT_FALSE(base.is_superbase_of(base2)); + ASSERT_TRUE(base2.is_superbase_of(base)); + } + { + // Order does not matter for subbase/superbase + RNSBase base({ 3, 13, 7 }, MemoryManager::GetPool()); + RNSBase base2({ 2, 3, 5, 7, 13, 19 }, MemoryManager::GetPool()); + ASSERT_TRUE(base.is_subbase_of(base2)); + ASSERT_FALSE(base2.is_subbase_of(base)); + ASSERT_FALSE(base.is_superbase_of(base2)); + ASSERT_TRUE(base2.is_superbase_of(base)); + } + { + RNSBase base({ 3, 13, 7, 23 }, MemoryManager::GetPool()); + RNSBase base2({ 2, 3, 5, 7, 13, 19 }, MemoryManager::GetPool()); + ASSERT_FALSE(base.is_subbase_of(base2)); + ASSERT_FALSE(base2.is_subbase_of(base)); + ASSERT_FALSE(base.is_superbase_of(base2)); + ASSERT_FALSE(base2.is_superbase_of(base)); + } + } + + TEST(RNSBaseTest, Extend) + { + auto pool = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW); + RNSBase base({ 3 }, pool); + ASSERT_EQ(2l, pool.use_count()); + + RNSBase base2 = base.extend(5); + ASSERT_EQ(3l, pool.use_count()); + ASSERT_EQ(size_t(2), base2.size()); + ASSERT_EQ(base[0], base2[0]); + ASSERT_EQ(Modulus(5), base2[1]); + + RNSBase base3 = base2.extend(7); + ASSERT_EQ(4l, pool.use_count()); + ASSERT_EQ(size_t(3), base3.size()); + ASSERT_EQ(base2[0], base3[0]); + ASSERT_EQ(base2[1], base3[1]); + ASSERT_EQ(Modulus(7), base3[2]); + + ASSERT_THROW(auto base4 = base3.extend(0), invalid_argument); + ASSERT_THROW(auto base4 = base3.extend(14), logic_error); + + RNSBase base4({ 3, 4, 5 }, pool); + RNSBase base5({ 7, 11, 13, 17 }, pool); + RNSBase base6 = base4.extend(base5); + ASSERT_EQ(size_t(7), base6.size()); + ASSERT_EQ(Modulus(3), base6[0]); + ASSERT_EQ(Modulus(4), base6[1]); + ASSERT_EQ(Modulus(5), base6[2]); + ASSERT_EQ(Modulus(7), base6[3]); + ASSERT_EQ(Modulus(11), base6[4]); + ASSERT_EQ(Modulus(13), base6[5]); + ASSERT_EQ(Modulus(17), base6[6]); + + ASSERT_THROW(auto base7 = base4.extend(RNSBase({ 7, 11, 15 }, pool)), logic_error); + } + + TEST(RNSBaseTest, Drop) + { + auto pool = MemoryManager::GetPool(mm_prof_opt::FORCE_NEW); + RNSBase base({ 3, 5, 7, 11 }, pool); + ASSERT_EQ(2l, pool.use_count()); + + RNSBase base2 = base.drop(); + ASSERT_EQ(3l, pool.use_count()); + ASSERT_EQ(size_t(3), base2.size()); + ASSERT_EQ(base[0], base2[0]); + ASSERT_EQ(base[1], base2[1]); + ASSERT_EQ(base[2], base2[2]); + + RNSBase base3 = base2.drop().drop(); + ASSERT_EQ(size_t(1), base3.size()); + ASSERT_EQ(base[0], base3[0]); + + ASSERT_THROW(auto b = base3.drop(), logic_error); + ASSERT_THROW(auto b = base3.drop(3), logic_error); + ASSERT_THROW(auto b = base3.drop(5), logic_error); + + RNSBase base4 = base.drop(5); + ASSERT_EQ(size_t(3), base4.size()); + ASSERT_EQ(base[0], base4[0]); + ASSERT_EQ(base[2], base4[1]); + ASSERT_EQ(base[3], base4[2]); + + ASSERT_THROW(auto b = base4.drop(13), logic_error); + ASSERT_THROW(auto b = base4.drop(0), logic_error); + ASSERT_NO_THROW(auto b = base4.drop(7).drop(11)); + ASSERT_THROW(auto b = base4.drop(7).drop(11).drop(3), logic_error); + } + + TEST(RNSBaseTest, ComposeDecompose) + { + MemoryPoolHandle pool = MemoryManager::GetPool(); + + auto rns_test = [&pool](const RNSBase &base, vector<uint64_t> in, vector<uint64_t> out) { + auto in_copy = in; + base.decompose(in_copy.data(), pool); + ASSERT_TRUE(in_copy == out); + base.compose(in_copy.data(), pool); + ASSERT_TRUE(in_copy == in); + }; + + { + RNSBase base({ 2 }, pool); + rns_test(base, { 0 }, { 0 }); + rns_test(base, { 1 }, { 1 }); + } + { + RNSBase base({ 5 }, pool); + rns_test(base, { 0 }, { 0 }); + rns_test(base, { 1 }, { 1 }); + rns_test(base, { 2 }, { 2 }); + rns_test(base, { 3 }, { 3 }); + rns_test(base, { 4 }, { 4 }); + } + { + RNSBase base({ 3, 5 }, pool); + rns_test(base, { 0, 0 }, { 0, 0 }); + rns_test(base, { 1, 0 }, { 1, 1 }); + rns_test(base, { 2, 0 }, { 2, 2 }); + rns_test(base, { 3, 0 }, { 0, 3 }); + rns_test(base, { 4, 0 }, { 1, 4 }); + rns_test(base, { 5, 0 }, { 2, 0 }); + rns_test(base, { 8, 0 }, { 2, 3 }); + rns_test(base, { 12, 0 }, { 0, 2 }); + rns_test(base, { 14, 0 }, { 2, 4 }); + } + { + RNSBase base({ 2, 3, 5 }, pool); + rns_test(base, { 0, 0, 0 }, { 0, 0, 0 }); + rns_test(base, { 1, 0, 0 }, { 1, 1, 1 }); + rns_test(base, { 2, 0, 0 }, { 0, 2, 2 }); + rns_test(base, { 3, 0, 0 }, { 1, 0, 3 }); + rns_test(base, { 4, 0, 0 }, { 0, 1, 4 }); + rns_test(base, { 5, 0, 0 }, { 1, 2, 0 }); + rns_test(base, { 10, 0, 0 }, { 0, 1, 0 }); + rns_test(base, { 11, 0, 0 }, { 1, 2, 1 }); + rns_test(base, { 16, 0, 0 }, { 0, 1, 1 }); + rns_test(base, { 27, 0, 0 }, { 1, 0, 2 }); + rns_test(base, { 29, 0, 0 }, { 1, 2, 4 }); + } + { + RNSBase base({ 13, 37, 53, 97 }, pool); + rns_test(base, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }); + rns_test(base, { 1, 0, 0, 0 }, { 1, 1, 1, 1 }); + rns_test(base, { 2, 0, 0, 0 }, { 2, 2, 2, 2 }); + rns_test(base, { 12, 0, 0, 0 }, { 12, 12, 12, 12 }); + rns_test(base, { 321, 0, 0, 0 }, { 9, 25, 3, 30 }); + } + { + // Large example + auto primes = get_primes(1024, 60, 4); + vector<uint64_t> in_values{ 0xAAAAAAAAAAA, 0xBBBBBBBBBB, 0xCCCCCCCCCC, 0xDDDDDDDDDD }; + RNSBase base(primes, pool); + rns_test( + base, in_values, + { modulo_uint(in_values.data(), in_values.size(), primes[0]), + modulo_uint(in_values.data(), in_values.size(), primes[1]), + modulo_uint(in_values.data(), in_values.size(), primes[2]), + modulo_uint(in_values.data(), in_values.size(), primes[3]) }); + } + } + + TEST(BaseConvToolTest, Initialize) + { + auto pool = MemoryManager::GetPool(); + + // Good cases + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2 }, pool), RNSBase({ 2 }, pool), pool)); + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2 }, pool), RNSBase({ 3 }, pool), pool)); + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2, 3, 5 }, pool), RNSBase({ 2 }, pool), pool)); + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2, 3, 5 }, pool), RNSBase({ 3, 5 }, pool), pool)); + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2, 3, 5 }, pool), RNSBase({ 2, 3, 5, 7, 11 }, pool), pool)); + ASSERT_NO_THROW(BaseConverter bct(RNSBase({ 2, 3, 5 }, pool), RNSBase({ 7, 11 }, pool), pool)); + } + + TEST(BaseConvToolTest, Convert) + { + auto pool = MemoryManager::GetPool(); + + auto bct_test = [&](const BaseConverter &bct, const vector<uint64_t> &in, const vector<uint64_t> &out) { + uint64_t in_array[3], out_array[3]; + copy(in.cbegin(), in.cend(), in_array); + bct.fast_convert(in.data(), out_array, pool); + for (size_t i = 0; i < out.size(); i++) + { + ASSERT_EQ(out[i], out_array[i]); + } + }; + + { + BaseConverter bct(RNSBase({ 2 }, pool), RNSBase({ 2 }, pool), pool); + bct_test(bct, { 0 }, { 0 }); + bct_test(bct, { 1 }, { 1 }); + } + { + BaseConverter bct(RNSBase({ 2 }, pool), RNSBase({ 3 }, pool), pool); + bct_test(bct, { 0 }, { 0 }); + bct_test(bct, { 1 }, { 1 }); + } + { + BaseConverter bct(RNSBase({ 3 }, pool), RNSBase({ 2 }, pool), pool); + bct_test(bct, { 0 }, { 0 }); + bct_test(bct, { 1 }, { 1 }); + bct_test(bct, { 2 }, { 0 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 2 }, pool), pool); + bct_test(bct, { 0, 0 }, { 0 }); + bct_test(bct, { 1, 1 }, { 1 }); + bct_test(bct, { 0, 2 }, { 0 }); + bct_test(bct, { 1, 0 }, { 1 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 2, 3 }, pool), pool); + bct_test(bct, { 0, 0 }, { 0, 0 }); + bct_test(bct, { 1, 1 }, { 1, 1 }); + bct_test(bct, { 1, 2 }, { 1, 2 }); + bct_test(bct, { 0, 2 }, { 0, 2 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 3, 4, 5 }, pool), pool); + bct_test(bct, { 0, 0 }, { 0, 0, 0 }); + bct_test(bct, { 1, 1 }, { 1, 3, 2 }); + bct_test(bct, { 1, 2 }, { 2, 1, 0 }); + } + { + BaseConverter bct(RNSBase({ 3, 4, 5 }, pool), RNSBase({ 2, 3 }, pool), pool); + bct_test(bct, { 0, 0, 0 }, { 0, 0 }); + bct_test(bct, { 1, 1, 1 }, { 1, 1 }); + } + } + + TEST(BaseConvToolTest, ConvertArray) + { + auto pool = MemoryManager::GetPool(); + + auto bct_test = [&](const BaseConverter &bct, const vector<uint64_t> &in, const vector<uint64_t> &out) { + uint64_t in_array[3 * 3], out_array[3 * 3]; + copy(in.cbegin(), in.cend(), in_array); + bct.fast_convert_array(in.data(), 3, out_array, pool); + for (size_t i = 0; i < out.size(); i++) + { + ASSERT_EQ(out[i], out_array[i]); + } + }; + + // In this test the input is an array of values in the first base and output + // an array of values in the secnod base. Both input and output are stored in + // array-major order, NOT modulus-major order. + + { + BaseConverter bct(RNSBase({ 3 }, pool), RNSBase({ 2 }, pool), pool); + bct_test(bct, { 0, 1, 2 }, { 0, 1, 0 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 2 }, pool), pool); + bct_test(bct, { 0, 1, 0, 0, 1, 2 }, { 0, 1, 0 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 2, 3 }, pool), pool); + bct_test(bct, { 1, 1, 0, 1, 2, 2 }, { 1, 1, 0, 1, 2, 2 }); + } + { + BaseConverter bct(RNSBase({ 2, 3 }, pool), RNSBase({ 3, 4, 5 }, pool), pool); + bct_test(bct, { 0, 1, 1, 0, 1, 2 }, { 0, 1, 2, 0, 3, 1, 0, 2, 0 }); + } + } + + TEST(RNSToolTest, Initialize) + { + auto pool = MemoryManager::GetPool(); + + size_t poly_modulus_degree = 32; + size_t coeff_base_count = 4; + int prime_bit_count = 20; + + Modulus plain_t = 65537; + RNSBase coeff_base(get_primes(poly_modulus_degree, prime_bit_count, coeff_base_count), pool); + + ASSERT_NO_THROW(RNSTool rns_tool(poly_modulus_degree, coeff_base, plain_t, pool)); + + // Succeeds with 0 plain_modulus (case of CKKS) + ASSERT_NO_THROW(RNSTool rns_tool(poly_modulus_degree, coeff_base, 0, pool)); + + // Fails when poly_modulus_degree is too small + ASSERT_THROW(RNSTool rns_tool(1, coeff_base, plain_t, pool), invalid_argument); + } + + TEST(RNSToolTest, FastBConvMTilde) + { + // This function multiplies an input array with m_tilde (modulo q-base) and subsequently + // performs base conversion to Bsk U {m_tilde}. + + Modulus plain_t = 0; + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_q()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk_m_tilde()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fastbconv_m_tilde(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + in[0] = 1; + in[1] = 2; + rns_tool->fastbconv_m_tilde(in.data(), out.data(), pool); + + // These are results for fase base conversion for a length-2 array ((m_tilde), (2*m_tilde)) + // before reduction to target base. + uint64_t temp = rns_tool->m_tilde().value() % 3; + uint64_t temp2 = (2 * rns_tool->m_tilde().value()) % 3; + + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[0].value(), out[0]); + ASSERT_EQ(temp2 % (*rns_tool->base_Bsk_m_tilde())[0].value(), out[1]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[1].value(), out[2]); + ASSERT_EQ(temp2 % (*rns_tool->base_Bsk_m_tilde())[1].value(), out[3]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[2].value(), out[4]); + ASSERT_EQ(temp2 % (*rns_tool->base_Bsk_m_tilde())[2].value(), out[5]); + } + { + size_t poly_modulus_degree = 2; + size_t coeff_modulus_size = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3, 5 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * coeff_modulus_size); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk_m_tilde()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fastbconv_m_tilde(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + in[0] = 1; + in[1] = 1; + in[2] = 2; + in[3] = 2; + rns_tool->fastbconv_m_tilde(in.data(), out.data(), pool); + uint64_t m_tilde = rns_tool->m_tilde().value(); + + // This is the result of fast base conversion for a length-2 array + // ((m_tilde, 2*m_tilde), (m_tilde, 2*m_tilde)) before reduction to target base. + uint64_t temp = ((2 * m_tilde) % 3) * 5 + ((4 * m_tilde) % 5) * 3; + + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[0].value(), out[0]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[0].value(), out[1]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[1].value(), out[2]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[1].value(), out[3]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[2].value(), out[4]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[2].value(), out[5]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[3].value(), out[6]); + ASSERT_EQ(temp % (*rns_tool->base_Bsk_m_tilde())[3].value(), out[7]); + } + } + + TEST(RNSToolTest, MontgomeryReduction) + { + // This function assumes the input is in base Bsk U {m_tilde}. If the input is + // |[c*m_tilde]_q + qu|_m for m in Bsk U {m_tilde}, then the output is c' in Bsk + // such that c' = c mod q. In other words, this function cancels the extra multiples + // of q in the Bsk U {m_tilde} representation. The functions works correctly for + // sufficiently small values of u. + + Modulus plain_t = 0; + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_Bsk_m_tilde()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->sm_mrq(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // Input base is Bsk U {m_tilde}, in this case consisting of 3 primes. + // m_tilde is always smaller than the primes in Bsk (SEAL_INTERNAL_MOD_BIT_COUNT (61) bits). + // Set the length-2 array to have values 1*m_tilde and 2*m_tilde. + in[0] = rns_tool->m_tilde().value(); + in[1] = 2 * rns_tool->m_tilde().value(); + in[2] = rns_tool->m_tilde().value(); + in[3] = 2 * rns_tool->m_tilde().value(); + + // Modulo m_tilde + in[4] = 0; + in[5] = 0; + + // This should simply get rid of the m_tilde factor + rns_tool->sm_mrq(in.data(), out.data(), pool); + + ASSERT_EQ(1, out[0]); + ASSERT_EQ(2, out[1]); + ASSERT_EQ(1, out[2]); + ASSERT_EQ(2, out[3]); + + // Next add a multiple of q to the input and see if it is reduced properly + in[0] = (*rns_tool->base_q())[0].value(); + in[1] = (*rns_tool->base_q())[0].value(); + in[2] = (*rns_tool->base_q())[0].value(); + in[3] = (*rns_tool->base_q())[0].value(); + in[4] = (*rns_tool->base_q())[0].value(); + in[5] = (*rns_tool->base_q())[0].value(); + + rns_tool->sm_mrq(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + } + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3, 5 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_Bsk_m_tilde()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->sm_mrq(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // Input base is Bsk U {m_tilde}, in this case consisting of 6 primes. + // m_tilde is always smaller than the primes in Bsk (SEAL_INTERNAL_MOD_BIT_COUNT (61) bits). + // Set the length-2 array to have values 1*m_tilde and 2*m_tilde. + in[0] = rns_tool->m_tilde().value(); + in[1] = 2 * rns_tool->m_tilde().value(); + in[2] = rns_tool->m_tilde().value(); + in[3] = 2 * rns_tool->m_tilde().value(); + in[4] = rns_tool->m_tilde().value(); + in[5] = 2 * rns_tool->m_tilde().value(); + + // Modulo m_tilde + in[6] = 0; + in[7] = 0; + + // This should simply get rid of the m_tilde factor + rns_tool->sm_mrq(in.data(), out.data(), pool); + + ASSERT_EQ(1, out[0]); + ASSERT_EQ(2, out[1]); + ASSERT_EQ(1, out[2]); + ASSERT_EQ(2, out[3]); + ASSERT_EQ(1, out[4]); + ASSERT_EQ(2, out[5]); + + // Next add a multiple of q to the input and see if it is reduced properly + in[0] = 15; + in[1] = 30; + in[2] = 15; + in[3] = 30; + in[4] = 15; + in[5] = 30; + in[6] = 15; + in[7] = 30; + + rns_tool->sm_mrq(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // Now with a multiple of m_tilde + multiple of q + in[0] = 2 * rns_tool->m_tilde().value() + 15; + in[1] = 2 * rns_tool->m_tilde().value() + 30; + in[2] = 2 * rns_tool->m_tilde().value() + 15; + in[3] = 2 * rns_tool->m_tilde().value() + 30; + in[4] = 2 * rns_tool->m_tilde().value() + 15; + in[5] = 2 * rns_tool->m_tilde().value() + 30; + in[6] = 2 * rns_tool->m_tilde().value() + 15; + in[7] = 2 * rns_tool->m_tilde().value() + 30; + + rns_tool->sm_mrq(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(2, val); + } + } + } + + TEST(RNSToolTest, FastFloor) + { + // This function assumes the input is in base q U Bsk. It outputs an approximation of + // the value divided by q floored in base Bsk. The approximation has absolute value up + // to k-1, where k is the number of primes in the base q. + + Modulus plain_t = 0; + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * (rns_tool->base_Bsk()->size() + rns_tool->base_q()->size())); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fast_floor(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // The size of q U Bsk is 3. We set the input to have values 15 and 5, and divide by 3 (i.e., q). + in[0] = 15; + in[1] = 3; + in[2] = 15; + in[3] = 3; + in[4] = 15; + in[5] = 3; + + // We get an exact result in this case since input base only has size 1 + rns_tool->fast_floor(in.data(), out.data(), pool); + ASSERT_EQ(5ULL, out[0]); + ASSERT_EQ(1ULL, out[1]); + ASSERT_EQ(5ULL, out[2]); + ASSERT_EQ(1ULL, out[3]); + + // Now a case where the floor really shows up + in[0] = 17; + in[1] = 4; + in[2] = 17; + in[3] = 4; + in[4] = 17; + in[5] = 4; + + // We get an exact result in this case since input base only has size 1 + rns_tool->fast_floor(in.data(), out.data(), pool); + ASSERT_EQ(5ULL, out[0]); + ASSERT_EQ(1ULL, out[1]); + ASSERT_EQ(5ULL, out[2]); + ASSERT_EQ(1ULL, out[3]); + } + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3, 5 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * (rns_tool->base_Bsk()->size() + rns_tool->base_q()->size())); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_Bsk()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fast_floor(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // The size of q U Bsk is now 5. We set the input to multiples of 15 an divide by 15 (i.e., q). + in[0] = 15; + in[1] = 30; + in[2] = 15; + in[3] = 30; + in[4] = 15; + in[5] = 30; + in[6] = 15; + in[7] = 30; + in[8] = 15; + in[9] = 30; + + // We get an exact result in this case + rns_tool->fast_floor(in.data(), out.data(), pool); + ASSERT_EQ(1ULL, out[0]); + ASSERT_EQ(2ULL, out[1]); + ASSERT_EQ(1ULL, out[2]); + ASSERT_EQ(2ULL, out[3]); + ASSERT_EQ(1ULL, out[4]); + ASSERT_EQ(2ULL, out[5]); + + // Now a case where the floor really shows up + in[0] = 21; + in[1] = 32; + in[2] = 21; + in[3] = 32; + in[4] = 21; + in[5] = 32; + in[6] = 21; + in[7] = 32; + in[8] = 21; + in[9] = 32; + + // The result is not exact but differs at most by 1 + rns_tool->fast_floor(in.data(), out.data(), pool); + ASSERT_TRUE(fabs(1ULL - out[0]) <= 1); + ASSERT_TRUE(fabs(2ULL - out[1]) <= 1); + ASSERT_TRUE(fabs(1ULL - out[2]) <= 1); + ASSERT_TRUE(fabs(2ULL - out[3]) <= 1); + ASSERT_TRUE(fabs(1ULL - out[4]) <= 1); + ASSERT_TRUE(fabs(2ULL - out[5]) <= 1); + } + } + + TEST(RNSToolTest, FastBConvSK) + { + // This function assumes the input is in base Bsk and outputs a fast base conversion + // with Shenoy-Kumaresan correction to base q. The conversion is exact. + + Modulus plain_t = 0; + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_Bsk()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fastbconv_sk(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // The size of Bsk is 2 + in[0] = 1; + in[1] = 2; + in[2] = 1; + in[3] = 2; + + rns_tool->fastbconv_sk(in.data(), out.data(), pool); + ASSERT_EQ(1ULL, out[0]); + ASSERT_EQ(2ULL, out[1]); + } + { + size_t poly_modulus_degree = 2; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3, 5 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_Bsk()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->fastbconv_sk(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // The size of Bsk is 3 + in[0] = 1; + in[1] = 2; + in[2] = 1; + in[3] = 2; + in[4] = 1; + in[5] = 2; + + rns_tool->fastbconv_sk(in.data(), out.data(), pool); + ASSERT_EQ(1ULL, out[0]); + ASSERT_EQ(2ULL, out[1]); + ASSERT_EQ(1ULL, out[2]); + ASSERT_EQ(2ULL, out[3]); + } + } + + TEST(RNSToolTest, ExactScaleAndRound) + { + // This function computes [round(t/q * |input|_q)]_t exactly using the gamma-correction technique. + + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + size_t poly_modulus_degree = 2; + Modulus plain_t = 3; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 5, 7 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_Bsk()->size()); + vector<uint64_t> out(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->decrypt_scale_and_round(in.data(), out.data(), pool); + for (auto val : out) + { + ASSERT_EQ(0, val); + } + + // The size of Bsk is 2. Both values here are multiples of 35 (i.e., q). + in[0] = 35; + in[1] = 70; + in[2] = 35; + in[3] = 70; + + // We expect to get a zero output in this case + rns_tool->decrypt_scale_and_round(in.data(), out.data(), pool); + ASSERT_EQ(0ULL, out[0]); + ASSERT_EQ(0ULL, out[1]); + + // Now try a non-trivial case + in[0] = 29; + in[1] = 30 + 35; + in[2] = 29; + in[3] = 30 + 35; + + // Here 29 will scale and round to 2 and 30 will scale and round to 0. + // The added 35 should not make a difference. + rns_tool->decrypt_scale_and_round(in.data(), out.data(), pool); + ASSERT_EQ(2ULL, out[0]); + ASSERT_EQ(0ULL, out[1]); + } + + TEST(RNSToolTest, DivideAndRoundQLastInplace) + { + // This function approximately divides the input values by the last prime in the base q. + // Input is in base q; the last RNS component becomes invalid. + + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + { + size_t poly_modulus_degree = 2; + Modulus plain_t = 0; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 13, 7 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + + // The size of q is 2. We set some values here and divide by the last modulus (i.e., 7). + in[0] = 1; + in[1] = 2; + in[2] = 1; + in[3] = 2; + + // We expect to get a zero output also in this case + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + + // Next a case with non-trivial rounding + in[0] = 4; + in[1] = 12; + in[2] = 4; + in[3] = 12; + + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(1ULL, in[0]); + ASSERT_EQ(2ULL, in[1]); + + // Input array (19, 15) + in[0] = 6; + in[1] = 2; + in[2] = 5; + in[3] = 1; + + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(3ULL, in[0]); + ASSERT_EQ(2ULL, in[1]); + } + { + size_t poly_modulus_degree = 2; + Modulus plain_t = 0; + ASSERT_NO_THROW( + rns_tool = + allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 3, 5, 7, 11 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + ASSERT_EQ(0ULL, in[2]); + ASSERT_EQ(0ULL, in[3]); + ASSERT_EQ(0ULL, in[4]); + ASSERT_EQ(0ULL, in[5]); + + // The size of q is 4. We set some values here and divide by the last modulus (i.e., 11). + in[0] = 1; + in[1] = 2; + in[2] = 1; + in[3] = 2; + in[4] = 1; + in[5] = 2; + in[6] = 1; + in[7] = 2; + + // We expect to get a zero output also in this case + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + ASSERT_EQ(0ULL, in[2]); + ASSERT_EQ(0ULL, in[3]); + ASSERT_EQ(0ULL, in[4]); + ASSERT_EQ(0ULL, in[5]); + + // Next a case with non-trivial rounding; array is (60, 70) + in[0] = 0; + in[1] = 1; + in[2] = 0; + in[3] = 0; + in[4] = 4; + in[5] = 0; + in[6] = 5; + in[7] = 4; + + // We get only approximate result in this case + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_TRUE((3ULL + 2ULL - in[0]) % 3ULL <= 1); + ASSERT_TRUE((3ULL + 0ULL - in[1]) % 3ULL <= 1); + ASSERT_TRUE((5ULL + 0ULL - in[2]) % 5ULL <= 1); + ASSERT_TRUE((5ULL + 1ULL - in[3]) % 5ULL <= 1); + ASSERT_TRUE((7ULL + 5ULL - in[4]) % 7ULL <= 1); + ASSERT_TRUE((7ULL + 6ULL - in[5]) % 7ULL <= 1); + } + } + + TEST(RNSToolTest, DivideAndRoundQLastNTTInplace) + { + // This function approximately divides the input values by the last prime in the base q. + // The input and output are both in NTT form. Input is in base q; the last RNS component + // becomes invalid. + + auto pool = MemoryManager::GetPool(); + Pointer<RNSTool> rns_tool; + size_t poly_modulus_degree = 2; + NTTTables ntt[]{ { 1, Modulus(53) }, { 1, Modulus(13) } }; + Modulus plain_t = 0; + ASSERT_NO_THROW( + rns_tool = allocate<RNSTool>(pool, poly_modulus_degree, RNSBase({ 53, 13 }, pool), plain_t, pool)); + + vector<uint64_t> in(poly_modulus_degree * rns_tool->base_q()->size()); + set_zero_uint(in.size(), in.data()); + rns_tool->divide_and_round_q_last_inplace(in.data(), pool); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + + // The size of q is 2. We set some values here and divide by the last modulus (i.e., 13). + in[0] = 1; + in[1] = 2; + in[2] = 1; + in[3] = 2; + ntt_negacyclic_harvey(in.data(), ntt[0]); + ntt_negacyclic_harvey(in.data() + poly_modulus_degree, ntt[1]); + + // We expect to get a zero output also in this case + rns_tool->divide_and_round_q_last_ntt_inplace(in.data(), ntt, pool); + inverse_ntt_negacyclic_harvey(in.data(), ntt[0]); + ASSERT_EQ(0ULL, in[0]); + ASSERT_EQ(0ULL, in[1]); + + // Next a case with non-trivial rounding + in[0] = 4; + in[1] = 12; + in[2] = 4; + in[3] = 12; + ntt_negacyclic_harvey(in.data(), ntt[0]); + ntt_negacyclic_harvey(in.data() + poly_modulus_degree, ntt[1]); + + rns_tool->divide_and_round_q_last_ntt_inplace(in.data(), ntt, pool); + inverse_ntt_negacyclic_harvey(in.data(), ntt[0]); + ASSERT_TRUE((53ULL + 1ULL - in[0]) % 53ULL <= 1); + ASSERT_TRUE((53ULL + 2ULL - in[1]) % 53ULL <= 1); + + // Input array (25, 35) + in[0] = 25; + in[1] = 35; + in[2] = 12; + in[3] = 9; + ntt_negacyclic_harvey(in.data(), ntt[0]); + ntt_negacyclic_harvey(in.data() + poly_modulus_degree, ntt[1]); + + rns_tool->divide_and_round_q_last_ntt_inplace(in.data(), ntt, pool); + inverse_ntt_negacyclic_harvey(in.data(), ntt[0]); + ASSERT_TRUE((53ULL + 2ULL - in[0]) % 53ULL <= 1); + ASSERT_TRUE((53ULL + 3ULL - in[1]) % 53ULL <= 1); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/stringtouint64.cpp b/bigpiseal3.5.1/native/tests/seal/util/stringtouint64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..588612f71dd038f5c5420d770be0cbd3f610efc1 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/stringtouint64.cpp @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/uintcore.h" +#include <cstdint> +#include <cstring> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(StringToUInt64, IsHexCharTest) + { + ASSERT_TRUE(is_hex_char('0')); + ASSERT_TRUE(is_hex_char('1')); + ASSERT_TRUE(is_hex_char('2')); + ASSERT_TRUE(is_hex_char('3')); + ASSERT_TRUE(is_hex_char('4')); + ASSERT_TRUE(is_hex_char('5')); + ASSERT_TRUE(is_hex_char('6')); + ASSERT_TRUE(is_hex_char('7')); + ASSERT_TRUE(is_hex_char('8')); + ASSERT_TRUE(is_hex_char('9')); + ASSERT_TRUE(is_hex_char('A')); + ASSERT_TRUE(is_hex_char('B')); + ASSERT_TRUE(is_hex_char('C')); + ASSERT_TRUE(is_hex_char('D')); + ASSERT_TRUE(is_hex_char('E')); + ASSERT_TRUE(is_hex_char('F')); + ASSERT_TRUE(is_hex_char('a')); + ASSERT_TRUE(is_hex_char('b')); + ASSERT_TRUE(is_hex_char('c')); + ASSERT_TRUE(is_hex_char('d')); + ASSERT_TRUE(is_hex_char('e')); + ASSERT_TRUE(is_hex_char('f')); + + ASSERT_FALSE(is_hex_char('/')); + ASSERT_FALSE(is_hex_char(' ')); + ASSERT_FALSE(is_hex_char('+')); + ASSERT_FALSE(is_hex_char('\\')); + ASSERT_FALSE(is_hex_char('G')); + ASSERT_FALSE(is_hex_char('g')); + ASSERT_FALSE(is_hex_char('Z')); + ASSERT_FALSE(is_hex_char('Z')); + } + + TEST(StringToUInt64, HexToNibbleTest) + { + ASSERT_EQ(0, hex_to_nibble('0')); + ASSERT_EQ(1, hex_to_nibble('1')); + ASSERT_EQ(2, hex_to_nibble('2')); + ASSERT_EQ(3, hex_to_nibble('3')); + ASSERT_EQ(4, hex_to_nibble('4')); + ASSERT_EQ(5, hex_to_nibble('5')); + ASSERT_EQ(6, hex_to_nibble('6')); + ASSERT_EQ(7, hex_to_nibble('7')); + ASSERT_EQ(8, hex_to_nibble('8')); + ASSERT_EQ(9, hex_to_nibble('9')); + ASSERT_EQ(10, hex_to_nibble('A')); + ASSERT_EQ(11, hex_to_nibble('B')); + ASSERT_EQ(12, hex_to_nibble('C')); + ASSERT_EQ(13, hex_to_nibble('D')); + ASSERT_EQ(14, hex_to_nibble('E')); + ASSERT_EQ(15, hex_to_nibble('F')); + ASSERT_EQ(10, hex_to_nibble('a')); + ASSERT_EQ(11, hex_to_nibble('b')); + ASSERT_EQ(12, hex_to_nibble('c')); + ASSERT_EQ(13, hex_to_nibble('d')); + ASSERT_EQ(14, hex_to_nibble('e')); + ASSERT_EQ(15, hex_to_nibble('f')); + } + + TEST(StringToUInt64, GetHexStringBitCount) + { + ASSERT_EQ(0, get_hex_string_bit_count(nullptr, 0)); + ASSERT_EQ(0, get_hex_string_bit_count("0", 1)); + ASSERT_EQ(0, get_hex_string_bit_count("000000000", 9)); + ASSERT_EQ(1, get_hex_string_bit_count("1", 1)); + ASSERT_EQ(1, get_hex_string_bit_count("00001", 5)); + ASSERT_EQ(2, get_hex_string_bit_count("2", 1)); + ASSERT_EQ(2, get_hex_string_bit_count("00002", 5)); + ASSERT_EQ(2, get_hex_string_bit_count("3", 1)); + ASSERT_EQ(2, get_hex_string_bit_count("0003", 4)); + ASSERT_EQ(3, get_hex_string_bit_count("4", 1)); + ASSERT_EQ(3, get_hex_string_bit_count("5", 1)); + ASSERT_EQ(3, get_hex_string_bit_count("6", 1)); + ASSERT_EQ(3, get_hex_string_bit_count("7", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("8", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("9", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("A", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("B", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("C", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("D", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("E", 1)); + ASSERT_EQ(4, get_hex_string_bit_count("F", 1)); + ASSERT_EQ(5, get_hex_string_bit_count("10", 2)); + ASSERT_EQ(5, get_hex_string_bit_count("00010", 5)); + ASSERT_EQ(5, get_hex_string_bit_count("11", 2)); + ASSERT_EQ(5, get_hex_string_bit_count("1F", 2)); + ASSERT_EQ(6, get_hex_string_bit_count("20", 2)); + ASSERT_EQ(6, get_hex_string_bit_count("2F", 2)); + ASSERT_EQ(7, get_hex_string_bit_count("7F", 2)); + ASSERT_EQ(7, get_hex_string_bit_count("0007F", 5)); + ASSERT_EQ(8, get_hex_string_bit_count("80", 2)); + ASSERT_EQ(8, get_hex_string_bit_count("FF", 2)); + ASSERT_EQ(8, get_hex_string_bit_count("00FF", 4)); + ASSERT_EQ(9, get_hex_string_bit_count("100", 3)); + ASSERT_EQ(9, get_hex_string_bit_count("000100", 6)); + ASSERT_EQ(22, get_hex_string_bit_count("200000", 6)); + ASSERT_EQ(35, get_hex_string_bit_count("7FFF30001", 9)); + + ASSERT_EQ(15, get_hex_string_bit_count("7FFF30001", 4)); + ASSERT_EQ(3, get_hex_string_bit_count("7FFF30001", 1)); + ASSERT_EQ(0, get_hex_string_bit_count("7FFF30001", 0)); + } + + TEST(StringToUInt64, HexStringToUInt64) + { + uint64_t correct[3]; + uint64_t parsed[3]; + + correct[0] = 0; + correct[1] = 0; + correct[2] = 0; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("0", 1, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("0", 1, 1, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 1 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint(nullptr, 0, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 1; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("1", 1, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("01", 2, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("001", 3, 1, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 1 * sizeof(uint64_t))); + + correct[0] = 0xF; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("F", 1, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x10; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("10", 2, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("010", 3, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x100; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("100", 3, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x123; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("123", 3, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("00000123", 8, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0; + correct[1] = 1; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("10000000000000000", 17, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x1123456789ABCDEF; + correct[1] = 0x1; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("11123456789ABCDEF", 17, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("000011123456789ABCDEF", 21, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x3456789ABCDEF123; + correct[1] = 0x23456789ABCDEF12; + correct[2] = 0x123456789ABCDEF1; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("123456789ABCDEF123456789ABCDEF123456789ABCDEF123", 48, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0xFFFFFFFFFFFFFFFF; + correct[1] = 0xFFFFFFFFFFFFFFFF; + correct[2] = 0xFFFFFFFFFFFFFFFF; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 48, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x100; + correct[1] = 0; + correct[2] = 0; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("100", 3, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x10; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("100", 2, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0x1; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("100", 1, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + + correct[0] = 0; + parsed[0] = 0x123; + parsed[1] = 0x123; + parsed[2] = 0x123; + hex_string_to_uint("100", 0, 3, parsed); + ASSERT_EQ(0, memcmp(correct, parsed, 3 * sizeof(uint64_t))); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/uint64tostring.cpp b/bigpiseal3.5.1/native/tests/seal/util/uint64tostring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33dc87a4b0ff1c1903fa23a50e4def8f6748132f --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/uint64tostring.cpp @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/common.h" +#include "seal/util/mempool.h" +#include "seal/util/polycore.h" +#include "seal/util/uintcore.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(UInt64ToString, NibbleToUpperHexTest) + { + ASSERT_EQ('0', nibble_to_upper_hex(0)); + ASSERT_EQ('1', nibble_to_upper_hex(1)); + ASSERT_EQ('2', nibble_to_upper_hex(2)); + ASSERT_EQ('3', nibble_to_upper_hex(3)); + ASSERT_EQ('4', nibble_to_upper_hex(4)); + ASSERT_EQ('5', nibble_to_upper_hex(5)); + ASSERT_EQ('6', nibble_to_upper_hex(6)); + ASSERT_EQ('7', nibble_to_upper_hex(7)); + ASSERT_EQ('8', nibble_to_upper_hex(8)); + ASSERT_EQ('9', nibble_to_upper_hex(9)); + ASSERT_EQ('A', nibble_to_upper_hex(10)); + ASSERT_EQ('B', nibble_to_upper_hex(11)); + ASSERT_EQ('C', nibble_to_upper_hex(12)); + ASSERT_EQ('D', nibble_to_upper_hex(13)); + ASSERT_EQ('E', nibble_to_upper_hex(14)); + ASSERT_EQ('F', nibble_to_upper_hex(15)); + } + + TEST(UInt64ToString, UInt64ToHexString) + { + uint64_t number[] = { 0, 0, 0 }; + string correct = "0"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + ASSERT_EQ(correct, uint_to_hex_string(number, 1)); + ASSERT_EQ(correct, uint_to_hex_string(number, 0)); + ASSERT_EQ(correct, uint_to_hex_string(nullptr, 0)); + + number[0] = 1; + correct = "1"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + ASSERT_EQ(correct, uint_to_hex_string(number, 1)); + + number[0] = 0xF; + correct = "F"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0x10; + correct = "10"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0x100; + correct = "100"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0x123; + correct = "123"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0; + number[1] = 1; + correct = "10000000000000000"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0x1123456789ABCDEF; + number[1] = 0x1; + correct = "11123456789ABCDEF"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0x3456789ABCDEF123; + number[1] = 0x23456789ABCDEF12; + number[2] = 0x123456789ABCDEF1; + correct = "123456789ABCDEF123456789ABCDEF123456789ABCDEF123"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + + number[0] = 0xFFFFFFFFFFFFFFFF; + number[1] = 0xFFFFFFFFFFFFFFFF; + number[2] = 0xFFFFFFFFFFFFFFFF; + correct = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; + ASSERT_EQ(correct, uint_to_hex_string(number, 3)); + } + + TEST(UInt64ToString, UInt64ToDecString) + { + uint64_t number[] = { 0, 0, 0 }; + string correct = "0"; + MemoryPool &pool = *global_variables::global_memory_pool; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + ASSERT_EQ(correct, uint_to_dec_string(number, 1, pool)); + ASSERT_EQ(correct, uint_to_dec_string(number, 0, pool)); + ASSERT_EQ(correct, uint_to_dec_string(nullptr, 0, pool)); + + number[0] = 1; + correct = "1"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + ASSERT_EQ(correct, uint_to_dec_string(number, 1, pool)); + + number[0] = 9; + correct = "9"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + + number[0] = 10; + correct = "10"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + + number[0] = 123; + correct = "123"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + + number[0] = 987654321; + correct = "987654321"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + + number[0] = 0; + number[1] = 1; + correct = "18446744073709551616"; + ASSERT_EQ(correct, uint_to_dec_string(number, 3, pool)); + } + + TEST(UInt64ToString, PolyToHexString) + { + uint64_t number[] = { 0, 0, 0, 0 }; + string correct = "0"; + ASSERT_EQ(correct, poly_to_hex_string(number, 0, 1)); + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 0)); + ASSERT_EQ(correct, poly_to_hex_string(number, 1, 1)); + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + ASSERT_EQ(correct, poly_to_hex_string(number, 2, 2)); + ASSERT_EQ(correct, poly_to_hex_string(number, 1, 4)); + + number[0] = 1; + correct = "1"; + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + ASSERT_EQ(correct, poly_to_hex_string(number, 2, 2)); + ASSERT_EQ(correct, poly_to_hex_string(number, 1, 4)); + + number[0] = 0; + number[1] = 1; + correct = "1x^1"; + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + correct = "10000000000000000"; + ASSERT_EQ(correct, poly_to_hex_string(number, 2, 2)); + ASSERT_EQ(correct, poly_to_hex_string(number, 1, 4)); + + number[0] = 1; + number[1] = 0; + number[2] = 0; + number[3] = 1; + correct = "1x^3 + 1"; + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + correct = "10000000000000000x^1 + 1"; + ASSERT_EQ(correct, poly_to_hex_string(number, 2, 2)); + correct = "1000000000000000000000000000000000000000000000001"; + ASSERT_EQ(correct, poly_to_hex_string(number, 1, 4)); + + number[0] = 0xF00000000000000F; + number[1] = 0xF0F0F0F0F0F0F0F0; + number[2] = 0; + number[3] = 0; + correct = "F0F0F0F0F0F0F0F0x^1 + F00000000000000F"; + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + correct = "F0F0F0F0F0F0F0F0F00000000000000F"; + + number[2] = 0xF0FF0F0FF0F0FF0F; + number[3] = 0xBABABABABABABABA; + correct = "BABABABABABABABAF0FF0F0FF0F0FF0Fx^1 + F0F0F0F0F0F0F0F0F00000000000000F"; + ASSERT_EQ(correct, poly_to_hex_string(number, 2, 2)); + correct = "BABABABABABABABAx^3 + F0FF0F0FF0F0FF0Fx^2 + F0F0F0F0F0F0F0F0x^1 + F00000000000000F"; + ASSERT_EQ(correct, poly_to_hex_string(number, 4, 1)); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/uintarith.cpp b/bigpiseal3.5.1/native/tests/seal/util/uintarith.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17c7f3d318a92fb1c75e9e1f98c4da4462fc959f --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/uintarith.cpp @@ -0,0 +1,1787 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/uintarith.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(UIntArith, AddUInt64Generic) + { + unsigned long long result; + ASSERT_FALSE(add_uint64_generic(0ULL, 0ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(add_uint64_generic(1ULL, 1ULL, 0, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64_generic(1ULL, 0ULL, 1, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64_generic(0ULL, 1ULL, 1, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64_generic(1ULL, 1ULL, 1, &result)); + ASSERT_EQ(3ULL, result); + ASSERT_TRUE(add_uint64_generic(0xFFFFFFFFFFFFFFFFULL, 1ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64_generic(1ULL, 0xFFFFFFFFFFFFFFFFULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64_generic(1ULL, 0xFFFFFFFFFFFFFFFFULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_TRUE(add_uint64_generic(2ULL, 0xFFFFFFFFFFFFFFFEULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64_generic(2ULL, 0xFFFFFFFFFFFFFFFEULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_FALSE(add_uint64_generic(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 0, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, result); + ASSERT_TRUE(add_uint64_generic(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 1, &result)); + ASSERT_EQ(0x0ULL, result); + } + +#if SEAL_COMPILER == SEAL_COMPILER_MSVC +#pragma optimize("", off) +#elif SEAL_COMPILER == SEAL_COMPILER_GCC +#pragma GCC push_options +#pragma GCC optimize("O0") +#elif SEAL_COMPILER == SEAL_COMPILER_CLANG +#pragma clang optimize off +#endif + + TEST(UIntArith, AddUInt64) + { + unsigned long long result; + ASSERT_FALSE(add_uint64(0ULL, 0ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(add_uint64(1ULL, 1ULL, 0, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64(1ULL, 0ULL, 1, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64(0ULL, 1ULL, 1, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_FALSE(add_uint64(1ULL, 1ULL, 1, &result)); + ASSERT_EQ(3ULL, result); + ASSERT_TRUE(add_uint64(0xFFFFFFFFFFFFFFFFULL, 1ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64(1ULL, 0xFFFFFFFFFFFFFFFFULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64(1ULL, 0xFFFFFFFFFFFFFFFFULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_TRUE(add_uint64(2ULL, 0xFFFFFFFFFFFFFFFEULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(add_uint64(2ULL, 0xFFFFFFFFFFFFFFFEULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_FALSE(add_uint64(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 0, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, result); + ASSERT_TRUE(add_uint64(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 1, &result)); + ASSERT_EQ(0x0ULL, result); + } + +#if SEAL_COMPILER == SEAL_COMPILER_MSVC +#pragma optimize("", on) +#elif SEAL_COMPILER == SEAL_COMPILER_GCC +#pragma GCC pop_options +#elif SEAL_COMPILER == SEAL_COMPILER_CLANG +#pragma clang optimize on +#endif + + TEST(UIntArith, SubUInt64Generic) + { + unsigned long long result; + ASSERT_FALSE(sub_uint64_generic(0ULL, 0ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(sub_uint64_generic(1ULL, 1ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(sub_uint64_generic(1ULL, 0ULL, 1, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(sub_uint64_generic(0ULL, 1ULL, 1, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFEULL, result); + ASSERT_TRUE(sub_uint64_generic(1ULL, 1ULL, 1, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, result); + ASSERT_FALSE(sub_uint64_generic(0xFFFFFFFFFFFFFFFFULL, 1ULL, 0, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFEULL, result); + ASSERT_TRUE(sub_uint64_generic(1ULL, 0xFFFFFFFFFFFFFFFFULL, 0, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_TRUE(sub_uint64_generic(1ULL, 0xFFFFFFFFFFFFFFFFULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_TRUE(sub_uint64_generic(2ULL, 0xFFFFFFFFFFFFFFFEULL, 0, &result)); + ASSERT_EQ(4ULL, result); + ASSERT_TRUE(sub_uint64_generic(2ULL, 0xFFFFFFFFFFFFFFFEULL, 1, &result)); + ASSERT_EQ(3ULL, result); + ASSERT_FALSE(sub_uint64_generic(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 0, &result)); + ASSERT_EQ(0xE01E01E01E01E01FULL, result); + ASSERT_FALSE(sub_uint64_generic(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 1, &result)); + ASSERT_EQ(0xE01E01E01E01E01EULL, result); + } + + TEST(UIntArith, SubUInt64) + { + unsigned long long result; + ASSERT_FALSE(sub_uint64(0ULL, 0ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(sub_uint64(1ULL, 1ULL, 0, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_FALSE(sub_uint64(1ULL, 0ULL, 1, &result)); + ASSERT_EQ(0ULL, result); + ASSERT_TRUE(sub_uint64(0ULL, 1ULL, 1, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFEULL, result); + ASSERT_TRUE(sub_uint64(1ULL, 1ULL, 1, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, result); + ASSERT_FALSE(sub_uint64(0xFFFFFFFFFFFFFFFFULL, 1ULL, 0, &result)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFEULL, result); + ASSERT_TRUE(sub_uint64(1ULL, 0xFFFFFFFFFFFFFFFFULL, 0, &result)); + ASSERT_EQ(2ULL, result); + ASSERT_TRUE(sub_uint64(1ULL, 0xFFFFFFFFFFFFFFFFULL, 1, &result)); + ASSERT_EQ(1ULL, result); + ASSERT_TRUE(sub_uint64(2ULL, 0xFFFFFFFFFFFFFFFEULL, 0, &result)); + ASSERT_EQ(4ULL, result); + ASSERT_TRUE(sub_uint64(2ULL, 0xFFFFFFFFFFFFFFFEULL, 1, &result)); + ASSERT_EQ(3ULL, result); + ASSERT_FALSE(sub_uint64(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 0, &result)); + ASSERT_EQ(0xE01E01E01E01E01FULL, result); + ASSERT_FALSE(sub_uint64(0xF00F00F00F00F00FULL, 0x0FF0FF0FF0FF0FF0ULL, 1, &result)); + ASSERT_EQ(0xE01E01E01E01E01EULL, result); + } + + TEST(UIntArith, AddUInt128) + { + auto set_uint128 = [](uint64_t *destination, uint64_t val0, uint64_t val1) { + destination[0] = val0; + destination[1] = val1; + }; + + auto assert_uint128_eq = [](unsigned long long *test, unsigned long long expect0, + unsigned long long expect1) { + ASSERT_EQ(expect0, test[0]); + ASSERT_EQ(expect1, test[1]); + }; + + uint64_t operand1[2]{ 0, 0 }; + uint64_t operand2[2]{ 0, 0 }; + unsigned long long result[2]{ 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL }; + ASSERT_FALSE(add_uint128(operand1, operand2, result)); + ASSERT_EQ(0, result[0] | result[1]); + + set_uint128(operand1, 1, 1); + set_uint128(operand2, 1, 1); + ASSERT_FALSE(add_uint128(operand1, operand2, result)); + assert_uint128_eq(result, 2, 2); + + set_uint128(operand1, 0xFFFFFFFFFFFFFFFFULL, 0); + set_uint128(operand2, 1, 0); + ASSERT_FALSE(add_uint128(operand1, operand2, result)); + assert_uint128_eq(result, 0, 1); + + set_uint128(operand1, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL); + set_uint128(operand2, 1, 0); + ASSERT_TRUE(add_uint128(operand1, operand2, result)); + assert_uint128_eq(result, 0, 0); + } + + TEST(UIntArith, AddUIntUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_FALSE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_TRUE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + + ASSERT_TRUE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_TRUE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(add_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(1ULL, ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 5; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(add_uint_uint(ptr.get(), 2, ptr2.get(), 1, false, 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(6), ptr3[1]); + ASSERT_FALSE(add_uint_uint(ptr.get(), 2, ptr2.get(), 1, true, 2, ptr3.get()) != 0); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(6), ptr3[1]); + } + + TEST(UIntArith, SubUIntUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_TRUE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_TRUE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_TRUE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0; + ptr[1] = 1; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(sub_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0; + ptr[1] = 1; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ASSERT_FALSE(sub_uint_uint(ptr.get(), 2, ptr2.get(), 1, false, 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + ASSERT_FALSE(sub_uint_uint(ptr.get(), 2, ptr2.get(), 1, true, 2, ptr3.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + } + + TEST(UIntArith, AddUIntUInt64) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + + ptr[0] = 0ULL; + ptr[1] = 0ULL; + ASSERT_FALSE(add_uint_uint64(ptr.get(), 0ULL, 2, ptr2.get())); + ASSERT_EQ(0ULL, ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFF00000000ULL; + ptr[1] = 0ULL; + ASSERT_FALSE(add_uint_uint64(ptr.get(), 0xFFFFFFFFULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFF00000000ULL; + ptr[1] = 0xFFFFFFFF00000000ULL; + ASSERT_FALSE(add_uint_uint64(ptr.get(), 0x100000000ULL, 2, ptr2.get())); + ASSERT_EQ(0ULL, ptr2[0]); + ASSERT_EQ(0xFFFFFFFF00000001ULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFFULL; + ptr[1] = 0xFFFFFFFFFFFFFFFFULL; + ASSERT_TRUE(add_uint_uint64(ptr.get(), 1ULL, 2, ptr2.get())); + ASSERT_EQ(0ULL, ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + } + + TEST(UIntArith, SubUIntUInt64) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + + ptr[0] = 0ULL; + ptr[1] = 0ULL; + ASSERT_FALSE(sub_uint_uint64(ptr.get(), 0ULL, 2, ptr2.get())); + ASSERT_EQ(0ULL, ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + + ptr[0] = 0ULL; + ptr[1] = 0ULL; + ASSERT_TRUE(sub_uint_uint64(ptr.get(), 1ULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[0]); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[1]); + + ptr[0] = 1ULL; + ptr[1] = 0ULL; + ASSERT_TRUE(sub_uint_uint64(ptr.get(), 2ULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[0]); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFF00000000ULL; + ptr[1] = 0ULL; + ASSERT_FALSE(sub_uint_uint64(ptr.get(), 0xFFFFFFFFULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFE00000001ULL, ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFF00000000ULL; + ptr[1] = 0xFFFFFFFF00000000ULL; + ASSERT_FALSE(sub_uint_uint64(ptr.get(), 0x100000000ULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFE00000000ULL, ptr2[0]); + ASSERT_EQ(0xFFFFFFFF00000000ULL, ptr2[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFFULL; + ptr[1] = 0xFFFFFFFFFFFFFFFFULL; + ASSERT_FALSE(sub_uint_uint64(ptr.get(), 1ULL, 2, ptr2.get())); + ASSERT_EQ(0xFFFFFFFFFFFFFFFEULL, ptr2[0]); + ASSERT_EQ(0xFFFFFFFFFFFFFFFFULL, ptr2[1]); + } + + TEST(UIntArith, IncrementUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr1[0] = 0; + ptr1[1] = 0; + ASSERT_FALSE(increment_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_FALSE(increment_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(2), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + + ptr1[0] = 0xFFFFFFFFFFFFFFFF; + ptr1[1] = 0; + ASSERT_FALSE(increment_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(1ULL, ptr2[1]); + ASSERT_FALSE(increment_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(1ULL, ptr1[0]); + ASSERT_EQ(1ULL, ptr1[1]); + + ptr1[0] = 0xFFFFFFFFFFFFFFFF; + ptr1[1] = 1; + ASSERT_FALSE(increment_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[1]); + ASSERT_FALSE(increment_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(1ULL, ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr1[1]); + + ptr1[0] = 0xFFFFFFFFFFFFFFFE; + ptr1[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_FALSE(increment_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[1]); + ASSERT_TRUE(increment_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + ASSERT_FALSE(increment_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + } + + TEST(UIntArith, DecrementUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr1[0] = 2; + ptr1[1] = 2; + ASSERT_FALSE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr1[1]); + ASSERT_FALSE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[0]); + ASSERT_EQ(1ULL, ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr1[0]); + ASSERT_EQ(1ULL, ptr1[1]); + + ptr1[0] = 2; + ptr1[1] = 1; + ASSERT_FALSE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(1ULL, ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + ASSERT_EQ(1ULL, ptr1[1]); + ASSERT_FALSE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + + ptr1[0] = 2; + ptr1[1] = 0; + ASSERT_FALSE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + ASSERT_TRUE(decrement_uint(ptr1.get(), 2, ptr2.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr2[1]); + ASSERT_FALSE(decrement_uint(ptr2.get(), 2, ptr1.get()) != 0); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr1[1]); + } + + TEST(UIntArith, NegateUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 1; + ptr[1] = 0; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 2; + ptr[1] = 0; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0; + ptr[1] = 1; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(1ULL, ptr[1]); + + ptr[0] = 0; + ptr[1] = 2; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[1]); + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[1]); + + ptr[0] = 1; + ptr[1] = 1; + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[1]); + negate_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(1ULL, ptr[1]); + } + + TEST(UIntArith, LeftShiftUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint(ptr.get(), 0, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint(ptr.get(), 10, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + left_shift_uint(ptr.get(), 10, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + left_shift_uint(ptr.get(), 0, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + left_shift_uint(ptr.get(), 0, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + left_shift_uint(ptr.get(), 1, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[1]); + left_shift_uint(ptr.get(), 2, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr2[1]); + left_shift_uint(ptr.get(), 64, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[1]); + left_shift_uint(ptr.get(), 65, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + left_shift_uint(ptr.get(), 127, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr2[1]); + + left_shift_uint(ptr.get(), 2, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr[1]); + left_shift_uint(ptr.get(), 64, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[1]); + } + + TEST(UIntArith, LeftShiftUInt128) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint128(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint128(ptr.get(), 10, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + left_shift_uint128(ptr.get(), 10, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + left_shift_uint128(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + left_shift_uint128(ptr.get(), 0, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + left_shift_uint128(ptr.get(), 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[1]); + left_shift_uint128(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr2[1]); + left_shift_uint128(ptr.get(), 64, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[1]); + left_shift_uint128(ptr.get(), 65, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + left_shift_uint128(ptr.get(), 127, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr2[1]); + + left_shift_uint128(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr[1]); + left_shift_uint128(ptr.get(), 64, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[1]); + } + + TEST(UIntArith, LeftShiftUInt192) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(3, pool)); + auto ptr2(allocate_uint(3, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr[2] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[2] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint192(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[2] = 0xFFFFFFFFFFFFFFFF; + left_shift_uint192(ptr.get(), 10, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + left_shift_uint192(ptr.get(), 10, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[2]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + ptr[2] = 0xCDCDCDCDCDCDCDCD; + left_shift_uint192(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0xCDCDCDCDCDCDCDCD), ptr2[2]); + left_shift_uint192(ptr.get(), 0, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0xCDCDCDCDCDCDCDCD), ptr[2]); + left_shift_uint192(ptr.get(), 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x9B9B9B9B9B9B9B9B), ptr2[2]); + left_shift_uint192(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x3737373737373736), ptr2[2]); + left_shift_uint192(ptr.get(), 64, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[2]); + left_shift_uint192(ptr.get(), 65, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr2[2]); + left_shift_uint192(ptr.get(), 191, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr2[2]); + + left_shift_uint192(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0x3737373737373736), ptr[2]); + + left_shift_uint192(ptr.get(), 64, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555554), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAA9), ptr[2]); + } + + TEST(UIntArith, RightShiftUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint(ptr.get(), 0, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint(ptr.get(), 10, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint(ptr.get(), 10, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + right_shift_uint(ptr.get(), 0, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + right_shift_uint(ptr.get(), 0, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + right_shift_uint(ptr.get(), 1, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[1]); + right_shift_uint(ptr.get(), 2, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr2[1]); + right_shift_uint(ptr.get(), 64, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint(ptr.get(), 65, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint(ptr.get(), 127, 2, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + + right_shift_uint(ptr.get(), 2, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr[1]); + right_shift_uint(ptr.get(), 64, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntArith, RightShiftUInt128) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint128(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint128(ptr.get(), 10, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint128(ptr.get(), 10, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + right_shift_uint128(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + right_shift_uint128(ptr.get(), 0, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + right_shift_uint128(ptr.get(), 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[1]); + right_shift_uint128(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr2[1]); + right_shift_uint128(ptr.get(), 64, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint128(ptr.get(), 65, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + right_shift_uint128(ptr.get(), 127, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + + right_shift_uint128(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr[1]); + right_shift_uint128(ptr.get(), 64, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntArith, RightShiftUInt192) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(3, pool)); + auto ptr2(allocate_uint(3, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr[2] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[2] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint192(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[2] = 0xFFFFFFFFFFFFFFFF; + right_shift_uint192(ptr.get(), 10, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + right_shift_uint192(ptr.get(), 10, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[2]); + + ptr[0] = 0x5555555555555555; + ptr[1] = 0xAAAAAAAAAAAAAAAA; + ptr[2] = 0xCDCDCDCDCDCDCDCD; + + right_shift_uint192(ptr.get(), 0, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0xCDCDCDCDCDCDCDCD), ptr2[2]); + right_shift_uint192(ptr.get(), 0, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x5555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0xCDCDCDCDCDCDCDCD), ptr[2]); + right_shift_uint192(ptr.get(), 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x2AAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xD555555555555555), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x66E6E6E6E6E6E6E6), ptr2[2]); + right_shift_uint192(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x6AAAAAAAAAAAAAAA), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0x3373737373737373), ptr2[2]); + right_shift_uint192(ptr.get(), 64, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xAAAAAAAAAAAAAAAA), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0xCDCDCDCDCDCDCDCD), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + right_shift_uint192(ptr.get(), 65, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0xD555555555555555), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x66E6E6E6E6E6E6E6), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + right_shift_uint192(ptr.get(), 191, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[2]); + + right_shift_uint192(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x9555555555555555), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x6AAAAAAAAAAAAAAA), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0x3373737373737373), ptr[2]); + right_shift_uint192(ptr.get(), 64, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x6AAAAAAAAAAAAAAA), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x3373737373737373), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[2]); + } + + TEST(UIntArith, HalfRoundUpUInt) + { + half_round_up_uint(nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + half_round_up_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 1; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + half_round_up_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 2; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(1ULL, ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + half_round_up_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 3; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + + ptr[0] = 4; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(2), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + half_round_up_uint(ptr.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr2[1]); + half_round_up_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr[1]); + } + + TEST(UIntArith, NotUInt) + { + not_uint(nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + not_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + + ptr[0] = 0xFFFFFFFF00000000; + ptr[1] = 0xFFFF0000FFFF0000; + not_uint(ptr.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x00000000FFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x0000FFFF0000FFFF), ptr[1]); + } + + TEST(UIntArith, AndUIntUInt) + { + and_uint_uint(nullptr, nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(2, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + and_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFF00000000; + ptr[1] = 0xFFFF0000FFFF0000; + ptr2[0] = 0x0000FFFF0000FFFF; + ptr2[1] = 0xFF00FF00FF00FF00; + ptr3[0] = 0; + ptr3[1] = 0; + and_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0x0000FFFF00000000), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFF000000FF000000), ptr3[1]); + and_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x0000FFFF00000000), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFF000000FF000000), ptr[1]); + } + + TEST(UIntArith, OrUIntUInt) + { + or_uint_uint(nullptr, nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(2, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + or_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0xFFFFFFFF00000000; + ptr[1] = 0xFFFF0000FFFF0000; + ptr2[0] = 0x0000FFFF0000FFFF; + ptr2[1] = 0xFF00FF00FF00FF00; + ptr3[0] = 0; + ptr3[1] = 0; + or_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFF0000FFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFF00FFFFFF00), ptr3[1]); + or_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFF0000FFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFF00FFFFFF00), ptr[1]); + } + + TEST(UIntArith, XorUIntUInt) + { + xor_uint_uint(nullptr, nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(2, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + xor_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + + ptr[0] = 0xFFFFFFFF00000000; + ptr[1] = 0xFFFF0000FFFF0000; + ptr2[0] = 0x0000FFFF0000FFFF; + ptr2[1] = 0xFF00FF00FF00FF00; + ptr3[0] = 0; + ptr3[1] = 0; + xor_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFF00000000FFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0x00FFFF0000FFFF00), ptr3[1]); + xor_uint_uint(ptr.get(), ptr2.get(), 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFF00000000FFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x00FFFF0000FFFF00), ptr[1]); + } + + TEST(UIntArith, MultiplyUInt64Generic) + { + unsigned long long result[2]; + + multiply_uint64_generic(0ULL, 0ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64_generic(0ULL, 1ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64_generic(1ULL, 0ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64_generic(1ULL, 1ULL, result); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64_generic(0x100000000ULL, 0xFAFABABAULL, result); + ASSERT_EQ(0xFAFABABA00000000ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64_generic(0x1000000000ULL, 0xFAFABABAULL, result); + ASSERT_EQ(0xAFABABA000000000ULL, result[0]); + ASSERT_EQ(0xFULL, result[1]); + multiply_uint64_generic(1111222233334444ULL, 5555666677778888ULL, result); + ASSERT_EQ(4140785562324247136ULL, result[0]); + ASSERT_EQ(334670460471ULL, result[1]); + } + + TEST(UIntArith, MultiplyUInt64) + { + unsigned long long result[2]; + + multiply_uint64(0ULL, 0ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64(0ULL, 1ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64(1ULL, 0ULL, result); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64(1ULL, 1ULL, result); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64(0x100000000ULL, 0xFAFABABAULL, result); + ASSERT_EQ(0xFAFABABA00000000ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + multiply_uint64(0x1000000000ULL, 0xFAFABABAULL, result); + ASSERT_EQ(0xAFABABA000000000ULL, result[0]); + ASSERT_EQ(0xFULL, result[1]); + multiply_uint64(1111222233334444ULL, 5555666677778888ULL, result); + ASSERT_EQ(4140785562324247136ULL, result[0]); + ASSERT_EQ(334670460471ULL, result[1]); + } + + TEST(UIntArith, MultiplyUInt64HW64Generic) + { + unsigned long long result; + + multiply_uint64_hw64_generic(0ULL, 0ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64_generic(0ULL, 1ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64_generic(1ULL, 0ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64_generic(1ULL, 1ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64_generic(0x100000000ULL, 0xFAFABABAULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64_generic(0x1000000000ULL, 0xFAFABABAULL, &result); + ASSERT_EQ(0xFULL, result); + multiply_uint64_hw64_generic(1111222233334444ULL, 5555666677778888ULL, &result); + ASSERT_EQ(334670460471ULL, result); + } + + TEST(UIntArith, MultiplyUInt64HW64) + { + unsigned long long result; + + multiply_uint64_hw64(0ULL, 0ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64(0ULL, 1ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64(1ULL, 0ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64(1ULL, 1ULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64(0x100000000ULL, 0xFAFABABAULL, &result); + ASSERT_EQ(0ULL, result); + multiply_uint64_hw64(0x1000000000ULL, 0xFAFABABAULL, &result); + ASSERT_EQ(0xFULL, result); + multiply_uint64_hw64(1111222233334444ULL, 5555666677778888ULL, &result); + ASSERT_EQ(334670460471ULL, result); + } + + TEST(UIntArith, MultiplyManyUInt64) + { + MemoryPool &pool = *global_variables::global_memory_pool; + + vector<uint64_t> in = { 0 }; + vector<uint64_t> out = { 0 }; + vector<uint64_t> expected = { 0 }; + multiply_many_uint64(in.data(), 1, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 1 }; + out = { 0 }; + expected = { 1 }; + multiply_many_uint64(in.data(), 1, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 0, 0, 0 }; + out = { 0, 0, 0 }; + expected = { 0, 0, 0 }; + multiply_many_uint64(in.data(), 1, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64(in.data(), 2, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64(in.data(), 3, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 1, 1, 1 }; + out = { 0, 0, 0 }; + expected = { 1, 0, 0 }; + multiply_many_uint64(in.data(), 1, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64(in.data(), 2, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64(in.data(), 3, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 10, 20, 40 }; + out = { 0, 0, 0 }; + expected = { 10, 0, 0 }; + multiply_many_uint64(in.data(), 1, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 200, 0, 0 }; + multiply_many_uint64(in.data(), 2, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 8000, 0, 0 }; + multiply_many_uint64(in.data(), 3, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 0xF0F0F0F0F0F0F0, 0xBABABABABABABA, 0xCECECECECECECE }; + out = { 0, 0, 0 }; + expected = { 0xade881380d001140, 0xd4d54d49088bd2dd, 0x8df9832af0 }; + multiply_many_uint64(in.data(), 3, out.data(), pool); + ASSERT_TRUE(expected == out); + } + + TEST(UIntArith, MultiplyManyUInt64Except) + { + MemoryPool &pool = *global_variables::global_memory_pool; + + vector<uint64_t> in = { 0, 0, 0 }; + vector<uint64_t> out = { 0, 0, 0 }; + vector<uint64_t> expected = { 0, 0, 0 }; + multiply_many_uint64_except(in.data(), 2, 0, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64_except(in.data(), 2, 1, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64_except(in.data(), 3, 0, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64_except(in.data(), 3, 1, out.data(), pool); + ASSERT_TRUE(expected == out); + multiply_many_uint64_except(in.data(), 3, 2, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 2, 3, 5 }; + out = { 0, 0, 0 }; + expected = { 3, 0, 0 }; + multiply_many_uint64_except(in.data(), 2, 0, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 2, 0, 0 }; + multiply_many_uint64_except(in.data(), 2, 1, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 15, 0, 0 }; + multiply_many_uint64_except(in.data(), 3, 0, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 10, 0, 0 }; + multiply_many_uint64_except(in.data(), 3, 1, out.data(), pool); + ASSERT_TRUE(expected == out); + expected = { 6, 0, 0 }; + multiply_many_uint64_except(in.data(), 3, 2, out.data(), pool); + ASSERT_TRUE(expected == out); + + in = { 0xF0F0F0F0F0F0F0, 0xBABABABABABABA, 0xCECECECECECECE }; + out = { 0, 0, 0 }; + expected = { 0x0c6a88a6c4e30120, 0xc2a486684a2c, 0x0 }; + multiply_many_uint64_except(in.data(), 3, 1, out.data(), pool); + ASSERT_TRUE(expected == out); + } + + TEST(UIntArith, MultiplyUIntUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + auto ptr3(allocate_uint(4, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[2] = 0xFFFFFFFFFFFFFFFF; + ptr3[3] = 0xFFFFFFFFFFFFFFFF; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[2] = 0xFFFFFFFFFFFFFFFF; + ptr3[3] = 0xFFFFFFFFFFFFFFFF; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 1; + ptr2[1] = 0; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0; + ptr2[1] = 1; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[3]); + + ptr[0] = 9756571004902751654ul; + ptr[1] = 731952007397389984; + ptr2[0] = 701538366196406307; + ptr2[1] = 1699883529753102283; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(static_cast<uint64_t>(9585656442714717618ul), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(1817697005049051848), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(14447416709120365380ul), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(67450014862939159), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), 2, ptr2.get(), 1, 2, ptr3.get()); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_uint_uint(ptr.get(), 2, ptr2.get(), 1, 3, ptr3.get()); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0; + ptr3[1] = 0; + ptr3[2] = 0; + ptr3[3] = 0; + multiply_truncate_uint_uint(ptr.get(), ptr2.get(), 2, ptr3.get()); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + } + + TEST(UIntArith, MultiplyUIntUInt64) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(3, pool)); + auto result(allocate_uint(4, pool)); + + ptr[0] = 0; + ptr[1] = 0; + ptr[2] = 0; + multiply_uint_uint64(ptr.get(), 3, 0ULL, 4, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + ptr[0] = 0xFFFFFFFFF; + ptr[1] = 0xAAAAAAAAA; + ptr[2] = 0x111111111; + multiply_uint_uint64(ptr.get(), 3, 0ULL, 4, result.get()); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + ptr[0] = 0xFFFFFFFFF; + ptr[1] = 0xAAAAAAAAA; + ptr[2] = 0x111111111; + multiply_uint_uint64(ptr.get(), 3, 1ULL, 4, result.get()); + ASSERT_EQ(0xFFFFFFFFFULL, result[0]); + ASSERT_EQ(0xAAAAAAAAAULL, result[1]); + ASSERT_EQ(0x111111111ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + ptr[0] = 0xFFFFFFFFF; + ptr[1] = 0xAAAAAAAAA; + ptr[2] = 0x111111111; + multiply_uint_uint64(ptr.get(), 3, 0x10000ULL, 4, result.get()); + ASSERT_EQ(0xFFFFFFFFF0000ULL, result[0]); + ASSERT_EQ(0xAAAAAAAAA0000ULL, result[1]); + ASSERT_EQ(0x1111111110000ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + ptr[0] = 0xFFFFFFFFF; + ptr[1] = 0xAAAAAAAAA; + ptr[2] = 0x111111111; + multiply_uint_uint64(ptr.get(), 3, 0x100000000ULL, 4, result.get()); + ASSERT_EQ(0xFFFFFFFF00000000ULL, result[0]); + ASSERT_EQ(0xAAAAAAAA0000000FULL, result[1]); + ASSERT_EQ(0x111111110000000AULL, result[2]); + ASSERT_EQ(1ULL, result[3]); + + ptr[0] = 5656565656565656ULL; + ptr[1] = 3434343434343434ULL; + ptr[2] = 1212121212121212ULL; + multiply_uint_uint64(ptr.get(), 3, 7878787878787878ULL, 4, result.get()); + ASSERT_EQ(8891370032116156560ULL, result[0]); + ASSERT_EQ(127835914414679452ULL, result[1]); + ASSERT_EQ(9811042505314082702ULL, result[2]); + ASSERT_EQ(517709026347ULL, result[3]); + } + + TEST(UIntArith, DivideUIntUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + divide_uint_uint_inplace(nullptr, nullptr, 0, nullptr, pool); + divide_uint_uint(nullptr, nullptr, 0, nullptr, nullptr, pool); + + auto ptr(allocate_uint(4, pool)); + auto ptr2(allocate_uint(4, pool)); + auto ptr3(allocate_uint(4, pool)); + auto ptr4(allocate_uint(4, pool)); + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0; + ptr2[1] = 1; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 2, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0; + ptr[1] = 0; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 2, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 2, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 2, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(1ULL, ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 14; + ptr[1] = 0; + ptr2[0] = 3; + ptr2[1] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 2, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(4), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[1]); + + ptr[0] = 9585656442714717620ul; + ptr[1] = 1817697005049051848; + ptr[2] = 14447416709120365380ul; + ptr[3] = 67450014862939159; + ptr2[0] = 701538366196406307; + ptr2[1] = 1699883529753102283; + ptr2[2] = 0; + ptr2[3] = 0; + ptr3[0] = 0xFFFFFFFFFFFFFFFF; + ptr3[1] = 0xFFFFFFFFFFFFFFFF; + ptr3[2] = 0xFFFFFFFFFFFFFFFF; + ptr3[3] = 0xFFFFFFFFFFFFFFFF; + ptr4[0] = 0xFFFFFFFFFFFFFFFF; + ptr4[1] = 0xFFFFFFFFFFFFFFFF; + ptr4[2] = 0xFFFFFFFFFFFFFFFF; + ptr4[3] = 0xFFFFFFFFFFFFFFFF; + divide_uint_uint(ptr.get(), ptr2.get(), 4, ptr3.get(), ptr4.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), ptr4[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr4[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr4[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr4[3]); + ASSERT_EQ(static_cast<uint64_t>(9756571004902751654ul), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(731952007397389984), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + + divide_uint_uint_inplace(ptr.get(), ptr2.get(), 4, ptr3.get(), pool); + ASSERT_EQ(static_cast<uint64_t>(2), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[3]); + ASSERT_EQ(static_cast<uint64_t>(9756571004902751654ul), ptr3[0]); + ASSERT_EQ(static_cast<uint64_t>(731952007397389984), ptr3[1]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[2]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr3[3]); + } + + TEST(UIntArith, DivideUInt128UInt64) + { + uint64_t input[2]; + uint64_t quotient[2]; + + input[0] = 0; + input[1] = 0; + divide_uint128_uint64_inplace(input, 1ULL, quotient); + ASSERT_EQ(0ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0ULL, quotient[0]); + ASSERT_EQ(0ULL, quotient[1]); + + input[0] = 1; + input[1] = 0; + divide_uint128_uint64_inplace(input, 1ULL, quotient); + ASSERT_EQ(0ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(1ULL, quotient[0]); + ASSERT_EQ(0ULL, quotient[1]); + + input[0] = 0x10101010; + input[1] = 0x2B2B2B2B; + divide_uint128_uint64_inplace(input, 0x1000ULL, quotient); + ASSERT_EQ(0x10ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0xB2B0000000010101ULL, quotient[0]); + ASSERT_EQ(0x2B2B2ULL, quotient[1]); + + input[0] = 1212121212121212ULL; + input[1] = 3434343434343434ULL; + divide_uint128_uint64_inplace(input, 5656565656565656ULL, quotient); + ASSERT_EQ(5252525252525252ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(11199808901895084909ULL, quotient[0]); + ASSERT_EQ(0ULL, quotient[1]); + } + + TEST(UIntArith, DivideUInt192UInt64) + { + uint64_t input[3]; + uint64_t quotient[3]; + + input[0] = 0; + input[1] = 0; + input[2] = 0; + divide_uint192_uint64_inplace(input, 1ULL, quotient); + ASSERT_EQ(0ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0ULL, input[2]); + ASSERT_EQ(0ULL, quotient[0]); + ASSERT_EQ(0ULL, quotient[1]); + ASSERT_EQ(0ULL, quotient[2]); + + input[0] = 1; + input[1] = 0; + input[2] = 0; + divide_uint192_uint64_inplace(input, 1ULL, quotient); + ASSERT_EQ(0ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0ULL, input[2]); + ASSERT_EQ(1ULL, quotient[0]); + ASSERT_EQ(0ULL, quotient[1]); + ASSERT_EQ(0ULL, quotient[2]); + + input[0] = 0x10101010; + input[1] = 0x2B2B2B2B; + input[2] = 0xF1F1F1F1; + divide_uint192_uint64_inplace(input, 0x1000ULL, quotient); + ASSERT_EQ(0x10ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0ULL, input[2]); + ASSERT_EQ(0xB2B0000000010101ULL, quotient[0]); + ASSERT_EQ(0x1F1000000002B2B2ULL, quotient[1]); + ASSERT_EQ(0xF1F1FULL, quotient[2]); + + input[0] = 1212121212121212ULL; + input[1] = 3434343434343434ULL; + input[2] = 5656565656565656ULL; + divide_uint192_uint64_inplace(input, 7878787878787878ULL, quotient); + ASSERT_EQ(7272727272727272ULL, input[0]); + ASSERT_EQ(0ULL, input[1]); + ASSERT_EQ(0ULL, input[2]); + ASSERT_EQ(17027763760347278414ULL, quotient[0]); + ASSERT_EQ(13243816258047883211ULL, quotient[1]); + ASSERT_EQ(0ULL, quotient[2]); + } + + TEST(UIntArith, ExponentiateUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto input(allocate_zero_uint(2, pool)); + auto result(allocate_zero_uint(8, pool)); + + result[0] = 1, result[1] = 2, result[2] = 3, result[3] = 4; + result[4] = 5, result[5] = 6, result[6] = 7, result[7] = 8; + + uint64_t exponent[2]{ 0, 0 }; + + input[0] = 0xFFF; + input[1] = 0; + exponentiate_uint(input.get(), 2, exponent, 1, 1, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(2ULL, result[1]); + + exponentiate_uint(input.get(), 2, exponent, 1, 2, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + + exponentiate_uint(input.get(), 1, exponent, 1, 4, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + + input[0] = 123; + exponent[0] = 5; + exponentiate_uint(input.get(), 1, exponent, 2, 2, result.get(), pool); + ASSERT_EQ(28153056843ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + + input[0] = 1; + exponent[0] = 1; + exponent[1] = 1; + exponentiate_uint(input.get(), 1, exponent, 2, 2, result.get(), pool); + ASSERT_EQ(1ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + + input[0] = 0; + input[1] = 1; + exponent[0] = 7; + exponent[1] = 0; + exponentiate_uint(input.get(), 2, exponent, 2, 8, result.get(), pool); + ASSERT_EQ(0ULL, result[0]); + ASSERT_EQ(0ULL, result[1]); + ASSERT_EQ(0ULL, result[2]); + ASSERT_EQ(0ULL, result[3]); + ASSERT_EQ(0ULL, result[4]); + ASSERT_EQ(0ULL, result[5]); + ASSERT_EQ(0ULL, result[6]); + ASSERT_EQ(1ULL, result[7]); + + input[0] = 121212; + input[1] = 343434; + exponent[0] = 3; + exponent[1] = 0; + exponentiate_uint(input.get(), 2, exponent, 2, 8, result.get(), pool); + ASSERT_EQ(1780889000200128ULL, result[0]); + ASSERT_EQ(15137556501701088ULL, result[1]); + ASSERT_EQ(42889743421486416ULL, result[2]); + ASSERT_EQ(40506979898070504ULL, result[3]); + ASSERT_EQ(0ULL, result[4]); + ASSERT_EQ(0ULL, result[5]); + ASSERT_EQ(0ULL, result[6]); + ASSERT_EQ(0ULL, result[7]); + } + + TEST(UIntArith, ExponentiateUInt64) + { + ASSERT_EQ(0ULL, exponentiate_uint64(0ULL, 1ULL)); + ASSERT_EQ(1ULL, exponentiate_uint64(1ULL, 0ULL)); + ASSERT_EQ(0ULL, exponentiate_uint64(0ULL, 0xFFFFFFFFFFFFFFFFULL)); + ASSERT_EQ(1ULL, exponentiate_uint64(0xFFFFFFFFFFFFFFFFULL, 0ULL)); + ASSERT_EQ(25ULL, exponentiate_uint64(5ULL, 2ULL)); + ASSERT_EQ(32ULL, exponentiate_uint64(2ULL, 5ULL)); + ASSERT_EQ(0x1000000000000000ULL, exponentiate_uint64(0x10ULL, 15ULL)); + ASSERT_EQ(0ULL, exponentiate_uint64(0x10ULL, 16ULL)); + ASSERT_EQ(12389286314587456613ULL, exponentiate_uint64(123456789ULL, 13ULL)); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/uintarithmod.cpp b/bigpiseal3.5.1/native/tests/seal/util/uintarithmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17785ae1f772aad61b346f2230155376c19c409b --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/uintarithmod.cpp @@ -0,0 +1,353 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/uintarithmod.h" +#include "seal/util/uintcore.h" +#include <algorithm> +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(UIntArithMod, IncrementUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value[0] = 0; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 0xFFFFFFFFFFFFFFFD; + value[1] = 0xFFFFFFFFFFFFFFFF; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), value[1]); + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + increment_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + } + + TEST(UIntArithMod, DecrementUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value[0] = 2; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 1; + value[1] = 0; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFE), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), value[1]); + decrement_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFD), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), value[1]); + } + + TEST(UIntArithMod, NegateUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value[0] = 0; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + negate_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 1; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + negate_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + negate_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 2; + value[1] = 0; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + negate_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFD), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), value[1]); + negate_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + } + + TEST(UIntArithMod, Div2UIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value[0] = 0; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(0ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + + value[0] = 1; + value[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(2ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + + value[0] = 8; + value[1] = 0; + modulus[0] = 17; + modulus[1] = 0; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(4ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + + value[0] = 5; + value[1] = 0; + modulus[0] = 17; + modulus[1] = 0; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(11ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + + value[0] = 1; + value[1] = 0; + modulus[0] = 0xFFFFFFFFFFFFFFFFULL; + modulus[1] = 0xFFFFFFFFFFFFFFFFULL; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(0ULL, value[0]); + ASSERT_EQ(0x8000000000000000ULL, value[1]); + + value[0] = 3; + value[1] = 0; + modulus[0] = 0xFFFFFFFFFFFFFFFFULL; + modulus[1] = 0xFFFFFFFFFFFFFFFFULL; + div2_uint_mod(value.get(), modulus.get(), 2, value.get()); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(0x8000000000000000ULL, value[1]); + } + + TEST(UIntArithMod, AddUIntUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value1(allocate_uint(2, pool)); + auto value2(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value1[0] = 0; + value1[1] = 0; + value2[0] = 0; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + add_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 1; + value1[1] = 0; + value2[0] = 1; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + add_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 1; + value1[1] = 0; + value2[0] = 2; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + add_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 2; + value1[1] = 0; + value2[0] = 2; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + add_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(1ULL, value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 0xFFFFFFFFFFFFFFFE; + value1[1] = 0xFFFFFFFFFFFFFFFF; + value2[0] = 0xFFFFFFFFFFFFFFFE; + value2[1] = 0xFFFFFFFFFFFFFFFF; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + add_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFD), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), value1[1]); + } + + TEST(UIntArithMod, SubUIntUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value1(allocate_uint(2, pool)); + auto value2(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value1[0] = 0; + value1[1] = 0; + value2[0] = 0; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + sub_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 2; + value1[1] = 0; + value2[0] = 1; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + sub_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(1ULL, value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 1; + value1[1] = 0; + value2[0] = 2; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + sub_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 2; + value1[1] = 0; + value2[0] = 2; + value2[1] = 0; + modulus[0] = 3; + modulus[1] = 0; + sub_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + + value1[0] = 1; + value1[1] = 0; + value2[0] = 0xFFFFFFFFFFFFFFFE; + value2[1] = 0xFFFFFFFFFFFFFFFF; + modulus[0] = 0xFFFFFFFFFFFFFFFF; + modulus[1] = 0xFFFFFFFFFFFFFFFF; + sub_uint_uint_mod(value1.get(), value2.get(), modulus.get(), 2, value1.get()); + ASSERT_EQ(static_cast<uint64_t>(2), value1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value1[1]); + } + + TEST(UIntArithMod, TryInvertUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(2, pool)); + auto modulus(allocate_uint(2, pool)); + value[0] = 0; + value[1] = 0; + modulus[0] = 5; + modulus[1] = 0; + ASSERT_FALSE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + + value[0] = 1; + value[1] = 0; + modulus[0] = 5; + modulus[1] = 0; + ASSERT_TRUE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 2; + value[1] = 0; + modulus[0] = 5; + modulus[1] = 0; + ASSERT_TRUE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + ASSERT_EQ(static_cast<uint64_t>(3), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 3; + value[1] = 0; + modulus[0] = 5; + modulus[1] = 0; + ASSERT_TRUE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + ASSERT_EQ(static_cast<uint64_t>(2), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 4; + value[1] = 0; + modulus[0] = 5; + modulus[1] = 0; + ASSERT_TRUE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + ASSERT_EQ(static_cast<uint64_t>(4), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + + value[0] = 2; + value[1] = 0; + modulus[0] = 6; + modulus[1] = 0; + ASSERT_FALSE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + + value[0] = 3; + value[1] = 0; + modulus[0] = 6; + modulus[1] = 0; + ASSERT_FALSE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + + value[0] = 331975426; + value[1] = 0; + modulus[0] = 1351315121; + modulus[1] = 0; + ASSERT_TRUE(try_invert_uint_mod(value.get(), modulus.get(), 2, value.get(), pool)); + ASSERT_EQ(static_cast<uint64_t>(1052541512), value[0]); + ASSERT_EQ(static_cast<uint64_t>(0), value[1]); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/uintarithsmallmod.cpp b/bigpiseal3.5.1/native/tests/seal/util/uintarithsmallmod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1b7e9dadfe34f4057b8f708465d8438b23f980a --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/uintarithsmallmod.cpp @@ -0,0 +1,378 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/memorymanager.h" +#include "seal/modulus.h" +#include "seal/util/uintarithsmallmod.h" +#include "seal/util/uintcore.h" +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace seal; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(UIntArithSmallMod, IncrementUIntMod) + { + Modulus mod(2); + ASSERT_EQ(1ULL, increment_uint_mod(0, mod)); + ASSERT_EQ(0ULL, increment_uint_mod(1ULL, mod)); + + mod = 0x10000; + ASSERT_EQ(1ULL, increment_uint_mod(0, mod)); + ASSERT_EQ(2ULL, increment_uint_mod(1ULL, mod)); + ASSERT_EQ(0ULL, increment_uint_mod(0xFFFFULL, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(1ULL, increment_uint_mod(0, mod)); + ASSERT_EQ(0ULL, increment_uint_mod(2305843009211596800ULL, mod)); + ASSERT_EQ(1ULL, increment_uint_mod(0, mod)); + } + + TEST(UIntArithSmallMod, DecrementUIntMod) + { + Modulus mod(2); + ASSERT_EQ(0ULL, decrement_uint_mod(1, mod)); + ASSERT_EQ(1ULL, decrement_uint_mod(0ULL, mod)); + + mod = 0x10000; + ASSERT_EQ(0ULL, decrement_uint_mod(1, mod)); + ASSERT_EQ(1ULL, decrement_uint_mod(2ULL, mod)); + ASSERT_EQ(0xFFFFULL, decrement_uint_mod(0ULL, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(0ULL, decrement_uint_mod(1, mod)); + ASSERT_EQ(2305843009211596800ULL, decrement_uint_mod(0ULL, mod)); + ASSERT_EQ(0ULL, decrement_uint_mod(1, mod)); + } + + TEST(UIntArithSmallMod, NegateUIntMod) + { + Modulus mod(2); + ASSERT_EQ(0ULL, negate_uint_mod(0, mod)); + ASSERT_EQ(1ULL, negate_uint_mod(1, mod)); + + mod = 0xFFFFULL; + ASSERT_EQ(0ULL, negate_uint_mod(0, mod)); + ASSERT_EQ(0xFFFEULL, negate_uint_mod(1, mod)); + ASSERT_EQ(0x1ULL, negate_uint_mod(0xFFFEULL, mod)); + + mod = 0x10000ULL; + ASSERT_EQ(0ULL, negate_uint_mod(0, mod)); + ASSERT_EQ(0xFFFFULL, negate_uint_mod(1, mod)); + ASSERT_EQ(0x1ULL, negate_uint_mod(0xFFFFULL, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(0ULL, negate_uint_mod(0, mod)); + ASSERT_EQ(2305843009211596800ULL, negate_uint_mod(1, mod)); + } + + TEST(UIntArithSmallMod, Div2UIntMod) + { + Modulus mod(3); + ASSERT_EQ(0ULL, div2_uint_mod(0ULL, mod)); + ASSERT_EQ(2ULL, div2_uint_mod(1ULL, mod)); + + mod = 17; + ASSERT_EQ(11ULL, div2_uint_mod(5ULL, mod)); + ASSERT_EQ(4ULL, div2_uint_mod(8ULL, mod)); + + mod = 0xFFFFFFFFFFFFFFFULL; + ASSERT_EQ(0x800000000000000ULL, div2_uint_mod(1ULL, mod)); + ASSERT_EQ(0x800000000000001ULL, div2_uint_mod(3ULL, mod)); + } + + TEST(UIntArithSmallMod, AddUIntMod) + { + Modulus mod(2); + ASSERT_EQ(0ULL, add_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(0ULL, add_uint_uint_mod(1, 1, mod)); + + mod = 10; + ASSERT_EQ(0ULL, add_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(2ULL, add_uint_uint_mod(1, 1, mod)); + ASSERT_EQ(4ULL, add_uint_uint_mod(7, 7, mod)); + ASSERT_EQ(3ULL, add_uint_uint_mod(6, 7, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(0ULL, add_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(2ULL, add_uint_uint_mod(1, 1, mod)); + ASSERT_EQ(0ULL, add_uint_uint_mod(1152921504605798400ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ(1ULL, add_uint_uint_mod(1152921504605798401ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ(2305843009211596799ULL, add_uint_uint_mod(2305843009211596800ULL, 2305843009211596800ULL, mod)); + } + + TEST(UIntArithSmallMod, SubUIntMod) + { + Modulus mod(2); + ASSERT_EQ(0ULL, sub_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(1, 1, mod)); + + mod = 10; + ASSERT_EQ(0ULL, sub_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(9ULL, sub_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(1, 1, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(7, 7, mod)); + ASSERT_EQ(9ULL, sub_uint_uint_mod(6, 7, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(7, 6, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(0ULL, sub_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(2305843009211596800ULL, sub_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(1, 1, mod)); + ASSERT_EQ(2305843009211596800ULL, sub_uint_uint_mod(1152921504605798400ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ(1ULL, sub_uint_uint_mod(1152921504605798401ULL, 1152921504605798400ULL, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(1152921504605798401ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ(0ULL, sub_uint_uint_mod(2305843009211596800ULL, 2305843009211596800ULL, mod)); + } + + TEST(UIntArithSmallMod, BarrettReduce128) + { + uint64_t input[2]; + + Modulus mod(2); + input[0] = 0; + input[1] = 0; + ASSERT_EQ(0ULL, barrett_reduce_128(input, mod)); + input[0] = 1; + input[1] = 0; + ASSERT_EQ(1ULL, barrett_reduce_128(input, mod)); + input[0] = 0xFFFFFFFFFFFFFFFFULL; + input[1] = 0xFFFFFFFFFFFFFFFFULL; + ASSERT_EQ(1ULL, barrett_reduce_128(input, mod)); + + mod = 3; + input[0] = 0; + input[1] = 0; + ASSERT_EQ(0ULL, barrett_reduce_128(input, mod)); + input[0] = 1; + input[1] = 0; + ASSERT_EQ(1ULL, barrett_reduce_128(input, mod)); + input[0] = 123; + input[1] = 456; + ASSERT_EQ(0ULL, barrett_reduce_128(input, mod)); + input[0] = 0xFFFFFFFFFFFFFFFFULL; + input[1] = 0xFFFFFFFFFFFFFFFFULL; + ASSERT_EQ(0ULL, barrett_reduce_128(input, mod)); + + mod = 13131313131313ULL; + input[0] = 0; + input[1] = 0; + ASSERT_EQ(0ULL, barrett_reduce_128(input, mod)); + input[0] = 1; + input[1] = 0; + ASSERT_EQ(1ULL, barrett_reduce_128(input, mod)); + input[0] = 123; + input[1] = 456; + ASSERT_EQ(8722750765283ULL, barrett_reduce_128(input, mod)); + input[0] = 24242424242424; + input[1] = 79797979797979; + ASSERT_EQ(1010101010101ULL, barrett_reduce_128(input, mod)); + } + + TEST(UIntArithSmallMod, MultiplyUIntUIntMod) + { + Modulus mod(2); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(1ULL, multiply_uint_uint_mod(1, 1, mod)); + + mod = 10; + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(1ULL, multiply_uint_uint_mod(1, 1, mod)); + ASSERT_EQ(9ULL, multiply_uint_uint_mod(7, 7, mod)); + ASSERT_EQ(2ULL, multiply_uint_uint_mod(6, 7, mod)); + ASSERT_EQ(2ULL, multiply_uint_uint_mod(7, 6, mod)); + + mod = 2305843009211596801ULL; + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 0, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(0, 1, mod)); + ASSERT_EQ(0ULL, multiply_uint_uint_mod(1, 0, mod)); + ASSERT_EQ(1ULL, multiply_uint_uint_mod(1, 1, mod)); + ASSERT_EQ( + 576460752302899200ULL, multiply_uint_uint_mod(1152921504605798400ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ( + 576460752302899200ULL, multiply_uint_uint_mod(1152921504605798401ULL, 1152921504605798400ULL, mod)); + ASSERT_EQ( + 1729382256908697601ULL, multiply_uint_uint_mod(1152921504605798401ULL, 1152921504605798401ULL, mod)); + ASSERT_EQ(1ULL, multiply_uint_uint_mod(2305843009211596800ULL, 2305843009211596800ULL, mod)); + } + + TEST(UIntArithSmallMod, MultiplyAddMod) + { + Modulus mod(7); + ASSERT_EQ(0ULL, multiply_add_uint_mod(0, 0, 0, mod)); + ASSERT_EQ(0ULL, multiply_add_uint_mod(1, 0, 0, mod)); + ASSERT_EQ(0ULL, multiply_add_uint_mod(0, 1, 0, mod)); + ASSERT_EQ(1ULL, multiply_add_uint_mod(0, 0, 1, mod)); + ASSERT_EQ(3ULL, multiply_add_uint_mod(3, 4, 5, mod)); + + mod = 0x1FFFFFFFFFFFFFFFULL; + ASSERT_EQ(0ULL, multiply_add_uint_mod(0, 0, 0, mod)); + ASSERT_EQ(0ULL, multiply_add_uint_mod(1, 0, 0, mod)); + ASSERT_EQ(0ULL, multiply_add_uint_mod(0, 1, 0, mod)); + ASSERT_EQ(1ULL, multiply_add_uint_mod(0, 0, 1, mod)); + ASSERT_EQ(0ULL, multiply_add_uint_mod(mod.value() - 1, mod.value() - 1, mod.value() - 1, mod)); + } + + TEST(UIntArithSmallMod, ModuloUIntMod) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto value(allocate_uint(4, pool)); + + Modulus mod(2); + value[0] = 0; + value[1] = 0; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(0ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + value[0] = 1; + value[1] = 0; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + value[0] = 2; + value[1] = 0; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(0ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + value[0] = 3; + value[1] = 0; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(1ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + mod = 0xFFFF; + value[0] = 9585656442714717620ul; + value[1] = 1817697005049051848; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(65143ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + mod = 0x1000; + value[0] = 9585656442714717620ul; + value[1] = 1817697005049051848; + value[2] = 0; + modulo_uint_inplace(value.get(), 3, mod); + ASSERT_EQ(0xDB4ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + + mod = 0xFFFFFFFFC001ULL; + value[0] = 9585656442714717620ul; + value[1] = 1817697005049051848; + value[2] = 14447416709120365380ul; + value[3] = 67450014862939159; + modulo_uint_inplace(value.get(), 4, mod); + ASSERT_EQ(124510066632001ULL, value[0]); + ASSERT_EQ(0ULL, value[1]); + ASSERT_EQ(0ULL, value[2]); + ASSERT_EQ(0ULL, value[3]); + } + + TEST(UIntArithSmallMod, TryInvertUIntMod) + { + uint64_t result; + Modulus mod(5); + ASSERT_FALSE(try_invert_uint_mod(0, mod, result)); + ASSERT_TRUE(try_invert_uint_mod(1, mod, result)); + ASSERT_EQ(1ULL, result); + ASSERT_TRUE(try_invert_uint_mod(2, mod, result)); + ASSERT_EQ(3ULL, result); + ASSERT_TRUE(try_invert_uint_mod(3, mod, result)); + ASSERT_EQ(2ULL, result); + ASSERT_TRUE(try_invert_uint_mod(4, mod, result)); + ASSERT_EQ(4ULL, result); + + mod = 6; + ASSERT_FALSE(try_invert_uint_mod(2, mod, result)); + ASSERT_FALSE(try_invert_uint_mod(3, mod, result)); + ASSERT_TRUE(try_invert_uint_mod(5, mod, result)); + ASSERT_EQ(5ULL, result); + + mod = 1351315121; + ASSERT_TRUE(try_invert_uint_mod(331975426, mod, result)); + ASSERT_EQ(1052541512ULL, result); + } + + TEST(UIntArithSmallMod, ExponentiateUIntMod) + { + Modulus mod(5); + ASSERT_EQ(1ULL, exponentiate_uint_mod(1, 0, mod)); + ASSERT_EQ(1ULL, exponentiate_uint_mod(1, 0xFFFFFFFFFFFFFFFFULL, mod)); + ASSERT_EQ(3ULL, exponentiate_uint_mod(2, 0xFFFFFFFFFFFFFFFFULL, mod)); + + mod = 0x1000000000000000ULL; + ASSERT_EQ(0ULL, exponentiate_uint_mod(2, 60, mod)); + ASSERT_EQ(0x800000000000000ULL, exponentiate_uint_mod(2, 59, mod)); + + mod = 131313131313; + ASSERT_EQ(39418477653ULL, exponentiate_uint_mod(2424242424, 16, mod)); + } + + TEST(UIntArithSmallMod, DotProductMod) + { + Modulus mod(5); + uint64_t arr1[64], arr2[64]; + for (size_t i = 0; i < 64; i++) + { + arr1[i] = 2; + arr2[i] = 3; + } + + ASSERT_EQ(0, dot_product_mod(arr1, arr2, 0, mod)); + ASSERT_EQ(1, dot_product_mod(arr1, arr2, 1, mod)); + ASSERT_EQ(2, dot_product_mod(arr1, arr2, 2, mod)); + ASSERT_EQ(15 % mod.value(), dot_product_mod(arr1, arr2, 15, mod)); + ASSERT_EQ(16 % mod.value(), dot_product_mod(arr1, arr2, 16, mod)); + ASSERT_EQ(17 % mod.value(), dot_product_mod(arr1, arr2, 17, mod)); + ASSERT_EQ(32 % mod.value(), dot_product_mod(arr1, arr2, 32, mod)); + ASSERT_EQ(64 % mod.value(), dot_product_mod(arr1, arr2, 64, mod)); + + mod = get_prime(1024, SEAL_MOD_BIT_COUNT_MAX); + for (size_t i = 0; i < 64; i++) + { + arr1[i] = mod.value() - 1; + arr2[i] = mod.value() - 1; + } + + ASSERT_EQ(0, dot_product_mod(arr1, arr2, 0, mod)); + ASSERT_EQ(1, dot_product_mod(arr1, arr2, 1, mod)); + ASSERT_EQ(2, dot_product_mod(arr1, arr2, 2, mod)); + ASSERT_EQ(15, dot_product_mod(arr1, arr2, 15, mod)); + ASSERT_EQ(16, dot_product_mod(arr1, arr2, 16, mod)); + ASSERT_EQ(17, dot_product_mod(arr1, arr2, 17, mod)); + ASSERT_EQ(32, dot_product_mod(arr1, arr2, 32, mod)); + ASSERT_EQ(64, dot_product_mod(arr1, arr2, 64, mod)); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/native/tests/seal/util/uintcore.cpp b/bigpiseal3.5.1/native/tests/seal/util/uintcore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35eebdde8b2d5237893d7317bf8a5305fbaf7773 --- /dev/null +++ b/bigpiseal3.5.1/native/tests/seal/util/uintcore.cpp @@ -0,0 +1,795 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "seal/util/uintcore.h" +#include <cstdint> +#include "gtest/gtest.h" + +using namespace seal::util; +using namespace std; + +namespace sealtest +{ + namespace util + { + TEST(UIntCore, AllocateUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(0, pool)); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_uint(1, pool); + ASSERT_TRUE(nullptr != ptr.get()); + + ptr = allocate_uint(2, pool); + ASSERT_TRUE(nullptr != ptr.get()); + } + + TEST(UIntCore, SetZeroUInt) + { + set_zero_uint(0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(1, pool)); + ptr[0] = 0x1234567812345678; + set_zero_uint(1, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + + ptr = allocate_uint(2, pool); + ptr[0] = 0x1234567812345678; + ptr[1] = 0x1234567812345678; + set_zero_uint(2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntCore, AllocateZeroUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_uint(0, pool)); + ASSERT_TRUE(nullptr == ptr.get()); + + ptr = allocate_zero_uint(1, pool); + ASSERT_TRUE(nullptr != ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + + ptr = allocate_zero_uint(2, pool); + ASSERT_TRUE(nullptr != ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntCore, SetUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(1, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + set_uint(1, 1, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + set_uint(0x1234567812345678, 1, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567812345678), ptr[0]); + + ptr = allocate_uint(2, pool); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + set_uint(1, 2, ptr.get()); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + set_uint(0x1234567812345678, 2, ptr.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567812345678), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntCore, SetUIntUInt) + { + set_uint_uint(nullptr, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_uint(1, pool)); + ptr1[0] = 0x1234567887654321; + auto ptr2(allocate_uint(1, pool)); + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + set_uint_uint(ptr1.get(), 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567887654321), ptr2[0]); + + ptr1[0] = 0x1231231231231231; + set_uint_uint(ptr1.get(), 1, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1231231231231231), ptr1[0]); + + ptr1 = allocate_uint(2, pool); + ptr2 = allocate_uint(2, pool); + ptr1[0] = 0x1234567887654321; + ptr1[1] = 0x8765432112345678; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + set_uint_uint(ptr1.get(), 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567887654321), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8765432112345678), ptr2[1]); + + ptr1[0] = 0x1231231231231321; + ptr1[1] = 0x3213213213213211; + set_uint_uint(ptr1.get(), 2, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1231231231231321), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0x3213213213213211), ptr1[1]); + } + + TEST(UIntCore, SetUIntUInt2) + { + set_uint_uint(nullptr, 0, 0, nullptr); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_uint(1, pool)); + ptr1[0] = 0x1234567887654321; + set_uint_uint(nullptr, 0, 1, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + + auto ptr2(allocate_uint(1, pool)); + ptr1[0] = 0x1234567887654321; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + set_uint_uint(ptr1.get(), 1, 1, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567887654321), ptr2[0]); + + ptr1[0] = 0x1231231231231231; + set_uint_uint(ptr1.get(), 1, 1, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1231231231231231), ptr1[0]); + + ptr1 = allocate_uint(2, pool); + ptr2 = allocate_uint(2, pool); + ptr1[0] = 0x1234567887654321; + ptr1[1] = 0x8765432112345678; + set_uint_uint(nullptr, 0, 2, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + + ptr1[0] = 0x1234567887654321; + ptr1[1] = 0x8765432112345678; + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + set_uint_uint(ptr1.get(), 1, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567887654321), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr2[1]); + + ptr2[0] = 0xFFFFFFFFFFFFFFFF; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + set_uint_uint(ptr1.get(), 2, 2, ptr2.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1234567887654321), ptr2[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8765432112345678), ptr2[1]); + + ptr1[0] = 0x1231231231231321; + ptr1[1] = 0x3213213213213211; + set_uint_uint(ptr1.get(), 2, 2, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1231231231231321), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0x3213213213213211), ptr1[1]); + + set_uint_uint(ptr1.get(), 1, 2, ptr1.get()); + ASSERT_EQ(static_cast<uint64_t>(0x1231231231231321), ptr1[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr1[1]); + } + + TEST(UIntCore, IsZeroUInt) + { + ASSERT_TRUE(is_zero_uint(nullptr, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(1, pool)); + ptr[0] = 1; + ASSERT_FALSE(is_zero_uint(ptr.get(), 1)); + ptr[0] = 0; + ASSERT_TRUE(is_zero_uint(ptr.get(), 1)); + + ptr = allocate_uint(2, pool); + ptr[0] = 0x8000000000000000; + ptr[1] = 0x8000000000000000; + ASSERT_FALSE(is_zero_uint(ptr.get(), 2)); + ptr[0] = 0; + ptr[1] = 0x8000000000000000; + ASSERT_FALSE(is_zero_uint(ptr.get(), 2)); + ptr[0] = 0x8000000000000000; + ptr[1] = 0; + ASSERT_FALSE(is_zero_uint(ptr.get(), 2)); + ptr[0] = 0; + ptr[1] = 0; + ASSERT_TRUE(is_zero_uint(ptr.get(), 2)); + } + + TEST(UIntCore, IsEqualUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(1, pool)); + ptr[0] = 1; + ASSERT_TRUE(is_equal_uint(ptr.get(), 1, 1)); + ASSERT_FALSE(is_equal_uint(ptr.get(), 1, 0)); + ASSERT_FALSE(is_equal_uint(ptr.get(), 1, 2)); + + ptr = allocate_uint(2, pool); + ptr[0] = 1; + ptr[1] = 1; + ASSERT_FALSE(is_equal_uint(ptr.get(), 2, 1)); + ptr[0] = 1; + ptr[1] = 0; + ASSERT_TRUE(is_equal_uint(ptr.get(), 2, 1)); + ptr[0] = 0x1234567887654321; + ptr[1] = 0; + ASSERT_TRUE(is_equal_uint(ptr.get(), 2, 0x1234567887654321)); + ASSERT_FALSE(is_equal_uint(ptr.get(), 2, 0x2234567887654321)); + } + + TEST(UIntCore, IsBitSetUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + for (int i = 0; i < 128; ++i) + { + ASSERT_FALSE(is_bit_set_uint(ptr.get(), 2, i)); + } + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + for (int i = 0; i < 128; ++i) + { + ASSERT_TRUE(is_bit_set_uint(ptr.get(), 2, i)); + } + + ptr[0] = 0x0000000000000001; + ptr[1] = 0x8000000000000000; + for (int i = 0; i < 128; ++i) + { + if (i == 0 || i == 127) + { + ASSERT_TRUE(is_bit_set_uint(ptr.get(), 2, i)); + } + else + { + ASSERT_FALSE(is_bit_set_uint(ptr.get(), 2, i)); + } + } + } + + TEST(UIntCore, IsHighBitSetUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ASSERT_FALSE(is_high_bit_set_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_TRUE(is_high_bit_set_uint(ptr.get(), 2)); + + ptr[0] = 0; + ptr[1] = 0x8000000000000000; + ASSERT_TRUE(is_high_bit_set_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x7FFFFFFFFFFFFFFF; + ASSERT_FALSE(is_high_bit_set_uint(ptr.get(), 2)); + } + + TEST(UIntCore, SetBitUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + set_bit_uint(ptr.get(), 2, 0); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + set_bit_uint(ptr.get(), 2, 127); + ASSERT_EQ(1ULL, ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr[1]); + + set_bit_uint(ptr.get(), 2, 63); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000001), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000000), ptr[1]); + + set_bit_uint(ptr.get(), 2, 64); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000001), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000001), ptr[1]); + + set_bit_uint(ptr.get(), 2, 3); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000009), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x8000000000000001), ptr[1]); + } + + TEST(UIntCore, GetSignificantBitCountUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ASSERT_EQ(0, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 1; + ptr[1] = 0; + ASSERT_EQ(1, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 2; + ptr[1] = 0; + ASSERT_EQ(2, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 3; + ptr[1] = 0; + ASSERT_EQ(2, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 29; + ptr[1] = 0; + ASSERT_EQ(5, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 4; + ptr[1] = 0; + ASSERT_EQ(3, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ASSERT_EQ(64, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0; + ptr[1] = 1; + ASSERT_EQ(65, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 1; + ASSERT_EQ(65, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x7000000000000000; + ASSERT_EQ(127, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(128, get_significant_bit_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(128, get_significant_bit_count_uint(ptr.get(), 2)); + } + + TEST(UIntCore, GetSignificantUInt64CountUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ASSERT_EQ(0ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 1; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 2; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0; + ptr[1] = 1; + ASSERT_EQ(2ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 1; + ASSERT_EQ(2ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(2ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(2ULL, get_significant_uint64_count_uint(ptr.get(), 2)); + } + + TEST(UIntCore, GetNonzeroUInt64CountUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0; + ptr[1] = 0; + ASSERT_EQ(0ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 1; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 2; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0; + ASSERT_EQ(1ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0; + ptr[1] = 1; + ASSERT_EQ(1ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 1; + ASSERT_EQ(2ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(2ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(2ULL, get_nonzero_uint64_count_uint(ptr.get(), 2)); + } + + TEST(UIntCore, GetPowerOfTwoUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_uint(2, pool)); + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 1)); + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 1)); + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000001; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(0, get_power_of_two_uint(ptr.get(), 1)); + ASSERT_EQ(0, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000001; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000000; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(127, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x8000000000000000; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(63, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x9000000000000000; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x8000000000000001; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(-1, get_power_of_two_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000000; + ptr[1] = 0x0000000000000001; + ASSERT_EQ(64, get_power_of_two_uint(ptr.get(), 2)); + } + + TEST(UIntCore, GetPowerOfTwoMinusOneUInt) + { + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_zero_uint(2, pool)); + ASSERT_EQ(0, get_power_of_two_minus_one_uint(ptr.get(), 1)); + ASSERT_EQ(0, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(64, get_power_of_two_minus_one_uint(ptr.get(), 1)); + ASSERT_EQ(128, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000001; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(1, get_power_of_two_minus_one_uint(ptr.get(), 1)); + ASSERT_EQ(1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000001; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(-1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0x0000000000000000; + ptr[1] = 0x8000000000000000; + ASSERT_EQ(-1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x7FFFFFFFFFFFFFFF; + ASSERT_EQ(127, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(-1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(64, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0x0000000000000000; + ASSERT_EQ(-1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0x0000000000000001; + ASSERT_EQ(65, get_power_of_two_minus_one_uint(ptr.get(), 2)); + + ptr[0] = 0xFFFFFFFFFFFFFFFE; + ptr[1] = 0x0000000000000001; + ASSERT_EQ(-1, get_power_of_two_minus_one_uint(ptr.get(), 2)); + } + + TEST(UIntCore, FilterHighBitsUInt) + { + filter_highbits_uint(nullptr, 0, 0); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + filter_highbits_uint(ptr.get(), 2, 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + ptr[0] = 0xFFFFFFFFFFFFFFFF; + ptr[1] = 0xFFFFFFFFFFFFFFFF; + filter_highbits_uint(ptr.get(), 2, 128); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 127); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 126); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0x3FFFFFFFFFFFFFFF), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 64); + ASSERT_EQ(static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 63); + ASSERT_EQ(static_cast<uint64_t>(0x7FFFFFFFFFFFFFFF), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 2); + ASSERT_EQ(static_cast<uint64_t>(0x3), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 1); + ASSERT_EQ(static_cast<uint64_t>(0x1), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + filter_highbits_uint(ptr.get(), 2, 0); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + + filter_highbits_uint(ptr.get(), 2, 128); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[0]); + ASSERT_EQ(static_cast<uint64_t>(0), ptr[1]); + } + + TEST(UIntCore, CompareUIntUInt) + { + ASSERT_EQ(0, compare_uint_uint(nullptr, nullptr, 0)); + ASSERT_TRUE(is_equal_uint_uint(nullptr, nullptr, 0)); + ASSERT_FALSE(is_not_equal_uint_uint(nullptr, nullptr, 0)); + ASSERT_FALSE(is_greater_than_uint_uint(nullptr, nullptr, 0)); + ASSERT_FALSE(is_less_than_uint_uint(nullptr, nullptr, 0)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(nullptr, nullptr, 0)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(nullptr, nullptr, 0)); + + MemoryPool &pool = *global_variables::global_memory_pool; + auto ptr1(allocate_uint(2, pool)); + auto ptr2(allocate_uint(2, pool)); + ptr1[0] = 0; + ptr1[1] = 0; + ptr2[0] = 0; + ptr2[1] = 0; + ASSERT_EQ(0, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 0x1234567887654321; + ptr1[1] = 0x8765432112345678; + ptr2[0] = 0x1234567887654321; + ptr2[1] = 0x8765432112345678; + ASSERT_EQ(0, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 1; + ptr1[1] = 0; + ptr2[0] = 2; + ptr2[1] = 0; + ASSERT_EQ(-1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 1; + ptr1[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 2; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(-1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 0xFFFFFFFFFFFFFFFF; + ptr1[1] = 0x0000000000000001; + ptr2[0] = 0x0000000000000000; + ptr2[1] = 0x0000000000000002; + ASSERT_EQ(-1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 2; + ptr1[1] = 0; + ptr2[0] = 1; + ptr2[1] = 0; + ASSERT_EQ(1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 2; + ptr1[1] = 0xFFFFFFFFFFFFFFFF; + ptr2[0] = 1; + ptr2[1] = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + + ptr1[0] = 0xFFFFFFFFFFFFFFFF; + ptr1[1] = 0x0000000000000003; + ptr2[0] = 0x0000000000000000; + ptr2[1] = 0x0000000000000002; + ASSERT_EQ(1, compare_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_not_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_TRUE(is_greater_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + ASSERT_FALSE(is_less_than_or_equal_uint_uint(ptr1.get(), ptr2.get(), 2)); + } + + TEST(UIntCore, GetPowerOfTwo) + { + ASSERT_EQ(-1, get_power_of_two(0)); + ASSERT_EQ(0, get_power_of_two(1)); + ASSERT_EQ(1, get_power_of_two(2)); + ASSERT_EQ(-1, get_power_of_two(3)); + ASSERT_EQ(2, get_power_of_two(4)); + ASSERT_EQ(-1, get_power_of_two(5)); + ASSERT_EQ(-1, get_power_of_two(6)); + ASSERT_EQ(-1, get_power_of_two(7)); + ASSERT_EQ(3, get_power_of_two(8)); + ASSERT_EQ(-1, get_power_of_two(15)); + ASSERT_EQ(4, get_power_of_two(16)); + ASSERT_EQ(-1, get_power_of_two(17)); + ASSERT_EQ(-1, get_power_of_two(255)); + ASSERT_EQ(8, get_power_of_two(256)); + ASSERT_EQ(-1, get_power_of_two(257)); + ASSERT_EQ(10, get_power_of_two(1 << 10)); + ASSERT_EQ(30, get_power_of_two(1 << 30)); + ASSERT_EQ(32, get_power_of_two(1ULL << 32)); + ASSERT_EQ(62, get_power_of_two(1ULL << 62)); + ASSERT_EQ(63, get_power_of_two(1ULL << 63)); + } + + TEST(UIntCore, GetPowerOfTwoMinusOne) + { + ASSERT_EQ(0, get_power_of_two_minus_one(0)); + ASSERT_EQ(1, get_power_of_two_minus_one(1)); + ASSERT_EQ(-1, get_power_of_two_minus_one(2)); + ASSERT_EQ(2, get_power_of_two_minus_one(3)); + ASSERT_EQ(-1, get_power_of_two_minus_one(4)); + ASSERT_EQ(-1, get_power_of_two_minus_one(5)); + ASSERT_EQ(-1, get_power_of_two_minus_one(6)); + ASSERT_EQ(3, get_power_of_two_minus_one(7)); + ASSERT_EQ(-1, get_power_of_two_minus_one(8)); + ASSERT_EQ(-1, get_power_of_two_minus_one(14)); + ASSERT_EQ(4, get_power_of_two_minus_one(15)); + ASSERT_EQ(-1, get_power_of_two_minus_one(16)); + ASSERT_EQ(8, get_power_of_two_minus_one(255)); + ASSERT_EQ(10, get_power_of_two_minus_one((1 << 10) - 1)); + ASSERT_EQ(30, get_power_of_two_minus_one((1 << 30) - 1)); + ASSERT_EQ(32, get_power_of_two_minus_one((1ULL << 32) - 1)); + ASSERT_EQ(63, get_power_of_two_minus_one((1ULL << 63) - 1)); + ASSERT_EQ(64, get_power_of_two_minus_one(~static_cast<uint64_t>(0))); + } + + TEST(UIntCore, DuplicateUIntIfNeeded) + { + // MemoryPool &pool = *global_variables::global_memory_pool; + MemoryPoolST pool; + auto ptr(allocate_uint(2, pool)); + ptr[0] = 0xF0F0F0F0F0; + ptr[1] = 0xABABABABAB; + auto ptr2 = duplicate_uint_if_needed(ptr.get(), 0, 0, false, pool); + // No forcing and sizes are same (although zero) so just alias + ASSERT_TRUE(ptr2.get() == ptr.get()); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 0, 0, true, pool); + // Forcing and size is zero so return nullptr + ASSERT_TRUE(ptr2.get() == nullptr); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 0, false, pool); + ASSERT_TRUE(ptr2.get() == ptr.get()); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 0, true, pool); + ASSERT_TRUE(ptr2.get() == nullptr); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 1, false, pool); + ASSERT_TRUE(ptr2.get() == ptr.get()); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 1, true, pool); + ASSERT_TRUE(ptr2.get() != ptr.get()); + ASSERT_EQ(ptr[0], ptr2[0]); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 2, 2, true, pool); + ASSERT_TRUE(ptr2.get() != ptr.get()); + ASSERT_EQ(ptr[0], ptr2[0]); + ASSERT_EQ(ptr[1], ptr2[1]); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 2, 2, false, pool); + ASSERT_TRUE(ptr2.get() == ptr.get()); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 2, 1, false, pool); + ASSERT_TRUE(ptr2.get() == ptr.get()); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 2, false, pool); + ASSERT_TRUE(ptr2.get() != ptr.get()); + ASSERT_EQ(ptr[0], ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + + ptr2 = duplicate_uint_if_needed(ptr.get(), 1, 2, true, pool); + ASSERT_TRUE(ptr2.get() != ptr.get()); + ASSERT_EQ(ptr[0], ptr2[0]); + ASSERT_EQ(0ULL, ptr2[1]); + } + + TEST(UIntCore, HammingWeight) + { + ASSERT_EQ(0ULL, hamming_weight(0ULL)); + ASSERT_EQ(1ULL, hamming_weight(1ULL)); + ASSERT_EQ(1ULL, hamming_weight(0x10000ULL)); + ASSERT_EQ(2ULL, hamming_weight(0x10001ULL)); + ASSERT_EQ(32ULL, hamming_weight(0xFFFFFFFFULL)); + ASSERT_EQ(64ULL, hamming_weight(0xFFFFFFFFFFFFFFFFULL)); + ASSERT_EQ(32ULL, hamming_weight(0xF0F0F0F0F0F0F0F0ULL)); + ASSERT_EQ(16ULL, hamming_weight(0xA0A0A0A0A0A0A0A0ULL)); + } + + TEST(UIntCore, HammingWeightSplit) + { + ASSERT_EQ(0ULL, hamming_weight_split(0ULL)); + ASSERT_EQ(1ULL, hamming_weight_split(1ULL)); + ASSERT_EQ(0x10000ULL, hamming_weight_split(0x10000ULL)); + ASSERT_EQ(1ULL, hamming_weight_split(0x10001ULL)); + ASSERT_EQ(0xFFFFULL, hamming_weight_split(0xFFFFFFFFULL)); + ASSERT_EQ(0xFFFFFFFFULL, hamming_weight_split(0xFFFFFFFFFFFFFFFFULL)); + ASSERT_EQ(0xF0F0F00ULL, hamming_weight_split(0xF0F0F0000F0F0F00ULL)); + ASSERT_EQ(0xA0A0A0A0ULL, hamming_weight_split(0xA0A0A0A0A0A0A0A0ULL)); + } + } // namespace util +} // namespace sealtest diff --git a/bigpiseal3.5.1/pipelines/android.yml b/bigpiseal3.5.1/pipelines/android.yml new file mode 100644 index 0000000000000000000000000000000000000000..c4dab5151dfa903be6a36fc22bf806021a6b53aa --- /dev/null +++ b/bigpiseal3.5.1/pipelines/android.yml @@ -0,0 +1,50 @@ +steps: +- task: CMake@1 + displayName: Verify CMake version + inputs: + workingDirectory: '$(Build.SourcesDirectory)' + cmakeArgs: '--version' + +- task: PowerShell@2 + displayName: Download Ninja + inputs: + targetType: 'inline' + script: | + # Download Ninja + $ToolsDirectory = Join-Path -Path $Env:BUILD_SOURCESDIRECTORY -ChildPath tools + $NinjaZipFile = Join-Path $ToolsDirectory -ChildPath ninja.zip + $NinjaExeFile = Join-Path $ToolsDirectory -ChildPath ninja.exe + + Invoke-WebRequest -Uri "https://github.com/ninja-build/ninja/releases/download/v1.10.0/ninja-win.zip" -OutFile $NinjaZipFile + Expand-Archive -Path $NinjaZipFile -DestinationPath $ToolsDirectory + Copy-Item -Path $NinjaExeFile -Destination "c:\Program Files\CMake\bin" + +- task: CmdLine@2 + displayName: Update NDK + inputs: + script: | + echo Android home: %ANDROID_HOME% + "%ANDROID_HOME%/tools/bin/sdkmanager.bat" --install ndk;21.0.6113669 + +- task: Gradle@2 + displayName: Compile Android Native Libraries + inputs: + workingDirectory: '$(Build.SourcesDirectory)\android' + gradleWrapperFile: '$(Build.SourcesDirectory)\android\gradlew' + gradleOptions: '' + publishJUnitResults: false + testResultsFiles: '**/TEST-*.xml' + tasks: 'compileReleaseSources' + +- task: CopyFiles@2 + displayName: Copy files to staging directory + inputs: + SourceFolder: '$(Build.SourcesDirectory)\lib' + Contents: '**/libsealc.so' + TargetFolder: '$(Build.ArtifactStagingDirectory)\lib' + +- task: PublishBuildArtifacts@1 + displayName: Publish build artifacts + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' + ArtifactName: ${{ parameters.artifactName }} diff --git a/bigpiseal3.5.1/pipelines/jobs.yml b/bigpiseal3.5.1/pipelines/jobs.yml new file mode 100644 index 0000000000000000000000000000000000000000..f24da0feb434f2330f6b3115afa0e68ee3851105 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/jobs.yml @@ -0,0 +1,83 @@ +# This file selects the correct job definition based on system and buildType. + +parameters: + debug: 'false' + +jobs: + +- ${{ if eq(parameters.name, 'Windows') }}: + - job: ${{ parameters.name }} + displayName: ${{ parameters.name }} + pool: + vmImage: 'windows-latest' + steps: + - template: windows.yml + parameters: + nuget_version: '5.4.0' + ${{ if eq(parameters.debug, 'true') }}: + configuration: 'Debug' + ${{ if eq(parameters.debug, 'false') }}: + configuration: 'Release' + +- ${{ if eq(parameters.name, 'Linux') }}: + - job: ${{ parameters.name }} + displayName: ${{ parameters.name }} + pool: + vmImage: 'ubuntu-latest' + steps: + - script: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt-get update + sudo apt-get install clang-9 + sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-9 50 + sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-9 50 + clang-9 --version + clang++-9 --version + which clang-9 + which clang++-9 + - template: nix.yml + parameters: + artifactName: linux-drop + ${{ if eq(parameters.debug, 'true') }}: + configuration: 'Debug' + ${{ if eq(parameters.debug, 'false') }}: + configuration: 'Release' + +- ${{ if eq(parameters.name, 'macOS') }}: + - job: ${{ parameters.name }} + displayName: ${{ parameters.name }} + pool: + vmImage: 'macos-latest' + steps: + - template: nix.yml + parameters: + artifactName: macos-drop + ${{ if eq(parameters.debug, 'true') }}: + configuration: 'Debug' + ${{ if eq(parameters.debug, 'false') }}: + configuration: 'Release' + +- ${{ if eq(parameters.name, 'Android') }}: + - job: ${{ parameters.name }} + displayName: ${{ parameters.name }} + pool: + vmImage: 'windows-latest' + steps: + - template: android.yml + parameters: + artifactName: android-drop + ${{ if eq(parameters.debug, 'true') }}: + configuration: 'Debug' + ${{ if eq(parameters.debug, 'false') }}: + configuration: 'Release' + +- ${{ if eq(parameters.name, 'NuGet') }}: + - job: ${{ parameters.name }} + displayName: ${{ parameters.name }} + dependsOn: [Windows, Linux, macOS, Android] + pool: + vmImage: 'windows-latest' + steps: + - template: nuget.yml + parameters: + nuget_version: '5.4.0' diff --git a/bigpiseal3.5.1/pipelines/nix.yml b/bigpiseal3.5.1/pipelines/nix.yml new file mode 100644 index 0000000000000000000000000000000000000000..fb4a47f3dd5bc225574fcee2a4f8a0bb239a0c06 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/nix.yml @@ -0,0 +1,42 @@ +steps: +- task: CMake@1 + displayName: 'CMake SEAL' + inputs: + workingDirectory: '$(Build.SourcesDirectory)' + cmakeArgs: '-DCMAKE_BUILD_TYPE=${{ parameters.configuration }} -DSEAL_BUILD_TESTS=ON -DSEAL_BUILD_SEAL_C=ON -DSEAL_BUILD_EXAMPLES=ON .' + +- script: | + cd $BUILD_SOURCESDIRECTORY + make + displayName: 'Build SEAL' + +- script: | + cd $BUILD_SOURCESDIRECTORY + ./bin/sealtest + displayName: 'Run unit tests' + +- task: UseDotNet@2 + displayName: 'Get .NET Core 3.1 SDK' + inputs: + packageType: 'sdk' + version: '3.1.x' + +- task: DotNetCoreCLI@2 + displayName: 'Run dotnet unit tests' + inputs: + command: test + projects: '**/SEALNetTest.csproj' + arguments: '--configuration ${{ parameters.configuration }} --verbosity detailed' + +- task: CopyFiles@2 + displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)/lib' + Contents: 'libsealc.*' + TargetFolder: '$(Build.ArtifactStagingDirectory)/lib' + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: drop' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: ${{ parameters.artifactName }} diff --git a/bigpiseal3.5.1/pipelines/nuget.yml b/bigpiseal3.5.1/pipelines/nuget.yml new file mode 100644 index 0000000000000000000000000000000000000000..c033d9ffc507da961de0feb8e3bb36233bb20aa3 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/nuget.yml @@ -0,0 +1,102 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet' + inputs: + versionSpec: ${{ parameters.nuget_version }} + + - task: DownloadBuildArtifacts@0 + inputs: + downloadType: 'single' + artifactName: 'windows-drop' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - task: DownloadBuildArtifacts@0 + inputs: + downloadType: 'single' + artifactName: 'linux-drop' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - task: DownloadBuildArtifacts@0 + inputs: + downloadType: 'single' + artifactName: 'macos-drop' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - task: DownloadBuildArtifacts@0 + inputs: + downloadType: 'single' + artifactName: 'android-drop' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - task: CopyFiles@2 + displayName: 'Copy Targets File to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)\dotnet\nuget\' + Contents: 'SEALNet.targets' + TargetFolder: '$(Build.ArtifactStagingDirectory)\windows-drop\dotnet\nuget\' + + - task: CopyFiles@2 + displayName: 'Copy License File to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: 'LICENSE' + TargetFolder: '$(Build.ArtifactStagingDirectory)\windows-drop\' + + - task: CopyFiles@2 + displayName: 'Copy Linux Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)\linux-drop\lib\' + Contents: '*' + TargetFolder: '$(Build.ArtifactStagingDirectory)\windows-drop\lib\' + + - task: CopyFiles@2 + displayName: 'Copy macOS Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)\macos-drop\lib\' + Contents: '*' + TargetFolder: '$(Build.ArtifactStagingDirectory)\windows-drop\lib\' + + - task: CopyFiles@2 + displayName: 'Copy Android Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)\android-drop\lib\' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)\windows-drop\lib\' + + - task: NuGetCommand@2 + displayName: 'Build NuGet Package' + inputs: + command: 'pack' + packagesToPack: '$(Build.ArtifactStagingDirectory)\windows-drop\dotnet\nuget\SEALNet-multi.nuspec' + packDestination: '$(Build.ArtifactStagingDirectory)\windows-drop\dotnet\nuget\Release' + buildProperties: 'Configuration=Release;NUGET_WINDOWS_SEAL_C_PATH=$(Build.ArtifactStagingDirectory)\windows-drop\lib\x64\Release\sealc.dll;NUGET_LINUX_SEAL_C_PATH=$(Build.ArtifactStagingDirectory)\windows-drop\lib\libsealc.so;NUGET_MACOS_SEAL_C_PATH=$(Build.ArtifactStagingDirectory)\windows-drop\lib\libsealc.dylib;NUGET_ANDROIDARM64_SEAL_C_PATH=$(Build.ArtifactStagingDirectory)\windows-drop\lib\arm64-v8a\libsealc.so;NUGET_ANDROIDX64_SEAL_C_PATH=$(Build.ArtifactStagingDirectory)\windows-drop\lib\x86_64\libsealc.so' + + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: 'ESRP CodeSigning NuGet package' + inputs: + ConnectedServiceName: 'ESRP CodeSigning' + FolderPath: '$(Build.ArtifactStagingDirectory)\windows-drop\dotnet\nuget\Release' + Pattern: '*.nupkg' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401405", + "operationSetCode": "NuGetSign", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-401405", + "operationSetCode": "NuGetVerify", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: drop' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' diff --git a/bigpiseal3.5.1/pipelines/pipeline-CI-Android.yml b/bigpiseal3.5.1/pipelines/pipeline-CI-Android.yml new file mode 100644 index 0000000000000000000000000000000000000000..2e1c81f08a6d8b835769303ec57c86006fe538ef --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-CI-Android.yml @@ -0,0 +1,28 @@ +# This defines a pipeline to build on Linux in Debug mode. + +trigger: + batch: true + branches: + include: + - master + paths: + exclude: + - 'tools/*' + - LICENSE + - NOTICE + - CHANGES.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + - ISSUES.md + - README.md + - SECURITY.md + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: false + name: Android + diff --git a/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Linux.yml b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Linux.yml new file mode 100644 index 0000000000000000000000000000000000000000..d042186c5d50f5a3ade59f21c831e33e14042056 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Linux.yml @@ -0,0 +1,27 @@ +# This defines a pipeline to build on Linux in Debug mode. + +trigger: + batch: true + branches: + include: + - master + paths: + exclude: + - 'tools/*' + - LICENSE + - NOTICE + - CHANGES.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + - ISSUES.md + - README.md + - SECURITY.md + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: true + name: Linux \ No newline at end of file diff --git a/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Windows.yml b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Windows.yml new file mode 100644 index 0000000000000000000000000000000000000000..50995a6cb2e17c1d5d2176a508aced53cb557f11 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-Windows.yml @@ -0,0 +1,27 @@ +# This defines a pipeline to build on Windows in Debug mode. + +trigger: + batch: true + branches: + include: + - master + paths: + exclude: + - 'tools/*' + - LICENSE + - NOTICE + - CHANGES.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + - ISSUES.md + - README.md + - SECURITY.md + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: true + name: Windows \ No newline at end of file diff --git a/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-macOS.yml b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-macOS.yml new file mode 100644 index 0000000000000000000000000000000000000000..6593aee61cf8e5b0d482fb7d083859166e11c128 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-CI-Debug-macOS.yml @@ -0,0 +1,27 @@ +# This defines a pipeline to build on macOS in Debug mode. + +trigger: + batch: true + branches: + include: + - master + paths: + exclude: + - 'tools/*' + - LICENSE + - NOTICE + - CHANGES.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + - ISSUES.md + - README.md + - SECURITY.md + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: true + name: macOS \ No newline at end of file diff --git a/bigpiseal3.5.1/pipelines/pipeline-CI-Release-All.yml b/bigpiseal3.5.1/pipelines/pipeline-CI-Release-All.yml new file mode 100644 index 0000000000000000000000000000000000000000..ad4eee644c108c84a00f8ac8d6074dcfe38d5f0b --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-CI-Release-All.yml @@ -0,0 +1,28 @@ +# This defines a pipeline to build on Windows, Linux, and macOS in Release mode. + +trigger: none + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: false + name: Windows + - template: jobs.yml + parameters: + debug: false + name: Linux + - template: jobs.yml + parameters: + debug: false + name: macOS + - template: jobs.yml + parameters: + debug: false + name: Android + - template: jobs.yml + parameters: + debug: false + name: NuGet diff --git a/bigpiseal3.5.1/pipelines/pipeline-PR-Debug-All.yml b/bigpiseal3.5.1/pipelines/pipeline-PR-Debug-All.yml new file mode 100644 index 0000000000000000000000000000000000000000..92c440b90323f5749d6dd1e7f2bc74d2ca1419c4 --- /dev/null +++ b/bigpiseal3.5.1/pipelines/pipeline-PR-Debug-All.yml @@ -0,0 +1,39 @@ +# This defines a pipeline to build on Windows, Linux, and macOS in Debug mode. + +pr: + batch: true + branches: + include: + - contrib + paths: + exclude: + - 'tools/*' + - LICENSE + - NOTICE + - CHANGES.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + - ISSUES.md + - README.md + - SECURITY.md + +stages: + - stage: build + displayName: Build + jobs: + - template: jobs.yml + parameters: + debug: true + name: Windows + - template: jobs.yml + parameters: + debug: true + name: Linux + - template: jobs.yml + parameters: + debug: true + name: macOS + - template: jobs.yml + parameters: + debug: true + name: Android diff --git a/bigpiseal3.5.1/pipelines/windows.yml b/bigpiseal3.5.1/pipelines/windows.yml new file mode 100644 index 0000000000000000000000000000000000000000..12748e216dad9d34af1f6ca943cf7eb6695a108e --- /dev/null +++ b/bigpiseal3.5.1/pipelines/windows.yml @@ -0,0 +1,225 @@ +steps: +- task: NuGetToolInstaller@1 + displayName: 'Use NuGet' + inputs: + versionSpec: ${{ parameters.nuget_version }} + +- task: NuGetCommand@2 + displayName: 'NuGet restore from Solution' + inputs: + command: 'restore' + restoreSolution: 'SEAL.sln' + feedsToUse: 'select' + +- task: NuGetCommand@2 + displayName: 'NuGet restore Configuration Packages' + inputs: + restoreSolution: tools/config/packages.config + restoreDirectory: ConfigPackages + +- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@2 + displayName: 'Run CredScan' + inputs: + toolMajorVersion: 'V2' + outputFormat: sarif + debugMode: false + +- ${{ if eq(parameters.configuration, 'Release') }}: + - task: UseDotNet@2 + displayName: 'Get .NET Core 2.0 SDK' + inputs: + packageType: 'sdk' + version: '2.0.x' + +- task: UseDotNet@2 + displayName: 'Get .NET Core 3.1 SDK' + inputs: + packageType: 'sdk' + version: '3.1.x' + +- ${{ if eq(parameters.configuration, 'Release') }}: + - task: PowerShell@2 + displayName: 'Download Strong Name certificate' + inputs: + targetType: 'inline' + script: | + # Get signing certificate + $CertOutFile = Join-Path -Path $env:BUILD_SOURCESDIRECTORY -ChildPath dotnet\src\SEALNetCert.snk + if (Test-Path env:SEALNetSigningCertificate) { + Invoke-WebRequest -Uri "$env:SEALNetSigningCertificate" -OutFile $CertOutFile + } + +- task: VSBuild@1 + displayName: 'Build solution SEAL' + inputs: + solution: 'SEAL.sln' + platform: 'x64' + configuration: ${{ parameters.configuration }} + +- task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@2 + displayName: 'Run Roslyn Analyzers' + +- task: VSTest@2 + displayName: 'VsTest - native tests' + inputs: + testAssemblyVer2: | + **\${{ parameters.configuration }}\*test*.dll + **\${{ parameters.configuration }}\*test*.exe + !**\obj\** + platform: 'x64' + configuration: ${{ parameters.configuration }} + diagnosticsEnabled: True + +- task: VSTest@2 + displayName: 'VsTest - dotnet tests' + inputs: + testAssemblyVer2: | + **\${{ parameters.configuration }}\**\sealnettest.dll + !**\obj\** + configuration: ${{ parameters.configuration }} + diagnosticsEnabled: True + +- task: PublishSymbols@2 + displayName: 'Publish symbols path' + inputs: + searchPattern: '**\bin\**\*.pdb' + PublishSymbols: false + continueOnError: true + +- ${{ if eq(parameters.configuration, 'Release') }}: + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: 'ESRP Add Strong Name' + inputs: + ConnectedServiceName: 'ESRP CodeSigning' + FolderPath: lib/dotnet/${{ parameters.configuration }}/netstandard2.0 + Pattern: '*.dll' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-235845-SN", + "OperationCode" : "StrongNameSign", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-235845-SN", + "OperationCode" : "StrongNameVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + +- ${{ if eq(parameters.configuration, 'Release') }}: + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: 'ESRP CodeSigning .NET Standard 2.0' + inputs: + ConnectedServiceName: 'ESRP CodeSigning' + FolderPath: lib/dotnet/${{ parameters.configuration }}/netstandard2.0 + Pattern: '*.dll' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode": "CP-230012", + "OperationCode": "SigntoolSign", + "Parameters": { + "OpusName": "Microsoft.Research.SEAL", + "OpusInfo": "https://github.com/microsoft/SEAL", + "FileDigest": "/fd \"SHA256\"", + "PageHash": "/PH", + "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-230012", + "OperationCode": "SigntoolVerify", + "Parameters": {}, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + +- ${{ if eq(parameters.configuration, 'Release') }}: + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: 'ESRP CodeSigning native' + inputs: + ConnectedServiceName: 'ESRP CodeSigning' + FolderPath: lib/x64/${{ parameters.configuration }} + Pattern: '*.dll' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode": "CP-230012", + "OperationCode": "SigntoolSign", + "Parameters": { + "OpusName": "Microsoft.Research.SEAL", + "OpusInfo": "https://github.com/microsoft/SEAL", + "FileDigest": "/fd \"SHA256\"", + "PageHash": "/PH", + "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-230012", + "OperationCode": "SigntoolVerify", + "Parameters": {}, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + +- task: CopyFiles@2 + displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: '**\${{ parameters.configuration }}\**\?(*.exe|*.dll|*.lib|*.xml)' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + +- task: CopyFiles@2 + displayName: 'Copy NuSpec File to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)\dotnet\nuget\' + Contents: 'SEALNet-multi.nuspec' + TargetFolder: '$(Build.ArtifactStagingDirectory)\dotnet\nuget\' + +- task: CopyFiles@2 + displayName: 'Copy Targets File to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)\dotnet\nuget\' + Contents: 'SEALNet.targets' + TargetFolder: '$(Build.ArtifactStagingDirectory)\dotnet\nuget\' + +- task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 + displayName: 'Run BinSkim' + inputs: + InputType: Basic + AnalyzeTarget: '$(Build.ArtifactStagingDirectory)\native\bin\x64\${{ parameters.configuration }}\*.exe' + AnalyzeSymPath: '**\bin\**\*.pdb' + enabled: false + +- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Detection' + +- task: corygehr.air-autoassess.uploadScanResults.uploadScanResults@1 + displayName: 'Upload Scan Results for Analysis' + inputs: + uploadUrl: 'https://airbuildscan.azurewebsites.net/api/Upload' + areaPathParent: 'SEAL' + enabled: false + +- task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 + displayName: 'Publish Security Analysis Logs' + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: drop' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: windows-drop diff --git a/bigpiseal3.5.1/thirdparty/googletest/CMakeLists.txt b/bigpiseal3.5.1/thirdparty/googletest/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..0d72e2b8b0d120cff72e689dac9266e0eb92abc1 --- /dev/null +++ b/bigpiseal3.5.1/thirdparty/googletest/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.12) + +project(GTEST_DOWNLOAD VERSION 1.10.0) + +include(ExternalProject) +ExternalProject_Add(EP_GTEST + TMP_DIR ${CMAKE_CURRENT_LIST_DIR}/tmp + STAMP_DIR ${CMAKE_CURRENT_LIST_DIR}/stamp + DOWNLOAD_DIR "" + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src + BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}/build + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-${PROJECT_VERSION} + GIT_CONFIG advice.detachedHead=false + CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/bigpiseal3.5.1/thirdparty/msgsl/CMakeLists.txt b/bigpiseal3.5.1/thirdparty/msgsl/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d751534d679987bf67950729f854f44325bdf291 --- /dev/null +++ b/bigpiseal3.5.1/thirdparty/msgsl/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.12) + +project(MSGSL_DOWNLOAD VERSION 3.0.1) + +if(EXISTS cache_init.txt) + set(MSGSL_CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DGSL_TEST=OFF -C../cache_init.txt) +else() + set(MSGSL_CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DGSL_TEST=OFF) +endif() + +include(ExternalProject) +ExternalProject_Add(EP_MSGSL + TMP_DIR ${CMAKE_CURRENT_LIST_DIR}/tmp + STAMP_DIR ${CMAKE_CURRENT_LIST_DIR}/stamp + DOWNLOAD_DIR "" + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src + BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}/build + GIT_REPOSITORY https://github.com/microsoft/GSL.git + GIT_TAG v${PROJECT_VERSION} + GIT_CONFIG advice.detachedHead=false + CMAKE_ARGS ${MSGSL_CMAKE_ARGS} + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/bigpiseal3.5.1/thirdparty/zlib/CMakeLists.txt b/bigpiseal3.5.1/thirdparty/zlib/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5233d085ac5977961499baf63dcd87a73869d0d7 --- /dev/null +++ b/bigpiseal3.5.1/thirdparty/zlib/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +cmake_minimum_required(VERSION 3.12) + +project(ZLIB_DOWNLOAD VERSION 1.2.11) + +if(MSVC) + set(TEMP_BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}/build/${ZLIB_PLATFORM}) +else() + set(TEMP_BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}/src) +endif() + +if(EXISTS cache_init.txt) + set(ZLIB_CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DSKIP_INSTALL_ALL=ON -Wno-dev -C../cache_init.txt) +else() + set(ZLIB_CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DSKIP_INSTALL_ALL=ON -Wno-dev) +endif() + +include(ExternalProject) +ExternalProject_Add(EP_ZLIB + TMP_DIR ${CMAKE_CURRENT_LIST_DIR}/tmp + STAMP_DIR ${CMAKE_CURRENT_LIST_DIR}/stamp + DOWNLOAD_DIR "" + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src + BINARY_DIR ${TEMP_BINARY_DIR} + GIT_REPOSITORY https://github.com/madler/zlib.git + GIT_TAG v${PROJECT_VERSION} + GIT_CONFIG advice.detachedHead=false + CMAKE_ARGS ${ZLIB_CMAKE_ARGS} + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/bigpiseal3.5.1/tools/config/packages.config b/bigpiseal3.5.1/tools/config/packages.config new file mode 100644 index 0000000000000000000000000000000000000000..76b3dfa7b893aa4e777f80991e18287c835e8725 --- /dev/null +++ b/bigpiseal3.5.1/tools/config/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="GoogleTestAdapter" version="0.16.1" /> +</packages> diff --git a/bigpiseal3.5.1/tools/scripts/clang-format-all.sh b/bigpiseal3.5.1/tools/scripts/clang-format-all.sh new file mode 100755 index 0000000000000000000000000000000000000000..c132dabf63deb21d923caa13b4522298abb7c72c --- /dev/null +++ b/bigpiseal3.5.1/tools/scripts/clang-format-all.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +BASE_DIR=$(dirname "$0") +SEAL_ROOT_DIR=$BASE_DIR/../../ +shopt -s globstar +clang-format -i $SEAL_ROOT_DIR/native/**/*.h +clang-format -i $SEAL_ROOT_DIR/native/**/*.cpp \ No newline at end of file diff --git a/bigpiseal3.5.1/tools/scripts/collect_system_info.sh b/bigpiseal3.5.1/tools/scripts/collect_system_info.sh new file mode 100755 index 0000000000000000000000000000000000000000..6221b7eb727846b546c9bdd0cc4fa30fbae1b145 --- /dev/null +++ b/bigpiseal3.5.1/tools/scripts/collect_system_info.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + +CMAKE_CXX_COMPILER=cxx_compiler.out +CMAKE_ENV=cmake_env.out +CMAKE_SYSTEM_INFO=system_information.out +SEALDIR=../native/src + +CMAKE_CXX_COMPILER_CMD=`cmake -LA $SEALDIR|sed -n 's/^CMAKE_CXX_COMPILER:FILEPATH=\(.*\)$/\1/p'` + +echo "Extracting: cmake -LA $SEALDIR > $CMAKE_ENV" +cmake -LA $SEALDIR > $CMAKE_ENV +echo "Extracting: cmake --system-information > $CMAKE_SYSTEM_INFO" +cmake --system-information > $CMAKE_SYSTEM_INFO +echo "Extracting: $CMAKE_CXX_COMPILER_CMD -v > $CMAKE_CXX_COMPILER 2>&1" +$CMAKE_CXX_COMPILER_CMD -v 2> $CMAKE_CXX_COMPILER + +ARCHIVE_NAME=../system_info.tar +FILES=( + "$SEALDIR/seal/util/config.h" + "$SEALDIR/CMakeCache.txt" + "$SEALDIR/CMakeFiles/CMakeOutput.log" + "$SEALDIR/CMakeFiles/CMakeError.log" + "/proc/cpuinfo" + "$CMAKE_ENV" + "$CMAKE_SYSTEM_INFO" + "$CMAKE_CXX_COMPILER" +) + +print_collecting_filename() { + echo -e "\033[0mCollecting \033[1;32m$1\033[0m" +} + +print_skipping_filename() { + echo -e "\033[0mSkipping \033[1;31m$1\033[0m" +} + +add_to_archive() { + BASENAME=`basename $1` + cp -f $1 $BASENAME 2>/dev/null + if [ -s $ARCHIVE_NAME ] + then + tar -rf $ARCHIVE_NAME ./$BASENAME + else + tar -cf $ARCHIVE_NAME ./$BASENAME + fi + rm -f ./$BASENAME +} + +rm -f "$ARCHIVE_NAME.gz" + +for i in ${FILES[@]} +do + if [ -r $i ] + then + print_collecting_filename $i + add_to_archive $i + else + print_skipping_filename $i + fi +done + +gzip $ARCHIVE_NAME +if [ $? -eq 0 ] +then + echo "Created `realpath $ARCHIVE_NAME.gz`" +else + echo "Could not create `realpath $ARCHIVE_NAME.gz`" + rm -f $ARCHIVE_NAME.gz +fi + +echo -n "Cleaning up ... " +rm -f $CMAKE_ENV +rm -f $CMAKE_SYSTEM_INFO +rm -f $CMAKE_CXX_COMPILER +echo done. diff --git a/dap-patternsearch-checker-cea.service b/dap-patternsearch-checker-cea.service new file mode 100644 index 0000000000000000000000000000000000000000..8165be6ae877b1392c127ed79950b97a4faf70de --- /dev/null +++ b/dap-patternsearch-checker-cea.service @@ -0,0 +1,19 @@ +[Unit] +Description=BIGPI FHE ANALYSIS PATTERN SEARCH microservice + +[Service] +User=bigpi +# The configuration file application.properties should be here: +#change this to your workspace +WorkingDirectory=/opt/deployment/dap/fhe +#path to executable. +#executable is a bash script which calls jar file +ExecStart=/usr/bin/java -Xms512m -Xmx2048m -Dspring.profiles.active=cea -Djava.net.preferIPv4Stack=true -jar /opt/deployment/dap/fhe/dap-patternsearch-analysis-service.jar +SuccessExitStatus=143 +TimeoutStopSec=10 +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target + diff --git a/dap-patternsearch-checker.service b/dap-patternsearch-checker.service new file mode 100644 index 0000000000000000000000000000000000000000..4434ed53cd70f2c790530eab4ff81a4d8a7161d7 --- /dev/null +++ b/dap-patternsearch-checker.service @@ -0,0 +1,19 @@ +[Unit] +Description=BIGPI FHE ANALYSIS PatternSearch microservice + +[Service] +User=bigpi +# The configuration file application.properties should be here: +#change this to your workspace +WorkingDirectory=/opt/deployment/dap/fhe +#path to executable. +#executable is a bash script which calls jar file +ExecStart=/usr/bin/java -Xms512m -Xmx512m -Dspring.profiles.active=prod -Djava.net.preferIPv4Stack=true -jar /opt/deployment/dap/fhe/dap-patternsearch-analysis-service.jar +SuccessExitStatus=143 +TimeoutStopSec=10 +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target + diff --git a/datalake/1.dpo b/datalake/1.dpo new file mode 100644 index 0000000000000000000000000000000000000000..c838d23beb19a9bfc2d95a1c5fdc0f5dd596fb57 --- /dev/null +++ b/datalake/1.dpo @@ -0,0 +1,1601 @@ +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 +Mb0N6/9D7QrXqLyT2iR0I/8PVb3mfQ== diff --git a/datalake/3.dpo b/datalake/3.dpo new file mode 100644 index 0000000000000000000000000000000000000000..15294bba88086d2d549fab20a2cba5f12c723365 --- /dev/null +++ b/datalake/3.dpo @@ -0,0 +1,1600 @@ +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 ++x8cBKMk diff --git a/datalake/4.dpo b/datalake/4.dpo new file mode 100644 index 0000000000000000000000000000000000000000..9e6907d7edb9fc741c4fbe674f05e1bcde1a8a13 --- /dev/null +++ b/datalake/4.dpo @@ -0,0 +1,1600 @@ +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 +wyfPzL0Q+of/BxcNFTU= diff --git a/datalake/5.dpo b/datalake/5.dpo new file mode 100644 index 0000000000000000000000000000000000000000..c86937527d263b2ca94fd829bb6a2d276ea1a95d --- /dev/null +++ b/datalake/5.dpo @@ -0,0 +1,1601 @@ +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 +fX1b8B+1I/YwwJOOXy2l4B/1P3/7e+k= diff --git a/datalake/clean.sh b/datalake/clean.sh new file mode 100644 index 0000000000000000000000000000000000000000..b3516b3144dd73188d416bf1fa6444cfe58cdcb2 --- /dev/null +++ b/datalake/clean.sh @@ -0,0 +1,4 @@ +rm -r *.ct +# rm -r result +rm -r result/* +rm -r result.* \ No newline at end of file diff --git a/dmp-fhe-aplusb.groovy b/dmp-fhe-aplusb.groovy new file mode 100644 index 0000000000000000000000000000000000000000..1925336238f0d23647300dfbebf03a36efff24a1 --- /dev/null +++ b/dmp-fhe-aplusb.groovy @@ -0,0 +1,71 @@ +node { + def mvnHome + def bigpi_ips = ['192.168.1.200', '192.168.1.201' , '192.168.1.202' , '192.168.1.203' , '192.168.1.204' , '192.168.1.205'] + def bigpi_git = 'git@s19430717.onlinehome-server.info:bigpi-platform/dmp_platform/dmp_fhe/dmp-fhe-libraries/dmp-fhe-aplusb-service.git' + //keep in the same order like bigpi_ips array + def bigpi_services = ['dmp-fhe-aplusb.service'] + def bigpi_dir = '/opt/deployment/dmp/fhe' + def bigpi_jar = 'dmp-fhe-aplusb-service.jar' + def bigpi_cred = 'vinext_git_lab' + + stage('Preparation') { // for display purposes + // Get some code from a GitHub repository + checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: bigpi_cred, url: bigpi_git]]] + // Get the Maven tool. + // ** NOTE: This 'M3' Maven tool must be configured in + // ** in the global configuration. + mvnHome = tool 'M3' + } + + stage ('Code analyse') { + sh 'echo "Run some lints for analysis"' + } + stage ('Unit test') { + sh 'echo "Tests will back"' + sh "'/usr/bin/mvn' clean test -B -T 4" + } + + stage('Build') { + // Run the maven build + if (isUnix()) { + sh "'/usr/bin/mvn' -Dmaven.test.skip=true clean package -B -T 4" + } else { + bat(/"${mvnHome}\bin\mvn" -Dmaven.test.skip=true clean package/) + } + } + + stage('Enable Daemon Service') { + for(int i = 0; i < bigpi_ips.size(); i++) { + parallel { + stage('Enable Daemon on Bigpi@'+bigpi_ips[i]) { + if ( fileExists("./${bigpi_services[0]}") ) { + sh "ssh bigpi@${bigpi_ips[i]} 'sudo mkdir -p ${bigpi_dir}'" + sh "ssh bigpi@${bigpi_ips[i]} 'sudo chown -R bigpi:bigpi ${bigpi_dir}'" + sh "scp ./${bigpi_services[0]} bigpi@${bigpi_ips[i]}:${bigpi_dir}" + sh "ssh bigpi@${bigpi_ips[i]} 'sudo cp -f ${bigpi_dir}/${bigpi_services[0]} /etc/systemd/system'" + sh "ssh bigpi@${bigpi_ips[i]} 'sudo systemctl daemon-reload'" + sh "ssh bigpi@${bigpi_ips[i]} 'sudo systemctl enable ${bigpi_services[0]}'" + } else { + echo 'File daemon service is not existed' + } + } + } + } + } + + stage('Deploy') { + for(int i = 0; i < bigpi_ips.size(); i++) { + parallel { + stage('Deploy on Bigpi@'+bigpi_ips[i]) { + sh "ssh bigpi@${bigpi_ips[i]} 'sudo systemctl stop ${bigpi_services[0]}'" + sh "ssh bigpi@${bigpi_ips[i]} 'mkdir -p ${bigpi_dir}'" + sh "ssh bigpi@${bigpi_ips[i]} 'rm -f ${bigpi_dir}/${bigpi_jar}'" + sh "scp target/*.jar bigpi@${bigpi_ips[i]}:${bigpi_dir}" + sh "ssh bigpi@${bigpi_ips[i]} 'sudo systemctl start ${bigpi_services[0]}'" + } + } + } + } + } + + \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3287591d6379cace23f18acb9d6225b74fac5cea --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,69 @@ +FROM ubuntu:20.04 + +COPY ../bigpiseal3.5.1 opt/bigpiseal3.5.1 + +#datalake for testing +COPY ../datalake opt/datalake + +COPY bigpiseal3.5.1/bin/patternSearch/v2/keys keys + + +RUN mkdir -p opt/bigpiseal3.5.1/bin/patternSearch/v2/data && mkdir -p opt/bigpiseal3.5.1/bin/patternSearch/v2/result && mkdir -p opt/bigpiseal3.5.1/bin/patternSearch/v2/upload && mkdir -p opt/bigpiseal3.5.1/bin/patternSearch/v2/keys + +RUN useradd -m bigpi + +RUN chown -R bigpi:bigpi /opt/bigpiseal3.5.1/ /opt/datalake/ /opt/bigpiseal3.5.1/bin/patternSearch/v2/data /opt/bigpiseal3.5.1/bin/patternSearch/v2/result /opt/bigpiseal3.5.1/bin/patternSearch/v2/upload /opt/bigpiseal3.5.1/bin/patternSearch/v2/keys +RUN chmod 777 /opt/bigpiseal3.5.1 /opt/datalake /opt/bigpiseal3.5.1/bin/patternSearch/v2/data /opt/bigpiseal3.5.1/bin/patternSearch/v2/result /opt/bigpiseal3.5.1/bin/patternSearch/v2/upload /opt/bigpiseal3.5.1/bin/patternSearch/v2/keys + + + +RUN apt-get update && apt-get install wget unzip zip -y +#RUN apt-get install wget unzip zip -y + +# ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install --no-install-recommends -y \ + g++ \ + make \ + cmake \ + libc6-dev \ + libboost-program-options-dev +# git \ +# ca-certificates + +#RUN mkdir -p storage && mkdir -p storage/data && mkdir -p storage/result && mkdir -p storage/upload +#RUN mkdir -p keys && mkdir -p storage && mkdir -p storage/data && mkdir -p storage/result && mkdir -p storage/upload + +RUN cd opt/bigpiseal3.5.1 && cmake . && make && make install && cmake . -DSEAL_BUILD_EXAMPLES=ON && make +#RUN cd opt/bigpiseal3.5.1 && cmake . && make && make install && cmake . -DSEAL_BUILD_EXAMPLES=OFF && make + + +RUN set -eux; \ + apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-11-jdk && apt-get clean +#RUN apt install openjdk-8-jdk +#RUN apt-get -y update +#RUN mkdir -p /usr/share/man/man1/ +#RUN apt-get install -y openjdk-8-jdk +#RUN apt-get install -y openjdk-8-jre +#RUN update-alternatives --config java +#RUN update-alternatives --config javac + + + +#WORKDIR /usr/src/ +WORKDIR /opt/datalake + +RUN mkdir -p /home/spring + +EXPOSE 19191 + +ARG JAR_FILE=./target/*.jar +COPY ${JAR_FILE} /home/spring/app.jar + +RUN chown -R bigpi:bigpi /home/spring + +USER bigpi:bigpi + +ENTRYPOINT ["java","-Xms100m", "-Xmx100m", "-Dspring.profiles.active=prod", "-DPORT=${APP_PORT}," "-DCONFIG=false", "-DEUREKA=false", "-jar","/home/app.jar"] + diff --git a/docker/Dockerfile.bk b/docker/Dockerfile.bk new file mode 100644 index 0000000000000000000000000000000000000000..27762f2d6b9c117660b943555294f14d3df62ff7 --- /dev/null +++ b/docker/Dockerfile.bk @@ -0,0 +1,10 @@ +# +# Copyright 2021 Hewlett Packard Enterprise Development Company, L.P. +# +FROM adoptopenjdk/openjdk11:alpine +RUN \ + addgroup -S spring && adduser -S spring -G spring +USER spring:spring +ARG JAR_FILE=./target/*.jar +COPY ${JAR_FILE} /home/app.jar +ENTRYPOINT ["java","-Xms100m", "-Xmx100m", "-Dspring.profiles.active=prod", "-DPORT=${APP_PORT}," "-DCONFIG=false", "-DEUREKA=false", "-jar","/home/app.jar"] \ No newline at end of file diff --git a/docker/build-docker-image.sh b/docker/build-docker-image.sh new file mode 100644 index 0000000000000000000000000000000000000000..ccb3bb28a559932b4586a7bf0fd14e2b819b67bd --- /dev/null +++ b/docker/build-docker-image.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +IAI_SPRINGBOOT_APP="devecorridor.iit.cnr.it:5000/ecorridor/iai/iai-fhe-analysis-4-database:latest" + +sudo docker build -f ./docker/Dockerfile -t ${IAI_SPRINGBOOT_APP} . + +sudo docker compose -f ./docker/docker-compose_iai-openapi.yml up \ No newline at end of file diff --git a/docker/docker-compose_iai-openapi.yml b/docker/docker-compose_iai-openapi.yml new file mode 100644 index 0000000000000000000000000000000000000000..180d7fcf52569aef19f9974ddee1074473e74c09 --- /dev/null +++ b/docker/docker-compose_iai-openapi.yml @@ -0,0 +1,28 @@ +version: "3.7" + +services: + # Spring Swagger Template + csi-openapi: + expose: + - "19191" + environment: + # Expose service to the Internet + LETSENCRYPT_HOST: "${IAI_VIRTUAL_HOST:-ecorridor.iit.cnr.it}" + VIRTUAL_HOST: "${IAI_VIRTUAL_HOST:-ecorridor.iit.cnr.it}" + VIRTUAL_PATH: "/iai-openapi/" + VIRTUAL_DEST: "/openapi/" + VIRTUAL_PORT: "5084" # this is not mandatory, if we have the "expose" directive + APP_PORT: 19191 + image: devecorridor.iit.cnr.it:5000/ecorridor/iai/iai-fhe-analysis-4-database:latest + networks: + - iai.ecorridor.local + - cea.ecorridor.local + restart: unless-stopped + +networks: + cea.ecorridor.local: + name: cea.ecorridor.local + driver: bridge + csi.ecorridor.local: + name: csi.ecorridor.local + driver: bridge \ No newline at end of file diff --git a/dockerUp.sh b/dockerUp.sh new file mode 100644 index 0000000000000000000000000000000000000000..af8518000313c54c216b1a8c1b0bb6906306035d --- /dev/null +++ b/dockerUp.sh @@ -0,0 +1,18 @@ +rm target/dap-patternsearch-analysis-service.jar +mvn clean package -DskipTests + +sudo docker container rm dap-patternsearch-analysis-service +# sudo docker container rm dap-patternsearch-analysis-service db +# sudo docker container rm dap-patternsearch-analysis-service +sudo docker image rm dap-patternsearch-analysis-service + +#mvn clean package -DskipTests +# cp target/dap-patternsearch-analysis-service.jar src/main/docker/ + +# cd src/main/docker/ + +# sudo docker compose up + +sudo docker build --tag dap-patternsearch-analysis-service . + +sudo docker run --publish 9191:9191 --name dap-patternsearch-analysis-service dap-patternsearch-analysis-service \ No newline at end of file diff --git a/docker_build.sh b/docker_build.sh new file mode 100644 index 0000000000000000000000000000000000000000..6e9d69d1513473c7c5a231b24ace743453da031b --- /dev/null +++ b/docker_build.sh @@ -0,0 +1,10 @@ +sudo docker container rm dap-patternsearch-analysis-service db +# sudo docker container rm dap-patternsearch-analysis-service +sudo docker image rm dap-patternsearch-analysis-service + +#mvn clean package -DskipTests +cp target/dap-patternsearch-analysis-service.jar src/main/docker/ + +cd src/main/docker/ + +sudo docker compose up \ No newline at end of file diff --git a/ecorridor/build.groovy b/ecorridor/build.groovy new file mode 100644 index 0000000000000000000000000000000000000000..def77ab1c97feaa519c90df53cbd009e8eac152d --- /dev/null +++ b/ecorridor/build.groovy @@ -0,0 +1,76 @@ +#!/usr/bin/env groovy +/** + * Copyright 2021 Hewlett Packard Enterprise Development Company, L.P. + */ +library 'hpe-jenkins-libs' + +// create (or update) the job input parameters +deriveJobParams(name:"build-job") + +pipeline { + /** + * These env variables depend on the software component + */ + environment { + GITLAB_URL="git@gitlab.troof.io:data-pi-platform/hoang-gia/dap-pattern-search-standalone.git" + GITLAB_BRANCH="master" + IMAGE="ecorridor/iai/iai-openapi" + LATEST_TAG="latest" + DOCKER_FILE="docker/Dockerfile" + DEPLOY_JOB="iai-openapi-deploy" + DEPLOY_ENV_DEFAULT="dev" + } + options { + copyArtifactPermission('/ECORRIDOR/IAI/iai-openapi-security') + timeout(time: 1, unit: 'HOURS') + buildDiscarder(logRotator(numToKeepStr: '100')) + gitLabConnection('dev-gitlab') + } + agent none + triggers { + gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All') + } + post { + failure { + updateGitlabCommitStatus name: 'build', state: 'failed' + } + success { + updateGitlabCommitStatus name: 'build', state: 'success' + } + } + stages { + stage('Checkout Code') { + agent { + label 'docker' + } + steps { + git url: "$GITLAB_URL", + branch: "$GITLAB_BRANCH", + credentialsId: 'user-jenkins-gitlab-ro-ssh' + } + } + stage('Manage Container') { + agent { + label 'docker' + } + steps { + manageContainer(name:"-manage container-") + } + } + // this calls the deploy job + stage('Call Deploy Job') { + steps { + build job: "${DEPLOY_JOB}", parameters: [string(name: 'GITLAB_URL', value: "${GITLAB_URL}"), string(name: 'PRJ_ENV', value: "${DEPLOY_ENV_DEFAULT}"), string(name: 'PRJ_IMAGE_TAG', value: "${LATEST_TAG}")] + } + } + // archive artifacts for other pipelines + stage('Archive Artifacts') { + agent { + label 'docker' + } + steps { + archiveArtifacts artifacts: '**/*', followSymlinks: false, onlyIfSuccessful: true + } + } + } +} diff --git a/ecorridor/deploy.groovy b/ecorridor/deploy.groovy new file mode 100644 index 0000000000000000000000000000000000000000..c9e8ab14c3f8f0ec28af61c07770c2c0d32e4a2e --- /dev/null +++ b/ecorridor/deploy.groovy @@ -0,0 +1,35 @@ +#!/usr/bin/env groovy +/** + * Copyright 2021 Hewlett Packard Enterprise Development Company, L.P. + */ +library 'hpe-jenkins-libs' + +// create (or update) the job input parameters +deriveJobParams(name:"deploy-job") + +// if you need to change a YAML file before applying it +// you can use the following snippet +/*node { + stage("Transform YAML") { + sh """ + cat mydir/myfile.yaml | sed "s/FOO/BAR/g" > mydir/myfile2.yaml + """ + } +}*/ + +// You need to pass: +// gitlaburl: the git URL +// gitlabbranch: the branch for git URL +// gitlabcomposeurl: the git URL to compose project +// yamls: a list of YAML files for deployment +// yamlsOverride: a list of YAML files that will replace those in yamls +// all YAML files will have the following transformation +// image tag 'latest' is replaced by version specified in input (PRJ_IMAGE_TAG) +deployPipeline(name:"deploy-pipeline", + gitlaburl:'git@gitlab.troof.io:data-pi-platform/hoang-gia/dap-pattern-search-standalone.git', + gitlabbranch:'master', + gitlabcomposeurl:'git@devecorridor.iit.cnr.it:ecorridor/ecorridor-compose.git', + wptfolder:'CSI', + yamls:"['docker/docker-compose_csi-openapi.yml']", + yamlsOverride:params.YAMLS_OVERRIDE + ) diff --git a/ecorridor/security.groovy b/ecorridor/security.groovy new file mode 100644 index 0000000000000000000000000000000000000000..2a2371f0b0bf2cb9da03e1f137e7aeeb49a8eb1b --- /dev/null +++ b/ecorridor/security.groovy @@ -0,0 +1,24 @@ +#!/usr/bin/env groovy +/** + * Copyright 2021 Hewlett Packard Enterprise Development Company, L.P. + */ +library 'hpe-jenkins-libs' + +// create (or update) the job input parameters +deriveJobParams(name:"security-job") + +/** + * name always "security-pipeline" + * productType the top level project + * product your component name + * buildJob where to copy artifacts from + * image the docker image to test hosted at the HPE_REGISTRY + * latestTag the tag of the docker image to test + */ +securityPipeline(name:"security-pipeline", + productType:"ECORRIDOR", + product:"iai-openapi", + buildJob:"/ECORRIDOR/CSI/iai-openapi-build", + image:"ecorridor/iai/iai-openapi", + latestTag:"latest" + ) diff --git a/keys/bfv.gk b/keys/bfv.gk new file mode 100755 index 0000000000000000000000000000000000000000..f0f16516d41db283c00cd1d52190e994de571638 Binary files /dev/null and b/keys/bfv.gk differ diff --git a/keys/bfv.lk b/keys/bfv.lk new file mode 100755 index 0000000000000000000000000000000000000000..0350b8c9e10995234ee0ccd962917cdf8f122833 Binary files /dev/null and b/keys/bfv.lk differ diff --git a/keys/bfv.pk b/keys/bfv.pk new file mode 100755 index 0000000000000000000000000000000000000000..9ea5a4bbb682989b2e069b31334548d0d7b3e954 Binary files /dev/null and b/keys/bfv.pk differ diff --git a/keys/bfv.sk b/keys/bfv.sk new file mode 100755 index 0000000000000000000000000000000000000000..2f4b0f88f9eba173e30d5855e4f96d919f2f0e3e Binary files /dev/null and b/keys/bfv.sk differ diff --git a/keys/bfv_params.conf b/keys/bfv_params.conf new file mode 100755 index 0000000000000000000000000000000000000000..1f05bca312982e9673fed071c7927f9f22dae15b Binary files /dev/null and b/keys/bfv_params.conf differ diff --git a/keys/bfv_params.confbfv_params.conf b/keys/bfv_params.confbfv_params.conf new file mode 100755 index 0000000000000000000000000000000000000000..1f05bca312982e9673fed071c7927f9f22dae15b Binary files /dev/null and b/keys/bfv_params.confbfv_params.conf differ diff --git a/logs/spring.log b/logs/spring.log new file mode 100644 index 0000000000000000000000000000000000000000..b93676c1f61fae525f3ae38be4cb6e093e1e8aa7 --- /dev/null +++ b/logs/spring.log @@ -0,0 +1,11382 @@ +2021-06-28 14:53:17.853 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4bb8855f: startup date [Mon Jun 28 14:53:17 CEST 2021]; root of context hierarchy +2021-06-28 14:53:18.307 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-28 14:53:18.368 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$88d290f3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:18.780 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2021-06-28 14:53:18.874 WARN [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2021-06-28 14:53:18.898 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2021-06-28 14:53:18.907 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@750a04ec: startup date [Mon Jun 28 14:53:18 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4bb8855f +2021-06-28 14:53:20.018 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2021-06-28 14:53:20.670 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=3d50a125-c8b6-3df8-850b-7dafa11896d9 +2021-06-28 14:53:20.758 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2021-06-28 14:53:20.762 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2021-06-28 14:53:20.785 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-28 14:53:21.008 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$6f1dd428] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.209 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.222 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$6cb88df6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.308 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$9ee53437] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.379 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.387 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.479 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$88d290f3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.497 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$ac4a66bc] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.525 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$549c3a15] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.543 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$194b5975] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-28 14:53:21.570 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-28 14:53:22.031 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2021-06-28 14:53:22.097 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2021-06-28 14:53:22.097 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2021-06-28 14:53:22.249 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2021-06-28 14:53:22.250 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3343 ms +2021-06-28 14:53:22.785 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2021-06-28 14:53:22.785 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2021-06-28 14:53:22.786 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2021-06-28 14:53:22.787 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2021-06-28 14:53:23.285 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2021-06-28 14:53:23.304 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2021-06-28 14:53:23.390 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2021-06-28 14:53:23.392 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2021-06-28 14:53:23.394 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2021-06-28 14:53:23.449 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2021-06-28 14:53:23.592 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2021-06-28 14:53:23.861 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException +2021-06-28 14:53:23.863 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@71eb4ea4 +2021-06-28 14:53:24.281 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2021-06-28 14:53:24.372 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' +2021-06-28 14:53:26.101 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2021-06-28 14:53:26.559 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/prepare-data-master/drivingLicense/01-uploadFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ClientControllerImpl.uploadDrivingLicenseFile(org.springframework.web.multipart.MultipartFile,java.lang.String) +2021-06-28 14:53:26.560 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/prepare-data-master/drivingLicense/02-checkByFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ClientControllerImpl.drivingLicenseCheckByFile(java.lang.String,java.lang.String) +2021-06-28 14:53:26.563 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/prepare-data-master/drivingLicense],methods=[POST]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.ClientControllerImpl.createDrivingLicense(org.springframework.web.multipart.MultipartFile,java.lang.String,java.lang.Integer,java.lang.String) +2021-06-28 14:53:26.566 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/prepare-data-master/drivingLicense],methods=[PUT]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.ClientControllerImpl.updateDrivingLicense(org.springframework.web.multipart.MultipartFile,java.lang.Integer,java.lang.String,java.lang.Integer,java.lang.String) +2021-06-28 14:53:26.566 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/prepare-data-master/drivingLicense],methods=[DELETE]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.ClientControllerImpl.deleteDrivingLicense(java.lang.Integer,java.lang.String) +2021-06-28 14:53:26.570 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/name/{username}],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.hello(java.lang.String) +2021-06-28 14:53:26.570 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/decrypteddrivingLicenses],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<java.util.List<fr.cea.bigpi.fhe.dap.patternsearch.model.DrivingLicense>> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.getAllDecryptedDrivingLicenses() +2021-06-28 14:53:26.571 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/drivingLicenses],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.DrivingLicense> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.getDecryptedDrivingLicense(java.lang.Integer) +2021-06-28 14:53:26.571 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/drivingLicenses],methods=[POST],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.createDrivingLicense(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String) +2021-06-28 14:53:26.572 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/drivingLicenses],methods=[PUT],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.updateDrivingLicense(java.lang.Integer,java.lang.String,java.lang.String,java.lang.Integer,java.lang.String) +2021-06-28 14:53:26.572 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/drivingLicenses],methods=[DELETE],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.Description> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.deleteDrivingLicense(java.lang.Integer) +2021-06-28 14:53:26.572 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/data/all/drivingLicenses],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<java.util.List<fr.cea.bigpi.fhe.dap.patternsearch.model.DrivingLicense>> fr.cea.bigpi.fhe.dap.patternsearch.controller.DrivingLicenseControllerImpl.getAllDrivingLicenses() +2021-06-28 14:53:26.573 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String fr.cea.bigpi.fhe.dap.patternsearch.controller.HomeController.index() +2021-06-28 14:53:26.575 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration() +2021-06-28 14:53:26.580 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration() +2021-06-28 14:53:26.582 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources() +2021-06-28 14:53:26.593 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) +2021-06-28 14:53:26.593 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) +2021-06-28 14:53:26.682 WARN [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2021-06-28 14:53:26.683 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2021-06-28 14:53:26.690 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.netflix.config.DynamicPropertyFactory : DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@e60c516 +2021-06-28 14:53:27.525 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) +2021-06-28 14:53:27.527 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/jolokia/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2021-06-28 14:53:27.531 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) +2021-06-28 14:53:27.531 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) +2021-06-28 14:53:27.532 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.532 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.533 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/hystrix.stream/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2021-06-28 14:53:27.533 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) +2021-06-28 14:53:27.534 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.537 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) +2021-06-28 14:53:27.537 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.538 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal) +2021-06-28 14:53:27.538 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.539 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.540 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.541 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.541 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>) +2021-06-28 14:53:27.542 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset() +2021-06-28 14:53:27.543 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.543 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.544 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke() +2021-06-28 14:53:27.547 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.549 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException +2021-06-28 14:53:27.550 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-28 14:53:27.791 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)] +2021-06-28 14:53:27.941 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet '' +2021-06-28 14:53:27.941 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started +2021-06-28 14:53:28.031 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-28 14:53:28.032 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-28 14:53:28.089 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-28 14:53:28.232 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@750a04ec: startup date [Mon Jun 28 14:53:18 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4bb8855f +2021-06-28 14:53:28.424 WARN [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .t.AbstractTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) +2021-06-28 14:53:28.788 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 846 ms +2021-06-28 14:53:28.859 WARN [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2021-06-28 14:53:28.859 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2021-06-28 14:53:29.295 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' +2021-06-28 14:53:29.939 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService +2021-06-28 14:53:30.017 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-28 14:53:30.551 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2021-06-28 14:53:30.555 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: jolokia:type=Config is already registered. Adding it with jolokia:type=Config,uuid=dea7fd9a-8189-4b3c-88f9-d662b835050c, but you should revise your setup in order to either use a qualifier or ensure, that only a single agent gets registered (otherwise history functionality might not work) +2021-06-28 14:53:30.559 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Cannot register (legacy) MBean handler for config store with name jmx4perl:type=Config since it already exists. This is the case if another agent has been already started within the same JVM. The registration is skipped. +2021-06-28 14:53:30.560 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Jolokia Discovery MBean registration is skipped because there is already one registered. +2021-06-28 14:53:30.633 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 +2021-06-28 14:53:30.634 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2021-06-28 14:53:30.634 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 1 subscriber(s). +2021-06-28 14:53:30.634 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger +2021-06-28 14:53:30.634 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 +2021-06-28 14:53:30.634 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed +2021-06-28 14:53:30.663 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s) +2021-06-28 14:53:30.725 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references +2021-06-28 14:53:30.884 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: createDrivingLicense_1 +2021-06-28 14:53:30.890 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: applySecureComputAPlusB_1 +2021-06-28 14:53:30.896 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: applySecureComputAPlusB_2 +2021-06-28 14:53:30.900 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: hello_1 +2021-06-28 14:53:30.904 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: applySecureComputAPlusB_3 +2021-06-28 14:53:30.917 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] ration$HystrixMetricsPollerConfiguration : Starting poller +2021-06-28 14:53:31.006 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 37133 (http) +2021-06-28 14:53:31.015 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Started SampleRepositoryTest in 14.152 seconds (JVM running for 15.195) +2021-06-28 14:53:31.069 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing 1 +2021-06-28 14:53:31.248 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : REsponse dmp-fhe-patternsearch-service say <test01get> +2021-06-28 14:53:31.267 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy +2021-06-28 14:53:31.529 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy result : 'Tests 21 + 12' + +2021-06-28 14:53:31.554 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@750a04ec: startup date [Mon Jun 28 14:53:18 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4bb8855f +2021-06-28 14:53:31.568 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 +2021-06-28 14:53:31.570 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 +2021-06-28 14:53:31.572 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2021-06-28 14:53:31.576 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 0 subscriber(s). +2021-06-28 14:53:31.576 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger +2021-06-28 14:53:31.579 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' +2021-06-28 14:53:31.596 INFO [dmp-fhe-patternsearch-service,,,] 292754 --- [Thread-7] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' +2021-06-29 22:23:05.090 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@65a5d4f9: startup date [Tue Jun 29 22:23:05 CEST 2021]; root of context hierarchy +2021-06-29 22:23:05.305 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-29 22:23:05.342 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$58ad45ec] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:05.720 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2021-06-29 22:23:05.796 WARN [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2021-06-29 22:23:05.808 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2021-06-29 22:23:05.811 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2d258eff: startup date [Tue Jun 29 22:23:05 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@65a5d4f9 +2021-06-29 22:23:06.546 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2021-06-29 22:23:06.969 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=78312829-c4ad-3770-82f5-9a0c28885fd2 +2021-06-29 22:23:07.027 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2021-06-29 22:23:07.031 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2021-06-29 22:23:07.043 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-29 22:23:07.150 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$3ef88921] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.285 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.293 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$3c9342ef] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.335 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$6ebfe930] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.382 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.389 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.445 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$58ad45ec] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.455 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$7c251bb5] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.468 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$2476ef0e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.481 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$e9260e6e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2021-06-29 22:23:07.507 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-29 22:23:07.879 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2021-06-29 22:23:07.902 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2021-06-29 22:23:07.902 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2021-06-29 22:23:08.012 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2021-06-29 22:23:08.012 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2201 ms +2021-06-29 22:23:08.385 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2021-06-29 22:23:08.385 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2021-06-29 22:23:08.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2021-06-29 22:23:09.548 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2021-06-29 22:23:09.558 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2021-06-29 22:23:09.611 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2021-06-29 22:23:09.613 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2021-06-29 22:23:09.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2021-06-29 22:23:09.653 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2021-06-29 22:23:09.724 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2021-06-29 22:23:14.379 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException +2021-06-29 22:23:14.382 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@7c8537e9 +2021-06-29 22:23:14.683 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2021-06-29 22:23:15.193 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' +2021-06-29 22:23:16.518 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2021-06-29 22:23:16.823 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/drivingLicense/01-uploadFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.uploadDrivingLicenseFile(org.springframework.web.multipart.MultipartFile,java.lang.String) +2021-06-29 22:23:16.823 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/drivingLicense/02-checkByFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.drivingLicenseCheckByFile(java.lang.String,java.lang.String) +2021-06-29 22:23:16.824 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/drivingLicense/checkByFilewList],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.drivingLicenseCheckByFilewList(java.lang.String,java.lang.String,java.util.ArrayList<java.lang.String>) +2021-06-29 22:23:16.824 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/drivingLicense/uploadFiles],methods=[POST]}" onto public org.springframework.http.ResponseEntity<fr.cea.bigpi.fhe.dap.patternsearch.model.FHEFileSystem> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.concateFiles(fr.cea.bigpi.fhe.dap.patternsearch.model.FHEFileSystem,fr.cea.bigpi.fhe.dap.patternsearch.model.FHEFileSystem,java.lang.String) +2021-06-29 22:23:16.824 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String fr.cea.bigpi.fhe.dap.patternsearch.controller.HomeController.index() +2021-06-29 22:23:16.825 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration() +2021-06-29 22:23:16.826 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration() +2021-06-29 22:23:16.826 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources() +2021-06-29 22:23:16.828 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) +2021-06-29 22:23:16.828 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) +2021-06-29 22:23:16.867 WARN [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2021-06-29 22:23:16.867 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2021-06-29 22:23:16.871 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.netflix.config.DynamicPropertyFactory : DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@61d9da53 +2021-06-29 22:23:17.375 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) +2021-06-29 22:23:17.375 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.376 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.376 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.377 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.378 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.379 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) +2021-06-29 22:23:17.380 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) +2021-06-29 22:23:17.380 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.381 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/jolokia/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2021-06-29 22:23:17.381 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal) +2021-06-29 22:23:17.382 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException +2021-06-29 22:23:17.383 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) +2021-06-29 22:23:17.384 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.384 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.385 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.385 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/hystrix.stream/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2021-06-29 22:23:17.385 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke() +2021-06-29 22:23:17.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.386 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) +2021-06-29 22:23:17.387 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>) +2021-06-29 22:23:17.387 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset() +2021-06-29 22:23:17.388 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.388 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2021-06-29 22:23:17.571 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)] +2021-06-29 22:23:17.679 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet '' +2021-06-29 22:23:17.679 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started +2021-06-29 22:23:17.732 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-29 22:23:17.732 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-29 22:23:17.778 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2021-06-29 22:23:17.902 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2d258eff: startup date [Tue Jun 29 22:23:05 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@65a5d4f9 +2021-06-29 22:23:18.068 WARN [dmp-fhe-patternsearch-service,,,] 54651 --- [main] .t.AbstractTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) +2021-06-29 22:23:18.318 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 639 ms +2021-06-29 22:23:18.355 WARN [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2021-06-29 22:23:18.355 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2021-06-29 22:23:18.620 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' +2021-06-29 22:23:19.133 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService +2021-06-29 22:23:19.180 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2021-06-29 22:23:19.558 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2021-06-29 22:23:19.561 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: jolokia:type=Config is already registered. Adding it with jolokia:type=Config,uuid=568cce0f-04c0-4c38-9ac1-0406267d54fe, but you should revise your setup in order to either use a qualifier or ensure, that only a single agent gets registered (otherwise history functionality might not work) +2021-06-29 22:23:19.561 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Cannot register (legacy) MBean handler for config store with name jmx4perl:type=Config since it already exists. This is the case if another agent has been already started within the same JVM. The registration is skipped. +2021-06-29 22:23:19.561 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Jolokia Discovery MBean registration is skipped because there is already one registered. +2021-06-29 22:23:19.613 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 +2021-06-29 22:23:19.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2021-06-29 22:23:19.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 1 subscriber(s). +2021-06-29 22:23:19.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger +2021-06-29 22:23:19.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 +2021-06-29 22:23:19.614 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed +2021-06-29 22:23:19.630 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s) +2021-06-29 22:23:19.660 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references +2021-06-29 22:23:19.749 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: drivingLicenseCheckByFile_1 +2021-06-29 22:23:19.775 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] ration$HystrixMetricsPollerConfiguration : Starting poller +2021-06-29 22:23:19.852 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 42169 (http) +2021-06-29 22:23:19.859 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Started SampleRepositoryTest in 15.556 seconds (JVM running for 16.489) +2021-06-29 22:23:19.888 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing 1 +2021-06-29 22:23:20.001 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : REsponse dmp-fhe-patternsearch-service say <test01get> +2021-06-29 22:23:20.008 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy +2021-06-29 22:23:20.230 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy result : 'Tests 21 + 12' + +2021-06-29 22:23:20.236 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2d258eff: startup date [Tue Jun 29 22:23:05 CEST 2021]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@65a5d4f9 +2021-06-29 22:23:20.239 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 +2021-06-29 22:23:20.242 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 +2021-06-29 22:23:20.243 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2021-06-29 22:23:20.243 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 0 subscriber(s). +2021-06-29 22:23:20.243 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger +2021-06-29 22:23:20.244 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' +2021-06-29 22:23:20.251 INFO [dmp-fhe-patternsearch-service,,,] 54651 --- [Thread-7] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' +2022-09-13 01:34:11.605 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2ca6546f: startup date [Tue Sep 13 01:34:11 CEST 2022]; root of context hierarchy +2022-09-13 01:34:11.949 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:12.001 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:12.519 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2022-09-13 01:34:12.617 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2022-09-13 01:34:12.636 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2022-09-13 01:34:12.640 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2753316c: startup date [Tue Sep 13 01:34:12 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@2ca6546f +2022-09-13 01:34:13.753 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2022-09-13 01:34:14.458 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=0618bd33-f6bc-3051-bd73-b82367fee82a +2022-09-13 01:34:14.546 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2022-09-13 01:34:14.552 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2022-09-13 01:34:14.572 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:14.807 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$a03148d9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.016 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.031 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9dcc02a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.105 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$cff8a8e8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.172 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.181 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.277 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.295 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$dd5ddb6d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.325 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$85afaec6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.343 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$4a5ece26] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:15.368 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:15.881 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2022-09-13 01:34:15.923 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2022-09-13 01:34:15.924 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2022-09-13 01:34:16.084 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2022-09-13 01:34:16.085 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3445 ms +2022-09-13 01:34:16.719 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2022-09-13 01:34:16.720 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2022-09-13 01:34:16.721 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2022-09-13 01:34:16.721 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2022-09-13 01:34:16.721 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2022-09-13 01:34:16.721 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2022-09-13 01:34:16.721 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2022-09-13 01:34:16.722 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2022-09-13 01:34:16.722 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2022-09-13 01:34:27.138 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 104 common frames omitted + +2022-09-13 01:34:27.142 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 104 common frames omitted + +2022-09-13 01:34:27.193 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2022-09-13 01:34:27.212 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2022-09-13 01:34:27.297 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2022-09-13 01:34:27.299 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2022-09-13 01:34:27.300 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2022-09-13 01:34:27.353 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2022-09-13 01:34:37.472 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 79 common frames omitted + +2022-09-13 01:34:37.473 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : The connection attempt failed. +2022-09-13 01:34:37.488 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2022-09-13 01:34:37.511 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000422: Disabling contextual LOB creation as connection was null +2022-09-13 01:34:37.513 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@696d28ee +2022-09-13 01:34:37.949 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2022-09-13 01:34:47.968 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 01:34:47.969 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001 +2022-09-13 01:34:47.970 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : The connection attempt failed. +2022-09-13 01:34:47.972 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection +2022-09-13 01:34:47.973 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2022-09-13 01:34:47.987 WARN [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-2] o.a.c.loader.WebappClassLoaderBase : Failed to clear soft references from ObjectStreamClass$Caches for web application [ROOT] + +java.lang.ClassCastException: class java.io.ObjectStreamClass$Caches$1 cannot be cast to class java.util.Map (java.io.ObjectStreamClass$Caches$1 and java.util.Map are in module java.base of loader 'bootstrap') + at org.apache.catalina.loader.WebappClassLoaderBase.clearCache(WebappClassLoaderBase.java:2211) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesObjectStreamClassCaches(WebappClassLoaderBase.java:2198) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1573) + at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1518) + at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:446) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5514) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1439) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1428) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:829) + +2022-09-13 01:34:48.010 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2022-09-13 01:34:48.018 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 47 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 58 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 01:34:48.130 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2b8106fa: startup date [Tue Sep 13 01:34:48 CEST 2022]; root of context hierarchy +2022-09-13 01:34:48.153 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:48.215 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:48.364 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2022-09-13 01:34:48.368 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2022-09-13 01:34:48.370 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2022-09-13 01:34:48.372 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2d1dbf4f: startup date [Tue Sep 13 01:34:48 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@2b8106fa +2022-09-13 01:34:48.763 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2022-09-13 01:34:48.883 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=0618bd33-f6bc-3051-bd73-b82367fee82a +2022-09-13 01:34:48.908 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2022-09-13 01:34:48.908 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2022-09-13 01:34:48.916 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:48.988 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$a03148d9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.017 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.029 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9dcc02a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.079 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$cff8a8e8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.103 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.108 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.156 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.165 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$dd5ddb6d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.179 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$85afaec6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.187 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$4a5ece26] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:34:49.196 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:34:49.345 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2022-09-13 01:34:49.347 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2022-09-13 01:34:49.348 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2022-09-13 01:34:49.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2022-09-13 01:34:49.364 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 992 ms +2022-09-13 01:34:49.775 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2022-09-13 01:34:49.776 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2022-09-13 01:35:00.028 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 103 common frames omitted + +2022-09-13 01:35:00.030 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 103 common frames omitted + +2022-09-13 01:35:00.076 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2022-09-13 01:35:00.079 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2022-09-13 01:35:10.095 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 78 common frames omitted + +2022-09-13 01:35:10.096 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : The connection attempt failed. +2022-09-13 01:35:10.096 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2022-09-13 01:35:10.097 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000422: Disabling contextual LOB creation as connection was null +2022-09-13 01:35:10.097 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@696d28ee +2022-09-13 01:35:10.110 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2022-09-13 01:35:20.121 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 73 common frames omitted + +2022-09-13 01:35:20.122 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001 +2022-09-13 01:35:20.123 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : The connection attempt failed. +2022-09-13 01:35:20.124 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection +2022-09-13 01:35:20.124 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2022-09-13 01:35:20.129 WARN [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-2] o.a.c.loader.WebappClassLoaderBase : Failed to clear soft references from ObjectStreamClass$Caches for web application [ROOT] + +java.lang.ClassCastException: class java.io.ObjectStreamClass$Caches$1 cannot be cast to class java.util.Map (java.io.ObjectStreamClass$Caches$1 and java.util.Map are in module java.base of loader 'bootstrap') + at org.apache.catalina.loader.WebappClassLoaderBase.clearCache(WebappClassLoaderBase.java:2211) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesObjectStreamClassCaches(WebappClassLoaderBase.java:2198) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1573) + at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1518) + at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:446) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5514) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1439) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1428) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:829) + +2022-09-13 01:35:20.140 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2022-09-13 01:35:20.143 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 46 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 57 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 73 common frames omitted + +2022-09-13 01:35:20.144 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@17fc391b] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@2ab4bc72] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 47 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 58 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 01:35:20.236 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7e3e1b7b: startup date [Tue Sep 13 01:35:20 CEST 2022]; root of context hierarchy +2022-09-13 01:35:20.254 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:20.275 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:20.407 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2022-09-13 01:35:20.410 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2022-09-13 01:35:20.413 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2022-09-13 01:35:20.414 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4bafe92f: startup date [Tue Sep 13 01:35:20 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7e3e1b7b +2022-09-13 01:35:20.773 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2022-09-13 01:35:20.884 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=0618bd33-f6bc-3051-bd73-b82367fee82a +2022-09-13 01:35:20.918 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2022-09-13 01:35:20.918 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2022-09-13 01:35:20.927 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:21.005 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$a03148d9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.031 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.046 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9dcc02a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.088 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$cff8a8e8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.109 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.115 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.156 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.167 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$dd5ddb6d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.182 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$85afaec6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.193 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$4a5ece26] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:21.208 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:21.388 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2022-09-13 01:35:21.390 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2022-09-13 01:35:21.390 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2022-09-13 01:35:21.395 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2022-09-13 01:35:21.396 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 982 ms +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2022-09-13 01:35:21.744 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2022-09-13 01:35:21.745 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2022-09-13 01:35:21.745 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2022-09-13 01:35:31.973 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 104 common frames omitted + +2022-09-13 01:35:31.974 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 104 common frames omitted + +2022-09-13 01:35:32.003 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2022-09-13 01:35:32.003 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2022-09-13 01:35:42.016 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 79 common frames omitted + +2022-09-13 01:35:42.017 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : The connection attempt failed. +2022-09-13 01:35:42.018 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2022-09-13 01:35:42.018 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000422: Disabling contextual LOB creation as connection was null +2022-09-13 01:35:42.018 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@696d28ee +2022-09-13 01:35:42.031 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2022-09-13 01:35:52.040 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 01:35:52.041 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001 +2022-09-13 01:35:52.041 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : The connection attempt failed. +2022-09-13 01:35:52.041 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection +2022-09-13 01:35:52.042 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2022-09-13 01:35:52.045 WARN [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-2] o.a.c.loader.WebappClassLoaderBase : Failed to clear soft references from ObjectStreamClass$Caches for web application [ROOT] + +java.lang.ClassCastException: class java.io.ObjectStreamClass$Caches$1 cannot be cast to class java.util.Map (java.io.ObjectStreamClass$Caches$1 and java.util.Map are in module java.base of loader 'bootstrap') + at org.apache.catalina.loader.WebappClassLoaderBase.clearCache(WebappClassLoaderBase.java:2211) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesObjectStreamClassCaches(WebappClassLoaderBase.java:2198) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1573) + at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1518) + at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:446) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5514) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1439) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1428) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:829) + +2022-09-13 01:35:52.056 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2022-09-13 01:35:52.058 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 47 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 58 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 01:35:52.122 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4dbad471: startup date [Tue Sep 13 01:35:52 CEST 2022]; root of context hierarchy +2022-09-13 01:35:52.143 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:52.161 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.281 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2022-09-13 01:35:52.284 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2022-09-13 01:35:52.287 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2022-09-13 01:35:52.289 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12e56e82: startup date [Tue Sep 13 01:35:52 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4dbad471 +2022-09-13 01:35:52.623 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2022-09-13 01:35:52.702 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=0618bd33-f6bc-3051-bd73-b82367fee82a +2022-09-13 01:35:52.720 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2022-09-13 01:35:52.720 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2022-09-13 01:35:52.727 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:52.790 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$a03148d9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.810 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.819 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9dcc02a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.856 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$cff8a8e8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.868 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.871 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.896 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b9e605a4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.903 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$dd5ddb6d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.912 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$85afaec6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.923 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$4a5ece26] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 01:35:52.933 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 01:35:53.070 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2022-09-13 01:35:53.071 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2022-09-13 01:35:53.071 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2022-09-13 01:35:53.075 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2022-09-13 01:35:53.076 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 788 ms +2022-09-13 01:35:53.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2022-09-13 01:35:53.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2022-09-13 01:35:53.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2022-09-13 01:35:53.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2022-09-13 01:35:53.355 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2022-09-13 01:35:53.356 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2022-09-13 01:35:53.356 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2022-09-13 01:35:53.356 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2022-09-13 01:35:53.356 INFO [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2022-09-13 01:36:03.529 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 103 common frames omitted + +2022-09-13 01:36:03.530 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7$$FastClassBySpringCGLIB$$8108bf0a.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$75266c7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.postgresql.util.PSQLException: The connection attempt failed. + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 103 common frames omitted + +2022-09-13 01:36:03.563 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2022-09-13 01:36:03.564 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2022-09-13 01:36:13.577 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 78 common frames omitted + +2022-09-13 01:36:13.578 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : The connection attempt failed. +2022-09-13 01:36:13.578 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2022-09-13 01:36:13.579 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000422: Disabling contextual LOB creation as connection was null +2022-09-13 01:36:13.579 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@696d28ee +2022-09-13 01:36:13.598 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2022-09-13 01:36:23.609 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 73 common frames omitted + +2022-09-13 01:36:23.609 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001 +2022-09-13 01:36:23.610 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.h.engine.jdbc.spi.SqlExceptionHelper : The connection attempt failed. +2022-09-13 01:36:23.610 WARN [dap-patternsearch-checker-service,,,] 63281 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection +2022-09-13 01:36:23.611 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2022-09-13 01:36:23.615 WARN [dap-patternsearch-checker-service,,,] 63281 --- [localhost-startStop-2] o.a.c.loader.WebappClassLoaderBase : Failed to clear soft references from ObjectStreamClass$Caches for web application [ROOT] + +java.lang.ClassCastException: class java.io.ObjectStreamClass$Caches$1 cannot be cast to class java.util.Map (java.io.ObjectStreamClass$Caches$1 and java.util.Map are in module java.base of loader 'bootstrap') + at org.apache.catalina.loader.WebappClassLoaderBase.clearCache(WebappClassLoaderBase.java:2211) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesObjectStreamClassCaches(WebappClassLoaderBase.java:2198) + at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1573) + at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1518) + at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:446) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5514) + at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1439) + at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1428) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:829) + +2022-09-13 01:36:23.623 INFO [dap-patternsearch-checker-service,,,] 63281 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2022-09-13 01:36:23.626 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 46 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 57 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 73 common frames omitted + +2022-09-13 01:36:23.626 ERROR [dap-patternsearch-checker-service,,,] 63281 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@17fc391b] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@19ec5a9c] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.exception.JDBCConnectionException: Unable to obtain JDBC Connection + at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115) + at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) + at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:65) + at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:64) + at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:123) + at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) + at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + ... 47 common frames omitted +Caused by: org.postgresql.util.PSQLException: The connection attempt failed. + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:272) + at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) + at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) + at org.postgresql.Driver.makeConnection(Driver.java:404) + at org.postgresql.Driver.connect(Driver.java:272) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.tool.schema.extract.internal.ExtractionContextImpl.getJdbcConnection(ExtractionContextImpl.java:62) + ... 58 common frames omitted +Caused by: java.net.SocketTimeoutException: connect timed out + at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) + at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) + at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) + at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) + at java.base/java.net.Socket.connect(Socket.java:609) + at org.postgresql.core.PGStream.<init>(PGStream.java:61) + at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144) + ... 74 common frames omitted + +2022-09-13 10:21:51.863 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@30404dba: startup date [Tue Sep 13 10:21:51 CEST 2022]; root of context hierarchy +2022-09-13 10:21:52.543 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 10:21:52.648 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$d819deaf] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:53.511 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2022-09-13 10:21:53.653 WARN [dap-patternsearch-checker-service,,,] 13506 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2022-09-13 10:21:53.674 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2022-09-13 10:21:53.685 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@468173fa: startup date [Tue Sep 13 10:21:53 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@30404dba +2022-09-13 10:21:56.219 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2022-09-13 10:21:57.259 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=0618bd33-f6bc-3051-bd73-b82367fee82a +2022-09-13 10:21:57.398 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2022-09-13 10:21:57.406 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2022-09-13 10:21:57.454 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 10:21:57.745 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$be6521e4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.074 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.108 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$bbffdbb2] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.260 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$ee2c81f3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.487 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.564 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.808 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$d819deaf] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.848 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$fb91b478] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.896 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$a3e387d1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.938 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$6892a731] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2022-09-13 10:21:58.989 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 10:21:59.862 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2022-09-13 10:21:59.954 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2022-09-13 10:21:59.959 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2022-09-13 10:22:00.293 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2022-09-13 10:22:00.295 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 6614 ms +2022-09-13 10:22:01.261 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2022-09-13 10:22:01.263 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2022-09-13 10:22:01.265 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2022-09-13 10:22:01.265 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2022-09-13 10:22:01.265 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2022-09-13 10:22:01.266 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2022-09-13 10:22:01.267 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2022-09-13 10:22:01.268 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2022-09-13 10:22:01.269 INFO [dap-patternsearch-checker-service,,,] 13506 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2022-09-13 10:22:02.565 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2022-09-13 10:22:02.628 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2022-09-13 10:22:02.975 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2022-09-13 10:22:02.978 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2022-09-13 10:22:02.981 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2022-09-13 10:22:03.105 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2022-09-13 10:22:03.433 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect +2022-09-13 10:22:06.521 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException +2022-09-13 10:22:06.526 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@7aaf0f0a +2022-09-13 10:22:07.461 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update +2022-09-13 10:22:07.868 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' +2022-09-13 10:22:11.284 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2022-09-13 10:22:11.922 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/01-uploadEncryptedFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.uploadEncryptedFile(org.springframework.web.multipart.MultipartFile,java.lang.String) +2022-09-13 10:22:11.924 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/02-checkWithEncryptedFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.checkWithEncryptedFile(java.lang.String,java.lang.String) +2022-09-13 10:22:11.925 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/crud-data-master/check/downloadEncryptedFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.downloadEncryptedFile(java.lang.Integer,java.lang.String) +2022-09-13 10:22:11.926 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String fr.cea.bigpi.fhe.dap.patternsearch.controller.HomeController.index() +2022-09-13 10:22:11.928 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration() +2022-09-13 10:22:11.929 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration() +2022-09-13 10:22:11.931 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources() +2022-09-13 10:22:11.936 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) +2022-09-13 10:22:11.938 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) +2022-09-13 10:22:12.016 WARN [dap-patternsearch-checker-service,,,] 13506 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2022-09-13 10:22:12.017 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2022-09-13 10:22:12.036 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] c.netflix.config.DynamicPropertyFactory : DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@5afaa87a +2022-09-13 10:22:13.110 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/jolokia/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2022-09-13 10:22:13.111 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke() +2022-09-13 10:22:13.113 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.114 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.115 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) +2022-09-13 10:22:13.117 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.118 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException +2022-09-13 10:22:13.119 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.121 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal) +2022-09-13 10:22:13.124 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) +2022-09-13 10:22:13.125 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.126 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.128 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) +2022-09-13 10:22:13.135 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) +2022-09-13 10:22:13.136 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.142 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.143 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) +2022-09-13 10:22:13.144 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.145 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/hystrix.stream/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2022-09-13 10:22:13.146 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.147 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>) +2022-09-13 10:22:13.147 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset() +2022-09-13 10:22:13.148 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.149 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2022-09-13 10:22:13.493 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)] +2022-09-13 10:22:13.692 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet '' +2022-09-13 10:22:13.693 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started +2022-09-13 10:22:13.891 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2022-09-13 10:22:13.892 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2022-09-13 10:22:13.983 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2022-09-13 10:22:14.281 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@468173fa: startup date [Tue Sep 13 10:21:53 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@30404dba +2022-09-13 10:22:14.630 WARN [dap-patternsearch-checker-service,,,] 13506 --- [main] .t.AbstractTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) +2022-09-13 10:22:15.686 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 1993 ms +2022-09-13 10:22:15.749 WARN [dap-patternsearch-checker-service,,,] 13506 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2022-09-13 10:22:15.750 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2022-09-13 10:22:16.295 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' +2022-09-13 10:22:17.839 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService +2022-09-13 10:22:17.950 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2022-09-13 10:22:18.757 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2022-09-13 10:22:18.762 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: jolokia:type=Config is already registered. Adding it with jolokia:type=Config,uuid=2e80b007-e602-4835-b3b5-a215ef833595, but you should revise your setup in order to either use a qualifier or ensure, that only a single agent gets registered (otherwise history functionality might not work) +2022-09-13 10:22:18.763 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Cannot register (legacy) MBean handler for config store with name jmx4perl:type=Config since it already exists. This is the case if another agent has been already started within the same JVM. The registration is skipped. +2022-09-13 10:22:18.764 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Jolokia Discovery MBean registration is skipped because there is already one registered. +2022-09-13 10:22:18.853 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 +2022-09-13 10:22:18.854 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2022-09-13 10:22:18.854 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 1 subscriber(s). +2022-09-13 10:22:18.854 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger +2022-09-13 10:22:18.854 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 +2022-09-13 10:22:18.855 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed +2022-09-13 10:22:18.895 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s) +2022-09-13 10:22:18.944 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references +2022-09-13 10:22:19.256 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] ration$HystrixMetricsPollerConfiguration : Starting poller +2022-09-13 10:22:19.364 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 46349 (http) +2022-09-13 10:22:19.384 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Started SampleRepositoryTest in 29.903 seconds (JVM running for 31.497) +2022-09-13 10:22:19.442 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing 1 +2022-09-13 10:22:19.722 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : REsponse dmp-fhe-patternsearch-service say <test01get> +2022-09-13 10:22:19.734 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy +2022-09-13 10:22:20.121 INFO [dap-patternsearch-checker-service,,,] 13506 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy result : 'Tests 21 + 12' + +2022-09-13 10:22:20.141 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@468173fa: startup date [Tue Sep 13 10:21:53 CEST 2022]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@30404dba +2022-09-13 10:22:20.155 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 +2022-09-13 10:22:20.162 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 +2022-09-13 10:22:20.162 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2022-09-13 10:22:20.163 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 0 subscriber(s). +2022-09-13 10:22:20.163 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger +2022-09-13 10:22:20.167 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' +2022-09-13 10:22:20.194 INFO [dap-patternsearch-checker-service,,,] 13506 --- [Thread-7] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' +2023-03-27 12:48:35.116 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@73ad7e90: startup date [Mon Mar 27 12:48:35 CEST 2023]; root of context hierarchy +2023-03-27 12:48:35.757 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:35.830 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:36.634 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-03-27 12:48:36.857 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-03-27 12:48:36.869 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-03-27 12:48:36.873 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7bbcf6f0: startup date [Mon Mar 27 12:48:36 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@73ad7e90 +2023-03-27 12:48:39.376 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-03-27 12:48:40.745 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-03-27 12:48:40.923 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-03-27 12:48:40.944 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-03-27 12:48:40.977 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:41.305 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$228237c1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:41.618 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:41.640 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$201cf18f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:41.803 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$524997d0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:41.927 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:41.958 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:42.095 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:42.125 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$5faeca55] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:42.161 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$8009dae] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:42.233 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$ccafbd0e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:42.263 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:43.322 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-03-27 12:48:43.476 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-03-27 12:48:43.478 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-03-27 12:48:43.709 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [Tomcat-startStop-1] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:43.710 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:43.711 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-03-27 12:48:43.714 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat +2023-03-27 12:48:43.739 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-03-27 12:48:43.762 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 35 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 40 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 42 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 44 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 46 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 48 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:44.008 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@650a0b50: startup date [Mon Mar 27 12:48:44 CEST 2023]; root of context hierarchy +2023-03-27 12:48:44.042 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:44.120 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:44.504 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-03-27 12:48:44.509 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-03-27 12:48:44.513 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-03-27 12:48:44.515 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4f70b659: startup date [Mon Mar 27 12:48:44 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@650a0b50 +2023-03-27 12:48:45.476 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-03-27 12:48:45.706 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-03-27 12:48:45.733 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-03-27 12:48:45.733 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-03-27 12:48:45.744 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:45.846 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$228237c1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:45.879 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:45.892 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$201cf18f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:45.971 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$524997d0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.029 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.041 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.129 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.141 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$5faeca55] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.152 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$8009dae] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.168 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$ccafbd0e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:46.180 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:46.542 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-03-27 12:48:46.543 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-03-27 12:48:46.544 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-03-27 12:48:46.569 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [Tomcat-startStop-1] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:46.579 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:46.580 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-03-27 12:48:46.581 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat +2023-03-27 12:48:46.620 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-03-27 12:48:46.624 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 34 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 39 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 41 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 43 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 45 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 47 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:46.625 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@9ebe38b] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@42b02722] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 35 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 40 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 42 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 44 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 46 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 48 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:46.847 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@79dcd7f1: startup date [Mon Mar 27 12:48:46 CEST 2023]; root of context hierarchy +2023-03-27 12:48:46.880 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:46.897 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:47.157 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-03-27 12:48:47.162 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-03-27 12:48:47.165 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-03-27 12:48:47.166 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@632cfbc5: startup date [Mon Mar 27 12:48:47 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@79dcd7f1 +2023-03-27 12:48:47.927 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-03-27 12:48:48.175 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-03-27 12:48:48.222 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-03-27 12:48:48.223 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-03-27 12:48:48.282 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:48.482 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$228237c1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.558 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.565 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$201cf18f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.602 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$524997d0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.624 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.631 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.724 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.733 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$5faeca55] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.744 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$8009dae] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.752 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$ccafbd0e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:48.762 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:48.950 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-03-27 12:48:48.952 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-03-27 12:48:48.953 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-03-27 12:48:48.981 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [Tomcat-startStop-1] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:48.982 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:48.984 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-03-27 12:48:48.985 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat +2023-03-27 12:48:48.999 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-03-27 12:48:49.006 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 35 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 40 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 42 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 44 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 46 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 48 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:49.117 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@781ce680: startup date [Mon Mar 27 12:48:49 CEST 2023]; root of context hierarchy +2023-03-27 12:48:49.136 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:49.152 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:49.315 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-03-27 12:48:49.320 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-03-27 12:48:49.323 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-03-27 12:48:49.324 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@49d52df2: startup date [Mon Mar 27 12:48:49 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@781ce680 +2023-03-27 12:48:50.164 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-03-27 12:48:50.355 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-03-27 12:48:50.374 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-03-27 12:48:50.374 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-03-27 12:48:50.392 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:50.491 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$228237c1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.523 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.532 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$201cf18f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.562 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$524997d0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.576 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.581 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.630 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$3c36f48c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.639 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$5faeca55] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.651 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$8009dae] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.659 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$ccafbd0e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-03-27 12:48:50.673 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-03-27 12:48:50.875 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-03-27 12:48:50.877 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-03-27 12:48:50.877 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-03-27 12:48:50.883 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [Tomcat-startStop-1] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:50.884 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] org.apache.catalina.core.ContainerBase : A child container failed during start + +java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:50.885 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-03-27 12:48:50.886 WARN [dap-patternsearch-checker-service,,,] 98168 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat +2023-03-27 12:48:50.899 INFO [dap-patternsearch-checker-service,,,] 98168 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-03-27 12:48:50.903 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 34 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 39 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 41 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 43 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 45 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 47 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-03-27 12:48:50.904 ERROR [dap-patternsearch-checker-service,,,] 98168 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@9ebe38b] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@a4664f3] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:139) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:138) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:87) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:554) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:166) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:136) + ... 35 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:366) + at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:114) + ... 40 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 42 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 44 common frames omitted +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 46 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 48 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423) + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: org.apache.catalina.LifecycleException: A child container failed during start + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:953) + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) + at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:942) + ... 8 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 6 common frames omitted +Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authenticator.NonLoginAuthenticator[]] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) + at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:182) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 8 common frames omitted +Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()' + at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1181) + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) + ... 10 common frames omitted + +2023-05-02 12:52:00.873 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7186333e: startup date [Tue May 02 12:52:00 CEST 2023]; root of context hierarchy +2023-05-02 12:52:01.387 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:01.462 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:02.461 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 12:52:02.607 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 12:52:02.622 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 12:52:02.628 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1ad9b8d3: startup date [Tue May 02 12:52:02 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7186333e +2023-05-02 12:52:04.480 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 12:52:05.494 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-05-02 12:52:05.626 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 12:52:05.643 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 12:52:05.670 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:05.932 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.210 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.226 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.372 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.509 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.551 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.733 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.773 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.815 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.838 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:06.873 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:07.661 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 12:52:07.708 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 12:52:07.709 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 12:52:08.050 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 12:52:08.053 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 5425 ms +2023-05-02 12:52:09.203 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 12:52:09.204 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 12:52:09.205 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 12:52:09.205 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 12:52:09.206 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 12:52:09.206 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 12:52:09.207 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 12:52:09.207 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 12:52:09.208 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 12:52:09.877 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 12:52:09.892 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 12:52:09.963 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 12:52:10.010 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 12:52:10.120 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2023-05-02 12:52:10.122 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2023-05-02 12:52:10.125 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2023-05-02 12:52:10.186 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2023-05-02 12:52:10.369 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 12:52:10.371 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 12:52:10.374 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 12:52:10.387 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 12:52:10.435 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 12:52:10.443 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 12:52:10.575 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@8eda949: startup date [Tue May 02 12:52:10 CEST 2023]; root of context hierarchy +2023-05-02 12:52:10.629 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:10.670 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:10.906 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 12:52:10.914 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 12:52:10.917 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 12:52:10.919 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a3c541e: startup date [Tue May 02 12:52:10 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@8eda949 +2023-05-02 12:52:11.688 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 12:52:11.996 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-05-02 12:52:12.024 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 12:52:12.025 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 12:52:12.036 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:12.142 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.183 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.192 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.238 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.256 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.261 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.360 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.374 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.407 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.417 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:12.433 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:12.720 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 12:52:12.722 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 12:52:12.723 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 12:52:12.735 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 12:52:12.738 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1819 ms +2023-05-02 12:52:13.377 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 12:52:13.377 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 12:52:13.377 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 12:52:13.378 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 12:52:13.378 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 12:52:13.378 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 12:52:13.378 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 12:52:13.379 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 12:52:13.379 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 12:52:13.755 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 12:52:13.761 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 12:52:13.819 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 12:52:13.820 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 12:52:13.831 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 12:52:13.832 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 12:52:13.833 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 12:52:13.834 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 12:52:13.849 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 12:52:13.854 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 12:52:13.855 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1869fbd2] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@1c33c17b] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 12:52:14.000 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@32578bc0: startup date [Tue May 02 12:52:14 CEST 2023]; root of context hierarchy +2023-05-02 12:52:14.044 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:14.065 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:14.276 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 12:52:14.281 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 12:52:14.283 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 12:52:14.291 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@166fa7ab: startup date [Tue May 02 12:52:14 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@32578bc0 +2023-05-02 12:52:14.991 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 12:52:15.153 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-05-02 12:52:15.183 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 12:52:15.183 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 12:52:15.201 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:15.323 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.344 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.355 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.397 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.412 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.416 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.478 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.508 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.535 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.544 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:15.556 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:15.780 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 12:52:15.787 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 12:52:15.787 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 12:52:15.798 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 12:52:15.799 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1508 ms +2023-05-02 12:52:16.264 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 12:52:16.267 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 12:52:16.268 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 12:52:16.268 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 12:52:16.269 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 12:52:16.269 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 12:52:16.269 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 12:52:16.270 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 12:52:16.270 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 12:52:16.571 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 12:52:16.576 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 12:52:16.638 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 12:52:16.645 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 12:52:16.664 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 12:52:16.665 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 12:52:16.666 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 12:52:16.667 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 12:52:16.682 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 12:52:16.685 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 12:52:16.806 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@988f4d5: startup date [Tue May 02 12:52:16 CEST 2023]; root of context hierarchy +2023-05-02 12:52:16.841 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:16.865 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:17.099 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 12:52:17.109 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 12:52:17.111 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 12:52:17.114 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@76966e68: startup date [Tue May 02 12:52:17 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@988f4d5 +2023-05-02 12:52:17.824 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 12:52:18.018 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=fb8cbd9f-e241-3fcb-88c3-e91e26d617fe +2023-05-02 12:52:18.059 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 12:52:18.060 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 12:52:18.071 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:18.162 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.209 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.222 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.257 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.273 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.277 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.314 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.323 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.342 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.350 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 12:52:18.361 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 12:52:18.501 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 12:52:18.503 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 12:52:18.503 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 12:52:18.513 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 12:52:18.514 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1400 ms +2023-05-02 12:52:19.096 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 12:52:19.099 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 12:52:19.102 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 12:52:19.102 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 12:52:19.102 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 12:52:19.103 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 12:52:19.103 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 12:52:19.103 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 12:52:19.103 INFO [dap-patternsearch-checker-service,,,] 33573 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 12:52:19.405 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 12:52:19.407 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 12:52:19.441 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 12:52:19.442 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 12:52:19.467 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 12:52:19.468 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 12:52:19.468 WARN [dap-patternsearch-checker-service,,,] 33573 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 12:52:19.469 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 12:52:19.495 INFO [dap-patternsearch-checker-service,,,] 33573 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 12:52:19.499 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 12:52:19.506 ERROR [dap-patternsearch-checker-service,,,] 33573 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1869fbd2] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@564d535c] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:44:36.030 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7a5b769b: startup date [Tue May 02 16:44:36 CEST 2023]; root of context hierarchy +2023-05-02 16:44:36.504 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:36.607 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:37.690 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:44:37.882 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:44:37.912 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:44:37.918 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5d508d22: startup date [Tue May 02 16:44:37 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7a5b769b +2023-05-02 16:44:40.736 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:44:41.939 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=02ee2764-4949-3e4e-969d-ec8f51cc3dd2 +2023-05-02 16:44:42.098 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:44:42.114 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:44:42.194 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:42.555 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$118e0dd9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.023 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.089 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f28c7a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.388 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$41556de8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.507 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.546 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:43.959 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:44.017 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$4ebaa06d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:44.094 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$f70c73c6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:44.117 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$bbbb9326] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:44.162 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:45.282 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:44:45.381 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:44:45.385 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:44:45.872 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:44:45.876 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 7959 ms +2023-05-02 16:44:47.315 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:44:47.316 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:44:47.317 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:44:47.317 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:44:47.318 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:44:47.318 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:44:47.319 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:44:47.319 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:44:47.320 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:44:48.145 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:44:48.157 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:44:48.241 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:44:48.269 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:44:48.420 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2023-05-02 16:44:48.423 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2023-05-02 16:44:48.426 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2023-05-02 16:44:48.521 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2023-05-02 16:44:48.796 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 16:44:48.798 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:44:48.801 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:44:48.802 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:44:48.851 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:44:48.866 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:44:49.127 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@40d0bff1: startup date [Tue May 02 16:44:49 CEST 2023]; root of context hierarchy +2023-05-02 16:44:49.163 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:49.217 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:49.510 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:44:49.525 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:44:49.534 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:44:49.539 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@495cac83: startup date [Tue May 02 16:44:49 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@40d0bff1 +2023-05-02 16:44:50.937 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:44:51.183 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=02ee2764-4949-3e4e-969d-ec8f51cc3dd2 +2023-05-02 16:44:51.273 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:44:51.277 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:44:51.312 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:51.500 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$118e0dd9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:51.533 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:51.560 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f28c7a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:51.674 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$41556de8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:51.722 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:51.784 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:52.007 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:52.021 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$4ebaa06d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:52.041 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$f70c73c6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:52.113 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$bbbb9326] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:52.128 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:52.404 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:44:52.409 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:44:52.410 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:44:52.422 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:44:52.424 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2885 ms +2023-05-02 16:44:53.284 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:44:53.285 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:44:53.286 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:44:53.287 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:44:53.287 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:44:53.288 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:44:53.288 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:44:53.289 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:44:53.289 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:44:53.891 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:44:53.902 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:44:53.984 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:44:53.985 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:44:54.007 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 16:44:54.015 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:44:54.016 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:44:54.019 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:44:54.046 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:44:54.052 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 16:44:54.058 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@600b90df] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@35432107] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:44:54.280 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4473bbc1: startup date [Tue May 02 16:44:54 CEST 2023]; root of context hierarchy +2023-05-02 16:44:54.313 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:54.392 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:54.698 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:44:54.703 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:44:54.705 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:44:54.706 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@43b70cb6: startup date [Tue May 02 16:44:54 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4473bbc1 +2023-05-02 16:44:55.590 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:44:55.876 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=02ee2764-4949-3e4e-969d-ec8f51cc3dd2 +2023-05-02 16:44:55.904 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:44:55.904 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:44:55.915 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:56.094 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$118e0dd9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.166 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.185 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f28c7a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.272 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$41556de8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.306 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.316 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.382 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.402 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$4ebaa06d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.425 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$f70c73c6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.450 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$bbbb9326] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:56.472 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:56.796 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:44:56.801 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:44:56.805 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:44:56.845 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:44:56.849 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2143 ms +2023-05-02 16:44:57.851 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:44:57.852 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:44:57.852 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:44:57.852 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:44:57.853 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:44:57.853 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:44:57.854 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:44:57.854 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:44:57.855 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:44:58.522 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:44:58.528 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:44:58.624 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:44:58.629 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:44:58.635 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 16:44:58.642 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:44:58.644 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:44:58.645 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:44:58.668 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:44:58.685 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:44:58.991 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@cc7eeb1: startup date [Tue May 02 16:44:58 CEST 2023]; root of context hierarchy +2023-05-02 16:44:59.052 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:44:59.143 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:44:59.422 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:44:59.430 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:44:59.435 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:44:59.437 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5a963a90: startup date [Tue May 02 16:44:59 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@cc7eeb1 +2023-05-02 16:45:00.092 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:45:00.473 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=02ee2764-4949-3e4e-969d-ec8f51cc3dd2 +2023-05-02 16:45:00.544 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:45:00.545 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:45:00.567 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:45:00.762 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$118e0dd9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:00.827 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:00.854 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f28c7a7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.009 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$41556de8] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.056 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.070 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.131 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$2b42caa4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.146 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$4ebaa06d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.199 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$f70c73c6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.248 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$bbbb9326] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:45:01.293 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:45:01.665 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:45:01.667 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:45:01.667 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:45:01.675 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:45:01.676 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2239 ms +2023-05-02 16:45:02.508 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:45:02.508 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:45:02.509 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:45:02.509 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:45:02.510 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:45:02.510 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:45:02.515 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:45:02.516 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:45:02.516 INFO [dap-patternsearch-checker-service,,,] 67587 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:45:03.033 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:45:03.037 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7$$FastClassBySpringCGLIB$$919831a8.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$78af2bc7.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:45:03.103 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:45:03.104 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:45:03.133 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 16:45:03.135 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:45:03.136 WARN [dap-patternsearch-checker-service,,,] 67587 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:45:03.138 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:45:03.177 INFO [dap-patternsearch-checker-service,,,] 67587 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:45:03.184 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 16:45:03.211 ERROR [dap-patternsearch-checker-service,,,] 67587 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@600b90df] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@67fdcc3] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:51:10.760 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7186333e: startup date [Tue May 02 16:51:10 CEST 2023]; root of context hierarchy +2023-05-02 16:51:11.628 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:11.801 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:12.964 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:51:13.174 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:51:13.206 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:51:13.222 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1ad9b8d3: startup date [Tue May 02 16:51:13 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7186333e +2023-05-02 16:51:15.943 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:51:17.751 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=90010db5-3bf8-33df-a625-84d536b011ce +2023-05-02 16:51:18.022 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:51:18.032 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:51:18.085 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:18.494 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:18.953 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:18.981 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.176 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.255 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.264 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.436 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.464 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.522 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.563 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:19.642 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:20.596 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:51:20.652 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:51:20.653 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:51:21.061 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:51:21.063 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 7842 ms +2023-05-02 16:51:22.550 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:51:22.551 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:51:22.552 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:51:22.552 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:51:22.553 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:51:22.554 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:51:22.555 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:51:22.556 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:51:22.557 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:51:23.341 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:51:23.349 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:51:23.460 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:51:23.504 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:51:23.723 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} +2023-05-02 16:51:23.726 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found +2023-05-02 16:51:23.730 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist +2023-05-02 16:51:23.888 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} +2023-05-02 16:51:24.196 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 16:51:24.198 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:51:24.200 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:51:24.202 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:51:24.285 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:51:24.306 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:51:24.607 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@26864891: startup date [Tue May 02 16:51:24 CEST 2023]; root of context hierarchy +2023-05-02 16:51:24.661 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:24.695 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:25.053 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:51:25.070 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:51:25.073 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:51:25.075 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7c98bac0: startup date [Tue May 02 16:51:25 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@26864891 +2023-05-02 16:51:25.663 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:51:25.848 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=90010db5-3bf8-33df-a625-84d536b011ce +2023-05-02 16:51:25.904 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:51:25.914 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:51:25.934 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:26.052 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.177 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.225 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.386 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.430 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.438 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.555 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.569 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.583 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.605 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:26.619 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:26.973 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:51:26.976 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:51:26.976 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:51:26.983 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:51:26.984 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1909 ms +2023-05-02 16:51:27.809 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:51:27.810 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:51:27.810 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:51:27.811 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:51:27.811 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:51:27.812 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:51:27.813 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:51:27.814 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:51:27.814 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:51:28.868 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:51:28.875 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:51:29.027 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:51:29.030 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:51:29.051 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 16:51:29.053 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:51:29.053 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:51:29.056 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:51:29.115 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:51:29.137 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 16:51:29.143 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1869fbd2] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@1c33c17b] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:51:29.496 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3628c2: startup date [Tue May 02 16:51:29 CEST 2023]; root of context hierarchy +2023-05-02 16:51:29.526 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:29.565 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:29.787 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:51:29.796 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:51:29.798 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:51:29.800 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3f2b55f8: startup date [Tue May 02 16:51:29 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3628c2 +2023-05-02 16:51:30.507 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:51:30.886 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=90010db5-3bf8-33df-a625-84d536b011ce +2023-05-02 16:51:30.930 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:51:30.933 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:51:30.958 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:31.125 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.160 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.175 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.223 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.242 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.247 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.337 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.369 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.411 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.426 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:31.491 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:31.820 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:51:31.822 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:51:31.822 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:51:31.862 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:51:31.862 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2062 ms +2023-05-02 16:51:32.883 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:51:32.892 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:51:32.893 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:51:32.894 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:51:32.896 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:51:32.896 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:51:32.897 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:51:32.898 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:51:32.899 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:51:33.569 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:51:33.574 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 88 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 89 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 99 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 100 common frames omitted + +2023-05-02 16:51:33.663 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:51:33.664 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:51:33.688 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 74 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 75 common frames omitted + +2023-05-02 16:51:33.691 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:51:33.694 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:51:33.696 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:51:33.735 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:51:33.752 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 16:51:33.985 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5a050bf9: startup date [Tue May 02 16:51:33 CEST 2023]; root of context hierarchy +2023-05-02 16:51:34.035 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:34.096 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:34.444 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 16:51:34.458 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 16:51:34.466 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 16:51:34.468 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1b96f15e: startup date [Tue May 02 16:51:34 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@5a050bf9 +2023-05-02 16:51:35.786 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 16:51:36.103 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=90010db5-3bf8-33df-a625-84d536b011ce +2023-05-02 16:51:36.128 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 16:51:36.129 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 16:51:36.140 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:36.281 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$94cc154a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.315 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.324 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9266cf18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.360 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$c4937559] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.377 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.385 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.442 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ae80d215] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.451 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$d1f8a7de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.465 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$7a4a7b37] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.474 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$3ef99a97] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 16:51:36.487 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 16:51:36.787 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 16:51:36.789 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 16:51:36.790 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 16:51:36.796 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 16:51:36.796 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2328 ms +2023-05-02 16:51:37.595 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 16:51:37.596 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 16:51:37.596 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 16:51:37.597 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 16:51:37.597 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 16:51:37.598 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 16:51:37.598 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 16:51:37.599 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 16:51:37.599 INFO [dap-patternsearch-checker-service,,,] 68150 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 16:51:38.055 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:51:38.057 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource + +org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:339) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) + at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) + at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) + at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.CGLIB$jpaVendorAdapter$5(<generated>) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338$$FastClassBySpringCGLIB$$586c18de.invoke(<generated>) + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) + at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fbed3338.jpaVendorAdapter(<generated>) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:564) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1136) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) + at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) + ... 87 common frames omitted +Caused by: java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) + at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) + ... 88 common frames omitted +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 98 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 99 common frames omitted + +2023-05-02 16:51:38.120 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' +2023-05-02 16:51:38.127 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ + name: default + ...] +2023-05-02 16:51:38.138 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool. + +java.sql.SQLException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292) + at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) + at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736) + at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668) + at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) + at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) + at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) + at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280) + ... 73 common frames omitted +Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:468) + at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) + ... 74 common frames omitted + +2023-05-02 16:51:38.139 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Unable to load class: org.postgresql.Driver from ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90;ClassLoader:jdk.internal.loader.ClassLoaders$AppClassLoader@446cdf90 +2023-05-02 16:51:38.140 WARN [dap-patternsearch-checker-service,,,] 68150 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] +2023-05-02 16:51:38.140 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 16:51:38.164 INFO [dap-patternsearch-checker-service,,,] 68150 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 16:51:38.169 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.boot.SpringApplication : Application startup failed + +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.outputConditionEvaluationReport(SpringBootDependencyInjectionTestExecutionListener.java:54) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 42 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 59 common frames omitted + +2023-05-02 16:51:38.169 ERROR [dap-patternsearch-checker-service,,,] 68150 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1869fbd2] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@173de441] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627) + ... 43 common frames omitted +Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) + ... 60 common frames omitted + +2023-05-02 17:02:14.367 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3d98d138: startup date [Tue May 02 17:02:14 CEST 2023]; root of context hierarchy +2023-05-02 17:02:14.959 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:15.082 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:16.266 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:02:16.471 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:02:16.493 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:02:16.500 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5f61371d: startup date [Tue May 02 17:02:16 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@3d98d138 +2023-05-02 17:02:18.171 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:02:19.582 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b4e16e3e-f1ea-3dfe-a541-85f69a031b06 +2023-05-02 17:02:19.719 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:02:19.768 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:02:19.818 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:20.321 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f64f3d13] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:20.689 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:20.716 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f3e9f6e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:20.815 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$26169d22] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:20.932 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:20.942 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:21.126 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:21.173 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$337bcfa7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:21.216 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dbcda300] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:21.236 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a07cc260] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:21.267 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:22.317 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:02:22.395 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:02:22.398 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:02:22.937 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:02:22.938 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 6438 ms +2023-05-02 17:02:24.127 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:02:24.128 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:02:24.129 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:02:24.129 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:02:24.129 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:02:24.130 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:02:24.130 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:02:24.131 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:02:24.131 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:02:24.177 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:02:24.181 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:02:24.225 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:02:24.430 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:02:24.568 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@24b4f4a: startup date [Tue May 02 17:02:24 CEST 2023]; root of context hierarchy +2023-05-02 17:02:24.630 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:24.652 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:24.945 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:02:24.957 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:02:24.961 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:02:24.967 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@19834eb7: startup date [Tue May 02 17:02:24 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@24b4f4a +2023-05-02 17:02:25.872 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:02:26.067 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b4e16e3e-f1ea-3dfe-a541-85f69a031b06 +2023-05-02 17:02:26.131 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:02:26.131 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:02:26.138 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:26.302 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f64f3d13] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.340 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.353 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f3e9f6e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.384 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$26169d22] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.416 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.421 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.482 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.498 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$337bcfa7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.527 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dbcda300] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.557 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a07cc260] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:26.587 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:26.973 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:02:26.976 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:02:26.976 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:02:26.998 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:02:27.006 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2039 ms +2023-05-02 17:02:27.881 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:02:27.881 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:02:27.882 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:02:27.884 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:02:27.885 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:02:27.885 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:02:27.886 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:02:27.887 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:02:27.889 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:02:27.920 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:02:27.922 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:02:28.019 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:02:28.327 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:02:28.335 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@63f259c3] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@6ccdb29f] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1198) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1100) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1491) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + ... 55 common frames omitted + +2023-05-02 17:02:28.623 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7d0bbc49: startup date [Tue May 02 17:02:28 CEST 2023]; root of context hierarchy +2023-05-02 17:02:28.662 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:28.690 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.020 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:02:29.034 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:02:29.038 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:02:29.047 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5035c23c: startup date [Tue May 02 17:02:29 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7d0bbc49 +2023-05-02 17:02:29.515 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:02:29.644 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b4e16e3e-f1ea-3dfe-a541-85f69a031b06 +2023-05-02 17:02:29.689 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:02:29.690 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:02:29.705 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:29.795 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f64f3d13] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.867 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.884 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f3e9f6e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.917 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$26169d22] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.945 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:29.950 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:30.003 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:30.014 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$337bcfa7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:30.027 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dbcda300] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:30.038 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a07cc260] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:30.048 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:30.213 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:02:30.215 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:02:30.216 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:02:30.220 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:02:30.220 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1173 ms +2023-05-02 17:02:30.746 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:02:30.747 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:02:30.747 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:02:30.748 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:02:30.748 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:02:30.749 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:02:30.749 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:02:30.749 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:02:30.749 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:02:30.762 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:02:30.763 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:02:30.805 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:02:31.116 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:02:31.319 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@f5a1b27: startup date [Tue May 02 17:02:31 CEST 2023]; root of context hierarchy +2023-05-02 17:02:31.350 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:31.395 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:31.774 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:02:31.783 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:02:31.786 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:02:31.788 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@72584c3f: startup date [Tue May 02 17:02:31 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@f5a1b27 +2023-05-02 17:02:32.322 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:02:32.572 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b4e16e3e-f1ea-3dfe-a541-85f69a031b06 +2023-05-02 17:02:32.617 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:02:32.623 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:02:32.629 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:32.793 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f64f3d13] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:32.885 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:32.898 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f3e9f6e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:32.940 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$26169d22] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:32.977 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:32.987 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:33.037 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1003f9de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:33.053 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$337bcfa7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:33.074 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dbcda300] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:33.083 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a07cc260] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:02:33.096 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:02:33.360 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:02:33.362 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:02:33.367 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:02:33.392 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:02:33.395 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1607 ms +2023-05-02 17:02:34.322 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:02:34.323 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:02:34.323 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:02:34.323 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:02:34.324 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:02:34.324 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:02:34.324 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:02:34.325 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:02:34.325 INFO [dap-patternsearch-checker-service,,,] 69136 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:02:34.342 WARN [dap-patternsearch-checker-service,,,] 69136 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:02:34.363 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:02:34.379 INFO [dap-patternsearch-checker-service,,,] 69136 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:02:34.603 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:02:34.605 ERROR [dap-patternsearch-checker-service,,,] 69136 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@63f259c3] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@408227af] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1198) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1100) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1491) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + ... 55 common frames omitted + +2023-05-02 17:04:26.604 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@21422231: startup date [Tue May 02 17:04:26 CEST 2023]; root of context hierarchy +2023-05-02 17:04:27.367 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:04:27.469 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$7a5b5a56] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:04:28.629 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:04:28.836 WARN [dap-patternsearch-checker-service,,,] 69405 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:04:28.867 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:04:28.881 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@28babeca: startup date [Tue May 02 17:04:28 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@21422231 +2023-05-02 17:04:31.123 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:04:32.542 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=28b03e6a-8059-397f-9a45-a0b5eb690ea5 +2023-05-02 17:04:32.598 ERROR [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.boot.SpringApplication : Application startup failed + +java.lang.NoClassDefFoundError: ObjectMapper + at java.base/java.lang.Class.getDeclaredFields0(Native Method) + at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3220) + at java.base/java.lang.Class.getDeclaredFields(Class.java:2341) + at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:713) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:685) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:671) + at org.springframework.boot.test.mock.mockito.DefinitionsParser.parse(DefinitionsParser.java:63) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:142) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:134) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:283) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: ObjectMapper + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + ... 47 common frames omitted + +2023-05-02 17:04:32.599 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@28babeca: startup date [Tue May 02 17:04:28 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@21422231 +2023-05-02 17:04:32.601 ERROR [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@146dfe6] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@332796d3] + +java.lang.NoClassDefFoundError: ObjectMapper + at java.base/java.lang.Class.getDeclaredFields0(Native Method) + at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3220) + at java.base/java.lang.Class.getDeclaredFields(Class.java:2341) + at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:713) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:685) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:671) + at org.springframework.boot.test.mock.mockito.DefinitionsParser.parse(DefinitionsParser.java:63) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:142) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:134) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:283) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: ObjectMapper + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + ... 47 common frames omitted + +2023-05-02 17:04:32.838 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@56d6e2e1: startup date [Tue May 02 17:04:32 CEST 2023]; root of context hierarchy +2023-05-02 17:04:32.891 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:04:32.923 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$7a5b5a56] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:04:33.290 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:04:33.301 WARN [dap-patternsearch-checker-service,,,] 69405 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:04:33.307 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:04:33.311 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@61c3d7ac: startup date [Tue May 02 17:04:33 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@56d6e2e1 +2023-05-02 17:04:34.326 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:04:34.894 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=28b03e6a-8059-397f-9a45-a0b5eb690ea5 +2023-05-02 17:04:34.961 ERROR [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.boot.SpringApplication : Application startup failed + +java.lang.NoClassDefFoundError: ObjectMapper + at java.base/java.lang.Class.getDeclaredFields0(Native Method) + at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3220) + at java.base/java.lang.Class.getDeclaredFields(Class.java:2341) + at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:713) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:685) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:671) + at org.springframework.boot.test.mock.mockito.DefinitionsParser.parse(DefinitionsParser.java:63) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:142) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:134) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:283) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: ObjectMapper + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + ... 47 common frames omitted + +2023-05-02 17:04:34.966 INFO [dap-patternsearch-checker-service,,,] 69405 --- [main] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@61c3d7ac: startup date [Tue May 02 17:04:33 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@56d6e2e1 +2023-05-02 17:04:34.968 ERROR [dap-patternsearch-checker-service,,,] 69405 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@146dfe6] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@624baf71] + +java.lang.NoClassDefFoundError: ObjectMapper + at java.base/java.lang.Class.getDeclaredFields0(Native Method) + at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3220) + at java.base/java.lang.Class.getDeclaredFields(Class.java:2341) + at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:713) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:685) + at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:671) + at org.springframework.boot.test.mock.mockito.DefinitionsParser.parse(DefinitionsParser.java:63) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:142) + at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:134) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:283) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: java.lang.ClassNotFoundException: ObjectMapper + at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) + at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) + at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) + ... 47 common frames omitted + +2023-05-02 17:06:34.115 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1686f0b4: startup date [Tue May 02 17:06:34 CEST 2023]; root of context hierarchy +2023-05-02 17:06:34.673 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:34.728 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:36.108 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:06:36.426 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:06:36.454 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:06:36.458 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@656a3d6b: startup date [Tue May 02 17:06:36 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@1686f0b4 +2023-05-02 17:06:38.901 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:06:40.365 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b0c311f5-697a-300e-a88e-6a0c0f4eeae2 +2023-05-02 17:06:40.529 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:06:40.550 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:06:40.565 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:40.890 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f7870e09] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.259 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.271 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f521c7d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.399 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$274e6e18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.551 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.582 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.847 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.870 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$34b3a09d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.924 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dd0573f6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:41.974 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a1b49356] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:42.080 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:43.045 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:06:43.168 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:06:43.169 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:06:43.450 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:06:43.451 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 6993 ms +2023-05-02 17:06:44.520 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:06:44.521 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:06:44.522 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:06:44.522 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:06:44.523 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:06:44.524 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:06:44.525 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:06:44.525 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:06:44.526 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:06:44.622 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:06:44.627 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:06:44.706 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:06:45.182 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:06:45.495 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@360d0c7a: startup date [Tue May 02 17:06:45 CEST 2023]; root of context hierarchy +2023-05-02 17:06:45.566 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:45.610 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:45.990 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:06:46.001 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:06:46.006 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:06:46.010 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3304362e: startup date [Tue May 02 17:06:46 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@360d0c7a +2023-05-02 17:06:46.877 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:06:47.106 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b0c311f5-697a-300e-a88e-6a0c0f4eeae2 +2023-05-02 17:06:47.155 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:06:47.157 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:06:47.185 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:47.323 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f7870e09] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.361 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.396 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f521c7d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.485 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$274e6e18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.538 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.544 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.655 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.678 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$34b3a09d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.711 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dd0573f6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.739 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a1b49356] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:47.762 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:48.043 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:06:48.046 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:06:48.047 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:06:48.063 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-1].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:06:48.064 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2054 ms +2023-05-02 17:06:48.633 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:06:48.634 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:06:48.634 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:06:48.635 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:06:48.635 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:06:48.636 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:06:48.636 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:06:48.636 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:06:48.637 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:06:48.651 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:06:48.652 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:06:48.684 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:06:48.904 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:06:48.908 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@6cce16f4] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@1e097d59] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1198) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1100) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1491) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + ... 55 common frames omitted + +2023-05-02 17:06:49.038 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@397ff526: startup date [Tue May 02 17:06:49 CEST 2023]; root of context hierarchy +2023-05-02 17:06:49.098 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:49.140 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:49.496 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:06:49.508 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:06:49.512 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:06:49.519 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@21e441d1: startup date [Tue May 02 17:06:49 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@397ff526 +2023-05-02 17:06:50.249 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:06:50.529 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b0c311f5-697a-300e-a88e-6a0c0f4eeae2 +2023-05-02 17:06:50.582 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:06:50.582 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:06:50.596 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:50.755 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f7870e09] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:50.811 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:50.830 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f521c7d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:50.906 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$274e6e18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:50.945 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:50.950 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:51.042 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:51.065 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$34b3a09d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:51.088 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dd0573f6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:51.105 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a1b49356] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:51.124 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:51.365 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:06:51.366 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:06:51.367 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:06:51.372 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-2].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:06:51.373 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1854 ms +2023-05-02 17:06:51.808 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:06:51.811 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:06:51.811 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:06:51.812 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:06:51.812 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:06:51.813 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:06:51.813 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:06:51.814 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:06:51.814 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:06:51.847 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:06:51.875 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:06:51.932 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:06:52.094 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:06:52.254 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1b6bb1bd: startup date [Tue May 02 17:06:52 CEST 2023]; root of context hierarchy +2023-05-02 17:06:52.303 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:52.368 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:52.811 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:06:52.824 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:06:52.827 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:06:52.831 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@d3e9b94: startup date [Tue May 02 17:06:52 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@1b6bb1bd +2023-05-02 17:06:53.951 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:06:54.168 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=b0c311f5-697a-300e-a88e-6a0c0f4eeae2 +2023-05-02 17:06:54.203 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:06:54.205 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:06:54.213 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:54.308 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$f7870e09] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.361 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.372 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$f521c7d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.433 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$274e6e18] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.453 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.458 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.515 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$113bcad4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.536 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$34b3a09d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.551 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$dd0573f6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.562 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$a1b49356] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:06:54.575 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:06:54.853 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:06:54.856 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:06:54.859 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:06:54.864 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:06:54.864 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2033 ms +2023-05-02 17:06:55.589 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:06:55.590 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:06:55.590 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:06:55.590 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:06:55.590 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:06:55.590 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:06:55.591 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:06:55.591 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:06:55.591 INFO [dap-patternsearch-checker-service,,,] 69615 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:06:55.646 WARN [dap-patternsearch-checker-service,,,] 69615 --- [main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} +2023-05-02 17:06:55.647 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2023-05-02 17:06:55.727 INFO [dap-patternsearch-checker-service,,,] 69615 --- [main] utoConfigurationReportLoggingInitializer : + +Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. +2023-05-02 17:06:55.943 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.b.d.LoggingFailureAnalysisReporter : + +*************************** +APPLICATION FAILED TO START +*************************** + +Description: + +Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a bean of type 'javax.sql.DataSource' that could not be found. + - Bean method 'dataSource' not loaded because @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' + - Bean method 'dataSource' not loaded because @ConditionalOnBean (types: org.springframework.boot.jta.XADataSourceWrapper; SearchStrategy: all) did not find any beans + + +Action: + +Consider revisiting the conditions above or defining a bean of type 'javax.sql.DataSource' in your configuration. + +2023-05-02 17:06:55.944 ERROR [dap-patternsearch-checker-service,,,] 69615 --- [main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@6cce16f4] to prepare test instance [fr.cea.bigpi.fhe.repository.test.SampleRepositoryTest@522ef462] + +java.lang.IllegalStateException: Failed to load ApplicationContext + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) + at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) + at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) + at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) + at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) + at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) + at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) +Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1198) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1100) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1178) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1072) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) + at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) + at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:124) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) + at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) + at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) + ... 27 common frames omitted +Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} + at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1491) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) + ... 55 common frames omitted + +2023-05-02 17:08:35.245 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3f0fae: startup date [Tue May 02 17:08:35 CEST 2023]; root of context hierarchy +2023-05-02 17:08:36.034 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:08:36.194 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$8c625b28] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:37.821 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-02 17:08:38.093 WARN [dap-patternsearch-checker-service,,,] 69895 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused; nested exception is java.net.ConnectException: Connection refused +2023-05-02 17:08:38.109 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-02 17:08:38.130 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@29bcf51d: startup date [Tue May 02 17:08:38 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3f0fae +2023-05-02 17:08:40.466 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-02 17:08:41.988 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=e3c80435-d67b-3b0a-bf90-04b64cc16cc7 +2023-05-02 17:08:42.222 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-02 17:08:42.243 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-02 17:08:42.276 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:08:42.580 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$72ad9e5d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:42.926 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:42.960 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$a274fe6c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.121 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.144 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.377 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$8c625b28] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.409 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$afda30f1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.449 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$582c044a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.473 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$1cdb23aa] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-02 17:08:43.545 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:08:44.677 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-02 17:08:44.799 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-02 17:08:44.802 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-02 17:08:45.317 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-02 17:08:45.319 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 7189 ms +2023-05-02 17:08:46.417 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-02 17:08:46.419 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-02 17:08:46.421 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-02 17:08:46.421 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-02 17:08:46.422 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-02 17:08:46.422 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-02 17:08:46.423 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-02 17:08:46.424 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-02 17:08:46.424 INFO [dap-patternsearch-checker-service,,,] 69895 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-02 17:08:49.058 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2023-05-02 17:08:49.945 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/01-uploadEncryptedFile],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.uploadEncryptedFile(org.springframework.web.multipart.MultipartFile,java.lang.String) +2023-05-02 17:08:49.946 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/checkEncryptedFileWDataList-Auto],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.checkEncryptedFileWDataListAuto(java.lang.String,java.lang.String,java.util.List<java.lang.String>) +2023-05-02 17:08:49.948 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/startAnalytics],methods=[POST],consumes=[application/json;charset=UTF-8]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.startAnalytics(fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.AnalyticRequestPayload) +2023-05-02 17:08:49.949 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/stopAnalytics],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.stopAnalytics(java.lang.String) +2023-05-02 17:08:49.951 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/receiveAnalyticsResult],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.receiveAnalyticsResult(fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.IaiResponse) +2023-05-02 17:08:49.959 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/02-checkEncryptedFileWList],methods=[POST]}" onto public org.springframework.http.ResponseEntity<byte[]> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.checkEncryptedFileWList(java.lang.String,java.lang.String,java.util.List<java.lang.String>) +2023-05-02 17:08:49.960 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String fr.cea.bigpi.fhe.dap.patternsearch.controller.HomeController.index() +2023-05-02 17:08:49.963 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration() +2023-05-02 17:08:49.964 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration() +2023-05-02 17:08:49.966 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources() +2023-05-02 17:08:49.971 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) +2023-05-02 17:08:49.973 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) +2023-05-02 17:08:50.191 WARN [dap-patternsearch-checker-service,,,] 69895 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2023-05-02 17:08:50.196 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2023-05-02 17:08:50.202 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] c.netflix.config.DynamicPropertyFactory : DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@322399e6 +2023-05-02 17:08:51.694 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.697 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/jolokia/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2023-05-02 17:08:51.701 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke() +2023-05-02 17:08:51.703 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) +2023-05-02 17:08:51.704 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.705 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.708 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>) +2023-05-02 17:08:51.711 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset() +2023-05-02 17:08:51.716 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) +2023-05-02 17:08:51.719 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.721 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException +2023-05-02 17:08:51.724 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.727 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) +2023-05-02 17:08:51.729 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) +2023-05-02 17:08:51.731 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.734 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.736 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.739 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) +2023-05-02 17:08:51.741 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.743 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal) +2023-05-02 17:08:51.746 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.749 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:51.750 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/hystrix.stream/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2023-05-02 17:08:51.751 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-02 17:08:52.226 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)] +2023-05-02 17:08:52.517 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet '' +2023-05-02 17:08:52.518 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started +2023-05-02 17:08:52.655 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-02 17:08:52.656 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-02 17:08:52.814 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-02 17:08:52.999 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@29bcf51d: startup date [Tue May 02 17:08:38 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3f0fae +2023-05-02 17:08:53.673 WARN [dap-patternsearch-checker-service,,,] 69895 --- [main] .t.AbstractTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) +2023-05-02 17:08:54.304 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 1785 ms +2023-05-02 17:08:54.405 WARN [dap-patternsearch-checker-service,,,] 69895 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2023-05-02 17:08:54.405 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2023-05-02 17:08:55.211 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' +2023-05-02 17:08:56.822 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService +2023-05-02 17:08:56.921 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-02 17:08:57.676 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2023-05-02 17:08:57.689 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: jolokia:type=Config is already registered. Adding it with jolokia:type=Config,uuid=c22f4bd9-0069-4ede-94e8-f226f06bd71a, but you should revise your setup in order to either use a qualifier or ensure, that only a single agent gets registered (otherwise history functionality might not work) +2023-05-02 17:08:57.696 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Cannot register (legacy) MBean handler for config store with name jmx4perl:type=Config since it already exists. This is the case if another agent has been already started within the same JVM. The registration is skipped. +2023-05-02 17:08:57.697 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Jolokia Discovery MBean registration is skipped because there is already one registered. +2023-05-02 17:08:57.850 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 +2023-05-02 17:08:57.869 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2023-05-02 17:08:57.870 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 1 subscriber(s). +2023-05-02 17:08:57.870 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger +2023-05-02 17:08:57.870 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 +2023-05-02 17:08:57.871 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed +2023-05-02 17:08:57.932 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s) +2023-05-02 17:08:58.004 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references +2023-05-02 17:08:58.512 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] ration$HystrixMetricsPollerConfiguration : Starting poller +2023-05-02 17:08:58.742 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 44643 (http) +2023-05-02 17:08:58.762 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Started SampleRepositoryTest in 26.197 seconds (JVM running for 29.103) +2023-05-02 17:08:58.899 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing 1 +2023-05-02 17:08:59.504 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : REsponse dmp-fhe-patternsearch-service say <test01get> +2023-05-02 17:08:59.516 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy +2023-05-02 17:09:00.243 INFO [dap-patternsearch-checker-service,,,] 69895 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy result : 'Tests 21 + 12' + +2023-05-02 17:09:00.294 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@29bcf51d: startup date [Tue May 02 17:08:38 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6f3f0fae +2023-05-02 17:09:00.298 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 +2023-05-02 17:09:00.300 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 +2023-05-02 17:09:00.307 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2023-05-02 17:09:00.308 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 0 subscriber(s). +2023-05-02 17:09:00.308 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger +2023-05-02 17:09:00.310 INFO [dap-patternsearch-checker-service,,,] 69895 --- [Thread-6] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' +2023-05-04 11:58:21.512 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7808fb9: startup date [Thu May 04 11:58:21 CEST 2023]; root of context hierarchy +2023-05-04 11:58:21.864 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-04 11:58:21.916 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$decd75f5] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:22.469 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888 +2023-05-04 11:58:22.559 WARN [dap-patternsearch-checker-service,,,] 251684 --- [main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/dmp-fhe-patternsearch-service/test": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) +2023-05-04 11:58:22.567 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : The following profiles are active: test +2023-05-04 11:58:22.572 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@45545e7a: startup date [Thu May 04 11:58:22 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7808fb9 +2023-05-04 11:58:23.668 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. +2023-05-04 11:58:24.168 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.cloud.context.scope.GenericScope : BeanFactory id=e3c80435-d67b-3b0a-bf90-04b64cc16cc7 +2023-05-04 11:58:24.248 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. +2023-05-04 11:58:24.255 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. +2023-05-04 11:58:24.271 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-04 11:58:24.420 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration' of type [org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration$$EnhancerBySpringCGLIB$$c518b92a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.639 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'sleuthAdvisorConfig' of type [org.springframework.cloud.sleuth.annotation.SleuthAdvisorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.655 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$f4e01939] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.714 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.724 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationGlobalProperties' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.794 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$decd75f5] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.819 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration$FeignBeanPostProcessorConfiguration$$EnhancerBySpringCGLIB$$2454bbe] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.843 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration$$EnhancerBySpringCGLIB$$aa971f17] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.860 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration' of type [org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration$$EnhancerBySpringCGLIB$$6f463e77] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2023-05-04 11:58:24.885 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-04 11:58:25.324 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http) +2023-05-04 11:58:25.360 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2023-05-04 11:58:25.361 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35 +2023-05-04 11:58:25.492 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2023-05-04 11:58:25.493 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2921 ms +2023-05-04 11:58:25.967 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*] +2023-05-04 11:58:25.969 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] +2023-05-04 11:58:25.969 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'traceFilter' to: [/*] +2023-05-04 11:58:25.970 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] +2023-05-04 11:58:25.970 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] +2023-05-04 11:58:25.970 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] +2023-05-04 11:58:25.971 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] +2023-05-04 11:58:25.971 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] +2023-05-04 11:58:25.972 INFO [dap-patternsearch-checker-service,,,] 251684 --- [localhost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] +2023-05-04 11:58:27.579 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2023-05-04 11:58:27.955 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/startAnalytics],methods=[POST],consumes=[application/json;charset=UTF-8]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.startAnalytics(fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.AnalyticRequestPayload) +2023-05-04 11:58:27.955 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/stopAnalytics],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.stopAnalytics(java.lang.String) +2023-05-04 11:58:27.956 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/openapi/v1/analysis/receiveAnalyticsResult],methods=[POST]}" onto public org.springframework.http.ResponseEntity<java.lang.String> fr.cea.bigpi.fhe.dap.patternsearch.controller.ControllerImpl.receiveAnalyticsResult(fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.IaiResponse) +2023-05-04 11:58:27.956 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String fr.cea.bigpi.fhe.dap.patternsearch.controller.HomeController.index() +2023-05-04 11:58:27.958 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/ui]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.UiConfiguration> springfox.documentation.swagger.web.ApiResourceController.uiConfiguration() +2023-05-04 11:58:27.958 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources/configuration/security]}" onto public org.springframework.http.ResponseEntity<springfox.documentation.swagger.web.SecurityConfiguration> springfox.documentation.swagger.web.ApiResourceController.securityConfiguration() +2023-05-04 11:58:27.959 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/swagger-resources]}" onto public org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web.SwaggerResource>> springfox.documentation.swagger.web.ApiResourceController.swaggerResources() +2023-05-04 11:58:27.963 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) +2023-05-04 11:58:27.964 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) +2023-05-04 11:58:28.028 WARN [dap-patternsearch-checker-service,,,] 251684 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2023-05-04 11:58:28.029 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2023-05-04 11:58:28.035 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] c.netflix.config.DynamicPropertyFactory : DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@359fd0a2 +2023-05-04 11:58:28.654 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.655 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.655 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.656 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.658 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) +2023-05-04 11:58:28.659 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.660 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.662 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) +2023-05-04 11:58:28.663 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.664 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.665 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>) +2023-05-04 11:58:28.666 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset() +2023-05-04 11:58:28.668 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal) +2023-05-04 11:58:28.670 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.671 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.672 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String) +2023-05-04 11:58:28.672 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>) +2023-05-04 11:58:28.673 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.673 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/hystrix.stream/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2023-05-04 11:58:28.674 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String) +2023-05-04 11:58:28.675 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/jolokia/**]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint.handle(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception +2023-05-04 11:58:28.676 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke() +2023-05-04 11:58:28.678 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() +2023-05-04 11:58:28.679 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException +2023-05-04 11:58:28.931 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)] +2023-05-04 11:58:29.026 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet '' +2023-05-04 11:58:29.027 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started +2023-05-04 11:58:29.083 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-04 11:58:29.083 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-04 11:58:29.120 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] +2023-05-04 11:58:29.221 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@45545e7a: startup date [Thu May 04 11:58:22 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7808fb9 +2023-05-04 11:58:29.412 WARN [dap-patternsearch-checker-service,,,] 251684 --- [main] .t.AbstractTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) +2023-05-04 11:58:29.743 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 716 ms +2023-05-04 11:58:29.791 WARN [dap-patternsearch-checker-service,,,] 251684 --- [main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources. +2023-05-04 11:58:29.791 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath. +2023-05-04 11:58:30.048 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' +2023-05-04 11:58:30.629 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService +2023-05-04 11:58:30.727 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +2023-05-04 11:58:31.155 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: No access restrictor found, access to any MBean is allowed +2023-05-04 11:58:31.158 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: jolokia:type=Config is already registered. Adding it with jolokia:type=Config,uuid=e77c6f4a-1220-4584-b76c-72c93e8e3775, but you should revise your setup in order to either use a qualifier or ensure, that only a single agent gets registered (otherwise history functionality might not work) +2023-05-04 11:58:31.159 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Cannot register (legacy) MBean handler for config store with name jmx4perl:type=Config since it already exists. This is the case if another agent has been already started within the same JVM. The registration is skipped. +2023-05-04 11:58:31.159 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : jolokia: Jolokia Discovery MBean registration is skipped because there is already one registered. +2023-05-04 11:58:31.226 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 +2023-05-04 11:58:31.226 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2023-05-04 11:58:31.227 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 1 subscriber(s). +2023-05-04 11:58:31.227 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger +2023-05-04 11:58:31.227 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 +2023-05-04 11:58:31.227 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed +2023-05-04 11:58:31.253 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s) +2023-05-04 11:58:31.299 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references +2023-05-04 11:58:31.456 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] ration$HystrixMetricsPollerConfiguration : Starting poller +2023-05-04 11:58:31.526 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 39381 (http) +2023-05-04 11:58:31.535 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Started SampleRepositoryTest in 11.165 seconds (JVM running for 12.107) +2023-05-04 11:58:31.579 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing 1 +2023-05-04 11:58:31.762 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : REsponse dmp-fhe-patternsearch-service say <test01get> +2023-05-04 11:58:31.786 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy +2023-05-04 11:58:32.038 INFO [dap-patternsearch-checker-service,,,] 251684 --- [main] f.c.b.f.r.test.SampleRepositoryTest : Testing a+b groovy result : 'Tests 21 + 12' + +2023-05-04 11:58:32.046 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@45545e7a: startup date [Thu May 04 11:58:22 CEST 2023]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7808fb9 +2023-05-04 11:58:32.071 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 +2023-05-04 11:58:32.072 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 +2023-05-04 11:58:32.072 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel +2023-05-04 11:58:32.081 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.i.channel.PublishSubscribeChannel : Channel 'dmp-fhe-patternsearch-service:test:0.errorChannel' has 0 subscriber(s). +2023-05-04 11:58:32.081 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger +2023-05-04 11:58:32.082 INFO [dap-patternsearch-checker-service,,,] 251684 --- [Thread-6] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' diff --git a/mvn_package.sh b/mvn_package.sh new file mode 100644 index 0000000000000000000000000000000000000000..19ceb18d8a161980784f2f9f3e127955edb63ca1 --- /dev/null +++ b/mvn_package.sh @@ -0,0 +1,2 @@ +rm target/dap-patternsearch-analysis-service.jar +mvn clean package -DskipTests \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..8397c4b76f4f74a5eade1a82b056cc7c953d9874 --- /dev/null +++ b/pom.xml @@ -0,0 +1,192 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <groupId>fr.cea.fhe.dap</groupId> + <artifactId>dap-patternsearch-analysis-service</artifactId> + <version>1.0-SNAPSHOT</version> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-dependencies</artifactId> + <version>Edgware.RELEASE</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>1.5.18.RELEASE</version> + <!-- <version>2.1.8.RELEASE</version> --> + <relativePath></relativePath> + </parent> + + <properties> + <java.version>1.8</java.version> + </properties> + + <dependencies> + + <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime --> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + <version>4.3.1</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + </dependency> + <dependency> + <groupId>com.sun.activation</groupId> + <artifactId>javax.activation</artifactId> + <version>1.2.0</version> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-config</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> + <!-- <version>2.0.2.RELEASE</version> --> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-openfeign</artifactId> + <!-- <version>2.2.1.RELEASE</version> --> + <!-- <artifactId>spring-cloud-starter-feign</artifactId> <version>1.4.7.RELEASE</version> --> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-sleuth</artifactId> + <!-- <version>2.2.1.RELEASE</version> --> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <!-- <version>2.6.1</version> --> + <version>2.9.2</version> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <!-- <version>2.6.1</version> --> + <version>2.9.2</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>20.0</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model</artifactId> + <version>3.3.9</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> + <!-- <version>1.0.0.RELEASE</version> --> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-contract-verifier</artifactId> + <!-- <version>2.2.1.RELEASE</version> --> + <scope>test</scope> + </dependency> + <!-- not construct instance of java.time.LocalDateTime --> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + </dependency> + <!-- Enable Hystrix --> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-hystrix</artifactId> + <!-- <version>1.4.7.RELEASE</version> --> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-thymeleaf</artifactId> + </dependency> + <!-- /Enable Hystrix --> + + <!-- set logstash for monitoring log system --> + <!-- <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> + <version>4.5.1</version> </dependency> --> + <!-- EnableAdminServer and log --> + <dependency> + <groupId>org.jolokia</groupId> + <artifactId>jolokia-core</artifactId> + </dependency> + <dependency> + <groupId>de.codecentric</groupId> + <artifactId>spring-boot-admin-starter-client</artifactId> + <version>1.5.1</version> + </dependency> + <!-- Enable spring config --> + <!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> + </dependency> --> + <!-- Enable Groovy --> + <!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all --> + <!-- <dependency> --> + <!-- <groupId>org.codehaus.groovy</groupId> --> + <!-- <artifactId>groovy-all</artifactId> --> + <!-- <version>3.0.1</version> --> + <!-- <type>pom</type> --> + <!-- </dependency> --> + <!-- dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency --> + <!-- dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> + </dependency --> + <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.4.0-b180830.0359</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> + </dependencies> + + <build> + <finalName>${project.artifactId}</finalName> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <configuration> + <mainClass>fr.cea.bigpi.fhe.dap.patternsearch.Application</mainClass> + <addResources>true</addResources> + </configuration> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> diff --git a/run.sh b/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..570904e6920f2954415d1971fc0adc770cc19b54 --- /dev/null +++ b/run.sh @@ -0,0 +1,10 @@ +#!/bin/sh +NAME=dmp-mem-service +dt=$(date '+%Y_%m_%d_%Hh_%Mm_%Ss'); +LOG_FILE="${dt}-${NAME}.log" +touch ${LOG_FILE} + +echo -------------------------------------------------------------------- +echo Starting dmp metadata service using the default parameter defined in application.yml +echo -------------------------------------------------------------------- +java -Xms512m -Xmx2048m -Djava.net.preferIPv4Stack=true -jar ${NAME}.jar >> ${LOG_FILE} diff --git a/src/docker/Dockerfile b/src/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e6bfdba584d020256b11de0620d135a6b51c27b5 --- /dev/null +++ b/src/docker/Dockerfile @@ -0,0 +1,7 @@ +FROM adoptopenjdk:11-jre-hotspot +ARG JAR_FILE=*.jar +COPY ${JAR_FILE} dap-patternsearch-analysis-service.jar +#ADD target/dap-patternsearch-analysis-service.jar dap-patternsearch-analysis-service.jar +ADD dap-patternsearch-analysis-service.jar dap-patternsearch-analysis-service.jar +ENTRYPOINT ["java", "-jar", "dap-patternsearch-analysis-service.jar"] +EXPOSE 9191 \ No newline at end of file diff --git a/src/docker/docker-compose.yml b/src/docker/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd2dff9ee037b4501cdda091517566a12ba84110 --- /dev/null +++ b/src/docker/docker-compose.yml @@ -0,0 +1,37 @@ +version: '2' + +services: + app: + image: 'dap-patternsearch-analysis-service:latest' + build: + context: . + container_name: dap-patternsearch-analysis-service + depends_on: + - db + environment: +# - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5555/patternSearchdb +# - SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5555/patternSearchdb + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/patternSearchdb + - SPRING_DATASOURCE_USERNAME=postgres + - SPRING_DATASOURCE_PASSWORD=123 + - SPRING_JPA_HIBERNATE_DDL_AUTO=update + + expose: + - 9191 + ports: + - 9191:9191 + # volumes: + # - /home/hgnguyen/Desktop/seal/PatternSearch/:/etc/PatternSearch/ + + db: + image: 'postgres:13.1-alpine' + restart: always + container_name: db + ports: + - 5555:5432 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=123 + - POSTGRES_DB=patternSearchdb + volumes: + - ./init_db.sh:/docker-entrypoint-initdb.d/init_db.sh \ No newline at end of file diff --git a/src/docker/init.sql b/src/docker/init.sql new file mode 100644 index 0000000000000000000000000000000000000000..5869c07f8d21ca94d669e03491254151544adaa1 --- /dev/null +++ b/src/docker/init.sql @@ -0,0 +1,2 @@ +CREATE DATABASE patternSearchdb; +GRANT ALL PRIVILEGES ON DATABASE patternSearchdb TO postgres; \ No newline at end of file diff --git a/src/docker/init_db.sh b/src/docker/init_db.sh new file mode 100644 index 0000000000000000000000000000000000000000..f09c6769766a9922f585230ca41888c2b63e698e --- /dev/null +++ b/src/docker/init_db.sh @@ -0,0 +1,7 @@ +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE patternSearchdb; + CREATE USER postgres WITH ENCRYPTED PASSWORD '123'; + GRANT ALL PRIVILEGES ON DATABASE patternSearchdb TO postgres; +EOSQL \ No newline at end of file diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e6bfdba584d020256b11de0620d135a6b51c27b5 --- /dev/null +++ b/src/main/docker/Dockerfile @@ -0,0 +1,7 @@ +FROM adoptopenjdk:11-jre-hotspot +ARG JAR_FILE=*.jar +COPY ${JAR_FILE} dap-patternsearch-analysis-service.jar +#ADD target/dap-patternsearch-analysis-service.jar dap-patternsearch-analysis-service.jar +ADD dap-patternsearch-analysis-service.jar dap-patternsearch-analysis-service.jar +ENTRYPOINT ["java", "-jar", "dap-patternsearch-analysis-service.jar"] +EXPOSE 9191 \ No newline at end of file diff --git a/src/main/docker/dap-patternsearch-analysis-service.jar b/src/main/docker/dap-patternsearch-analysis-service.jar new file mode 100644 index 0000000000000000000000000000000000000000..ef26591330dfd5808718c681f321f798257a22da Binary files /dev/null and b/src/main/docker/dap-patternsearch-analysis-service.jar differ diff --git a/src/main/docker/docker-compose.yml b/src/main/docker/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..5247826dba659ff155b44d3c2c61d108a2215622 --- /dev/null +++ b/src/main/docker/docker-compose.yml @@ -0,0 +1,31 @@ +version: '2' + +services: + app: + image: 'dap-patternsearch-analysis-service:latest' + build: + context: . + container_name: dap-patternsearch-analysis-service + depends_on: + - db + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/patternSearchdb + # - SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/patternSearchdb + - SPRING_DATASOURCE_USERNAME=postgres + - SPRING_DATASOURCE_PASSWORD=123 + - SPRING_JPA_HIBERNATE_DDL_AUTO=update + expose: + - 9191 + ports: + - 9191:9191 + db: + image: 'postgres:13.1-alpine' + container_name: db + ports: + - '5432:5432' + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=123 + - POSTGRES_DB=patternSearchdb + volumes: + - ./init_db.sh:/docker-entrypoint-initdb.d/init_db.sh \ No newline at end of file diff --git a/src/main/docker/init.sql b/src/main/docker/init.sql new file mode 100644 index 0000000000000000000000000000000000000000..5869c07f8d21ca94d669e03491254151544adaa1 --- /dev/null +++ b/src/main/docker/init.sql @@ -0,0 +1,2 @@ +CREATE DATABASE patternSearchdb; +GRANT ALL PRIVILEGES ON DATABASE patternSearchdb TO postgres; \ No newline at end of file diff --git a/src/main/docker/init_db.sh b/src/main/docker/init_db.sh new file mode 100644 index 0000000000000000000000000000000000000000..f09c6769766a9922f585230ca41888c2b63e698e --- /dev/null +++ b/src/main/docker/init_db.sh @@ -0,0 +1,7 @@ +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE patternSearchdb; + CREATE USER postgres WITH ENCRYPTED PASSWORD '123'; + GRANT ALL PRIVILEGES ON DATABASE patternSearchdb TO postgres; +EOSQL \ No newline at end of file diff --git a/src/main/groovy/executor.groovy b/src/main/groovy/executor.groovy new file mode 100644 index 0000000000000000000000000000000000000000..29019d06aa217b5a491665f42c5c1aaa59023c5d --- /dev/null +++ b/src/main/groovy/executor.groovy @@ -0,0 +1,10 @@ +def String fhe_aplusb(def a, def b) { + def command = "echo 'Tests ${a} + ${b}' " + def proc = command.execute() + proc.waitFor() + if(proc.exitValue() != 0) { + println "Process exit code: ${proc.exitValue()}" + println "Std Err: ${proc.err.text}" + } + return proc.in.text +} \ No newline at end of file diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/Application.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/Application.java new file mode 100644 index 0000000000000000000000000000000000000000..78d8a3e880df8ba699b1a607a2e196a6600cabe0 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/Application.java @@ -0,0 +1,143 @@ +package fr.cea.bigpi.fhe.dap.patternsearch; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.sleuth.sampler.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.BasicAuth; +import springfox.documentation.service.Contact; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableSwagger2 +@EnableCircuitBreaker +//@EnableAutoConfiguration +@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) +//@Configuration +//@EnableAsync +//@EnableFeignClients(clients = { AccountClient.class }) +public class Application { + + @Value("${security.activation.status}") + private boolean securityActivationStatus; + + /** + * Using this Postconstruct For cannot deserialized Datetime Format + */ + @Autowired + private ObjectMapper objectMapper; + + @PostConstruct + public void setUp() { + objectMapper.registerModule(new JavaTimeModule()); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public AlwaysSampler defaultSampler() { + return new AlwaysSampler(); + } + + private final String filterPatern = "/openapi/.*"; + private final String basePackage = "fr.cea.bigpi.fhe.dap.patternsearch.controller"; + + /** + * the metadata are information visualized in the /basepath/swagger-ui.html + * interface, only for documentation + */ + private ApiInfo metadata() { + return new ApiInfoBuilder().title("DAP - PATTERN SEARCH - Analysis Service API documentation") + .description("This is API documentation for working with DAP - PARTTERN SEARCH - Function Engine") + .license("CEA 2.0").licenseUrl("http://www.cea.fr/bigpi/licenses/LICENSE-2.0.html") + .termsOfServiceUrl("").version("1.0.0").contact(new Contact("", "", "contact@cea.fr")).build(); + } + + /** + * Docket is a SwaggerUI configuration component, in particular specifies to use + * the V2.0 (SWAGGER_2) of swagger generated interfaces it also tells to include + * only paths that are under /v1/. If other rest interfaces are added with + * different base path, they won't be included this path selector can be removed + * if all interfaces should be documented. + */ + @Bean + public Docket documentation() { + Docket docket = new Docket(DocumentationType.SWAGGER_2); + docket.apiInfo(metadata()); + if (!securityActivationStatus) { + return docket.select().apis(RequestHandlerSelectors.basePackage(basePackage)) + .paths(PathSelectors.regex(filterPatern)).build(); + } else { + return docket + // .securitySchemes(new ArrayList<ApiKey>(Arrays.asList(new ApiKey("mykey", + // "api_key", "header")))) + .securitySchemes(new ArrayList<BasicAuth>(Arrays.asList(new BasicAuth("basicAuth")))) + .securityContexts(new ArrayList<SecurityContext>(Arrays.asList(securityContext()))).select() + .apis(RequestHandlerSelectors.basePackage(basePackage)).paths(PathSelectors.regex(filterPatern)) + .build() + // .directModelSubstitute(java.time.LocalDateTime.class, java.sql.Date.class) + // .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) + ; + } + } + + /** + * Selector for the paths this security context applies to ("filterPatern) + */ + private SecurityContext securityContext() { + return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex(filterPatern)) + .build(); + } + + /** + * Here we use the same key defined in the security scheme (basicAuth) + */ + List<SecurityReference> defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + // return new ArrayList<SecurityReference>(Arrays.asList(new + // SecurityReference("mykey", authorizationScopes))); + return new ArrayList<SecurityReference>(Arrays.asList(new SecurityReference("basicAuth", authorizationScopes))); + } + +// @Bean +// public Executor taskExecutor() { +// ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); +// executor.setCorePoolSize(2); +// executor.setMaxPoolSize(2); +// executor.setQueueCapacity(500); +// executor.setThreadNamePrefix("E-corridor-"); +// executor.initialize(); +// return executor; +// } + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/Controller.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/Controller.java new file mode 100644 index 0000000000000000000000000000000000000000..e5b283f328b2ee602791206cec42136502339d07 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/Controller.java @@ -0,0 +1,156 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.controller; + +import java.util.List; + +//import java.util.ArrayList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.multipart.MultipartFile; + +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.AnalyticRequestPayload; +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.IaiResponse; +//import fr.cea.bigpi.fhe.dap.patternsearch.model.FHEFileSystem; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +@RequestMapping("/openapi/v1") +public interface Controller { + + final Logger logger = LoggerFactory.getLogger(Controller.class.getName()); + +// @ApiOperation(value = "Upload Encrypted File (.ct)", notes = "This method uploads an encrypted file and return the requestID number", nickname = "uploadEncryptedFile", response = String.class, authorizations = {}, tags = { +// "Generic - Analysis With Data Management", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/01-uploadEncryptedFile") +// public @ResponseBody ResponseEntity<String> uploadEncryptedFile( +// @ApiParam(name = "file", value = "", example = "", required = true) @RequestParam("file") MultipartFile file, +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID); + +// @ApiOperation(value = "Check If An Uploaded Encrypted File's Information Is In Database (SQL)", notes = "This method checks if an uploaded encrypted file's information exists in database and returns an encrypted .ct file result (or a zip file for multiple encrypted .ct files). The file result is decrypted with 04-decryptCheckedResult at client micro-service. Note that: the requestID number is used in this method generated from the 01-uploadFile", nickname = "checkWithEncryptedFile", response = ResponseEntity.class, authorizations = {}, tags = { +// "Generic - Analysis With Data Management", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/02-checkWithEncryptedFile") +// public @ResponseBody ResponseEntity<byte[]> checkWithEncryptedFile( +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID); + + // +// @ApiOperation(value = "Check If An Uploaded Encrypted File's Information Is In A Given Local Data List", notes = "This method checks if an uploaded encrypted file's information exists in a given data list and returns an encrypted .ct file result (or a zip file for multiple encrypted .ct files). The file result is decrypted with 04-decryptCheckedResult at client micro-service. Note that: the requestID number is used in this method generated from the 01-uploadFile", nickname = "checkUploadedEncryptedFileWDataList", response = ResponseEntity.class, authorizations = {}, tags = { +// "Generic - Analysis With Data Management", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/02-checkEncryptedFileWList") +// public @ResponseBody ResponseEntity<byte[]> checkEncryptedFileWList( +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID, +// @ApiParam(name = "dataList", value = "", example = "", required = true) @RequestParam("dataList") List<String> dataList); + +// @ApiOperation(value = "Download Encrpted File", notes = "This method download an encrpted file", nickname = "downloadEncrptedFile", response = ResponseEntity.class, authorizations = {}, tags = { +// "Generic - Analysis With Data Management", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response"), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/downloadEncryptedFile") +// public ResponseEntity<byte[]> downloadEncryptedFile( +// @ApiParam(name = "Id", value = "", example = "", required = true) @RequestParam(name = "Id") Integer Id, +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID); + +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/checkEncryptedFileWDataList-Auto") +// @ApiOperation(value = "Check an encrypted file with a list of encrypted file", notes = "This method checks if an encrypted file's information is stored in a give data list and then returns an result", tags = { +// "Generic - Analysis", }) +// public ResponseEntity<byte[]> checkEncryptedFileWDataListAuto( +// @ApiParam(name = "file2bchecked", value = "Any Character", example = "", required = true) @RequestParam("file2bchecked") String file2bchecked, +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "dataList", value = "", example = "", required = true) @RequestParam("dataList") List<String> dataList); + + // E-Corridor Part - Begin + @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), + @ApiResponse(code = 400, message = "Bad request", response = String.class), + @ApiResponse(code = 401, message = "Unauthorized", response = String.class), + @ApiResponse(code = 404, message = "Not found", response = String.class), + @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping(value = "/analysis/checkEncryptedFileWDataList-Base64", consumes = { +// "application/json;charset=UTF-8" }) +// @ApiOperation(value = "checkEncryptedFileWDataList", notes = "Used for E-Corridor project, receives a predefined payload with ", tags = { "E-Corridor - Analysis", }) +// public ResponseEntity<String> checkEncryptedFileWDataListAutoBase64( +// @RequestBody AnalyticRequestPayload analyticRequestPayload); + @PostMapping(value = "/analysis/startAnalytics", consumes = { "application/json;charset=UTF-8" }) + @ApiOperation(value = "startAnalytics", notes = "Used for E-Corridor project, receives a predefined payload with ", tags = { + "E-Corridor - Analysis", }) + public ResponseEntity<String> startAnalytics(@RequestBody AnalyticRequestPayload analyticRequestPayload); + + @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), + @ApiResponse(code = 400, message = "Bad request", response = String.class), + @ApiResponse(code = 401, message = "Unauthorized", response = String.class), + @ApiResponse(code = 404, message = "Not found", response = String.class), + @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) + @PostMapping(value = "/analysis/stopAnalytics") + @ApiOperation(value = "stopAnalytics", notes = "", tags = { "E-Corridor - Analysis", }) + public @ResponseBody ResponseEntity<String> stopAnalytics( + @ApiParam(name = "partnerID", value = "Used for stopping the running analysis", example = "", required = true) @RequestParam("partnerID") String partnerID); + + @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), + @ApiResponse(code = 400, message = "Bad request", response = String.class), + @ApiResponse(code = 401, message = "Unauthorized", response = String.class), + @ApiResponse(code = 404, message = "Not found", response = String.class), + @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) + @PostMapping(value = "/analysis/receiveAnalyticsResult") + @ApiOperation(value = "receiveAnalyticsResult", notes = "Used as the on_finish_url and receives result from checkEncryptedFileWDataList-Base64 api", tags = { + "E-Corridor - Analysis", }) + public @ResponseBody ResponseEntity<String> receiveAnalyticsResult(@RequestBody IaiResponse iaiResponse); + // E-Corridor Part - End + +// @ApiOperation(value = "Concate Checked Result Files", notes = "This method concates multiple checked result files", nickname = "concateCheckedResultFiles", response = ResponseEntity.class, authorizations = {}, tags = { +// "Driving License For Distributed Computing", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response"), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/drivingLicense/concateCheckedResultFiles") +// public ResponseEntity<FHEFileSystem> concateFiles( +// @ApiParam(name = "file1", value = "", example = "", required = true) @RequestParam("file1") FHEFileSystem file1, +// @ApiParam(name = "file2", value = "", example = "", required = true) @RequestParam("file2") FHEFileSystem file2, +// @ApiParam(name = "filename", value = "", example = "", required = true) @RequestParam("filename") String filename); + +// @ApiOperation(value = "Check If An Uploaded Encrypted Driving License Number Is In A List", notes = "This method checks if an uploaded encrypted driving license number exists in the given list. The file result is decrypted with 04-decryptCheckedResult", nickname = "checkByFilewList", response = ResponseEntity.class, authorizations = {}, tags = { +// "Driving License For Distributed Computing", }) +// @ApiResponses(value = { @ApiResponse(code = 200, message = "Server response", response = String.class), +// @ApiResponse(code = 400, message = "Bad request", response = String.class), +// @ApiResponse(code = 401, message = "Unauthorized", response = String.class), +// @ApiResponse(code = 404, message = "Not found", response = String.class), +// @ApiResponse(code = 500, message = "Error for HTTPS call trustAnchors", response = String.class) }) +// @PostMapping("/analysis/drivingLicense/checkByFilewList") +// public @ResponseBody ResponseEntity<byte[]> drivingLicenseCheckByFilewList( +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID, +// @ApiParam(name = "files", value = "", example = "", required = true) @RequestParam("files") ArrayList<String> files); + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/ControllerImpl.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/ControllerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6c42ca430008415f80b87d9106cd535eb86d5823 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/ControllerImpl.java @@ -0,0 +1,550 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.controller; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Async; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import fr.cea.bigpi.fhe.dap.patternsearch.helper.Tools; +import fr.cea.bigpi.fhe.dap.patternsearch.helper.Zip; +//import fr.cea.bigpi.fhe.dap.patternsearch.model.Data; +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.AnalyticRequestPayload; +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.IaiResponse; +import fr.cea.bigpi.fhe.dap.patternsearch.service.AnalysisServices; +//import fr.cea.bigpi.fhe.dap.patternsearch.service.DataService; +import fr.cea.bigpi.fhe.dap.patternsearch.service.FHEPatternSearchService; +import fr.cea.bigpi.fhe.dap.patternsearch.service.FilesStorageService; +import io.swagger.annotations.ApiParam; + +@RestController +public class ControllerImpl implements Controller { + + @Autowired + private FHEPatternSearchService fhePatternSearchService; + +// @Autowired +// DataService dataService; + + @Autowired + FilesStorageService storageService; + + @Autowired + Zip zip; + + @Autowired + Tools tools; + + @Autowired + AnalysisServices analysisServices; + + static final Logger logger = LoggerFactory.getLogger(ControllerImpl.class); + +// @Override + public ResponseEntity<String> uploadEncryptedFile( + @ApiParam(name = "file", value = "", example = "", required = true) @RequestParam("file") MultipartFile file, + @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID) { + String message = ""; + try { + String requestID = UUID.randomUUID().toString(); + String filename = requestID + ".ct"; + + byte[] bytes = file.getBytes(); + String path = storageService.getFileDir().toString() + "/" + filename; + Files.write(Paths.get(path), bytes); + message = requestID; + return new ResponseEntity<String>(message, HttpStatus.OK); + } catch (Exception e) { + message = "Could not upload the file: " + file.getOriginalFilename() + "!"; + e.printStackTrace(); + } + return new ResponseEntity<String>(message, HttpStatus.INTERNAL_SERVER_ERROR); + } + + // chops a list into non-view sublists of length L + static <T> List<List<T>> chopped(List<T> list, final int L) { + List<List<T>> parts = new ArrayList<List<T>>(); + final int N = list.size(); + for (int i = 0; i < N; i += L) { + parts.add(new ArrayList<T>(list.subList(i, Math.min(N, i + L)))); + } + return parts; + } + +// @Override + public ResponseEntity<byte[]> checkEncryptedFileWList( + @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, + @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID, + @ApiParam(name = "dataList", value = "", example = "", required = true) @RequestParam("dataList") List<String> dataList) { + int vectorSize = 102; + // clean result +// fhePatternSearchService.deleteDir(fhePatternSearchService.getResultDir() + "requestID" + ".ct"); + // +// List<Data> allData = dataService.getAllData(); + ArrayList<String> data = new ArrayList<String>(); +// for (Data datum : allData) { +// if (datum.getPartnerId().equals(partnerID)) { +//// data.add(datum.getContent() + fhePatternSearchService.getFilename() + ".ct"); +// data.add(datum.getContent() + datum.getDataId() + ".ct"); +// } +// } + data = (ArrayList<String>) dataList; + // + + try { +// if (data.size() > 0 && data.size() <= vectorSize) { +//// String message = ""; +// String fileName = requestID + ".ct"; +// String encryptedFilePath = storageService.getFileDir() + "/" + fileName; +// fhePatternSearchService.checkData(encryptedFilePath, data, requestID); +// String resultPath = fhePatternSearchService.getResultDir() + "/" + requestID + ".ct"; +//// Resource resource = storageService.load(resultPath); +// Path path = Paths.get(resultPath); +// byte[] returnData = Files.readAllBytes(path); +// fhePatternSearchService.deleteDir(path.toString()); +// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +// // +// } else if (data.size() > 0 && data.size() > vectorSize) { + + List<List<String>> parts = chopped(data, vectorSize); + String fileName = requestID + ".ct"; + String encryptedFilePath = storageService.getFileDir() + "/" + fileName; + + String[] resultPaths = new String[parts.size()]; + for (int i = 0; i < parts.size(); i++) { + try { + String outputPath = requestID + "." + (i + 1) + "." + parts.size(); + System.out.println(outputPath); + fhePatternSearchService.checkData(encryptedFilePath, (ArrayList<String>) parts.get(i), outputPath); + resultPaths[i] = fhePatternSearchService.getResultDir() + "/" + outputPath + ".ct"; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + ; + + // Check if file exist +// boolean ready = false; +// String strCheckPath = resultPath[(parts.size()-1)]; +// Path checkPath = Paths.get(strCheckPath); +// while (!ready) { +// checkPath = Paths.get(strCheckPath); +// System.out.println(checkPath + " : " + Files.exists(checkPath)); +// if (Files.exists(checkPath)) { +// ready = true; +// } +// } + + // Zip result files - start +// boolean isDirCreated = tools.creatDir(fhePatternSearchService.getResultDir() + "/" + requestID); +// if (isDirCreated) { + + String zipResultPath = zip.zipMultipleFiles(fhePatternSearchService.getResultDir() + "/" + requestID, + requestID, resultPaths); + // Zip result files - end + +// for (int i = 0; i < resultPaths.length; i++) { +// fhePatternSearchService.deleteDir(resultPaths[i]); +// } + + Path path = Paths.get(zipResultPath); + byte[] returnData = Files.readAllBytes(path); +// fhePatternSearchService.deleteDir(path.toString()); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION, + // for direct downlad "inline", for "save as" dialog "attachment" (browser + // dependent) + String.format("attachment; filename=\"" + requestID + ".zip\"")); + + return new ResponseEntity<byte[]>(returnData, responseHeaders, HttpStatus.OK); + +// } else { +// throw new Exception("Could not created the directory"); +// } + } catch (Exception e) { + e.printStackTrace(); + } + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + +// @Override + public @ResponseBody ResponseEntity<byte[]> checkEncryptedFileWDataListAuto( + @RequestParam("file2bchecked") String file2bchecked, @RequestParam("partnerID") String partnerID, + @RequestParam("dataList") List<String> dataList) { + try { + String requestID = UUID.randomUUID().toString(); + String filename = requestID + ".ct"; + String filePath = file2bchecked; + byte[] bytes = Files.readAllBytes(Paths.get(filePath)); + String path = storageService.getFileDir().toString() + "/" + filename; + Files.write(Paths.get(path), bytes); + + ResponseEntity<byte[]> zipResultResponse = checkEncryptedFileWList(partnerID, requestID, dataList); + return zipResultResponse; + + } catch (Exception e) { + e.printStackTrace(); + } + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Async + @Override +// public ResponseEntity<String> checkEncryptedFileWDataListAutoBase64( +// @RequestBody AnalyticRequestPayload analyticRequestPayload) { + public ResponseEntity<String> startAnalytics(@RequestBody AnalyticRequestPayload analyticRequestPayload) { + try { + System.out.println(fhePatternSearchService.toString()); + analysisServices.startAnalysis(analyticRequestPayload, "CEA", "result"); + +// return new ResponseEntity<byte[]>(result, HttpStatus.OK); + return new ResponseEntity<String>("Received Request", HttpStatus.OK); + } catch (Exception e) { + e.printStackTrace(); + } + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Override + public ResponseEntity<String> stopAnalytics(@RequestParam("partnerID") String partnerID) { + String message = ""; + try { + boolean result = fhePatternSearchService.stopChecking(); + message = String.valueOf(result); + return new ResponseEntity<String>(message, HttpStatus.OK); + } catch (Exception e) { +// message = "Could not upload the file: " + file.getOriginalFilename() + "!"; + e.printStackTrace(); + } + return new ResponseEntity<String>(message, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Override + public ResponseEntity<String> receiveAnalyticsResult(@RequestBody IaiResponse iaiResponse) { + String message = ""; + try { + System.out.println("Received response: " + iaiResponse.getSuccess() + " " + iaiResponse.getValue() + " " + + iaiResponse.getResults()); + return new ResponseEntity<String>(message, HttpStatus.OK); + } catch (Exception e) { +// message = "Could not upload the file: " + file.getOriginalFilename() + "!"; + e.printStackTrace(); + } + return new ResponseEntity<String>(message, HttpStatus.INTERNAL_SERVER_ERROR); + } + +// @Override +// public ResponseEntity<byte[]> checkWithEncryptedFile( +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID) { +// int vectorSize = 102; +// // clean result +// fhePatternSearchService.deleteDir(fhePatternSearchService.getResultDir() + "requestID" + ".ct"); +// // +// List<Data> allData = dataService.getAllData(); +// ArrayList<String> data = new ArrayList<String>(); +// for (Data datum : allData) { +// if (datum.getPartnerId().equals(partnerID)) { +//// data.add(datum.getContent() + fhePatternSearchService.getFilename() + ".ct"); +// data.add(datum.getContent() + datum.getDataId() + ".ct"); +// } +// } +// // +// +// try { +//// if (data.size() > 0 && data.size() <= vectorSize) { +////// String message = ""; +//// String fileName = requestID + ".ct"; +//// String encryptedFilePath = storageService.getFileDir() + "/" + fileName; +//// fhePatternSearchService.checkData(encryptedFilePath, data, requestID); +//// String resultPath = fhePatternSearchService.getResultDir() + "/" + requestID + ".ct"; +////// Resource resource = storageService.load(resultPath); +//// Path path = Paths.get(resultPath); +//// byte[] returnData = Files.readAllBytes(path); +//// fhePatternSearchService.deleteDir(path.toString()); +//// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +//// // +//// } else if (data.size() > 0 && data.size() > vectorSize) { +// +// List<List<String>> parts = chopped(data, vectorSize); +// String fileName = requestID + ".ct"; +// String encryptedFilePath = storageService.getFileDir() + "/" + fileName; +// +// String[] resultPaths = new String[parts.size()]; +// for (int i = 0; i < parts.size(); i++) { +// try { +// String outputPath = requestID + "." + (i + 1) + "." + parts.size(); +// System.out.println(outputPath); +// fhePatternSearchService.checkData(encryptedFilePath, (ArrayList<String>) parts.get(i), outputPath); +// resultPaths[i] = fhePatternSearchService.getResultDir() + "/" + outputPath + ".ct"; +// } catch (Exception e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// ; +// +// // Check if file exist +//// boolean ready = false; +//// String strCheckPath = resultPath[(parts.size()-1)]; +//// Path checkPath = Paths.get(strCheckPath); +//// while (!ready) { +//// checkPath = Paths.get(strCheckPath); +//// System.out.println(checkPath + " : " + Files.exists(checkPath)); +//// if (Files.exists(checkPath)) { +//// ready = true; +//// } +//// } +// +// // Zip result files - start +//// boolean isDirCreated = tools.creatDir(fhePatternSearchService.getResultDir() + "/" + requestID); +//// if (isDirCreated) { +// +// String zipResultPath = zip.zipMultipleFiles(fhePatternSearchService.getResultDir() + "/" + requestID, +// requestID, resultPaths); +// // Zip result files - end +// +//// for (int i = 0; i < resultPaths.length; i++) { +//// fhePatternSearchService.deleteDir(resultPaths[i]); +//// } +// +// Path path = Paths.get(zipResultPath); +// byte[] returnData = Files.readAllBytes(path); +//// fhePatternSearchService.deleteDir(path.toString()); +// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +// +//// } else { +//// throw new Exception("Could not created the directory"); +//// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +// } + +// // chops a list into non-view sublists of length L +// static <T> List<List<T>> chopped(List<T> list, final int L) { +// List<List<T>> parts = new ArrayList<List<T>>(); +// final int N = list.size(); +// for (int i = 0; i < N; i += L) { +// parts.add(new ArrayList<T>(list.subList(i, Math.min(N, i + L)))); +// } +// return parts; +// } + +// @Override +// public ResponseEntity<byte[]> downloadEncryptedFile( +// @ApiParam(name = "Id", value = "", example = "", required = true) @RequestParam(name = "Id") Integer Id, +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID) { +// try { +// List<Data> allData = dataService.getAllData(); +// for (Data datum : allData) { +// if (datum.getPartnerId().equals(partnerID) && datum.getDataId().equals(Id)) { +// String fileName = Id + ".ct"; +// String encryptedFilePath = datum.getContent() + fileName; +// Path path = Paths.get(encryptedFilePath); +// byte[] returnData = Files.readAllBytes(path); +// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +// } +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +// } + +// @Override +// public ResponseEntity<byte[]> drivingLicenseCheckByFilewList( +// @ApiParam(name = "partnerID", value = "", example = "", required = true) @RequestParam("partnerID") String partnerID, +// @ApiParam(name = "requestID", value = "", example = "", required = true) @RequestParam("requestID") String requestID, +// @ApiParam(name = "files", value = "", example = "", required = true) @RequestParam("files") ArrayList<String> files) { +// try { +// // clean result +// fhePatternSearchService.deleteDir(fhePatternSearchService.getResultDir() + "requestID" + ".ct"); +// // +// if (files.size() > 0 && files.size() <= 102) { +//// String message = ""; +// String fileName = requestID + ".ct"; +// String encryptedFilePath = storageService.getFileDir() + "/" + fileName; +// fhePatternSearchService.checkLicense(encryptedFilePath, files, requestID); +// String resultPath = fhePatternSearchService.getResultDir() + "/" + requestID + ".ct"; +//// Resource resource = storageService.load(resultPath); +// Path path = Paths.get(resultPath); +// byte[] returnData = Files.readAllBytes(path); +//// fhePatternSearchService.deleteDir(path.toString()); +// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +// } else { +// throw new Exception("Number of files must be smaller than 102"); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +// } + +// @Override +// public ResponseEntity<FHEFileSystem> concateFiles( +// @ApiParam(name = "file1", value = "", example = "", required = true) @RequestParam("file1") FHEFileSystem file1, +// @ApiParam(name = "file2", value = "", example = "", required = true) @RequestParam("file2") FHEFileSystem file2, +// @ApiParam(name = "filename", value = "", example = "", required = true) @RequestParam("filename") String filename) { +// System.out.println("debug 0"); +// logger.info("debug 0"); +// try { +// if (file1.getFormat().equals(file2.getFormat())) { +// FHEFileSystem ffs = new FHEFileSystem(); +// System.out.println("debug 1"); +// logger.info("debug 1"); +// ffs.setContentBase64(file1.getContentBase64() + "#####" + file2.getContentBase64()); +// System.out.println("debug 2"); +// logger.info("debug 2"); +// ffs.setFileName(filename); +// System.out.println("debug 3"); +// logger.info("debug 3"); +// ffs.setFormat(file1.getFormat()); +// System.out.println("debug 4"); +// logger.info("debug 4"); +// return new ResponseEntity<FHEFileSystem>(ffs, HttpStatus.OK); +// } else { +// throw new Exception("The format must be the same"); +// } +// } catch (Exception e) { +// // TODO: handle exception +// e.printStackTrace(); +// } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +// } + +////@Async +//@Override +//public ResponseEntity<byte[]> checkEncryptedFileWDataListAutoBase64( +// @RequestBody AnalyticRequestPayload analyticRequestPayload) { +// try { +// +//// System.out.println(analyticRequestPayload.getFile_extension()); +//// System.out.println(analyticRequestPayload.getIai_files().toString()); +//// System.out.println(analyticRequestPayload.getIai_dpo_metadata().toString()); +// +// String checkFileID = analyticRequestPayload.getIai_params().get("checkFileID"); +// +// String checkFilePath = ""; +// +// System.out.println("checkFileID!!!!!!" + checkFileID.toString()); +// +// List<String> fileInputs = new ArrayList<String>(); +// if (analyticRequestPayload.getIai_files().size() == analyticRequestPayload.getIai_dpo_metadata().size()) { +//// for (String dpoFile : analyticRequestPayload.getIai_files()) { +//// String[] tokens = dpoFile.split("\\.(?=[^\\.]+$)"); +//// System.out.println(analyticRequestPayload.getIai_datalake() + analyticRequestPayload.getIai_dpo_metadata()[] + ".ct"); +//// } +// for (int i = 0; i < analyticRequestPayload.getIai_files().size(); i++) { +// String[] tokens = analyticRequestPayload.getIai_files().get(i).split("\\.(?=[^\\.]+$)"); +//// System.out.println(tokens[0] + "?????" +//// + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString()); +// if (tokens[0].toString() +// .equals(analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString())) { +// System.out.println(analyticRequestPayload.getIai_datalake().toString() + "/" +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension().toString()); +// +// Path path = Paths.get(analyticRequestPayload.getIai_datalake().toString() + "/" +// + analyticRequestPayload.getIai_files().get(i)); +// +// byte[] bytes = Files.readAllBytes(path); +// String fileContent = new String(bytes); +// +//// byte[] byteArray = Base64.decodeBase64(fileContent.getBytes()); +// byte[] byteArray = Base64.decodeBase64(bytes); +// +// String filePath = analyticRequestPayload.getIai_datalake().toString() + "/" +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension().toString(); +// BufferedOutputStream stream = new BufferedOutputStream( +// new FileOutputStream(new File(filePath))); +// stream.write(byteArray); +// stream.close(); +// +// if (analyticRequestPayload.getIai_dpo_metadata().get(i).getId().equals(checkFileID)) { +// +// checkFilePath = analyticRequestPayload.getIai_datalake().toString() + "/" +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension() +// .toString(); +// } else { +// fileInputs.add(analyticRequestPayload.getIai_datalake().toString() + "/" +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." +// + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension() +// .toString()); +// } +// +// } else { +// throw new Exception("Iai_files(" + i + ") id not equals Iai_dpo_metadata size(" + i + ") id"); +// } +// } +// } else { +// throw new Exception("Iai_files size not equals Iai_dpo_metadata size"); +// } +// +// String file2bchecked = checkFilePath; +// +// System.out.println("file2bchecked!!!!!!" + file2bchecked); +// +//// String file2bchecked = fileInputs.get(0); +//// fileInputs.remove(0); +// +//// System.out.println(file2bchecked); +//// System.out.println(fileInputs); +// +// // Set CEA as partnerID +// ResponseEntity<byte[]> response = checkEncryptedFileWDataListAuto(file2bchecked, "CEA", fileInputs); +// byte[] byteArray = response.getBody(); +// byte[] encoded = Base64.encodeBase64(byteArray); +//// println(encoded); // Outputs "SGVsbG8=" +//// System.out.println(encoded); +// String s = new String(encoded, StandardCharsets.UTF_8); +// +//// IaiDPOResponse iaiDPOResponse = new IaiDPOResponse() +// +// return new ResponseEntity<byte[]>(encoded, response.getHeaders(), HttpStatus.OK); +// +//// return new ResponseEntity<byte[]>(encoded, HttpStatus.OK); +//// return new ResponseEntity<byte[]>(encoded, HttpStatus.OK); +// +//// return checkEncryptedFileWDataListAuto(file2bchecked, "CEA", fileInputs); +// +//// MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(); +//// parameters.add("partnerID", "1"); +//// parameters.add("file2bchecked", file2bchecked); +//// parameters.add("dataList", fileInputs); +//// HttpHeaders headers = new HttpHeaders(); +//// RestTemplate restTemplate = new RestTemplate(); +//// +//// System.out.println(fheServerAnalysis); +//// +//// byte[] result = restTemplate.postForObject( +//// fheServerAnalysis + "/openapi/v1/client/generic/checkEncryptedFileWDataList-Auto", +//// new HttpEntity<MultiValueMap<String, Object>>(parameters, headers), byte[].class); +//// return new ResponseEntity<byte[]>(result, HttpStatus.OK); +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +//} + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/HomeController.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/HomeController.java new file mode 100644 index 0000000000000000000000000000000000000000..3b28b1949f2b4564730d02cb251ce42ab104976b --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/controller/HomeController.java @@ -0,0 +1,16 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Home redirection to swagger api documentation + */ +@Controller +public class HomeController { + @RequestMapping(value = "/") + public String index() { + System.out.println("swagger-ui.html"); + return "redirect:swagger-ui.html"; + } +} \ No newline at end of file diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/fhe/CommandExecution.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/fhe/CommandExecution.java new file mode 100644 index 0000000000000000000000000000000000000000..8437f7b0adbc150e5791dc115d2eb406f7e4aaf9 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/fhe/CommandExecution.java @@ -0,0 +1,161 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.fhe; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.FileSystems; +//import java.util.ArrayList; +import java.util.List; + +public class CommandExecution { + + private String sysPath; + private String OS; + + private ProcessBuilder processBuilder; + private Process process; + + public ProcessBuilder getProcessBuilder() { + return processBuilder; + } + + public void setProcessBuilder(ProcessBuilder processBuilder) { + this.processBuilder = processBuilder; + } + + public Process getProcess() { + return process; + } + + public void setProcess(Process process) { + this.process = process; + } + + public CommandExecution() { + this.sysPath = FileSystems.getDefault().getPath("").toAbsolutePath().toString(); + this.OS = System.getProperty("os.name"); + + this.processBuilder = new ProcessBuilder(); + } + + public String getSysPath() { + return sysPath; + } + + public void setSysPath(String sysPath) { + this.sysPath = sysPath; + } + + public String getOS() { + return OS; + } + + public void setOS(String oS) { + OS = oS; + } + + public boolean isWindows() { + return getOS().startsWith("Windows"); + } + + public boolean isUnix() { + return getOS().startsWith("Linux"); + } + +// public String execCm(String command) { +// String content = ""; +// try { +// Process process = Runtime.getRuntime().exec(command); +// +// BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); +// String line; +// while ((line = reader.readLine()) != null) { +// System.out.println(line); +// content = content + "\n" + line; +// } +// reader.close(); +// +// // for debugging +//// BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); +//// while ((line = errorReader.readLine()) != null) { +//// System.out.println(line); +//// content = content + "\n" + line; +//// } +//// errorReader.close(); +// +// } catch (IOException e) { +// e.printStackTrace(); +// } +// return content; +// } + + public boolean destroyProcess() { + if (process != null) { + process.destroy(); + if (process.isAlive()) { + process.destroyForcibly(); + } + return true; + } else { + return false; + } +// if (process.isAlive()) { +// return false; +// } else { +// return true; +// } + } + + public String execCm2(List<String> command, String workDir) { + String content = ""; + + processBuilder.command(command); + processBuilder.directory(new File(workDir)); + + try { + + process = processBuilder.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + content = content + "\n" + line; + } + + int exitCode = process.waitFor(); + System.out.println("\nExited with error code : " + exitCode); + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return content; + } + + // note: write unit tests later +// public static void main(String[] args) { +// +// List<String> command = new ArrayList<>(); +// command.add("./tfhe-license_check-encrypt"); +// command.add("7475"); +// command.add("data/1/"); +// command.add("tfhe.sk"); +// +// +// CommandExecution ce = new CommandExecution(); +// ce.execCm2(command, "/home/hgnguyen/workspace-spring-tool-suite-4-4.9.0.RELEASE/DrivingLicenseCheckingProject/DrivingLicenseDataService/cingulata"); +// +//// String content = ""; +// +//// ProcessBuilder processBuilder = new ProcessBuilder(); +//// processBuilder.command("./tfhe-license_check-encrypt", "8475591", "data/1/", "tfhe.sk"); +//// processBuilder.directory(new File("/home/hgnguyen/Bureau/DrivingLicenseCheck/cingulata")); +// +// } + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Tools.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Tools.java new file mode 100644 index 0000000000000000000000000000000000000000..cfd3057390ba6349366a10cb1ab3420d2498008e --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Tools.java @@ -0,0 +1,181 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.helper; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import fr.cea.bigpi.fhe.dap.patternsearch.model.Description; +import fr.cea.bigpi.fhe.dap.patternsearch.model.ObjectProperty; + +@Component +public class Tools { + + final static Logger logger = LoggerFactory.getLogger(Tools.class); + + private static final Logger log = LoggerFactory.getLogger(Tools.class); + + @Value("${spring.application.datetimeFormat:yyyy-MM-dd HH:mm:ss}") + private String dateTimeFormat; // + + @Value("${spring.application.dateFormat:yyyy-MM-dd}") + private String dateFormat; // + + public Tools() { + dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + dateFormat = "yyyy-MM-dd"; + } + + public void testString() + { + logger.info("Test of testString methode"); + } + + public boolean creatDir(String dirPath) { + File f = new File(dirPath); + // check if the directory can be created + // using the specified path name + if (f.mkdir() == true) { + System.out.println("Directory has been created successfully"); + return true; + } else { + System.out.println("Directory cannot be created"); + return false; + } + } + + public String extractValue(String key, ObjectProperty objProp) { + for (Description element : objProp.getAdditionalProperties()) { + if (element.getMessage().equals(key)) + return element.getValue(); + } + return null; + } + +// public String formatInteger(int integer) +// { +// return integer >= 10 ? "" + integer : "0" + integer; +// } + +// public String dateTimeToString(OffsetDateTime currentDate) +// { +// DateTimeFormatter formatter = +// DateTimeFormatter.ofPattern(dateTimeFormat); +// return currentDate.format(formatter); +// } + +// public OffsetDateTime stringToOffsetDateTime(String currentDate) +// { +// try { +// DateTimeFormatter formatter = +// DateTimeFormatter.ofPattern(dateTimeFormat); +// return OffsetDateTime.parse(currentDate, formatter); +// } catch (DateTimeParseException e) { +// // TODO: handle exception +// } +// return null; +// } + +// public String dateTimeToStringWithTime(LocalDateTime currentDate) +// { +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateTimeFormat); +// return currentDate.format(formatter); +// } + +// public LocalDateTime stringToLocalDateTime(String currentDate) +// { +// SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); +// try { +// Date dateToConvert = sdf.parse(currentDate); +// return Instant.ofEpochMilli(dateToConvert.getTime()) +// .atZone(ZoneId.systemDefault()) +// .toLocalDateTime(); +// } catch (ParseException e) { +// e.printStackTrace(); +// } +// return null; +// } + +// public String dateTimeToString(LocalDateTime currentDate) +// { +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat); +// return currentDate.format(formatter); +// } + +// public LocalDateTime stringToLocalDateWithTime(String currentDate) +// { +// return stringToDateTime(currentDate, dateTimeFormat); +// } + +// private LocalDateTime stringToDateTime(String currentDate, String dateTimeformater) +// { +// LocalDateTime date = null; +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateTimeformater); +// +// try { +// date = LocalDateTime.parse(currentDate, formatter); +// } catch (DateTimeParseException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// return date; +// } + + /** + * @implSpec: get the week of year from the current date + * @param currentDate: this date is format yyyy-MM-dd, the method is not + * supported to the date format yyyy-MM-dd HH:mm:ss + */ +// public int getWeekOfYear(String currentDate) +// { +// LocalDateTime lcCurrentDate = stringToLocalDateTime(currentDate); +// WeekFields weekFields = WeekFields.of(Locale.getDefault()); +// int weekNumber = lcCurrentDate.get(weekFields.weekOfWeekBasedYear()); +// return weekNumber; +// } + +// public LocalDateTime getMonDayFromCurrentDate(LocalDateTime lcCurrentDate) +// { +// return lcCurrentDate.with(DayOfWeek.MONDAY); +// } + +// public LocalDateTime getFirstDayOfCurrentTrimester(Integer year, Integer trimester) { +// String monthDate = "01-01"; //MM-dd +// switch (trimester) { +// case 1: +// monthDate = "01-01"; //MM-dd +// break; +// case 2: +// monthDate = "04-01"; //MM-dd +// break; +// case 3: +// monthDate = "07-01"; //MM-dd +// break; +// case 4: +// monthDate = "10-01"; //MM-dd +// break; +// } +// return stringToLocalDateTime(year + "-"+monthDate); +// } + +// public String genNewPassword() +// { +// int minLength = 8; +// +// String generatedString = RandomStringUtils.randomAlphanumeric(minLength); +// log.debug("String random gen {}", generatedString); +// +// return generatedString; +// } + +// public String extractValue(String key, ObjectProperty objProp) { +// for (Description element : objProp.getAdditionalProperties()) { +// if(element.getMessage().equals(key)) +// return element.getValue(); +// } +// return null; +// } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/ToolsError.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/ToolsError.java new file mode 100644 index 0000000000000000000000000000000000000000..830dc1aa5b8b4dd636a2aa94e93922df2ddd7352 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/ToolsError.java @@ -0,0 +1,25 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.helper; + +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +@Component +public class ToolsError { + + public HttpStatus getHttpStatus(String message) { + int errorCode = Integer.parseInt(message.replace("error", "").trim()); + System.out.println("Error code = " + errorCode); + + HttpStatus httpStatus = HttpStatus.valueOf(errorCode); + return httpStatus; + } + + public String createError (HttpStatus httpStatus) { + return "error " + httpStatus.value(); + } + + + public boolean isError (String message) { + return message != null && message.contains("error"); + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Zip.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Zip.java new file mode 100644 index 0000000000000000000000000000000000000000..cc311aa12595c91f1ba1940326a521ab2e80a72c --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/helper/Zip.java @@ -0,0 +1,149 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.helper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import org.springframework.stereotype.Service; + +@Service +public class Zip { + + public String zipMultipleFiles(String zipDirStr, String fileNameStr, String[] resultPathsStr) throws IOException { + String zipPath = zipDirStr + "/" + fileNameStr + ".zip"; + FileOutputStream fos = new FileOutputStream(zipPath); + ZipOutputStream zipOut = new ZipOutputStream(fos); + for (String srcFile : resultPathsStr) { + File fileToZip = new File(srcFile); + FileInputStream fis = new FileInputStream(fileToZip); + ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); + zipOut.putNextEntry(zipEntry); + byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + fis.close(); + } + zipOut.close(); + fos.close(); + return zipPath; + } + + public ArrayList<String> UnzipFile(String fileZipStr, String destDirStr) throws IOException { + String fileZip = fileZipStr; + File destDir = new File(destDirStr); + byte[] buffer = new byte[1024]; + @SuppressWarnings("resource") + ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip)); + ZipEntry zipEntry = zis.getNextEntry(); + ArrayList<String> extractedFiles = new ArrayList<String>(); + while (zipEntry != null) { + File newFile = newFile(destDir, zipEntry); + extractedFiles.add(newFile.getAbsolutePath()); +// System.out.println("halllooooo!: " + newFile.getAbsolutePath()); + if (zipEntry.isDirectory()) { + if (!newFile.isDirectory() && !newFile.mkdirs()) { + throw new IOException("Failed to create directory " + newFile); + } + } else { + // fix for Windows-created archives + File parent = newFile.getParentFile(); + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IOException("Failed to create directory " + parent); + } + // write file content + FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + } + zipEntry = zis.getNextEntry(); + } + zis.closeEntry(); + zis.close(); + return extractedFiles; + } + + @SuppressWarnings("unused") + private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException { + if (fileToZip.isHidden()) { + return; + } + if (fileToZip.isDirectory()) { + if (fileName.endsWith("/")) { + zipOut.putNextEntry(new ZipEntry(fileName)); + zipOut.closeEntry(); + } else { + zipOut.putNextEntry(new ZipEntry(fileName + "/")); + zipOut.closeEntry(); + } + File[] children = fileToZip.listFiles(); + for (File childFile : children) { + zipFile(childFile, fileName + "/" + childFile.getName(), zipOut); + } + return; + } + FileInputStream fis = new FileInputStream(fileToZip); + ZipEntry zipEntry = new ZipEntry(fileName); + zipOut.putNextEntry(zipEntry); + byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + fis.close(); + } + + public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { + File destFile = new File(destinationDir, zipEntry.getName()); + String destDirPath = destinationDir.getCanonicalPath(); + String destFilePath = destFile.getCanonicalPath(); + if (!destFilePath.startsWith(destDirPath + File.separator)) { + throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); + } + return destFile; + } + +// public void UnzipFile(String fileZipStr, String destDirStr) throws IOException { +// String fileZip = fileZipStr; +// File destDir = new File(destDirStr); +// byte[] buffer = new byte[1024]; +// @SuppressWarnings("resource") +// ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip)); +// ZipEntry zipEntry = zis.getNextEntry(); +// while (zipEntry != null) { +// File newFile = newFile(destDir, zipEntry); +// if (zipEntry.isDirectory()) { +// if (!newFile.isDirectory() && !newFile.mkdirs()) { +// throw new IOException("Failed to create directory " + newFile); +// } +// } else { +// // fix for Windows-created archives +// File parent = newFile.getParentFile(); +// if (!parent.isDirectory() && !parent.mkdirs()) { +// throw new IOException("Failed to create directory " + parent); +// } +// +// // write file content +// FileOutputStream fos = new FileOutputStream(newFile); +// int len; +// while ((len = zis.read(buffer)) > 0) { +// fos.write(buffer, 0, len); +// } +// fos.close(); +// } +// zipEntry = zis.getNextEntry(); +// } +// zis.closeEntry(); +// zis.close(); +//} + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/message/ResponseMessage.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/message/ResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..e7ca1048164038b2b081b5213eb89bef06328895 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/message/ResponseMessage.java @@ -0,0 +1,17 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.message; + +public class ResponseMessage { + private String message; + + public ResponseMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Data.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Data.java new file mode 100644 index 0000000000000000000000000000000000000000..78b466b09b92161aeeaf8ceaad4382818f08fd5e --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Data.java @@ -0,0 +1,281 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model; + +//import javax.persistence.Column; +//import javax.persistence.Entity; +//import javax.persistence.GeneratedValue; +//import javax.persistence.GenerationType; +//import javax.persistence.Id; +//import javax.persistence.Table; +//import java.util.Objects; +//import com.fasterxml.jackson.annotation.JsonProperty; +////import com.fasterxml.jackson.annotation.JsonCreator; +////import io.swagger.annotations.ApiModel; +//import io.swagger.annotations.ApiModelProperty; +//import org.springframework.validation.annotation.Validated; +// +//@Entity +//@Table(name = "data") +//@Validated +//@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2021-06-25T21:18:03.467Z") +//public class Data { +// +// @Id +// @GeneratedValue(strategy = GenerationType.IDENTITY) +// @JsonProperty("dataId") +//// @Column(name = "data_id") +// private Integer dataId = null; +// +// @JsonProperty("dataType") +// private Integer dataType = null; +// +// @JsonProperty("partnerId") +// private String partnerId = null; +// +// @JsonProperty("contractId") +// private String contractId = null; +// +// @Column(columnDefinition = "TEXT", name = "content") +// @JsonProperty("content") +// private String content = null; +// +// @JsonProperty("status") +// private Integer status = null; +// +// @JsonProperty("description") +// private String description = null; +// +// @JsonProperty("createdDate") +// @Column(name = "created_date") +// private String createdDate = null; +// +// @JsonProperty("updatedDate") +// @Column(name = "updated_date") +// private String updatedDate = null; +// +// public Data dataId(Integer dataId) { +// this.dataId = dataId; +// return this; +// } +// +// /** +// * Get dataId +// * +// * @return dataId +// **/ +// @ApiModelProperty(value = "") +// +// public Integer getDataId() { +// return dataId; +// } +// +// public void setDataId(Integer dataId) { +// this.dataId = dataId; +// } +// +// // +// public Data dataType(Integer dataType) { +// this.dataType = dataType; +// return this; +// } +// +// /** +// * Get dataType +// * +// * @return dataType +// **/ +// @ApiModelProperty(value = "") +// +// public Integer getDataType() { +// return dataType; +// } +// +// public void setDataType(Integer dataType) { +// this.dataType = dataType; +// } +// // +// +// public Data partnerId(String partnerId) { +// this.partnerId = partnerId; +// return this; +// } +// +// /** +// * Get partnerId +// * +// * @return partnerId +// **/ +// @ApiModelProperty(value = "") +// +// public String getPartnerId() { +// return partnerId; +// } +// +// public void setPartnerId(String partnerId) { +// this.partnerId = partnerId; +// } +// +// /** +// * Get contractId +// * +// * @return contractId +// **/ +// @ApiModelProperty(value = "") +// +// public String getContractId() { +// return contractId; +// } +// +// public void setContractId(String contractId) { +// this.contractId = contractId; +// } +// +// public Data dataNo(String content) { +// this.content = content; +// return this; +// } +// +// /** +// * Get content +// * +// * @return content +// **/ +// @ApiModelProperty(value = "") +// +// public String getContent() { +// return content; +// } +// +// public void setContent(String content) { +// this.content = content; +// } +// +// public Data status(Integer status) { +// this.status = status; +// return this; +// } +// +// /** +// * Get status +// * +// * @return status +// **/ +// @ApiModelProperty(value = "") +// +// public Integer getStatus() { +// return status; +// } +// +// public void setStatus(Integer status) { +// this.status = status; +// } +// +// public Data description(String description) { +// this.description = description; +// return this; +// } +// +// /** +// * Get description +// * +// * @return description +// **/ +// @ApiModelProperty(value = "") +// +// public String getDescription() { +// return description; +// } +// +// public void setDescription(String description) { +// this.description = description; +// } +// +// public Data createdDate(String createdDate) { +// this.createdDate = createdDate; +// return this; +// } +// +// /** +// * Get createdDate +// * +// * @return createdDate +// **/ +// @ApiModelProperty(value = "") +// +// public String getCreatedDate() { +// return createdDate; +// } +// +// public void setCreatedDate(String createdDate) { +// this.createdDate = createdDate; +// } +// +// public Data updatedDate(String updatedDate) { +// this.updatedDate = updatedDate; +// return this; +// } +// +// /** +// * Get updatedDate +// * +// * @return updatedDate +// **/ +// @ApiModelProperty(value = "") +// +// public String getUpdatedDate() { +// return updatedDate; +// } +// +// public void setUpdatedDate(String updatedDate) { +// this.updatedDate = updatedDate; +// } +// +// @Override +// public boolean equals(java.lang.Object o) { +// if (this == o) { +// return true; +// } +// if (o == null || getClass() != o.getClass()) { +// return false; +// } +// Data data = (Data) o; +// return Objects.equals(this.dataId, data.dataId) && Objects.equals(this.dataType, data.dataType) +// && Objects.equals(this.partnerId, data.partnerId) && Objects.equals(this.contractId, data.contractId) +// && Objects.equals(this.content, data.content) && Objects.equals(this.status, data.status) +// && Objects.equals(this.description, data.description) +// && Objects.equals(this.createdDate, data.createdDate) +// && Objects.equals(this.updatedDate, data.updatedDate); +// } +// +// @Override +// public int hashCode() { +// return Objects.hash(dataId, dataType, partnerId, content, status, description, createdDate, updatedDate); +// } +// +// @Override +// public String toString() { +// StringBuilder sb = new StringBuilder(); +// sb.append("class Data {\n"); +// sb.append(" dataId: ").append(toIndentedString(dataId)).append("\n"); +// sb.append(" dataType: ").append(toIndentedString(dataType)).append("\n"); +// sb.append(" partnerId: ").append(toIndentedString(partnerId)).append("\n"); +// sb.append(" contractId: ").append(toIndentedString(contractId)).append("\n"); +// sb.append(" content: ").append(toIndentedString(content)).append("\n"); +// sb.append(" status: ").append(toIndentedString(status)).append("\n"); +// sb.append(" description: ").append(toIndentedString(description)).append("\n"); +// sb.append(" createdDate: ").append(toIndentedString(createdDate)).append("\n"); +// sb.append(" updatedDate: ").append(toIndentedString(updatedDate)).append("\n"); +// sb.append("}"); +// return sb.toString(); +// } +// +// /** +// * Convert the given object to string with each line indented by 4 spaces +// * (except the first line). +// */ +// private String toIndentedString(java.lang.Object o) { +// if (o == null) { +// return "null"; +// } +// return o.toString().replace("\n", "\n "); +// } +//} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Description.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Description.java new file mode 100644 index 0000000000000000000000000000000000000000..7e86141989242f9b31f5ce1fc4383c4440f85568 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/Description.java @@ -0,0 +1,103 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.*; + +/** + * Description + */ +@Validated +@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2019-11-03T21:01:38.571Z") + +public class Description { + @JsonProperty("message") + private String message = null; + + @JsonProperty("value") + private String value = null; + + public Description message(String message) { + this.message = message; + return this; + } + + /** + * Get message + * + * @return message + **/ + @ApiModelProperty(required = true, value = "") + @NotNull + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Description value(String value) { + this.value = value; + return this; + } + + /** + * Get value + * + * @return value + **/ + @ApiModelProperty(required = true, value = "") + @NotNull + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Description description = (Description) o; + return Objects.equals(this.message, description.message) && Objects.equals(this.value, description.value); + } + + @Override + public int hashCode() { + return Objects.hash(message, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Description {\n"); + + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/FHEFileSystem.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/FHEFileSystem.java new file mode 100644 index 0000000000000000000000000000000000000000..8ccdc035752ed07b5c4c617051e125f6ab752d02 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/FHEFileSystem.java @@ -0,0 +1,153 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model; + +import java.util.Base64; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * @implSpec the file content if use would like to store in plain/text, user should get String and store it directly + * if use want to store in byte, then the content will be convert to Base64 string and save it + * */ + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; + +/** + * FHEFileSystem + */ +@Validated +@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2020-10-06T13:08:21.134Z") +public class FHEFileSystem { + @JsonProperty("fileName") + private String fileName = null; + + @JsonProperty("format") + private String format = null; + + @JsonProperty("contentBase64") + private String contentBase64 = null; + + public FHEFileSystem fileName(String fileName) { + this.fileName = fileName; + return this; + } + + /** + * Get fileName + * @return fileName + **/ + @ApiModelProperty(example = "filename can be empty or not if defined", required = true, value = "") + @NotNull + + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public FHEFileSystem format(String format) { + this.format = format; + return this; + } + + /** + * Get format + * @return format + **/ + @ApiModelProperty(example = "version supported for 'zip', 'tar', '.gz' format", value = "") + + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public FHEFileSystem contentBase64(String contentBase64) { + this.contentBase64 = contentBase64; + return this; + } + + /** + * Get contentBase64 + * @return contentBase64 + **/ + @ApiModelProperty(example = "U3dhZ2dlciByb2Nrcw== (CONTENT in BINARY format : base64-encoded characters)", required = true, value = "") + @NotNull + + + public String getContentBase64() { + return contentBase64; + } + + public void setContentBase64(String contentBase64) { + this.contentBase64 = contentBase64; + } + + + + @JsonIgnore + public byte [] getContentByteArray () { + return Base64.getDecoder().decode(contentBase64.getBytes()); + } + + @JsonIgnore + public void setContentBase64(byte[] content) { + this.contentBase64 = Base64.getEncoder().encodeToString(content); + } + + public FHEFileSystem contentByteArray(byte[] content) { + this.contentBase64 = Base64.getEncoder().encodeToString(content); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FHEFileSystem fhEFileSystem = (FHEFileSystem) o; + return Objects.equals(this.fileName, fhEFileSystem.fileName) && + Objects.equals(this.format, fhEFileSystem.format) && + Objects.equals(this.contentBase64, fhEFileSystem.contentBase64); + } + + @Override + public int hashCode() { + return Objects.hash(fileName, format, contentBase64); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class FHEFileSystem {\n"); + + sb.append(" fileName: ").append(toIndentedString(fileName)).append("\n"); + sb.append(" format: ").append(toIndentedString(format)).append("\n"); + sb.append(" contentBase64: ").append(toIndentedString(contentBase64)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/ObjectProperty.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/ObjectProperty.java new file mode 100644 index 0000000000000000000000000000000000000000..6736a0e47ce3b9678530d2bf0b99ad33307d79d6 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/ObjectProperty.java @@ -0,0 +1,142 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.swagger.annotations.ApiModelProperty; +import org.springframework.validation.annotation.Validated; +import javax.validation.Valid; +import javax.validation.constraints.*; + +/** + * ObjectProperty + */ +@Validated +@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2019-11-03T21:01:38.571Z") + +public class ObjectProperty { + @JsonProperty("sessionId") + private String sessionId = null; + + @JsonProperty("description") + private String description = null; + + @JsonProperty("additionalProperties") + @Valid + private List<Description> additionalProperties = new ArrayList<Description>(); + + public ObjectProperty sessionId(String sessionId) { + this.sessionId = sessionId; + return this; + } + + /** + * Get sessionId + * @return sessionId + **/ + @ApiModelProperty(required = true, value = "") + @NotNull + + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public ObjectProperty description(String description) { + this.description = description; + return this; + } + + /** + * Get description + * @return description + **/ + @ApiModelProperty(required = true, value = "") + @NotNull + + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ObjectProperty additionalProperties(List<Description> additionalProperties) { + this.additionalProperties = additionalProperties; + return this; + } + + public ObjectProperty addAdditionalPropertiesItem(Description additionalPropertiesItem) { + this.additionalProperties.add(additionalPropertiesItem); + return this; + } + + /** + * Get additionalProperties + * @return additionalProperties + **/ + @ApiModelProperty(required = true, value = "") + @NotNull + + @Valid + + public List<Description> getAdditionalProperties() { + return additionalProperties; + } + + public void setAdditionalProperties(List<Description> additionalProperties) { + this.additionalProperties = additionalProperties; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ObjectProperty objectProperty = (ObjectProperty) o; + return Objects.equals(this.sessionId, objectProperty.sessionId) && + Objects.equals(this.description, objectProperty.description) && + Objects.equals(this.additionalProperties, objectProperty.additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(sessionId, description, additionalProperties); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ObjectProperty {\n"); + + sb.append(" sessionId: ").append(toIndentedString(sessionId)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/AnalyticRequestPayload.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/AnalyticRequestPayload.java new file mode 100644 index 0000000000000000000000000000000000000000..ef69ab19b9032486cab3e0198afec0548070dad2 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/AnalyticRequestPayload.java @@ -0,0 +1,119 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.validation.annotation.Validated; + +import com.fasterxml.jackson.annotation.JsonProperty; + +@Validated +public class AnalyticRequestPayload { + @JsonProperty("session_id") + private String session_id; + @JsonProperty("iai_datalake") + private String iai_datalake; + @JsonProperty("iai_datacipher") + private String iai_datacipher; + @JsonProperty("iai_datakey") + private String iai_datakey = null; + @JsonProperty("iai_files") + private List<String> iai_files = new ArrayList<String>(); + @JsonProperty("on_finish_url") + private String on_finish_url; +// IaiParams iai_params; + @JsonProperty("iai_params") + private Map<String, String> iai_params = new HashMap<>(); ; + @JsonProperty("iai_dpo_metadata") + private List<IaiMetadata> iai_dpo_metadata = new ArrayList<IaiMetadata>(); + + // Getter Methods + + public String getSession_id() { + return session_id; + } + + public String getIai_datalake() { + return iai_datalake; + } + + public String getIai_datacipher() { + return iai_datacipher; + } + + public String getIai_datakey() { + return iai_datakey; + } + + public String getOn_finish_url() { + return on_finish_url; + } + + public Map<String, String> getIai_params() { + return iai_params; + } + + public void setIai_params(Map<String, String> iai_params) { + this.iai_params = iai_params; + } + +// public void setIai_params(IaiParams iai_params) { +// this.iai_params = iai_params; +//} + +// public IaiParams getIai_params() { +// return iai_params; +// } + +// public MultiValueMap<String, Object> getIai_params() { +// return iai_params; +// } + + // Setter Methods + + public void setSession_id(String session_id) { + this.session_id = session_id; + } + + public void setIai_datalake(String iai_datalake) { + this.iai_datalake = iai_datalake; + } + + public void setIai_datacipher(String iai_datacipher) { + this.iai_datacipher = iai_datacipher; + } + + public void setIai_datakey(String iai_datakey) { + this.iai_datakey = iai_datakey; + } + + public void setOn_finish_url(String on_finish_url) { + this.on_finish_url = on_finish_url; + } + + public List<String> getIai_files() { + return iai_files; + } + + public void setIai_files(List<String> iai_files) { + this.iai_files = iai_files; + } + + public List<IaiMetadata> getIai_dpo_metadata() { + return iai_dpo_metadata; + } + + public void setIai_dpo_metadata(List<IaiMetadata> iai_dpo_metadata) { + this.iai_dpo_metadata = iai_dpo_metadata; + } +} + +//public class Iai_params { +// +// // Getter Methods +// +// // Setter Methods +// +//} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiMetadata.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiMetadata.java new file mode 100644 index 0000000000000000000000000000000000000000..a512093fc6747f62de18c1e5aa05f3fe2d39c362 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiMetadata.java @@ -0,0 +1,84 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload; + +import org.springframework.validation.annotation.Validated; + +import com.fasterxml.jackson.annotation.JsonProperty; + + +@Validated +public class IaiMetadata { + @JsonProperty("id") + private String id; + @JsonProperty("dsa_id") + private String dsa_id; + @JsonProperty("start_time") + private String start_time; + @JsonProperty("end_time") + private String end_time; + @JsonProperty("event_type") + private String event_type; + @JsonProperty("organization") + private String organization; + @JsonProperty("file_extension") + private String file_extension; + + // Getter Methods + + public String getId() { + return id; + } + + public String getDsa_id() { + return dsa_id; + } + + public String getStart_time() { + return start_time; + } + + public String getEnd_time() { + return end_time; + } + + public String getEvent_type() { + return event_type; + } + + public String getOrganization() { + return organization; + } + + public String getFile_extension() { + return file_extension; + } + + // Setter Methods + + public void setId(String id) { + this.id = id; + } + + public void setDsa_id(String dsa_id) { + this.dsa_id = dsa_id; + } + + public void setStart_time(String start_time) { + this.start_time = start_time; + } + + public void setEnd_time(String end_time) { + this.end_time = end_time; + } + + public void setEvent_type(String event_type) { + this.event_type = event_type; + } + + public void setOrganization(String organization) { + this.organization = organization; + } + + public void setFile_extension(String file_extension) { + this.file_extension = file_extension; + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiParams.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiParams.java new file mode 100644 index 0000000000000000000000000000000000000000..79715fd5cc64ccd80c495123ae3760b3a4c0340f --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiParams.java @@ -0,0 +1,5 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload; + +public class IaiParams { + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiResponse.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..0957f530cc51baa655339bd3cb8b292bb0a0ec15 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/model/analyticRequestPayload/IaiResponse.java @@ -0,0 +1,48 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload; + +import java.util.ArrayList; +import java.util.List; + +public class IaiResponse { + private Boolean success; + private String value; + private List<String> results = new ArrayList<String>(); + + public IaiResponse(Boolean success, String value, List<String> results) { + super(); + this.success = success; + this.value = value; + this.results = results; + } + + public IaiResponse() { + } + + // Getter Methods + + public Boolean getSuccess() { + return success; + } + + public String getValue() { + return value; + } + + // Setter Methods + + public void setSuccess(Boolean success) { + this.success = success; + } + + public void setValue(String value) { + this.value = value; + } + + public List<String> getResults() { + return results; + } + + public void setResults(List<String> results) { + this.results = results; + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/repository/DataRepository.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/repository/DataRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..0ec3b0ad354260a888ad524a73f151bb8b1abe2c --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/repository/DataRepository.java @@ -0,0 +1,8 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.repository; + +//import org.springframework.data.repository.CrudRepository; +//import fr.cea.bigpi.fhe.dap.patternsearch.model.Data; +// +//@org.springframework.stereotype.Repository +//public interface DataRepository extends CrudRepository<Data, Integer> { +//} \ No newline at end of file diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/AnalysisServices.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/AnalysisServices.java new file mode 100644 index 0000000000000000000000000000000000000000..9ad46905f80b2ac637dd64e9017e7374d35c2fb0 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/AnalysisServices.java @@ -0,0 +1,294 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import fr.cea.bigpi.fhe.dap.patternsearch.helper.Tools; +import fr.cea.bigpi.fhe.dap.patternsearch.helper.Zip; +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.AnalyticRequestPayload; +import fr.cea.bigpi.fhe.dap.patternsearch.model.analyticRequestPayload.IaiResponse; + +@Service +public class AnalysisServices { + + @Autowired + FilesStorageService storageService; + + @Autowired + private FHEPatternSearchService fhePatternSearchService; + + @Autowired + Zip zip; + + // 4 E-Corridor Project + @Async + public CompletableFuture<String> startAnalysis(AnalyticRequestPayload analyticRequestPayload, String PartnerId, + String resultName) throws InterruptedException { + + try { + + System.out.println(fhePatternSearchService.toString()); + + String checkFileID = analyticRequestPayload.getIai_params().get("checkFileID"); + + String checkFilePath = ""; + +// System.out.println("checkFileID!!!!!!" + checkFileID.toString()); + + List<String> fileInputs = new ArrayList<String>(); + if (analyticRequestPayload.getIai_files().size() == analyticRequestPayload.getIai_dpo_metadata().size()) { + for (int i = 0; i < analyticRequestPayload.getIai_files().size(); i++) { + String[] tokens = analyticRequestPayload.getIai_files().get(i).split("\\.(?=[^\\.]+$)"); + if (tokens[0].toString() + .equals(analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString())) { + System.out.println(analyticRequestPayload.getIai_datalake().toString() + "/" + + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." + + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension().toString()); + + Path path = Paths.get(analyticRequestPayload.getIai_datalake().toString() + "/" + + analyticRequestPayload.getIai_files().get(i)); + + byte[] bytes = Files.readAllBytes(path); + + byte[] byteArray = Base64.decodeBase64(bytes); + + String filePath = analyticRequestPayload.getIai_datalake().toString() + "/" + + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." + + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension().toString(); + BufferedOutputStream stream = new BufferedOutputStream( + new FileOutputStream(new File(filePath))); + stream.write(byteArray); + stream.close(); + + if (analyticRequestPayload.getIai_dpo_metadata().get(i).getId().equals(checkFileID)) { + + checkFilePath = analyticRequestPayload.getIai_datalake().toString() + "/" + + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." + + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension() + .toString(); + } else { + fileInputs.add(analyticRequestPayload.getIai_datalake().toString() + "/" + + analyticRequestPayload.getIai_dpo_metadata().get(i).getId().toString() + "." + + analyticRequestPayload.getIai_dpo_metadata().get(i).getFile_extension() + .toString()); + } + + } else { + throw new Exception("Iai_files(" + i + ") id not equals Iai_dpo_metadata size(" + i + ") id"); + } + } + } else { + throw new Exception("Iai_files size not equals Iai_dpo_metadata size"); + } + + String file2bchecked = checkFilePath; + + System.out.println("file2bchecked!!!!!!" + file2bchecked); + + // Set CEA as partnerID + byte[] response = checkEncryptedFileWDataListAuto(file2bchecked, "CEA", fileInputs); +// byte[] encoded = Base64.encodeBase64(response); +// String path = analyticRequestPayload.getIai_datalake().toString() + "/" + resultName + ".dpo"; + String path = analyticRequestPayload.getIai_datalake().toString() + "/" + resultName + ".zip"; + + Boolean success = false; + String value = resultName; + List<String> results = new ArrayList<String>(); + + try { +// Files.write(Paths.get(path), encoded); + Files.write(Paths.get(path), response); + results.add(path); + success = true; + + } catch (IOException ex) { + System.out.println("Could not write file, error: " + ex.toString()); + success = false; + } + +// File f = new File(filePathString); +// if(f.exists() && !f.isDirectory()) { +// // do something +// } + + IaiResponse iaiResponse = new IaiResponse(success, value, results); + + sendResultBack(analyticRequestPayload.getOn_finish_url(), iaiResponse); + +// sendByteArray(analyticRequestPayload.getOn_finish_url(), encoded); + + } catch (Exception e) { + e.printStackTrace(); + } + + return CompletableFuture.completedFuture("Admin"); + } + + // 4 E-Corridor Project +// public void sendByteArray(String address, byte[] byteArray) throws URISyntaxException, IOException { +// URI url = new URI(address); +// +// RestTemplate restTemplate = new RestTemplate(); +// ResponseEntity<String> response = restTemplate.postForEntity(url, byteArray, String.class); +// +// System.out.println(response.getStatusCodeValue()); +// System.out.println(response.getBody()); +// } + public void sendResultBack(String address, IaiResponse iaiResponse) throws URISyntaxException, IOException { + URI url = new URI(address); + System.out.println("Send result: " + iaiResponse.getSuccess() + " " + iaiResponse.getValue() + " " + iaiResponse.getResults() ); + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity<String> response = restTemplate.postForEntity(url, iaiResponse, String.class); + +// System.out.println(response.getStatusCodeValue()); +// System.out.println(response.getBody()); + } + + public byte[] checkEncryptedFileWDataListAuto(String file2bchecked, String partnerID, List<String> dataList) { + try { + String requestID = UUID.randomUUID().toString(); + String filename = requestID + ".ct"; + String filePath = file2bchecked; + byte[] bytes = Files.readAllBytes(Paths.get(filePath)); + String path = storageService.getFileDir().toString() + "/" + filename; + Files.write(Paths.get(path), bytes); + + byte[] zipResult = checkEncryptedFileWList(partnerID, requestID, dataList); + return zipResult; + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + static <T> List<List<T>> chopped(List<T> list, final int L) { + List<List<T>> parts = new ArrayList<List<T>>(); + final int N = list.size(); + for (int i = 0; i < N; i += L) { + parts.add(new ArrayList<T>(list.subList(i, Math.min(N, i + L)))); + } + return parts; + } + + public byte[] checkEncryptedFileWList(String partnerID, String requestID, List<String> dataList) { + int vectorSize = 102; + // clean result +// FHEPatternSearchService fhePatternSearchService = new FHEPatternSearchService(); + fhePatternSearchService.deleteDir(fhePatternSearchService.getResultDir() + "requestID" + ".ct"); + // +// List<Data> allData = dataService.getAllData(); + ArrayList<String> data = new ArrayList<String>(); +// for (Data datum : allData) { +// if (datum.getPartnerId().equals(partnerID)) { +//// data.add(datum.getContent() + fhePatternSearchService.getFilename() + ".ct"); +// data.add(datum.getContent() + datum.getDataId() + ".ct"); +// } +// } + data = (ArrayList<String>) dataList; + // + + try { +// if (data.size() > 0 && data.size() <= vectorSize) { +//// String message = ""; +// String fileName = requestID + ".ct"; +// String encryptedFilePath = storageService.getFileDir() + "/" + fileName; +// fhePatternSearchService.checkData(encryptedFilePath, data, requestID); +// String resultPath = fhePatternSearchService.getResultDir() + "/" + requestID + ".ct"; +//// Resource resource = storageService.load(resultPath); +// Path path = Paths.get(resultPath); +// byte[] returnData = Files.readAllBytes(path); +// fhePatternSearchService.deleteDir(path.toString()); +// return new ResponseEntity<byte[]>(returnData, HttpStatus.OK); +// // +// } else if (data.size() > 0 && data.size() > vectorSize) { + + List<List<String>> parts = chopped(data, vectorSize); + String fileName = requestID + ".ct"; +// FilesStorageService storageService = new FilesStorageServiceImpl(); + String encryptedFilePath = storageService.getFileDir() + "/" + fileName; + + String[] resultPaths = new String[parts.size()]; + for (int i = 0; i < parts.size(); i++) { + try { + String outputPath = requestID + "." + (i + 1) + "." + parts.size(); + System.out.println(outputPath); + fhePatternSearchService.checkData(encryptedFilePath, (ArrayList<String>) parts.get(i), outputPath); + +// System.out.println("bug!!!!!!!!!!here!!!!! : " + encryptedFilePath ); + + resultPaths[i] = fhePatternSearchService.getResultDir() + "/" + outputPath + ".ct"; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + ; + + // Check if file exist +// boolean ready = false; +// String strCheckPath = resultPath[(parts.size()-1)]; +// Path checkPath = Paths.get(strCheckPath); +// while (!ready) { +// checkPath = Paths.get(strCheckPath); +// System.out.println(checkPath + " : " + Files.exists(checkPath)); +// if (Files.exists(checkPath)) { +// ready = true; +// } +// } + + // Zip result files - start + Tools tools = new Tools(); + boolean isDirCreated = tools.creatDir(fhePatternSearchService.getResultDir() + "/" + requestID); +// if (isDirCreated) { + +// Zip zip = new Zip(); + String zipResultPath = zip.zipMultipleFiles(fhePatternSearchService.getResultDir() + "/" + requestID, + requestID, resultPaths); + // Zip result files - end + +// for (int i = 0; i < resultPaths.length; i++) { +// fhePatternSearchService.deleteDir(resultPaths[i]); +// } + + Path path = Paths.get(zipResultPath); + byte[] returnData = Files.readAllBytes(path); +// fhePatternSearchService.deleteDir(path.toString()); + +// HttpHeaders responseHeaders = new HttpHeaders(); +// responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION, +// // for direct downlad "inline", for "save as" dialog "attachment" (browser +// // dependent) +// String.format("attachment; filename=\"" + requestID + ".zip\"")); + + return returnData; + +// } else { +// throw new Exception("Could not created the directory"); +// } + } catch (Exception e) { + e.printStackTrace(); + } +// return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + return null; + } + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/DataService.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/DataService.java new file mode 100644 index 0000000000000000000000000000000000000000..98c57df347e5a591b9dd9c123092f7f3c5f8bb6f --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/DataService.java @@ -0,0 +1,57 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +//import java.time.LocalDate; +//import java.util.ArrayList; +//import java.util.List; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +//import fr.cea.bigpi.fhe.dap.patternsearch.model.Data; +//import fr.cea.bigpi.fhe.dap.patternsearch.repository.DataRepository; +// +//@Service +//public class DataService { +// +// @Autowired +// DataRepository dataRepository; +// +// // getting all data by using the method findaAll() of CrudRepository +// public List<Data> getAllData() { +// List<Data> data = new ArrayList<Data>(); +// dataRepository.findAll().forEach(datum -> data.add(datum)); +// return data; +// } +// +// // getting a specific item by using the method findById() of CrudRepository +// public Data getDataById(int id) { +//// return dataRepository.findById(id).get(); +// return dataRepository.findOne(id); +// } +// +// public Data saveOrUpdate(String dataNo, String partnerID, Integer status, String description) { +// Data data = new Data(); +// data.setStatus(status); +// data.setDescription(description); +// data.setCreatedDate(LocalDate.now().toString()); +// data.setPartnerId(partnerID); +// data = saveOrUpdate(data); +// return data; +// } +// +// // saving a specific item by using the method save() of CrudRepository +// public Data saveOrUpdate(Data data) { +// return dataRepository.save(data); +// } +// +// // deleting a specific item by using the method deleteById() of CrudRepository +// public void delete(int id) { +//// dataRepository.deleteById(id); +// dataRepository.delete(id); +// } +// +// // updating a item by using the method save() of CrudRepository +// public void update(Data data, int dataid) { +// data.setDataId(dataid); +// dataRepository.save(data); +// } +// +//} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEPatternSearchService.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEPatternSearchService.java new file mode 100644 index 0000000000000000000000000000000000000000..1bbe102f697adcc0ab730608cb1e52e52f22fcd1 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEPatternSearchService.java @@ -0,0 +1,251 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import fr.cea.bigpi.fhe.dap.patternsearch.fhe.CommandExecution; + + +@Service +public class FHEPatternSearchService { + @Value("${application.seal.sealDir}") + private String sealDir; + @Value("${application.seal.dataDir}") + private String dataDir; + @Value("${application.seal.resultDir}") + private String resultDir; + @Value("${application.seal.keyDir}") + private String keyDir; + @Value("${application.seal.uploadDir}") + private String uploadDir; + @Value("${application.seal.sample}") + private int sample; + @Value("${application.seal.filename}") + private String filename; + @Value("${application.seal.encryptPath}") + private String encryptPath; + @Value("${application.seal.decryptPath}") + private String decryptPath; + @Value("${application.seal.decrypCheckedResulttPath}") + private String decrypCheckedResulttPath; + @Value("${application.seal.evaluatePath}") + private String evaluatePath; + + // Bash execution library + CommandExecution ce; + // HE parameters + + + @PostConstruct + public void init() { + this.ce = new CommandExecution(); + } + + public String encrypt(String content, String dir, String filename) { + System.out.println("HE Engine: Encrypting vector.... start"); + List<String> command = Arrays.asList(encryptPath, content, filename, dir, String.valueOf(sample), keyDir); + System.out.println("HE Engine: Encrypting vector.... end"); + return ce.execCm2(command, sealDir); + } + + public String decrypt(String dir, String filename) throws Exception { + System.out.println("HE Engine: Decrypting vector.... start"); + List<String> command = Arrays.asList(decryptPath, dir + filename + ".ct", String.valueOf(sample), keyDir); + String result_string = ce.execCm2(command, sealDir); + if (!result_string.isEmpty()) { + System.out.println(result_string); + result_string = convertASCII2Data(result_string); + System.out.println("HE Engine: Decrypting vector.... end"); + return result_string; + } else { + System.out.println("The return result is empty! Vector decrypting failed! \n " + + "HE Engine: Decrypting vector....end"); + return dir; + } + } + + public String createDir(String dir) { + System.out.println("HE Engine: Creating directories...."); + List<String> command = Arrays.asList("mkdir", "-p", dir); + return ce.execCm2(command, sealDir); + } + + public String deleteDir(String dir) { + System.out.println("HE Engine: Deleting " + dir + "...."); + List<String> command = Arrays.asList("rm", "-r", dir); + return ce.execCm2(command, sealDir); + } + + public String createDataDir(String uniqueID) { + String path = dataDir + uniqueID + "/"; + createDir(path); + System.out.println("HE Engine: Creating directory: " + path + "...."); + return path; + } + + // Create data with randomUUID name + public String createUUID4Data(String content, String filename) { + String uniqueID = UUID.randomUUID().toString(); + String path = dataDir + uniqueID + "/"; + createDir(path); + System.out.println("HE Engine: Creating directory: " + path + "...."); + content = convertData2ASCII(content); + System.out.println(content); + encrypt(content, path, filename); + return path; + } + + // Create DBID for data + public String createID4Data(String content, int id) { + String uniqueID = String.valueOf(id); + String path = dataDir + uniqueID + "/"; + createDir(path); + System.out.println("HE Engine: Creating data in " + path + "...."); + content = convertData2ASCII(content); + System.out.println(content); + encrypt(content, path, uniqueID); + return path; + } + + public String createData(String content, String dir, String filename) { + System.out.println("HE Engine: Creating data in " + dir + "...."); + createDir(dir); + content = convertData2ASCII(content); + encrypt(content, dir, filename); + return dir; + } + + public static String convertData2ASCII(String content) { + System.out.println("HE Engine: Converting content string to ASCII...."); + byte[] ascii = content.getBytes(StandardCharsets.US_ASCII); + String asciiString = Arrays.toString(ascii); + asciiString = asciiString.replace("[", "").replace("]", "").replace(", ", " "); + return asciiString; + } + + public static String convertASCII2Data(String asciiString) { + System.out.println("HE Engine: Converting ASCII to content string...." + asciiString); + String[] asciiStringSplited = asciiString.replace("\n", "").split("\\s+"); + int size = asciiStringSplited.length; + byte[] asciiArray = new byte[size]; + + for (int i = 0; i < size; i++) { + // Try to fix this warning later !!!! + try { + asciiArray[i] = (byte) Integer.parseInt(asciiStringSplited[i]); + } catch (NumberFormatException ex) { // handle your exception + // Print something + } + } + + String content = new String(asciiArray, StandardCharsets.US_ASCII); + // remove zero padding + content = content.replaceAll("\u0000", ""); + return content; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public String decryptCheckResult(String dir) throws Exception { + System.out.println("HE Engine: Decrypting HE muti-bit array.... start"); + List<String> command = Arrays.asList(decrypCheckedResulttPath, dir, String.valueOf(sample), keyDir); + String result_string = ce.execCm2(command, sealDir); + if (!result_string.isEmpty()) { + System.out.println(result_string); + System.out.println("HE Engine: Decrypting vector.... end"); + return result_string; + } else { + System.out.println("The return result is empty! Vector decrypting failed! \n " + + "HE Engine: Decrypting vector....end"); + return dir; + } + } + + public boolean checkData(String source, ArrayList<String> data, String filename) throws Exception { + System.out.println("HE Engine: Checking data in " + source + " and " + data + "...."); + ArrayList<String> cm = new ArrayList<>(); + cm.add(evaluatePath); + cm.add(source); + cm.addAll(data); + cm.add(filename); + cm.add(resultDir); + cm.add(String.valueOf(sample)); + cm.add(keyDir); + List<String> command = cm; + System.out.println(resultDir); + String result_string = ce.execCm2(command, sealDir); + if (result_string == "done") { + return true; + } else { + return false; + } + } + + public boolean stopChecking() { + return ce.destroyProcess(); + } + + + public String getSealDir() { + return sealDir; + } + + public void setSealDir(String sealDir) { + this.sealDir = sealDir; + } + + public String getResultDir() { + return resultDir; + } + + public void setResultDir(String resultDir) { + this.resultDir = resultDir; + } + + public String getUploadDir() { + return uploadDir; + } + + public void setUploadDir(String uploadDir) { + this.uploadDir = uploadDir; + } + + public String getDataDir() { + return dataDir; + } + + public void setDataDir(String dataDir) { + this.dataDir = dataDir; + } + + public String getKeyDir() { + return keyDir; + } + + public void setKeyDir(String keyDir) { + this.keyDir = keyDir; + } + + public int getSample() { + return sample; + } + + public void setSample(int sample) { + this.sample = sample; + } + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEService.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEService.java new file mode 100644 index 0000000000000000000000000000000000000000..098e536dd782751f695a3dc97cba5d17bd033d04 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FHEService.java @@ -0,0 +1,65 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +import java.io.File; +import java.io.IOException; + +import org.codehaus.groovy.control.CompilationFailedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; + +//import fr.cea.bigpi.fhe.dap.patternsearch.repository.DataRepository; +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import groovy.lang.Script; + +@Service +public class FHEService { + + protected Logger logger = LoggerFactory.getLogger(FHEService.class.getName()); + private String appName; // a way to get the default parameter from application.yml + +// @Autowired +// DataRepository drivingLicenseRepository; +// @Autowired private FHEPatternSearchService seal; + + @Autowired + public FHEService(@Value("${spring.application.name}") String appName) { + this.appName = appName; + } + + @HystrixCommand(groupKey = "FHE_Service", commandKey = "FHE_PingService", fallbackMethod = "defaultPing") + public String ping(String userName) { + + return appName + " say <" + userName + ">"; + } + + public String defaultPing(String name, Throwable exception) { + logger.info("callling from fallback Ping"); + logger.error("real exception : {}", exception.getMessage()); + return appName + "RuntimeException ! from instance to say Hello <" + name + ">"; + } + + @HystrixCommand(groupKey = "FHE_Service", commandKey = "FHE_AplusBService", fallbackMethod = "defaultAplusB") + public String fhe_executor(String a, String b) throws CompilationFailedException, IOException { + Binding binding = new Binding(); + GroovyShell shell = new GroovyShell(binding); + Script scrpt = shell.parse(new File("src/main/groovy/executor.groovy")); + + binding.setVariable("a", a); + binding.setVariable("b", b); + binding.setVariable("tools", scrpt); + + String res = (String) shell.evaluate("tools.fhe_aplusb(a, b)"); + return res; + } + + public String defaultAplusB(String a, String b, Throwable error) { + logger.error("real exception wheen executing a+b : {}", error.getMessage()); + return null; + } +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageService.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageService.java new file mode 100644 index 0000000000000000000000000000000000000000..e422ccdf90fbf51304942c637b4c0142267c1d57 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageService.java @@ -0,0 +1,28 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +import java.nio.file.Path; +import java.util.stream.Stream; + +import org.springframework.core.io.Resource; +import org.springframework.web.multipart.MultipartFile; + +public interface FilesStorageService { + public void init(); + + public void save(MultipartFile file); + + public void save(MultipartFile file, String filename); + + public void saveAll(MultipartFile[] file); + + public Resource load(String filename); + + public void deleteAll(); + + public Stream<Path> loadAll(); + + public Path getFileDir(); + + public void setFileDir(Path fileDir); +} + diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageServiceImpl.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..2700e795ca55ba3f8c86aa0227640c767cd4a964 --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/service/FilesStorageServiceImpl.java @@ -0,0 +1,154 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.service; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.stereotype.Service; +import org.springframework.util.FileSystemUtils; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class FilesStorageServiceImpl implements FilesStorageService { + + @Value("${application.seal.uploadDir}") + private String fileDirStr; + // = "/home/hgnguyen/Desktop/seal/upload/"; + private Path fileDir; //= Paths.get(fileDirStr); + + @PostConstruct public void initService() + { + fileDir = Paths.get(fileDirStr); + } + + @Override + public void setFileDir(Path fileDir) { + this.fileDir = fileDir; + } + + @Override + public Path getFileDir() { + return fileDir; + } + + @Override + public void init() { + try { + Files.createDirectory(fileDir); + System.out.println(fileDir.toString()); + } catch (IOException e) { + throw new RuntimeException("Could not initialize folder for upload!"); + } + } + + @Override + public void save(MultipartFile file) { + try { + Files.copy(file.getInputStream(), this.fileDir.resolve(file.getOriginalFilename())); + } catch (Exception e) { + throw new RuntimeException("Could not store the file. Error: " + e.getMessage()); + } + } + + public void save(MultipartFile file, String filename) { + try { + Files.copy(file.getInputStream(), this.fileDir.resolve(filename)); + } catch (Exception e) { + throw new RuntimeException("Could not store the file. Error: " + e.getMessage()); + } + } + + @Override + public void saveAll(MultipartFile[] files) { + // TODO Auto-generated method stub + for (MultipartFile file : files) { + save(file); + } + } + + @Override + public Resource load(String filename) { + try { + Path file = fileDir.resolve(filename); + Resource resource = new UrlResource(file.toUri()); + + if (resource.exists() || resource.isReadable()) { + return resource; + } else { + throw new RuntimeException("Could not read the file!"); + } + } catch (MalformedURLException e) { + throw new RuntimeException("Error: " + e.getMessage()); + } + } + + @Override + public void deleteAll() { + FileSystemUtils.deleteRecursively(fileDir.toFile()); + } + + @Override + public Stream<Path> loadAll() { + try { + return Files.walk(this.fileDir, 1).filter(path -> !path.equals(this.fileDir)).map(this.fileDir::relativize); + } catch (IOException e) { + throw new RuntimeException("Could not load the files!"); + } + } + + public static File createEmptyFile(String dir, MultipartFile multipartFile, String name) { + String originalName = multipartFile.getOriginalFilename(); + File file = new File(dir + originalName); + try { + final boolean newFile = file.createNewFile(); + if (newFile) { + return file; + } + throw new IOException("Could not save empty file!"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static void saveContain(MultipartFile multipartFile, File file) { + + // Creates a file stream of the file created. + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + // If the stream of files is not null then it passes the data of the file passed. + if (fileOutputStream != null) { + try { + fileOutputStream.write(multipartFile.getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Closes the file stream. + try { + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/tools/BashTools.java b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/tools/BashTools.java new file mode 100644 index 0000000000000000000000000000000000000000..2e3b48fa2efd8698787542419e3d31902166086f --- /dev/null +++ b/src/main/java/fr/cea/bigpi/fhe/dap/patternsearch/tools/BashTools.java @@ -0,0 +1,171 @@ +package fr.cea.bigpi.fhe.dap.patternsearch.tools; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class encapsulates the execution of shell commands. + * + */ +public class BashTools { + + private static final Logger log = LoggerFactory.getLogger(BashTools.class); + + public static boolean Exec( + boolean isShowLog, + boolean isWithBash, + String script1, + String script2, + String script3, + String script4, + String script5, + String script6, + String script7, + String script8, + String script9) + { + if(isShowLog) log.info("Starting exec inputs paramaters"); + Process childExec = null; + String bash = "/bin/bash"; + + log.info(String.format("%s %s %s %s %s %s %s %s %s %s %s\n", "Start Exec String Params:", + isWithBash ? bash : "", script1, script2, script3, + script4, script5, script6, + script7, script8, script9)); + + try { + if(script2.length() == 0) + childExec = new ProcessBuilder(script1).start(); + else if(script3.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2).start(); + else + childExec = new ProcessBuilder(script1, script2).start(); + } + else if(script4.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3).start(); + else + childExec = new ProcessBuilder(script1, script2, script3).start(); + } + else if(script5.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4).start(); + } + else if(script6.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4, script5).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4, script5).start(); + } + else if(script7.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4, script5, script6).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4, script5, script6).start(); + } + else if(script8.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4, script5, script6, script7).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4, script5, script6, script7).start(); + } + else if(script8.length() == 0) { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4, script5, script6, script7, script8).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4, script5, script6, script7, script8).start(); + } + else { + if(isWithBash) + childExec = new ProcessBuilder(bash, script1, script2, script3, script4, script5, script6, script7, script8, script9).start(); + else + childExec = new ProcessBuilder(script1, script2, script3, script4, script5, script6, script7, script8, script9).start(); + } + int code = childExec.waitFor(); + + if(isShowLog) + { + BufferedReader output = new BufferedReader( + new InputStreamReader(childExec.getInputStream())); + String line = null; + while ((line = output.readLine()) != null) + log.info("Exec output > " + line); + } + log.info(String.format("%s %d %s %s %s %s %s %s %s %s %s %s %s\n", "End with code :", code, " Exec String Params:", + isWithBash ? bash : "", script1, script2, script3, + script4, script5, script6, + script7, script8, script9)); + } + catch (SecurityException e) + { + e.printStackTrace(); + log.error("SecurityException ERROR exec script : " + e.toString()); + return false; + } + catch (InterruptedException e) + { + e.printStackTrace(); + log.error("InterruptedException ERROR exec script : " + e.toString()); + return false; + } catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + log.error("IOException ERROR exec script : " + e.toString()); + return false; + } + return true; + } + + public static boolean Exec( + boolean isWithBash, + String script1, + String script2, + String script3, + String script4, + String script5, + String script6, + String script7, + String script8, + String script9) { + return Exec(false, isWithBash, script1, script2, script3, script4, script5, script6, script7, script8, script9); + } + + public static boolean Exec(boolean isWithBash, String script1, String script2, String script3, String script4, + String script5, String script6, String script7, String script8) + { + return Exec(isWithBash, script1, script2, script3, script4, script5, script6, script7, script8, ""); + } + + public static boolean Exec( boolean isWithBash, String script1, String script2, String script3, String script4, String script5, String script6, String script7) + { + return Exec(isWithBash, script1, script2, script3, script4, script5, script6, script7, "", ""); + } + public static boolean Exec(boolean isWithBash, String script1, String script2, String script3, String script4, String script5, String script6) + { + return Exec(isWithBash, script1, script2, script3, script4, script5, script6, "", "", ""); + } + public static boolean Exec(boolean isWithBash, String script1, String script2, String script3, String script4, String script5) + { + return Exec(isWithBash, script1, script2, script3, script4, script5, "", "", "", ""); + } + public static boolean Exec(boolean isWithBash, String script1, String script2, String script3, String script4) + { + return Exec(isWithBash, script1, script2, script3, script4, "", "", "", "", ""); + } + public static boolean Exec(boolean isWithBash, String script1, String script2, String script3) + { + return Exec(isWithBash, script1, script2, script3, "", "", "", "", "", ""); + } + public static boolean Exec(boolean isWithBash, String script1, String script2) + { + return Exec(isWithBash, script1, script2, "", "", "", "", "", "", ""); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..95c7b295b04cd3849f52770d6d5b01b5f73ae043 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,103 @@ +server: + port: ${PORT:9191} + servlet: + session: + timeout: 18000 # Session timeout. If a duration suffix is not specified, seconds is used. +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +#use for admin client +management: + security: + enabled: false + +application: + seal: +# For Docker Only - Begin + sealDir: /opt/bigpiseal3.5.1/bin/patternSearch/v2 +# storageDir: /storage +# keyDir: /keys/ +# dataDir: ${application.seal.storageDir}/data/ +# resultDir: ${application.seal.storageDir}/result/ +# uploadDir: ${application.seal.storageDir}/upload/ +# For Docker Only - End +# For Local Only - Begin +# sealDir: /home/hgnguyen/Desktop/seal/PatternSearch + dataDir: ${application.seal.sealDir}/data/ + resultDir: ${application.seal.sealDir}/result/ + uploadDir: ${application.seal.sealDir}/upload/ + keyDir: ${application.seal.sealDir}/keys/ +# For Local Only - End + sample: 40 + filename: l + encryptPath: ${application.seal.sealDir}/patternSearch_encrypt_v2 + decryptPath: ${application.seal.sealDir}/patternSearch_decrypt_v2 + decrypCheckedResulttPath: ${application.seal.sealDir}/patternSearch_decrypt_result_v2 + evaluatePath: ${application.seal.sealDir}/patternSearch_evaluate_v2 + +#spring: +# datasource: +# driver-class-name: org.postgresql.Driver +# url: jdbc:postgresql://localhost:5432/patternSearchdb +# username: postgres +# password: 123 + +# datasource: +# url: jdbc:postgresql://10.8.34.73:5432/PatternSearch +# username: postgres +# password: bigpi!123! + +# jpa: +# hibernate.ddl-auto: update +# show-sql: true +# properties: +# hibernate: +# dialect: org.hibernate.dialect.PostgreSQLDialect +## format_sql: true + +#logging.level.org.hibernate.SQL: DEBUG +#logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +#filesStorageServiceConfig: +# fileDirStr: /home/hgnguyen/Desktop/seal/upload/ + +#seal: +# sealDir: /home/hgnguyen/Desktop/seal/ +# dataDir: /home/hgnguyen/Desktop/seal/data/ +# resultDir: /home/hgnguyen/Desktop/seal/result/ +# keyDir: /home/hgnguyen/Desktop/seal/keys/ +# uploadDir: /home/hgnguyen/Desktop/seal/upload/ +# sample: 40 +# filename: l + +# seal: +# sealDir: /opt/fhe/datalake/seal +## sealDir: /opt/fhe/seal/bin/patternSearch +# dataDir: ${application.seal.sealDir}/data/ +# resultDir: ${application.seal.sealDir}/result/ +# uploadDir: ${application.seal.sealDir}/upload/ +# sample: 40 +# filename: l +# keyDir: ${application.seal.sealDir}/keys/ +# +## patternSearchBin: /opt/fhe/datalake/seal +# patternSearchBin: /opt/fhe/seal/bin/patternSearch +# encryptPath: ${application.seal.patternSearchBin}/patternSearch_encrypt_v2 +# decryptPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_v2 +# decrypCheckedResulttPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_result_v2 +# evaluatePath: ${application.seal.patternSearchBin}/patternSearch_evaluate_v2 +## keyDir: ${application.seal.patternSearchBin}/keys/ + + \ No newline at end of file diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000000000000000000000000000000000000..aac0dccc59aa2b402e8de113a6ec8e274239d1a3 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,5 @@ +============================= + +DMP FHE-PTTERN SEARCH SERVICE STARTING + +============================= \ No newline at end of file diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000000000000000000000000000000000..b221f86e24848fa063e67326f46b38cd5cb31ed0 --- /dev/null +++ b/src/main/resources/bootstrap.yml @@ -0,0 +1,32 @@ +--- +spring: + application: + name: dap-patternsearch-checker-service + +logging: + level: + ROOT: INFO + org.springframework.cloud.config: ${LOG:DEBUG} +#--- +#spring: +# profiles: cea +# cloud: +# config: +# uri: http://192.168.1.201:9498 +# +#--- +#spring: +# profiles: dev +# cloud: +# config: +# uri: http://192.168.0.203:9398 +# #uri: http://192.168.0.26:9498 +# +#--- +#spring: +# profiles: prod +# cloud: +# config: +# uri: http://152.228.167.133:9498 + + diff --git a/src/main/resources/bootstrap.yml.old b/src/main/resources/bootstrap.yml.old new file mode 100644 index 0000000000000000000000000000000000000000..4b1a9c439631f837873541d7e8a24a1e93fa36f6 --- /dev/null +++ b/src/main/resources/bootstrap.yml.old @@ -0,0 +1,20 @@ +--- +spring: + application: + name: dmp-mem-service + +--- +spring: + profiles: dev + config: + label: master + cloud: + config: + uri: http://192.168.0.23:9098 + +--- +spring: + profiles: prod + cloud: + config: + uri: todo diff --git a/src/main/resources/dap-patternsearch-checker-service-cea.yml b/src/main/resources/dap-patternsearch-checker-service-cea.yml new file mode 100644 index 0000000000000000000000000000000000000000..0b11a7584b11328054abf75af49cacec3dce4dab --- /dev/null +++ b/src/main/resources/dap-patternsearch-checker-service-cea.yml @@ -0,0 +1,83 @@ +server: + servlet: + session: + timeout: 1800 # Session timeout. If a duration suffix is not specified, seconds is used. + +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +#use for admin client +management: + security: + enabled: false + +#spring: +# datasource: +# driver-class-name: org.postgresql.Driver +# url: jdbc:postgresql://localhost:5432/patternSearchdb +# username: postgres +# password: 123 +# datasource: +# url: jdbc:postgresql://10.8.34.73:5432/PatternSearch +# username: postgres +# password: bigpi!123! + +# jpa: +# hibernate.ddl-auto: update +# show-sql: true +# properties: +# hibernate: +# dialect: org.hibernate.dialect.PostgreSQLDialect +## format_sql: true + + +#logging.level.org.hibernate.SQL: DEBUG +#logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + + +#filesStorageServiceConfig: +# fileDirStr: /home/hgnguyen/Desktop/seal/upload/ + +#seal: +# sealDir: /home/hgnguyen/Desktop/seal/ +# dataDir: /home/hgnguyen/Desktop/seal/data/ +# resultDir: /home/hgnguyen/Desktop/seal/result/ +# keyDir: /home/hgnguyen/Desktop/seal/keys/ +# uploadDir: /home/hgnguyen/Desktop/seal/upload/ +# sample: 40 +# filename: l + + +application: + seal: +# sealDir: /opt/fhe/datalake/seal + sealDir: /opt/fhe/seal/bin/patternSearch + dataDir: ${application.seal.sealDir}/data/ + resultDir: ${application.seal.sealDir}/result/ + uploadDir: ${application.seal.sealDir}/upload/ + sample: 40 + filename: l + keyDir: ${application.seal.sealDir}/keys/ +# patternSearchBin: /opt/fhe/datalake/seal + patternSearchBin: /opt/fhe/seal/bin/patternSearch + encryptPath: ${application.seal.patternSearchBin}/patternSearch_encrypt_v2 + decryptPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_v2 + decrypCheckedResulttPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_result_v2 + evaluatePath: ${application.seal.patternSearchBin}/patternSearch_evaluate_v2 +# keyDir: ${application.seal.patternSearchBin}/keys/ + + + + \ No newline at end of file diff --git a/src/main/resources/dap-patternsearch-checker-service-prod.yml b/src/main/resources/dap-patternsearch-checker-service-prod.yml new file mode 100644 index 0000000000000000000000000000000000000000..0b11a7584b11328054abf75af49cacec3dce4dab --- /dev/null +++ b/src/main/resources/dap-patternsearch-checker-service-prod.yml @@ -0,0 +1,83 @@ +server: + servlet: + session: + timeout: 1800 # Session timeout. If a duration suffix is not specified, seconds is used. + +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +#use for admin client +management: + security: + enabled: false + +#spring: +# datasource: +# driver-class-name: org.postgresql.Driver +# url: jdbc:postgresql://localhost:5432/patternSearchdb +# username: postgres +# password: 123 +# datasource: +# url: jdbc:postgresql://10.8.34.73:5432/PatternSearch +# username: postgres +# password: bigpi!123! + +# jpa: +# hibernate.ddl-auto: update +# show-sql: true +# properties: +# hibernate: +# dialect: org.hibernate.dialect.PostgreSQLDialect +## format_sql: true + + +#logging.level.org.hibernate.SQL: DEBUG +#logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + + +#filesStorageServiceConfig: +# fileDirStr: /home/hgnguyen/Desktop/seal/upload/ + +#seal: +# sealDir: /home/hgnguyen/Desktop/seal/ +# dataDir: /home/hgnguyen/Desktop/seal/data/ +# resultDir: /home/hgnguyen/Desktop/seal/result/ +# keyDir: /home/hgnguyen/Desktop/seal/keys/ +# uploadDir: /home/hgnguyen/Desktop/seal/upload/ +# sample: 40 +# filename: l + + +application: + seal: +# sealDir: /opt/fhe/datalake/seal + sealDir: /opt/fhe/seal/bin/patternSearch + dataDir: ${application.seal.sealDir}/data/ + resultDir: ${application.seal.sealDir}/result/ + uploadDir: ${application.seal.sealDir}/upload/ + sample: 40 + filename: l + keyDir: ${application.seal.sealDir}/keys/ +# patternSearchBin: /opt/fhe/datalake/seal + patternSearchBin: /opt/fhe/seal/bin/patternSearch + encryptPath: ${application.seal.patternSearchBin}/patternSearch_encrypt_v2 + decryptPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_v2 + decrypCheckedResulttPath: ${application.seal.patternSearchBin}/patternSearch_decrypt_result_v2 + evaluatePath: ${application.seal.patternSearchBin}/patternSearch_evaluate_v2 +# keyDir: ${application.seal.patternSearchBin}/keys/ + + + + \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..5d03f79413815de8cfffdc114e57b1cc53b68be4 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <include resource="org/springframework/boot/logging/logback/base.xml"/> + <!-- Required for Loglevel managment into the Spring Petclinic Admin Server--> + <jmxConfigurator/> +</configuration> diff --git a/src/main/resources/logback_xml b/src/main/resources/logback_xml new file mode 100644 index 0000000000000000000000000000000000000000..5db64d490d37f76fd3c2ff247f27940f4de5c628 --- /dev/null +++ b/src/main/resources/logback_xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration debug="false"> + <property scope="context" name="logger.type" value="transfer-service"/> + <include resource="org/springframework/boot/logging/logback/base.xml" /> + <appender name="STASH" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>/opt/deployment/dmp/dmp-mem-service.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>/opt/deployment/dmp/dmp-mem-service.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>7</maxHistory> + </rollingPolicy> + <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> + </appender> + <root level="INFO"> + <appender-ref ref="STASH" /> + </root> + <logger name="org.springframework" level="INFO"/> +</configuration> \ No newline at end of file diff --git a/src/main/resources/patternSearch.sql b/src/main/resources/patternSearch.sql new file mode 100644 index 0000000000000000000000000000000000000000..45421993d22ff9f3aa1fd39ea09438d271d2644d --- /dev/null +++ b/src/main/resources/patternSearch.sql @@ -0,0 +1,25 @@ +-- Database: patternSearchdb + +-- DROP DATABASE patternSearchdb; + +CREATE DATABASE patternSearchdb + WITH + OWNER = postgres + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.UTF-8' + LC_CTYPE = 'en_US.UTF-8' + TABLESPACE = pg_default + CONNECTION LIMIT = -1; + +CREATE TABLE IF NOT EXISTS public.driving_license +( + driving_license_id integer NOT NULL DEFAULT nextval('driving_license_driving_license_id_seq'::regclass), + created_date character varying(255) COLLATE pg_catalog."default", + description character varying(255) COLLATE pg_catalog."default", + driving_license_no character varying(255) COLLATE pg_catalog."default", + partnerid character varying(255) COLLATE pg_catalog."default", + status integer, + updated_date character varying(255) COLLATE pg_catalog."default", + partner_id character varying(255) COLLATE pg_catalog."default", + CONSTRAINT driving_license_pkey PRIMARY KEY (driving_license_id) +) diff --git a/src/test/java/fr/cea/bigpi/fhe/repository/test/SampleRepositoryTest.java b/src/test/java/fr/cea/bigpi/fhe/repository/test/SampleRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..52cb4a43edf5c488774d54c5ce943524b944a33b --- /dev/null +++ b/src/test/java/fr/cea/bigpi/fhe/repository/test/SampleRepositoryTest.java @@ -0,0 +1,89 @@ +package fr.cea.bigpi.fhe.repository.test; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import org.codehaus.groovy.control.CompilationFailedException; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +import fr.cea.bigpi.fhe.dap.patternsearch.Application; +import fr.cea.bigpi.fhe.dap.patternsearch.service.FHEPatternSearchService; +import fr.cea.bigpi.fhe.dap.patternsearch.service.FHEService; + +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = Application.class, + webEnvironment = WebEnvironment.RANDOM_PORT) +@ContextConfiguration(classes=Application.class) +@AutoConfigureMockMvc +@ActiveProfiles("test") // load application-test.properties (or .yml) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class SampleRepositoryTest { + + //@Autowired MetadataRepository repository; + + @Autowired FHEService service; + @Autowired FHEPatternSearchService fhePatternService; + + final static Logger logger = LoggerFactory.getLogger( SampleRepositoryTest.class ); + + @Test + public void test01get() throws Exception { + + logger.info("Testing 1"); + String res = service.ping("test01get"); + logger.info("REsponse " + res); + //fhePatternService.checkLicense(res, null, res) + } + + @Test + public void testAddAccount() { + logger.info("Testing a+b groovy "); + String restul = null; + try { + restul = service.fhe_executor("21", "12"); + } catch (CompilationFailedException | IOException e) { + e.printStackTrace(); + } + logger.info("Testing a+b groovy result : {}", restul); + assert(restul.isBlank() == false); + +// Account a = new Account(); +// a.setNumber("12345678909"); +// a.setBalance(1232); +// a.setCustomerId("234353464576586464"); +// repository.save(a); + } + +// @Test +// public void test02get() throws Exception { +// +// String param = "checker"; +// //expected output structure = "{\"name\":\"aName\",\"id\":\"anIdValue\",\"path\":\"aPath\",\"version\":\"1\"}"; +// +// System.out.println("Testing get DSA ID"); +// this.mockMvc.perform( +// MockMvcRequestBuilders.fileUpload(endPoint) +// .file(firstFile) +// .file(secondFile) +// .param("dsaId", "DSA-2d072942-9ed8-4258-95c2-da8c4a1a2e9a") +// .param("hashCode", "1") +// .accept(MediaType.APPLICATION_JSON) +// ) +// .andDo(MockMvcResultHandlers.print()) +// .andExpect(status().isOk()) +// ;// } + +} diff --git a/src/test/resources/application-test-cea.yml b/src/test/resources/application-test-cea.yml new file mode 100644 index 0000000000000000000000000000000000000000..d2381bc8f24b785d0dcdbb15f728e21cbf3202be --- /dev/null +++ b/src/test/resources/application-test-cea.yml @@ -0,0 +1,60 @@ +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +server: + port: ${PORT:0} + +#use for admin client +management: + security: + enabled: false + +spring: + application: + name: dmp-fhe-patternsearch-service + +# datasource: +# url: jdbc:postgresql://localhost:5432/cingulatadb +# username: postgres +# password: 123 + datasource: + url: jdbc:postgresql://10.8.34.73:5432/PatternSearch + username: postgres + password: bigpi!123! + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + hibernate_dialect: org.hibernate.dialect.PostgreSQLDialect + +logging.level.org.hibernate.SQL: DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +application: + seal: + #sealDir: '/home/hgnguyen/Desktop/seal/' + sealDir: '/opt/fhe/datalake/seal' + dataDir: ${application.seal.sealDir} + 'data/' + resultDir: ${application.seal.sealDir} + 'result/' + keyDir: ${application.seal.sealDir} + 'keys/' + uploadDir: ${application.seal.sealDir} + 'upload/' + sample: 40 + filename: l + + \ No newline at end of file diff --git a/src/test/resources/application-test-prod.yml b/src/test/resources/application-test-prod.yml new file mode 100644 index 0000000000000000000000000000000000000000..d2381bc8f24b785d0dcdbb15f728e21cbf3202be --- /dev/null +++ b/src/test/resources/application-test-prod.yml @@ -0,0 +1,60 @@ +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +server: + port: ${PORT:0} + +#use for admin client +management: + security: + enabled: false + +spring: + application: + name: dmp-fhe-patternsearch-service + +# datasource: +# url: jdbc:postgresql://localhost:5432/cingulatadb +# username: postgres +# password: 123 + datasource: + url: jdbc:postgresql://10.8.34.73:5432/PatternSearch + username: postgres + password: bigpi!123! + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + hibernate_dialect: org.hibernate.dialect.PostgreSQLDialect + +logging.level.org.hibernate.SQL: DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +application: + seal: + #sealDir: '/home/hgnguyen/Desktop/seal/' + sealDir: '/opt/fhe/datalake/seal' + dataDir: ${application.seal.sealDir} + 'data/' + resultDir: ${application.seal.sealDir} + 'result/' + keyDir: ${application.seal.sealDir} + 'keys/' + uploadDir: ${application.seal.sealDir} + 'upload/' + sample: 40 + filename: l + + \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 0000000000000000000000000000000000000000..d2381bc8f24b785d0dcdbb15f728e21cbf3202be --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,60 @@ +eureka: + client: + enabled: false + +#logging: +# level: INFO + +security: + activation: + status: false + # basic auth credentials + user: + name: bigpi + password: password + +server: + port: ${PORT:0} + +#use for admin client +management: + security: + enabled: false + +spring: + application: + name: dmp-fhe-patternsearch-service + +# datasource: +# url: jdbc:postgresql://localhost:5432/cingulatadb +# username: postgres +# password: 123 + datasource: + url: jdbc:postgresql://10.8.34.73:5432/PatternSearch + username: postgres + password: bigpi!123! + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + hibernate_dialect: org.hibernate.dialect.PostgreSQLDialect + +logging.level.org.hibernate.SQL: DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +application: + seal: + #sealDir: '/home/hgnguyen/Desktop/seal/' + sealDir: '/opt/fhe/datalake/seal' + dataDir: ${application.seal.sealDir} + 'data/' + resultDir: ${application.seal.sealDir} + 'result/' + keyDir: ${application.seal.sealDir} + 'keys/' + uploadDir: ${application.seal.sealDir} + 'upload/' + sample: 40 + filename: l + + \ No newline at end of file diff --git a/src/test/resources/logback-spring.xml b/src/test/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..c94ace83949423b59ce81d3bebf80cb15a3e5255 --- /dev/null +++ b/src/test/resources/logback-spring.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <property name="LOG_TEMP" value="./logs"/> + <include resource="org/springframework/boot/logging/logback/base.xml"/> + <!-- Required for Loglevel managment into the Spring Petclinic Admin Server--> + <jmxConfigurator/> +</configuration> diff --git a/stop_service.sh b/stop_service.sh new file mode 100755 index 0000000000000000000000000000000000000000..e84160f9c5961a4578af2955df85bbadaca9e828 --- /dev/null +++ b/stop_service.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +STOP_SERVICE=$1 + +if [ -z "$STOP_SERVICE" ] ; +then + echo "ERROR : Please define STOP_SERVICE in parameter" + echo "ERROR : STOP_SERVICE : the service to stop" + exit $E_ARG_ERR +fi + +pids=( $(ps -ef | grep ${STOP_SERVICE} | grep -v 'grep' | awk -F" " '{ print $2}') ) +echo ${pids[@]} + +for i in "${pids[@]}" +do + kill $i +done