diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d51fb5a..6cefd31c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ set(META_PROJECT_EXPORT "ElectionGuard")
set(META_PROJECT_TARGET "electionguard")
set(META_VERSION_MAJOR "0")
set(META_VERSION_MINOR "1")
-set(META_VERSION_PATCH "11")
+set(META_VERSION_PATCH "12")
set(META_VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}")
set(LIBRARY_PUBLIC_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
diff --git a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestCollections.cs b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestCollections.cs
index c94f3c46..e84745b5 100644
--- a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestCollections.cs
+++ b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestCollections.cs
@@ -23,6 +23,9 @@ public void Test_Can_Create_Linked_list()
// Assert
Assert.That(firstValue == "value");
Assert.That(secondValue == "thing");
+ Assert.That(list["some"] == "value");
+ Assert.That(list["another"] == "thing");
+ Assert.That(list["notthere"] == null);
}
}
}
diff --git a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Collections.cs b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Collections.cs
index 098a3c24..badb7441 100644
--- a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Collections.cs
+++ b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Collections.cs
@@ -77,6 +77,27 @@ public unsafe string GetValueAt(ulong position)
return Marshal.PtrToStringAnsi(value);
}
+
+ ///
+ /// Get the value using the designated key
+ ///
+ public unsafe string this[string searchKey]
+ {
+ get
+ {
+ var count = NativeInterface.LinkedList.GetCount(Handle);
+ for (ulong position = 0; position < count; position++)
+ {
+ var status = NativeInterface.LinkedList.GetElementAt(
+ Handle, position, out IntPtr key, out IntPtr value);
+ status.ThrowIfError();
+ if (Marshal.PtrToStringAnsi(key) == searchKey)
+ return Marshal.PtrToStringAnsi(value);
+ }
+ return null;
+ }
+ }
+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
protected override unsafe void DisposeUnmanaged()
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
diff --git a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj
index 067156c3..36161457 100644
--- a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj
+++ b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj
@@ -7,9 +7,9 @@
ElectionGuard
ElectionGuard.Encryption
- 0.1.11
- 0.1.11.0
- 0.1.11.0
+ 0.1.12
+ 0.1.12.0
+ 0.1.12.0
@@ -19,7 +19,7 @@
ElectionGuard Encryption
Open source implementation of ElectionGuard's ballot encryption.
Microsoft
- 0.1.11
+ 0.1.12
MIT
https://github.com/microsoft/electionguard-cpp
https://github.com/microsoft/electionguard-cpp
diff --git a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Manifest.cs b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Manifest.cs
index 95a22e70..a30b85ec 100644
--- a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Manifest.cs
+++ b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Manifest.cs
@@ -2209,6 +2209,79 @@ public unsafe Manifest(
}
}
+ ///
+ /// Creates a `Manifest` object
+ ///
+ ///
+ /// election type
+ /// start date for election
+ /// end data for the election
+ /// array of the `GeopoliticalUnit` for election
+ /// array of the `Party` for election
+ /// array of the `Candidate` for election
+ /// array of the `ContestDescription` for election
+ /// array of the `BallotStyle` for election
+ /// name of the election
+ /// contact information for the election
+ public unsafe Manifest(
+ string electionScopeId, ElectionType electionType,
+ DateTime startDate, DateTime endDate,
+ GeopoliticalUnit[] gpUnits, Party[] parties,
+ Candidate[] candidates, ContestDescription[] contests,
+ BallotStyle[] ballotStyles, InternationalizedText name, ContactInformation contact)
+ {
+ IntPtr[] gpUnitPointers = new IntPtr[gpUnits.Length];
+ for (var i = 0; i < gpUnits.Length; i++)
+ {
+ gpUnitPointers[i] = gpUnits[i].Handle.Ptr;
+ gpUnits[i].Dispose();
+ }
+
+ IntPtr[] partyPointers = new IntPtr[parties.Length];
+ for (var i = 0; i < parties.Length; i++)
+ {
+ partyPointers[i] = parties[i].Handle.Ptr;
+ parties[i].Dispose();
+ }
+
+ IntPtr[] candidatePointers = new IntPtr[candidates.Length];
+ for (var i = 0; i < candidates.Length; i++)
+ {
+ candidatePointers[i] = candidates[i].Handle.Ptr;
+ candidates[i].Dispose();
+ }
+
+ IntPtr[] contestPointers = new IntPtr[contests.Length];
+ for (var i = 0; i < contests.Length; i++)
+ {
+ contestPointers[i] = contests[i].Handle.Ptr;
+ contests[i].Dispose();
+ }
+
+ IntPtr[] ballotStylePointers = new IntPtr[ballotStyles.Length];
+ for (var i = 0; i < ballotStyles.Length; i++)
+ {
+ ballotStylePointers[i] = ballotStyles[i].Handle.Ptr;
+ ballotStyles[i].Dispose();
+ }
+
+ var status = NativeInterface.Manifest.New(
+ electionScopeId, electionType, name.Handle,
+ (ulong)new DateTimeOffset(startDate).ToUnixTimeMilliseconds(),
+ (ulong)new DateTimeOffset(endDate).ToUnixTimeMilliseconds(),
+ gpUnitPointers, (ulong)gpUnitPointers.LongLength,
+ partyPointers, (ulong)partyPointers.LongLength,
+ candidatePointers, (ulong)candidatePointers.LongLength,
+ contestPointers, (ulong)contestPointers.LongLength,
+ ballotStylePointers, (ulong)ballotStylePointers.LongLength,
+ contact.Handle,
+ out Handle);
+ if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
+ {
+ throw new ElectionGuardException($"Manifest Error Status: {status}");
+ }
+ }
+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
protected override unsafe void DisposeUnmanaged()
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
diff --git a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/NativeInterface.cs b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/NativeInterface.cs
index e72e03c2..8bdf6a08 100644
--- a/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/NativeInterface.cs
+++ b/bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/NativeInterface.cs
@@ -1888,7 +1888,31 @@ internal static extern Status New(
ulong ballotStylesSize,
out ManifestHandle handle);
- // TODO: eg_election_manifest_new_with_contact
+ [DllImport(DllName, EntryPoint = "eg_election_manifest_new_with_contact",
+ CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ internal static extern Status New(
+ [MarshalAs(UnmanagedType.LPStr)] string electionScopeId,
+ ElectionType electionType,
+ InternationalizedText.InternationalizedTextHandle name,
+ ulong startDate,
+ ulong endDate,
+ // TODO ISSUE #212: type safety
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] gpUnits,
+ ulong gpUnitsSize,
+ // TODO ISSUE #212: type safety
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] parties,
+ ulong partiesSize,
+ // TODO ISSUE #212: type safety
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] candidates,
+ ulong candidatesSize,
+ // TODO ISSUE #212: type safety
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] contests,
+ ulong contestSize,
+ // TODO ISSUE #212: type safety
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] ballotStyles,
+ ulong ballotStylesSize,
+ ContactInformation.ContactInformationHandle contact,
+ out ManifestHandle handle);
[DllImport(DllName, EntryPoint = "eg_election_manifest_free",
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
diff --git a/src/electionguard/serialize.hpp b/src/electionguard/serialize.hpp
index b694ec1d..0cf12154 100644
--- a/src/electionguard/serialize.hpp
+++ b/src/electionguard/serialize.hpp
@@ -513,6 +513,8 @@ namespace electionguard
serialized.push_back({"contact_information", contactInformation});
}
+ serialized.push_back({"spec_version", "1.0"});
+
return serialized;
}
@@ -1059,7 +1061,7 @@ namespace electionguard
{"manifest_hash", serializable.getManifestHash()->toHex()},
{"code_seed", serializable.getBallotCodeSeed()->toHex()},
{"contests", contests},
- {"ballot_code", serializable.getBallotCode()->toHex()},
+ {"code", serializable.getBallotCode()->toHex()},
{"timestamp", serializable.getTimestamp()},
{"crypto_hash", serializable.getCryptoHash()->toHex()},
};
@@ -1074,7 +1076,7 @@ namespace electionguard
auto style_id = j["style_id"].get();
auto manifest_hash = j["manifest_hash"].get();
auto code_seed = j["code_seed"].get();
- auto ballot_code = j["ballot_code"].get();
+ auto ballot_code = j["code"].get();
auto timestamp = j["timestamp"].get();
auto ballot_nonce = j["nonce"].is_null() ? "" : j["nonce"].get();
auto crypto_hash = j["crypto_hash"].get();
@@ -1265,7 +1267,7 @@ namespace electionguard
{
auto result = SubmittedBallotWrapper::fromObjectWrapper(serializable);
- result["state"] = getBallotBoxStateString(serializable.getState());
+ result["state"] = serializable.getState();
return result;
}
@@ -1273,7 +1275,7 @@ namespace electionguard
static unique_ptr toObject(json j)
{
auto ciphertext = SubmittedBallotWrapper::toObjectWrapper(j);
- auto state = getBallotBoxState(j["state"].get());
+ auto state = electionguard::BallotBoxState(j["state"].get());
// TODO: make this a move instead of a copy
return electionguard::SubmittedBallot::from(*ciphertext, state);
}
@@ -1327,30 +1329,29 @@ namespace electionguard
json plaintext =
CompactPlaintextBallotWrapper::fromObjectWrapper(*serializable.getPlaintext());
- json result = {
- {"plaintext", plaintext},
- {"code_seed", serializable.getBallotCodeSeed()->toHex()},
- {"ballot_code", serializable.getBallotCode()->toHex()},
- {"nonce", serializable.getNonce()->toHex()},
- {"timestamp", serializable.getTimestamp()},
- {"ballot_box_state", getBallotBoxStateString(serializable.getBallotBoxState())}};
+ json result = {{"plaintext", plaintext},
+ {"code_seed", serializable.getBallotCodeSeed()->toHex()},
+ {"code", serializable.getBallotCode()->toHex()},
+ {"nonce", serializable.getNonce()->toHex()},
+ {"timestamp", serializable.getTimestamp()},
+ {"ballot_box_state", serializable.getBallotBoxState()}};
return result;
}
static unique_ptr toObject(json j)
{
auto codeSeed = j["code_seed"].get();
- auto ballotCode = j["ballot_code"].get();
+ auto ballotCode = j["code"].get();
auto nonce = j["nonce"].get();
auto timestamp = j["timestamp"].get();
- auto ballotBoxState = j["ballot_box_state"].get();
+ auto ballotBoxState =
+ electionguard::BallotBoxState(j["ballot_box_state"].get());
auto plaintext = CompactPlaintextBallotWrapper::toObjectWrapper(j["plaintext"]);
return make_unique(
- move(plaintext), getBallotBoxState(ballotBoxState),
- ElementModQ::fromHex(codeSeed), ElementModQ::fromHex(ballotCode), timestamp,
- ElementModQ::fromHex(nonce));
+ move(plaintext), ballotBoxState, ElementModQ::fromHex(codeSeed),
+ ElementModQ::fromHex(ballotCode), timestamp, ElementModQ::fromHex(nonce));
}
public: