diff --git a/neo.sln b/neo.sln
index 3779ae8d78..523849127d 100644
--- a/neo.sln
+++ b/neo.sln
@@ -1,4 +1,5 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32516.85
MinimumVisualStudioVersion = 10.0.40219.1
@@ -88,164 +89,500 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Cryptography.MPTTrie.Te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Network.RPC.Tests", "tests\Neo.Network.RPC.Tests\Neo.Network.RPC.Tests.csproj", "{19B1CF1A-17F4-4E04-AB9C-55CE74952E11}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Plugins.SignClient.Tests", "tests\Neo.Plugins.SignClient.Tests\Neo.Plugins.SignClient.Tests.csproj", "{61E46D13-9AB7-460E-8B34-65502E757059}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignClient", "src\Plugins\SignClient\SignClient.csproj", "{BA754911-8945-41F1-89E4-BFE99FB0AB9D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|x64.Build.0 = Debug|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Debug|x86.Build.0 = Debug|Any CPU
{36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|x64.ActiveCfg = Release|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|x64.Build.0 = Release|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|x86.ActiveCfg = Release|Any CPU
+ {36447A9B-0311-4D4D-A3D5-AECBE9C15BBC}.Release|x86.Build.0 = Release|Any CPU
{6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|x64.Build.0 = Debug|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Debug|x86.Build.0 = Debug|Any CPU
{6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|x64.ActiveCfg = Release|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|x64.Build.0 = Release|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|x86.ActiveCfg = Release|Any CPU
+ {6B709ED6-64C0-451D-B07F-8F49185AE191}.Release|x86.Build.0 = Release|Any CPU
{5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|x64.Build.0 = Debug|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Debug|x86.Build.0 = Debug|Any CPU
{5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|x64.ActiveCfg = Release|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|x64.Build.0 = Release|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|x86.ActiveCfg = Release|Any CPU
+ {5B783B30-B422-4C2F-AC22-187A8D1993F4}.Release|x86.Build.0 = Release|Any CPU
{AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|x64.Build.0 = Debug|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Debug|x86.Build.0 = Debug|Any CPU
{AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|x64.ActiveCfg = Release|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|x64.Build.0 = Release|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|x86.ActiveCfg = Release|Any CPU
+ {AE6C32EE-8447-4E01-8187-2AE02BB64251}.Release|x86.Build.0 = Release|Any CPU
{BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|x64.Build.0 = Debug|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Debug|x86.Build.0 = Debug|Any CPU
{BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|x64.ActiveCfg = Release|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|x64.Build.0 = Release|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|x86.ActiveCfg = Release|Any CPU
+ {BCD03521-5F8F-4775-9ADF-FA361480804F}.Release|x86.Build.0 = Release|Any CPU
{E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|x64.Build.0 = Debug|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Debug|x86.Build.0 = Debug|Any CPU
{E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|x64.ActiveCfg = Release|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|x64.Build.0 = Release|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|x86.ActiveCfg = Release|Any CPU
+ {E83633BA-FCF0-4A1A-B5BC-42000E24D437}.Release|x86.Build.0 = Release|Any CPU
{0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|x64.Build.0 = Debug|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Debug|x86.Build.0 = Debug|Any CPU
{0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|x64.ActiveCfg = Release|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|x64.Build.0 = Release|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|x86.ActiveCfg = Release|Any CPU
+ {0603710E-E0BA-494C-AA0F-6FB0C8A8C754}.Release|x86.Build.0 = Release|Any CPU
{005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|x64.Build.0 = Debug|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Debug|x86.Build.0 = Debug|Any CPU
{005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|x64.ActiveCfg = Release|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|x64.Build.0 = Release|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|x86.ActiveCfg = Release|Any CPU
+ {005F84EB-EA2E-449F-930A-7B4173DDC7EC}.Release|x86.Build.0 = Release|Any CPU
{9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|x64.Build.0 = Debug|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Debug|x86.Build.0 = Debug|Any CPU
{9E886812-7243-48D8-BEAF-47AADC11C054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E886812-7243-48D8-BEAF-47AADC11C054}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|x64.ActiveCfg = Release|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|x64.Build.0 = Release|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|x86.ActiveCfg = Release|Any CPU
+ {9E886812-7243-48D8-BEAF-47AADC11C054}.Release|x86.Build.0 = Release|Any CPU
{02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|x64.Build.0 = Debug|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Debug|x86.Build.0 = Debug|Any CPU
{02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|Any CPU.Build.0 = Release|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|x64.ActiveCfg = Release|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|x64.Build.0 = Release|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|x86.ActiveCfg = Release|Any CPU
+ {02ABDE42-9880-43B4-B6F7-8D618602A277}.Release|x86.Build.0 = Release|Any CPU
{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|x64.Build.0 = Debug|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Debug|x86.Build.0 = Debug|Any CPU
{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|x64.ActiveCfg = Release|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|x64.Build.0 = Release|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|x86.ActiveCfg = Release|Any CPU
+ {BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}.Release|x86.Build.0 = Release|Any CPU
{B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|x64.Build.0 = Debug|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Debug|x86.Build.0 = Debug|Any CPU
{B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|x64.ActiveCfg = Release|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|x64.Build.0 = Release|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|x86.ActiveCfg = Release|Any CPU
+ {B40F8584-5AFB-452C-AEFA-009C80CC23A9}.Release|x86.Build.0 = Release|Any CPU
{D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|x64.Build.0 = Debug|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Debug|x86.Build.0 = Debug|Any CPU
{D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|x64.ActiveCfg = Release|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|x64.Build.0 = Release|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|x86.ActiveCfg = Release|Any CPU
+ {D48C1FAB-3471-4CA0-8688-25E6F43F2C25}.Release|x86.Build.0 = Release|Any CPU
{387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|x64.Build.0 = Debug|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|x86.Build.0 = Debug|Any CPU
{387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|x64.ActiveCfg = Release|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|x64.Build.0 = Release|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|x86.ActiveCfg = Release|Any CPU
+ {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|x86.Build.0 = Release|Any CPU
{4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|x64.Build.0 = Debug|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|x86.Build.0 = Debug|Any CPU
{4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|x64.ActiveCfg = Release|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|x64.Build.0 = Release|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|x86.ActiveCfg = Release|Any CPU
+ {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|x86.Build.0 = Release|Any CPU
{9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|x64.Build.0 = Debug|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|x86.Build.0 = Debug|Any CPU
{9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|x64.ActiveCfg = Release|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|x64.Build.0 = Release|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|x86.ActiveCfg = Release|Any CPU
+ {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|x86.Build.0 = Release|Any CPU
{5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|x64.Build.0 = Debug|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Debug|x86.Build.0 = Debug|Any CPU
{5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|x64.ActiveCfg = Release|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|x64.Build.0 = Release|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|x86.ActiveCfg = Release|Any CPU
+ {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89}.Release|x86.Build.0 = Release|Any CPU
{2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|x64.Build.0 = Debug|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|x86.Build.0 = Debug|Any CPU
{2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|x64.ActiveCfg = Release|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|x64.Build.0 = Release|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|x86.ActiveCfg = Release|Any CPU
+ {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|x86.Build.0 = Release|Any CPU
{EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|x64.Build.0 = Debug|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|x86.Build.0 = Debug|Any CPU
{EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|x64.ActiveCfg = Release|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|x64.Build.0 = Release|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|x86.ActiveCfg = Release|Any CPU
+ {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|x86.Build.0 = Release|Any CPU
{22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|x64.Build.0 = Debug|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|x86.Build.0 = Debug|Any CPU
{22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|x64.ActiveCfg = Release|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|x64.Build.0 = Release|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|x86.ActiveCfg = Release|Any CPU
+ {22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|x86.Build.0 = Release|Any CPU
{4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|x64.Build.0 = Debug|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Debug|x86.Build.0 = Debug|Any CPU
{4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|x64.ActiveCfg = Release|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|x64.Build.0 = Release|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|x86.ActiveCfg = Release|Any CPU
+ {4C39E872-FC37-4BFD-AE4C-3E3F0546B726}.Release|x86.Build.0 = Release|Any CPU
{4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|x64.Build.0 = Debug|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Debug|x86.Build.0 = Debug|Any CPU
{4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|x64.ActiveCfg = Release|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|x64.Build.0 = Release|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|x86.ActiveCfg = Release|Any CPU
+ {4C4D8180-9326-486C-AECF-8368BBD0766A}.Release|x86.Build.0 = Release|Any CPU
{DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|x64.Build.0 = Debug|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Debug|x86.Build.0 = Debug|Any CPU
{DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|x64.ActiveCfg = Release|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|x64.Build.0 = Release|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|x86.ActiveCfg = Release|Any CPU
+ {DE0FB77E-3099-4C88-BB7D-BFAED75D813E}.Release|x86.Build.0 = Release|Any CPU
{3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|x64.Build.0 = Debug|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Debug|x86.Build.0 = Debug|Any CPU
{3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|x64.ActiveCfg = Release|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|x64.Build.0 = Release|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|x86.ActiveCfg = Release|Any CPU
+ {3DE59148-59D6-4CD3-8086-0BC74E3D4E0B}.Release|x86.Build.0 = Release|Any CPU
{A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|x64.Build.0 = Debug|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Debug|x86.Build.0 = Debug|Any CPU
{A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|x64.ActiveCfg = Release|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|x64.Build.0 = Release|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|x86.ActiveCfg = Release|Any CPU
+ {A3941551-E72C-42D7-8C4D-5122CB60D73D}.Release|x86.Build.0 = Release|Any CPU
{F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Debug|x86.Build.0 = Debug|Any CPU
{F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|x64.Build.0 = Release|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F53D5FF0-5D3D-4E8B-A44F-C4C5D9B563B1}.Release|x86.Build.0 = Release|Any CPU
{88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|x64.Build.0 = Debug|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Debug|x86.Build.0 = Debug|Any CPU
{88975A8D-4797-45A4-BC3E-15962A425A54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88975A8D-4797-45A4-BC3E-15962A425A54}.Release|Any CPU.Build.0 = Release|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Release|x64.ActiveCfg = Release|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Release|x64.Build.0 = Release|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Release|x86.ActiveCfg = Release|Any CPU
+ {88975A8D-4797-45A4-BC3E-15962A425A54}.Release|x86.Build.0 = Release|Any CPU
{FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|x64.Build.0 = Debug|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Debug|x86.Build.0 = Debug|Any CPU
{FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|x64.ActiveCfg = Release|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|x64.Build.0 = Release|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|x86.ActiveCfg = Release|Any CPU
+ {FF76D8A4-356B-461A-8471-BC1B83E57BBC}.Release|x86.Build.0 = Release|Any CPU
{5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|x64.Build.0 = Debug|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Debug|x86.Build.0 = Debug|Any CPU
{5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|x64.ActiveCfg = Release|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|x64.Build.0 = Release|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|x86.ActiveCfg = Release|Any CPU
+ {5E4947F3-05D3-4806-B0F3-30DAC71B5986}.Release|x86.Build.0 = Release|Any CPU
{8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|x64.Build.0 = Debug|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Debug|x86.Build.0 = Debug|Any CPU
{8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|x64.ActiveCfg = Release|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|x64.Build.0 = Release|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|x86.ActiveCfg = Release|Any CPU
+ {8C866DC8-2E55-4399-9563-2F47FD4602EC}.Release|x86.Build.0 = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|x64.Build.0 = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|x86.Build.0 = Debug|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|Any CPU.Build.0 = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|x64.ActiveCfg = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|x64.Build.0 = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|x86.ActiveCfg = Release|Any CPU
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|x86.Build.0 = Release|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|x64.Build.0 = Debug|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|x86.Build.0 = Debug|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|x64.ActiveCfg = Release|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|x64.Build.0 = Release|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|x86.ActiveCfg = Release|Any CPU
+ {77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|x86.Build.0 = Release|Any CPU
{B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|x64.Build.0 = Debug|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Debug|x86.Build.0 = Debug|Any CPU
{B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|x64.ActiveCfg = Release|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|x64.Build.0 = Release|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|x86.ActiveCfg = Release|Any CPU
+ {B6CB2559-10F9-41AC-8D58-364BFEF9688B}.Release|x86.Build.0 = Release|Any CPU
{5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|x64.Build.0 = Debug|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Debug|x86.Build.0 = Debug|Any CPU
{5F984D2B-793F-4683-B53A-80050E6E0286}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F984D2B-793F-4683-B53A-80050E6E0286}.Release|Any CPU.Build.0 = Release|Any CPU
- {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {72997EAB-9B0C-4BC8-B797-955C219C2C97}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Release|x64.ActiveCfg = Release|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Release|x64.Build.0 = Release|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Release|x86.ActiveCfg = Release|Any CPU
+ {5F984D2B-793F-4683-B53A-80050E6E0286}.Release|x86.Build.0 = Release|Any CPU
{9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|x64.Build.0 = Debug|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Debug|x86.Build.0 = Debug|Any CPU
{9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|x64.ActiveCfg = Release|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|x64.Build.0 = Release|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|x86.ActiveCfg = Release|Any CPU
+ {9ADB4E11-8655-42C2-8A75-E4436F56F17A}.Release|x86.Build.0 = Release|Any CPU
{E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|x64.Build.0 = Debug|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Debug|x86.Build.0 = Debug|Any CPU
{E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|x64.ActiveCfg = Release|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|x64.Build.0 = Release|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|x86.ActiveCfg = Release|Any CPU
+ {E384C5EF-493E-4ED6-813C-6364F968CEE8}.Release|x86.Build.0 = Release|Any CPU
{40A23D45-1E81-41A4-B587-16AF26630103}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40A23D45-1E81-41A4-B587-16AF26630103}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Debug|x64.Build.0 = Debug|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Debug|x86.Build.0 = Debug|Any CPU
{40A23D45-1E81-41A4-B587-16AF26630103}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40A23D45-1E81-41A4-B587-16AF26630103}.Release|Any CPU.Build.0 = Release|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Release|x64.ActiveCfg = Release|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Release|x64.Build.0 = Release|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Release|x86.ActiveCfg = Release|Any CPU
+ {40A23D45-1E81-41A4-B587-16AF26630103}.Release|x86.Build.0 = Release|Any CPU
{19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|x64.Build.0 = Debug|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Debug|x86.Build.0 = Debug|Any CPU
{19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|x64.ActiveCfg = Release|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|x64.Build.0 = Release|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|x86.ActiveCfg = Release|Any CPU
+ {19B1CF1A-17F4-4E04-AB9C-55CE74952E11}.Release|x86.Build.0 = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|x64.Build.0 = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Debug|x86.Build.0 = Debug|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|Any CPU.Build.0 = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|x64.ActiveCfg = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|x64.Build.0 = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|x86.ActiveCfg = Release|Any CPU
+ {61E46D13-9AB7-460E-8B34-65502E757059}.Release|x86.Build.0 = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|x64.Build.0 = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Debug|x86.Build.0 = Debug|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|x64.ActiveCfg = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|x64.Build.0 = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|x86.ActiveCfg = Release|Any CPU
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -282,14 +619,16 @@ Global
{FF76D8A4-356B-461A-8471-BC1B83E57BBC} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{5E4947F3-05D3-4806-B0F3-30DAC71B5986} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{8C866DC8-2E55-4399-9563-2F47FD4602EC} = {7F257712-D033-47FF-B439-9D4320D06599}
+ {72997EAB-9B0C-4BC8-B797-955C219C2C97} = {7F257712-D033-47FF-B439-9D4320D06599}
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1}
{B6CB2559-10F9-41AC-8D58-364BFEF9688B} = {C25EB0B0-0CAC-4CC1-8F36-F9229EFB99EC}
{5F984D2B-793F-4683-B53A-80050E6E0286} = {C25EB0B0-0CAC-4CC1-8F36-F9229EFB99EC}
- {72997EAB-9B0C-4BC8-B797-955C219C2C97} = {7F257712-D033-47FF-B439-9D4320D06599}
{9ADB4E11-8655-42C2-8A75-E4436F56F17A} = {B5339DF7-5D1D-43BA-B332-74B825E1770E}
{E384C5EF-493E-4ED6-813C-6364F968CEE8} = {B5339DF7-5D1D-43BA-B332-74B825E1770E}
{40A23D45-1E81-41A4-B587-16AF26630103} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1}
{19B1CF1A-17F4-4E04-AB9C-55CE74952E11} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1}
+ {61E46D13-9AB7-460E-8B34-65502E757059} = {7F257712-D033-47FF-B439-9D4320D06599}
+ {BA754911-8945-41F1-89E4-BFE99FB0AB9D} = {C2DC830A-327A-42A7-807D-295216D30DBB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC}
diff --git a/src/Neo.CLI/CLI/MainService.Wallet.cs b/src/Neo.CLI/CLI/MainService.Wallet.cs
index 9e75235d9b..9b6dbd3058 100644
--- a/src/Neo.CLI/CLI/MainService.Wallet.cs
+++ b/src/Neo.CLI/CLI/MainService.Wallet.cs
@@ -73,7 +73,7 @@ private void OnCloseWalletCommand()
if (CurrentWallet is not null)
{
- SignerFactory.UnregisterSigner(CurrentWallet.Name);
+ SignerManager.UnregisterSigner(CurrentWallet.Name);
}
CurrentWallet = null;
diff --git a/src/Neo.CLI/CLI/MainService.cs b/src/Neo.CLI/CLI/MainService.cs
index 71c1cc82be..449fa9c14b 100644
--- a/src/Neo.CLI/CLI/MainService.cs
+++ b/src/Neo.CLI/CLI/MainService.cs
@@ -161,7 +161,7 @@ public void CreateWallet(string path, string password, bool createDefaultAccount
wallet.Save();
CurrentWallet = wallet;
- SignerFactory.RegisterSigner(wallet.Name, wallet);
+ SignerManager.RegisterSigner(wallet.Name, wallet);
}
private bool NoWallet()
@@ -296,10 +296,10 @@ public void OpenWallet(string path, string password)
throw new FileNotFoundException($"Wallet file \"{path}\" not found.");
}
- if (CurrentWallet is not null) SignerFactory.UnregisterSigner(CurrentWallet.Name);
+ if (CurrentWallet is not null) SignerManager.UnregisterSigner(CurrentWallet.Name);
CurrentWallet = Wallet.Open(path, password, NeoSystem.Settings) ?? throw new NotSupportedException();
- SignerFactory.RegisterSigner(CurrentWallet.Name, CurrentWallet);
+ SignerManager.RegisterSigner(CurrentWallet.Name, CurrentWallet);
}
public async void Start(CommandLineOptions options)
diff --git a/src/Neo/Sign/ISigner.cs b/src/Neo/Sign/ISigner.cs
index 77fe2f82cd..0251387403 100644
--- a/src/Neo/Sign/ISigner.cs
+++ b/src/Neo/Sign/ISigner.cs
@@ -21,7 +21,7 @@ namespace Neo.Sign
public interface ISigner
{
///
- /// Signs the with the wallet.
+ /// Signs the with the signer.
///
/// The to be used.
///
diff --git a/src/Neo/Sign/SignException.cs b/src/Neo/Sign/SignException.cs
index 36bb8cc504..e734b6fb66 100644
--- a/src/Neo/Sign/SignException.cs
+++ b/src/Neo/Sign/SignException.cs
@@ -22,6 +22,7 @@ public class SignException : Exception
/// Initializes a new instance of the class.
///
/// The message that describes the error.
- public SignException(string message) : base(message) { }
+ /// The cause of the exception.
+ public SignException(string message, Exception cause = null) : base(message, cause) { }
}
}
diff --git a/src/Neo/Sign/SignerFactory.cs b/src/Neo/Sign/SignerManager.cs
similarity index 96%
rename from src/Neo/Sign/SignerFactory.cs
rename to src/Neo/Sign/SignerManager.cs
index ffe17b9c08..967fa6becf 100644
--- a/src/Neo/Sign/SignerFactory.cs
+++ b/src/Neo/Sign/SignerManager.cs
@@ -1,6 +1,6 @@
// Copyright (C) 2015-2025 The Neo Project.
//
-// SignerFactory.cs file belongs to the neo project and is free
+// SignerManager.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
@@ -15,7 +15,7 @@
namespace Neo.Sign
{
- public static class SignerFactory
+ public static class SignerManager
{
private static readonly ConcurrentDictionary s_signers = new();
diff --git a/src/Plugins/DBFTPlugin/DBFTPlugin.cs b/src/Plugins/DBFTPlugin/DBFTPlugin.cs
index 206d4d22b7..7c7b203b52 100644
--- a/src/Plugins/DBFTPlugin/DBFTPlugin.cs
+++ b/src/Plugins/DBFTPlugin/DBFTPlugin.cs
@@ -87,7 +87,7 @@ void IWalletChangedHandler.IWalletProvider_WalletChanged_Handler(object sender,
[ConsoleCommand("start consensus", Category = "Consensus", Description = "Start consensus service (dBFT)")]
private void OnStart(string signerName = "")
{
- var signer = SignerFactory.GetSignerOrDefault(signerName);
+ var signer = SignerManager.GetSignerOrDefault(signerName);
Start(signer ?? walletProvider.GetWallet());
}
diff --git a/src/Plugins/SignClient/Settings.cs b/src/Plugins/SignClient/Settings.cs
new file mode 100644
index 0000000000..6a09a4f89e
--- /dev/null
+++ b/src/Plugins/SignClient/Settings.cs
@@ -0,0 +1,57 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// Settings.cs file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+using Microsoft.Extensions.Configuration;
+using System.Net;
+
+namespace Neo.Plugins.SignClient
+{
+ public class Settings : PluginSettings
+ {
+ ///
+ /// Only support local host at present, so host always is "127.0.0.1" or "::1" now.
+ ///
+ public static readonly string DefaultEndpoint = $"http://{IPAddress.Loopback}:9991";
+ public const string SectionName = "PluginConfiguration";
+
+ ///
+ /// The name of the sign client(i.e. Signer).
+ ///
+ public readonly string Name;
+
+ ///
+ /// The host of the sign client(i.e. Signer).
+ ///
+ public readonly string Endpoint;
+
+ public Settings(IConfigurationSection section) : base(section)
+ {
+ Name = section.GetValue("Name", "SignClient");
+ Endpoint = section.GetValue("Endpoint", DefaultEndpoint);
+ }
+
+ public static Settings Default
+ {
+ get
+ {
+ var section = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary
+ {
+ [SectionName + ":Name"] = "SignClient",
+ [SectionName + ":Endpoint"] = DefaultEndpoint
+ })
+ .Build()
+ .GetSection(SectionName);
+ return new Settings(section);
+ }
+ }
+ }
+}
diff --git a/src/Plugins/SignClient/SignClient.cs b/src/Plugins/SignClient/SignClient.cs
new file mode 100644
index 0000000000..395e9db7dd
--- /dev/null
+++ b/src/Plugins/SignClient/SignClient.cs
@@ -0,0 +1,304 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// SignClient.cs file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Net.Client;
+using Grpc.Net.Client.Configuration;
+using Neo.ConsoleService;
+using Neo.Cryptography.ECC;
+using Neo.Extensions;
+using Neo.Network.P2P;
+using Neo.Sign;
+using Neo.SmartContract;
+using Servicepb;
+using Signpb;
+using System.Diagnostics.CodeAnalysis;
+using static Neo.SmartContract.Helper;
+
+namespace Neo.Plugins.SignClient
+{
+ ///
+ /// A signer that uses a client to sign transactions.
+ ///
+ public class SignClient : Plugin, ISigner
+ {
+ private GrpcChannel? _channel;
+
+ private SecureSign.SecureSignClient? _client;
+
+ private string _name = string.Empty;
+
+ public override string Description => "Signer plugin for signer service.";
+
+ public override string ConfigFile => System.IO.Path.Combine(RootPath, "SignClient.json");
+
+ public SignClient() { }
+
+ public SignClient(Settings settings)
+ {
+ Reset(settings);
+ }
+
+ // It's for test now.
+ internal SignClient(string name, SecureSign.SecureSignClient client)
+ {
+ Reset(name, client);
+ }
+
+ private void Reset(string name, SecureSign.SecureSignClient? client)
+ {
+ if (_client is not null) SignerManager.UnregisterSigner(_name);
+
+ _name = name;
+ _client = client;
+ if (!string.IsNullOrEmpty(_name)) SignerManager.RegisterSigner(_name, this);
+ }
+
+ private void Reset(Settings settings)
+ {
+ // _settings = settings;
+ var methodConfig = new MethodConfig
+ {
+ Names = { MethodName.Default },
+ RetryPolicy = new RetryPolicy
+ {
+ MaxAttempts = 3,
+ InitialBackoff = TimeSpan.FromMilliseconds(50),
+ MaxBackoff = TimeSpan.FromMilliseconds(200),
+ BackoffMultiplier = 1.5,
+ RetryableStatusCodes = {
+ StatusCode.Cancelled,
+ StatusCode.DeadlineExceeded,
+ StatusCode.ResourceExhausted,
+ StatusCode.Unavailable,
+ StatusCode.Aborted,
+ StatusCode.Internal,
+ StatusCode.DataLoss,
+ StatusCode.Unknown
+ }
+ }
+ };
+
+ var channel = GrpcChannel.ForAddress(settings.Endpoint, new GrpcChannelOptions
+ {
+ ServiceConfig = new ServiceConfig { MethodConfigs = { methodConfig } }
+ });
+
+ _channel?.Dispose();
+ _channel = channel;
+ Reset(settings.Name, new SecureSign.SecureSignClient(_channel));
+ }
+
+ ///
+ /// Get account status command
+ ///
+ /// The hex public key, compressed or uncompressed
+ [ConsoleCommand("get account status", Category = "Signer Commands", Description = "Get account status")]
+ public void AccountStatusCommand(string hexPublicKey)
+ {
+ if (_client is null)
+ {
+ ConsoleHelper.Error("No signer service is connected");
+ return;
+ }
+
+ try
+ {
+ var publicKey = ECPoint.DecodePoint(hexPublicKey.HexToBytes(), ECCurve.Secp256r1);
+ var output = _client.GetAccountStatus(new()
+ {
+ PublicKey = ByteString.CopyFrom(publicKey.EncodePoint(true))
+ });
+ ConsoleHelper.Info($"Account status: {output.Status}");
+ }
+ catch (RpcException rpcEx)
+ {
+ if (rpcEx.StatusCode == StatusCode.Unavailable)
+ {
+ ConsoleHelper.Error("No available signer service");
+ }
+ else
+ {
+ ConsoleHelper.Error($"Failed to get account status: {rpcEx.StatusCode}: {rpcEx.Status.Detail}");
+ }
+ }
+ catch (FormatException formatEx)
+ {
+ ConsoleHelper.Error($"Invalid public key: {formatEx.Message}");
+ }
+ }
+
+ private AccountStatus GetAccountStatus(ECPoint publicKey)
+ {
+ if (_client is null) throw new SignException("No signer service is connected");
+
+ try
+ {
+ var output = _client.GetAccountStatus(new()
+ {
+ PublicKey = ByteString.CopyFrom(publicKey.EncodePoint(true))
+ });
+ return output.Status;
+ }
+ catch (RpcException ex)
+ {
+ throw new SignException($"Get account status: {ex.Status}", ex);
+ }
+ }
+
+ ///
+ /// Check if the account is signable
+ ///
+ /// The public key
+ /// True if the account is signable, false otherwise
+ /// If no signer service is available, or other rpc error occurs.
+ public bool ContainsSignable(ECPoint publicKey)
+ {
+ var status = GetAccountStatus(publicKey);
+ return status == AccountStatus.Single || status == AccountStatus.Multiple;
+ }
+
+ private static bool TryDecodePublicKey(ByteString publicKey, [NotNullWhen(true)] out ECPoint? point)
+ {
+ try
+ {
+ point = ECPoint.DecodePoint(publicKey.Span, ECCurve.Secp256r1);
+ }
+ catch (FormatException) // add log later
+ {
+ point = null;
+ }
+ return point is not null;
+ }
+
+ internal bool Sign(ContractParametersContext context, IEnumerable signs)
+ {
+ var succeed = false;
+ foreach (var (accountSigns, scriptHash) in signs.Zip(context.ScriptHashes))
+ {
+ var accountStatus = accountSigns.Status;
+ if (accountStatus == AccountStatus.NoSuchAccount || accountStatus == AccountStatus.NoPrivateKey)
+ {
+ succeed |= context.AddWithScriptHash(scriptHash); // Same as Wallet.Sign(context)
+ continue;
+ }
+
+ var contract = accountSigns.Contract;
+ var accountContract = Contract.Create(
+ contract?.Parameters?.Select(p => (ContractParameterType)p).ToArray() ?? [],
+ contract?.Script?.ToByteArray() ?? []);
+ if (accountStatus == AccountStatus.Multiple)
+ {
+ if (!IsMultiSigContract(accountContract.Script, out int m, out ECPoint[] publicKeys))
+ throw new SignException("Sign context: multi-sign account but not multi-sign contract");
+
+ foreach (var sign in accountSigns.Signs)
+ {
+ if (!TryDecodePublicKey(sign.PublicKey, out var publicKey)) continue;
+
+ if (!publicKeys.Contains(publicKey))
+ throw new SignException($"Sign context: public key {publicKey} not in multi-sign contract");
+
+ var ok = context.AddSignature(accountContract, publicKey, sign.Signature.ToByteArray());
+ if (ok) m--;
+
+ succeed |= ok;
+ if (context.Completed || m <= 0) break;
+ }
+ }
+ else if (accountStatus == AccountStatus.Single)
+ {
+ if (accountSigns.Signs is null || accountSigns.Signs.Count != 1)
+ throw new SignException($"Sign context: single account but {accountSigns.Signs?.Count} signs");
+
+ var sign = accountSigns.Signs[0];
+ if (!TryDecodePublicKey(sign.PublicKey, out var publicKey)) continue;
+ succeed |= context.AddSignature(accountContract, publicKey, sign.Signature.ToByteArray());
+ }
+ }
+ return succeed;
+ }
+
+ ///
+ /// Signs the with the signer.
+ ///
+ /// The context of the transaction
+ /// True if the transaction is signed, false otherwise
+ /// If no signer service is available, or other rpc error occurs.
+ public bool Sign(ContractParametersContext context)
+ {
+ if (_client is null) throw new SignException("No signer service is connected");
+
+ try
+ {
+ var signData = context.Verifiable.GetSignData(context.Network);
+ var output = _client.SignWithScriptHashes(new()
+ {
+ SignData = ByteString.CopyFrom(signData),
+ ScriptHashes = { context.ScriptHashes.Select(h160 => ByteString.CopyFrom(h160.GetSpan())) }
+ });
+
+ int signCount = output.Signs.Count, hashCount = context.ScriptHashes.Count;
+ if (signCount != hashCount)
+ {
+ throw new SignException($"Sign context: Signs.Count({signCount}) != Hashes.Count({hashCount})");
+ }
+ return Sign(context, output.Signs);
+ }
+ catch (RpcException ex)
+ {
+ throw new SignException($"Sign context: {ex.Status}", ex);
+ }
+ }
+
+ ///
+ /// Signs the specified data with the corresponding private key of the specified public key.
+ ///
+ /// The data to sign
+ /// The public key
+ /// The signature
+ /// If no signer service is available, or other rpc error occurs.
+ public ReadOnlyMemory Sign(byte[] signData, ECPoint publicKey)
+ {
+ if (_client is null) throw new SignException("No signer service is connected");
+
+ try
+ {
+ var output = _client.SignWithPublicKey(new()
+ {
+ SignData = ByteString.CopyFrom(signData),
+ PublicKey = ByteString.CopyFrom(publicKey.EncodePoint(true)),
+ });
+ return output.Signature.Memory;
+ }
+ catch (RpcException ex)
+ {
+ throw new SignException($"Sign with public key: {ex.Status}", ex);
+ }
+ }
+
+ ///
+ protected override void Configure()
+ {
+ var config = GetConfiguration();
+ if (config is not null) Reset(new Settings(config));
+ }
+
+ ///
+ public override void Dispose()
+ {
+ Reset(string.Empty, null);
+ _channel?.Dispose();
+ base.Dispose();
+ }
+ }
+}
diff --git a/src/Plugins/SignClient/SignClient.csproj b/src/Plugins/SignClient/SignClient.csproj
new file mode 100644
index 0000000000..36e289e3b4
--- /dev/null
+++ b/src/Plugins/SignClient/SignClient.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net9.0
+ latest
+ enable
+ enable
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Plugins/SignClient/SignClient.json b/src/Plugins/SignClient/SignClient.json
new file mode 100644
index 0000000000..35cdb5a074
--- /dev/null
+++ b/src/Plugins/SignClient/SignClient.json
@@ -0,0 +1,6 @@
+{
+ "PluginConfiguration": {
+ "Name": "SignClient",
+ "EndPoint": "http://127.0.0.1:9991"
+ }
+}
diff --git a/src/Plugins/SignClient/proto/servicepb.proto b/src/Plugins/SignClient/proto/servicepb.proto
new file mode 100644
index 0000000000..43d3b2685b
--- /dev/null
+++ b/src/Plugins/SignClient/proto/servicepb.proto
@@ -0,0 +1,58 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// servicepb.proto file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+syntax = "proto3";
+
+import "signpb.proto";
+
+package servicepb;
+
+message SignWithScriptHashesRequest {
+ // the data to be signed
+ bytes sign_data = 1;
+
+ // script hashes, H160
+ repeated bytes script_hashes = 3;
+}
+
+message SignWithScriptHashesResponse {
+ // script_hash -> script_hash_signs
+ repeated signpb.AccountSigns signs = 1;
+}
+
+message SignWithPublicKeyRequest {
+ // the data to be signed
+ bytes sign_data = 1;
+
+ // compressed or uncompressed public key
+ bytes public_key = 3;
+}
+
+message SignWithPublicKeyResponse {
+ bytes signature = 1;
+}
+
+message GetAccountStatusRequest {
+ // compressed or uncompressed public key
+ bytes public_key = 1;
+}
+
+message GetAccountStatusResponse {
+ signpb.AccountStatus status = 1;
+}
+
+service SecureSign {
+ rpc SignWithScriptHashes(SignWithScriptHashesRequest) returns (SignWithScriptHashesResponse) {}
+
+ rpc SignWithPublicKey(SignWithPublicKeyRequest) returns (SignWithPublicKeyResponse) {}
+
+ rpc GetAccountStatus(GetAccountStatusRequest) returns (GetAccountStatusResponse) {}
+}
diff --git a/src/Plugins/SignClient/proto/signpb.proto b/src/Plugins/SignClient/proto/signpb.proto
new file mode 100644
index 0000000000..0b058eacd7
--- /dev/null
+++ b/src/Plugins/SignClient/proto/signpb.proto
@@ -0,0 +1,64 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// signpb.proto file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+syntax = "proto3";
+
+package signpb;
+
+message AccountSign {
+ // the signature
+ bytes signature = 1;
+
+ // the compressed or uncompressed public key
+ bytes public_key = 2;
+}
+
+message AccountContract {
+ // the contract script
+ bytes script = 1;
+
+ // the contract parameters
+ repeated uint32 parameters = 2;
+
+ // if the contract is deployed
+ bool deployed = 3;
+}
+
+enum AccountStatus {
+ /// no such account
+ NoSuchAccount = 0;
+
+ /// no private key
+ NoPrivateKey = 1;
+
+ /// single sign
+ Single = 2;
+
+ /// multiple signs, aka. multisig
+ Multiple = 3;
+
+ /// this key-pair is locked
+ Locked = 4;
+}
+
+message AccountSigns {
+ // if the status is Single, there is only one sign
+ // if the status is Multiple, there are multiple signs
+ // if the status is NoSuchAccount, NoPrivateKey or Locked, there are no signs
+ repeated AccountSign signs = 1;
+
+ // the account contract
+ // If the account hasn't a contract, the contract is null
+ AccountContract contract = 2;
+
+ // the account status
+ AccountStatus status = 3;
+}
diff --git a/tests/Neo.Plugins.SignClient.Tests/Neo.Plugins.SignClient.Tests.csproj b/tests/Neo.Plugins.SignClient.Tests/Neo.Plugins.SignClient.Tests.csproj
new file mode 100644
index 0000000000..5e0cd293ef
--- /dev/null
+++ b/tests/Neo.Plugins.SignClient.Tests/Neo.Plugins.SignClient.Tests.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net9.0
+ latest
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Neo.Plugins.SignClient.Tests/UT_SignClient.cs b/tests/Neo.Plugins.SignClient.Tests/UT_SignClient.cs
new file mode 100644
index 0000000000..b0b0c7dc1f
--- /dev/null
+++ b/tests/Neo.Plugins.SignClient.Tests/UT_SignClient.cs
@@ -0,0 +1,195 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// UT_SignClient.cs file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+using Google.Protobuf;
+using Grpc.Core;
+using Microsoft.Extensions.Configuration;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Neo.Cryptography;
+using Neo.Cryptography.ECC;
+using Neo.Extensions;
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
+using Neo.Persistence.Providers;
+using Neo.Sign;
+using Neo.SmartContract;
+using Neo.Wallets;
+using Servicepb;
+using Signpb;
+
+namespace Neo.Plugins.SignClient.Tests
+{
+ [TestClass]
+ public class UT_SignClient
+ {
+ const string PrivateKey = "0101010101010101010101010101010101010101010101010101010101010101";
+ const string PublicKey = "026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca16";
+ const uint TestNetwork = 0x334F454Eu;
+
+ private static readonly ECPoint s_publicKey = ECPoint.DecodePoint(PublicKey.HexToBytes(), ECCurve.Secp256r1);
+
+ private static SignClient NewClient()
+ {
+ // for test sign service, set SIGN_SERVICE_ENDPOINT env
+ var endPoint = Environment.GetEnvironmentVariable("SIGN_SERVICE_ENDPOINT");
+ if (endPoint is not null)
+ {
+ var section = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary
+ {
+ [Settings.SectionName + ":Name"] = "SignClient",
+ [Settings.SectionName + ":EndPoint"] = endPoint
+ })
+ .Build()
+ .GetSection(Settings.SectionName);
+ return new SignClient(new Settings(section));
+ }
+
+ var mockClient = new Mock();
+
+ // setup GetAccountStatus
+ mockClient.Setup(c => c.GetAccountStatus(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny())
+ )
+ .Returns((req, _, _, _) =>
+ {
+ if (req.PublicKey.ToByteArray().ToHexString() == PublicKey)
+ return new GetAccountStatusResponse() { Status = AccountStatus.Single };
+ return new GetAccountStatusResponse() { Status = AccountStatus.NoSuchAccount };
+ });
+
+ // setup SignWithPublicKey
+ mockClient.Setup(c => c.SignWithPublicKey(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny())
+ )
+ .Returns((req, _, _, _) =>
+ {
+ if (req.PublicKey.ToByteArray().ToHexString() == PublicKey)
+ {
+ var sign = Crypto.Sign(req.SignData.ToByteArray(), PrivateKey.HexToBytes(), ECCurve.Secp256r1);
+ return new SignWithPublicKeyResponse() { Signature = ByteString.CopyFrom(sign) };
+ }
+ throw new RpcException(new Status(StatusCode.NotFound, "no such account"));
+ });
+
+ // setup SignWithScriptHashes
+ mockClient.Setup(c => c.SignWithScriptHashes(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny())
+ )
+ .Returns((req, _, _, _) =>
+ {
+ var script = Contract.CreateSignatureRedeemScript(s_publicKey);
+ var res = new SignWithScriptHashesResponse();
+ foreach (var scriptHash in req.ScriptHashes)
+ {
+ if (scriptHash.ToByteArray().ToHexString() == script.ToScriptHash().GetSpan().ToHexString())
+ {
+ var contract = new AccountContract() { Script = ByteString.CopyFrom(script) };
+ contract.Parameters.Add((uint)ContractParameterType.Signature);
+
+ var sign = Crypto.Sign(req.SignData.ToByteArray(), PrivateKey.HexToBytes(), ECCurve.Secp256r1);
+ var signs = new AccountSigns() { Status = AccountStatus.Single, Contract = contract };
+ signs.Signs.Add(new AccountSign()
+ {
+ PublicKey = ByteString.CopyFrom(s_publicKey.EncodePoint(false).ToArray()),
+ Signature = ByteString.CopyFrom(sign)
+ });
+
+ res.Signs.Add(signs);
+ }
+ else
+ {
+ res.Signs.Add(new AccountSigns() { Status = AccountStatus.NoSuchAccount });
+ }
+ }
+ return res;
+ });
+
+ return new SignClient("TestSignClient", mockClient.Object);
+ }
+
+ [TestMethod]
+ public void TestSignPublicKey()
+ {
+ using var signClient = NewClient();
+
+ // sign with public key
+ var signature = signClient.Sign([1, 2, 3], s_publicKey);
+ Assert.IsNotNull(signature);
+
+ // verify signature
+ var verified = Crypto.VerifySignature([1, 2, 3], signature.Span, s_publicKey);
+ Assert.IsTrue(verified);
+
+ var privateKey = Enumerable.Repeat((byte)0x0f, 32).ToArray();
+ var keypair = new KeyPair(privateKey);
+
+ // sign with a not exists private key
+ var action = () => { _ = signClient.Sign([1, 2, 3], keypair.PublicKey); };
+ Assert.ThrowsExactly(action);
+ }
+
+ [TestMethod]
+ public void TestSignContext()
+ {
+ using var signClient = NewClient();
+ using var store = new MemoryStore();
+ using var snapshot = new StoreCache(store, false);
+
+ // get account of the public key
+ var script = Contract.CreateSignatureRedeemScript(s_publicKey);
+ var tx = new Transaction
+ {
+ Script = script,
+ Signers = [new() { Account = script.ToScriptHash() }],
+ Attributes = [],
+ Witnesses = [Witness.Empty],
+ };
+
+ var context = new ContractParametersContext(snapshot, tx, TestNetwork);
+ var ok = signClient.Sign(context);
+ Assert.IsTrue(ok);
+ }
+
+ [TestMethod]
+ public void TestGetAccountStatus()
+ {
+ using var signClient = NewClient();
+
+ // exists
+ var contains = signClient.ContainsSignable(s_publicKey);
+ Assert.IsTrue(contains);
+
+ var privateKey = Enumerable.Repeat((byte)0x0f, 32).ToArray();
+ var keypair = new KeyPair(privateKey);
+
+ // not exists
+ contains = signClient.ContainsSignable(keypair.PublicKey);
+ Assert.IsFalse(contains);
+
+ // exists
+ signClient.AccountStatusCommand(PublicKey);
+
+ // not exists
+ signClient.AccountStatusCommand(keypair.PublicKey.EncodePoint(true).ToHexString());
+ }
+ }
+}