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

Mock the confidential datastore for Foundry #40

Merged
merged 7 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
12 changes: 6 additions & 6 deletions src/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ interface ConfidentialInputsWrapperI {
function resetConfidentialInputs() external;
}

interface ConfidentialStoreI {
function reset() external;
}

contract SuaveEnabled is Test {
ConfidentialInputsWrapperI constant confInputsWrapper = ConfidentialInputsWrapperI(Suave.CONFIDENTIAL_INPUTS);
ConfidentialStoreI constant confStoreWrapper = ConfidentialStoreI(0x0101010101010101010101010101010101010101);

function setUp() public {
string[] memory inputs = new string[](3);
Expand Down Expand Up @@ -82,11 +87,6 @@ contract SuaveEnabled is Test {
}

function resetConfidentialStore() public {
string[] memory inputs = new string[](3);
inputs[0] = "suave-geth";
inputs[1] = "forge";
inputs[2] = "reset-conf-store";

vm.ffi(inputs);
confStoreWrapper.reset();
}
}
2 changes: 0 additions & 2 deletions src/Transactions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ library Transactions {

function signTxn(Transactions.EIP1559Request memory request, string memory signingKey)
internal
view
returns (Transactions.EIP1559 memory response)
{
bytes memory rlp = Transactions.encodeRLP(request);
Expand All @@ -325,7 +324,6 @@ library Transactions {

function signTxn(Transactions.EIP155Request memory request, string memory signingKey)
internal
view
returns (Transactions.EIP155 memory response)
{
bytes memory rlp = Transactions.encodeRLP(request);
Expand Down
106 changes: 106 additions & 0 deletions src/forge/ConfidentialStore.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: UNLICENSED

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to add a license?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing is licensed for now. I will bring this up during weekly tomorrow.

pragma solidity ^0.8.8;

import "../suavelib/Suave.sol";
import "forge-std/Test.sol";

contract ConfidentialStore is Test {
mapping(bytes32 => Suave.DataRecord[]) private dataRecordsByConditionAndNamespace;
mapping(Suave.DataId => mapping(string => bytes)) private dataRecordsContent;
uint64 private numRecords;

type DataId is bytes16;

constructor() {
vm.record();
}

function newDataRecord(
uint64 decryptionCondition,
address[] memory allowedPeekers,
address[] memory allowedStores,
string memory dataType
) public returns (Suave.DataRecord memory) {
numRecords++;

// Use a counter of the records to create a unique key
Suave.DataId id = Suave.DataId.wrap(bytes16(keccak256(abi.encodePacked(numRecords))));
numRecords++;

Suave.DataRecord memory newRecord;
newRecord.id = id;
newRecord.decryptionCondition = decryptionCondition;
newRecord.allowedPeekers = allowedPeekers;
newRecord.allowedStores = allowedStores;
newRecord.version = dataType;

// Use a composite index to store the records for the 'fetchDataRecords' function
bytes32 key = keccak256(abi.encodePacked(decryptionCondition, dataType));
dataRecordsByConditionAndNamespace[key].push(newRecord);

return newRecord;
}

function fetchDataRecords(uint64 cond, string memory namespace) public view returns (Suave.DataRecord[] memory) {
bytes32 key = keccak256(abi.encodePacked(cond, namespace));
return dataRecordsByConditionAndNamespace[key];
}

function confidentialStore(Suave.DataId dataId, string memory key, bytes memory value) public {
dataRecordsContent[dataId][key] = value;
}

function confidentialRetrieve(Suave.DataId dataId, string memory key) public view returns (bytes memory) {
return dataRecordsContent[dataId][key];
}

function reset() public {
(, bytes32[] memory writes) = vm.accesses(address(this));
for (uint256 i = 0; i < writes.length; i++) {
vm.store(address(this), writes[i], 0);
}
}
}

contract ConfidentialStoreWrapper is Test {
fallback() external {
address confidentialStoreAddr = 0x0101010101010101010101010101010101010101;

address addr = address(this);
bytes4 sig;

// You can use 'forge selectors list' to retrieve the function signatures
if (addr == Suave.CONFIDENTIAL_STORE) {
sig = 0xd22a3b0b;
} else if (addr == Suave.CONFIDENTIAL_RETRIEVE) {
sig = 0xe3b417bc;
} else if (addr == Suave.FETCH_DATA_RECORDS) {
sig = 0xccb885c4;
} else if (addr == Suave.NEW_DATA_RECORD) {
sig = 0xe3fbcfc3;
} else {
revert("function signature not found in the confidential store");
}

bytes memory input = msg.data;

// call 'confidentialStore' with the selector and the input data.
(bool success, bytes memory output) = confidentialStoreAddr.call(abi.encodePacked(sig, input));
if (!success) {
revert("Call to confidentialStore failed");
}

if (addr == Suave.CONFIDENTIAL_RETRIEVE) {
// special case we have to unloop the value from the abi
// since it comes encoded as tuple() but we return the value normally
// this was a special case that was not fixed yet in suave-geth.
output = abi.decode(output, (bytes));
}

assembly {
let location := output
let length := mload(output)
return(add(location, 0x20), length)
}
}
}
18 changes: 18 additions & 0 deletions src/forge/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import "../suavelib/Suave.sol";
import "./Connector.sol";
import "./ConfidentialInputs.sol";
import "./SuaveAddrs.sol";
import "./ConfidentialStore.sol";

interface registryVM {
function etch(address, bytes calldata) external;
}

library Registry {
registryVM constant vm = registryVM(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
address public constant confidentialStoreAddr = 0x0101010101010101010101010101010101010101;

function enable() public {
// enable all suave libraries
Expand All @@ -22,7 +24,23 @@ library Registry {
vm.etch(addrList[i], type(Connector).runtimeCode);
}

// enable the confidential store
deployCodeTo(type(ConfidentialStore).creationCode, confidentialStoreAddr);

// enable the confidential inputs wrapper
vm.etch(Suave.CONFIDENTIAL_RETRIEVE, type(ConfidentialStoreWrapper).runtimeCode);
vm.etch(Suave.CONFIDENTIAL_STORE, type(ConfidentialStoreWrapper).runtimeCode);
vm.etch(Suave.NEW_DATA_RECORD, type(ConfidentialStoreWrapper).runtimeCode);
vm.etch(Suave.FETCH_DATA_RECORDS, type(ConfidentialStoreWrapper).runtimeCode);

// enable is confidential wrapper
vm.etch(Suave.CONFIDENTIAL_INPUTS, type(ConfidentialInputsWrapper).runtimeCode);
}

function deployCodeTo(bytes memory creationCode, address where) internal {
vm.etch(where, creationCode);
(bool success, bytes memory runtimeBytecode) = where.call("");
require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
vm.etch(where, runtimeBytecode);
}
}
2 changes: 1 addition & 1 deletion src/protocols/Bundle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ library Bundle {
bytes[] txns;
}

function sendBundle(string memory url, BundleObj memory bundle) internal view returns (bytes memory) {
function sendBundle(string memory url, BundleObj memory bundle) internal returns (bytes memory) {
Suave.HttpRequest memory request = encodeBundle(bundle);
request.url = url;
return Suave.doHTTPRequest(request);
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/MevShare.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ library MevShare {
return request;
}

function sendBundle(string memory url, Bundle memory bundle) internal view {
function sendBundle(string memory url, Bundle memory bundle) internal {
Suave.HttpRequest memory request = encodeBundle(bundle);
request.url = url;
Suave.doHTTPRequest(request);
Expand Down
Loading
Loading