Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add casting #50

Merged
merged 2 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion codegen/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
uint256 public constant Multiply = 72;
uint256 public constant LessThan = 73;
uint256 public constant OptimisticRequire = 75;
uint256 public constant Cast = 76;
uint256 public constant TrivialEncrypt = 77;
}
"""
Expand Down Expand Up @@ -299,7 +300,7 @@
bytes32[1] memory output;
uint256 outputLen = 32;

// Call the cast precompile.
// Call the verify precompile.
uint256 precompile = Precompiles.Verify;
assembly {
// jump over the 32-bit `size` field of the `bytes` data structure of the `input` to read actual bytes
Expand All @@ -310,6 +311,36 @@
result = uint256(output[0]);
}

function cast(
uint256 ciphertext,
uint8 toType
) internal view returns (uint256 result) {
bytes memory input = bytes.concat(bytes32(ciphertext), bytes1(toType));
uint256 inputLen = input.length;

bytes32[1] memory output;
uint256 outputLen = 32;

// Call the cast precompile.
uint256 precompile = Precompiles.Cast;
assembly {
// jump over the 32-bit `size` field of the `bytes` data structure of the `input` to read actual bytes
if iszero(
staticcall(
gas(),
precompile,
add(input, 32),
inputLen,
output,
outputLen
)
) {
revert(0, 0)
}
}
result = uint256(output[0]);
}

function trivialEncrypt(
uint256 value,
uint8 toType
Expand Down Expand Up @@ -402,6 +433,17 @@
if i == j: # TODO: remove this line when casting is implemented
f.write(to_print.format(i=i, j=j, k=i if i>j else j))

to_print="""
function asEuint{i}(euint{j} ciphertext) internal view returns (euint{i}) {{
return euint{i}.wrap(Impl.cast(euint{j}.unwrap(ciphertext), Common.euint{i}_t));
}}
"""

for i in (2**p for p in range(3, 6)):
for j in (2**p for p in range(3, 6)):
if i != j:
f.write(to_print.format(i=i, j=j))

to_print="""
function asEuint{i}(bytes memory ciphertext) internal view returns (euint{i}) {{
return euint{i}.wrap(Impl.verify(ciphertext, Common.euint{i}_t));
Expand Down
156 changes: 46 additions & 110 deletions lib/Impl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,7 @@ library Impl {
// Call the add precompile.
uint256 precompile = Precompiles.Add;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
output,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, output, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -64,16 +55,7 @@ library Impl {
// Call the sub precompile.
uint256 precompile = Precompiles.Subtract;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
output,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, output, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -98,16 +80,7 @@ library Impl {
// Call the mul precompile.
uint256 precompile = Precompiles.Multiply;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
output,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, output, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -117,10 +90,7 @@ library Impl {

// Evaluate `lhs <= rhs` on the given ciphertexts and, if successful, return the resulting ciphertext.
// If successful, the resulting ciphertext is automatically verified.
function lte(
uint256 lhs,
uint256 rhs
) internal view returns (uint256 result) {
function lte(uint256 lhs, uint256 rhs) internal view returns (uint256 result) {
bytes32[2] memory input;
input[0] = bytes32(lhs);
input[1] = bytes32(rhs);
Expand All @@ -132,16 +102,7 @@ library Impl {
// Call the lte precompile.
uint256 precompile = Precompiles.LessThanOrEqual;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
output,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, output, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -151,10 +112,7 @@ library Impl {

// Evaluate `lhs < rhs` on the given ciphertexts and, if successful, return the resulting ciphertext.
// If successful, the resulting ciphertext is automatically verified.
function lt(
uint256 lhs,
uint256 rhs
) internal view returns (uint256 result) {
function lt(uint256 lhs, uint256 rhs) internal view returns (uint256 result) {
bytes32[2] memory input;
input[0] = bytes32(lhs);
input[1] = bytes32(rhs);
Expand All @@ -166,16 +124,7 @@ library Impl {
// Call the lte precompile.
uint256 precompile = Precompiles.LessThan;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
output,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, output, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -186,11 +135,7 @@ library Impl {
// If `control`'s value is 1, the resulting value is the same value as `ifTrue`.
// If `control`'s value is 0, the resulting value is the same value as `ifFalse`.
// If successful, the resulting ciphertext is automatically verified.
function cmux(
uint256 control,
uint256 ifTrue,
uint256 ifFalse
) internal view returns (uint256 result) {
function cmux(uint256 control, uint256 ifTrue, uint256 ifFalse) internal view returns (uint256 result) {
// result = (ifTrue - ifFalse) * control + ifFalse

bytes32[2] memory input;
Expand All @@ -203,16 +148,7 @@ library Impl {
uint256 precompile = Precompiles.Subtract;
bytes32[1] memory subOutput;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
subOutput,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, subOutput, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -223,16 +159,7 @@ library Impl {
precompile = Precompiles.Multiply;
bytes32[1] memory mulOutput;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
mulOutput,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, mulOutput, outputLen)) {
revert(0, 0)
}
}
Expand All @@ -243,23 +170,14 @@ library Impl {
precompile = Precompiles.Add;
bytes32[1] memory addOutput;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
addOutput,
outputLen
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, addOutput, outputLen)) {
revert(0, 0)
}
}

result = uint256(addOutput[0]);
}

// Optimistically requires that the `ciphertext` is true.
//
// This function does not evaluate the given `ciphertext` at the time of the call.
Expand All @@ -286,10 +204,7 @@ library Impl {
}
}

function reencrypt(
uint256 ciphertext,
bytes32 publicKey
) internal view returns (bytes memory reencrypted) {
function reencrypt(uint256 ciphertext, bytes32 publicKey) internal view returns (bytes memory reencrypted) {
bytes32[2] memory input;
input[0] = bytes32(ciphertext);
input[1] = publicKey;
Expand All @@ -300,16 +215,7 @@ library Impl {
// Call the reencrypt precompile.
uint256 precompile = Precompiles.Reencrypt;
assembly {
if iszero(
staticcall(
gas(),
precompile,
input,
inputLen,
reencrypted,
reencryptedSize
)
) {
if iszero(staticcall(gas(), precompile, input, inputLen, reencrypted, reencryptedSize)) {
revert(0, 0)
}
}
Expand All @@ -321,7 +227,16 @@ library Impl {
// Call the fhePubKey precompile.
uint256 precompile = Precompiles.FhePubKey;
assembly {
if iszero(staticcall(gas(), precompile, 0, 0, key, fhePubKeySize)) {
if iszero(
staticcall(
gas(),
precompile,
0,
0,
key,
fhePubKeySize
)
) {
revert(0, 0)
}
}
Expand All @@ -337,8 +252,29 @@ library Impl {
bytes32[1] memory output;
uint256 outputLen = 32;

// Call the cast precompile.
// Call the verify precompile.
uint256 precompile = Precompiles.Verify;
assembly {
// jump over the 32-bit `size` field of the `bytes` data structure of the `input` to read actual bytes
if iszero(staticcall(gas(), precompile, add(input, 32), inputLen, output, outputLen)) {
revert(0, 0)
}
}
result = uint256(output[0]);
}

function cast(
uint256 ciphertext,
uint8 toType
) internal view returns (uint256 result) {
bytes memory input = bytes.concat(bytes32(ciphertext), bytes1(toType));
uint256 inputLen = input.length;

bytes32[1] memory output;
uint256 outputLen = 32;

// Call the cast precompile.
uint256 precompile = Precompiles.Cast;
assembly {
// jump over the 32-bit `size` field of the `bytes` data structure of the `input` to read actual bytes
if iszero(
Expand Down
1 change: 1 addition & 0 deletions lib/Precompiles.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ library Precompiles {
uint256 public constant Multiply = 72;
uint256 public constant LessThan = 73;
uint256 public constant OptimisticRequire = 75;
uint256 public constant Cast = 76;
uint256 public constant TrivialEncrypt = 77;
}
Loading