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

Oyster Secret Storage Implementation #14

Open
wants to merge 65 commits into
base: master
Choose a base branch
from
Open

Conversation

@rajatlko13 rajatlko13 self-assigned this Sep 23, 2024
@rajatlko13 rajatlko13 requested a review from vg-27 September 23, 2024 07:10
contracts/secret-storage/SecretStorage.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStorage.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStorage.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStorage.sol Outdated Show resolved Hide resolved
@vg-27 vg-27 force-pushed the rajat/secret-store branch from 54d5f5d to 738a5e0 Compare September 25, 2024 06:17
contracts/secret-storage/EnclaveStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Show resolved Hide resolved
contracts/secret-storage/EnclaveStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
@vg-27
Copy link
Member

vg-27 commented Sep 27, 2024

Impl looks, good, can add UTs and scripts for deployment.

Copy link
Member

@vg-27 vg-27 left a comment

Choose a reason for hiding this comment

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

review pending for secret manager UT

scripts/deploySecretStore.ts Show resolved Hide resolved
scripts/deploySecretStore.ts Outdated Show resolved Hide resolved
test/secret-storage/SecretStore.ts Outdated Show resolved Hide resolved
test/secret-storage/SecretStore.ts Outdated Show resolved Hide resolved
test/secret-storage/SecretStore.ts Outdated Show resolved Hide resolved
test/secret-storage/SecretStore.ts Show resolved Hide resolved
test/secret-storage/SecretStore.ts Outdated Show resolved Hide resolved
wallets = signers.map((_, idx) => walletForIndex(idx));

token = addrs[1],
noOfNodesToSelect = 3,
Copy link
Member

Choose a reason for hiding this comment

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

nit: indent to left

test/secret-storage/SecretManager.ts Show resolved Hide resolved
await expect(secretManager.acknowledgeStoreFailed(secretId))
.to.be.revertedWithCustomError(secretManager, "SecretManagerAcknowledgedAlready");
});
});
Copy link
Member

Choose a reason for hiding this comment

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

add case where at least one secret store has acknowledged but not others.

test/secret-storage/SecretManager.ts Show resolved Hide resolved
test/secret-storage/SecretManager.ts Show resolved Hide resolved
test/secret-storage/SecretManager.ts Outdated Show resolved Hide resolved
test/secret-storage/SecretManager.ts Outdated Show resolved Hide resolved
let secretId = 1;
await expect(secretManager.connect(signers[1]).terminateSecret(secretId))
.to.be.revertedWithCustomError(secretManager, "SecretManagerNotUserStoreOwner");
});
Copy link
Member

Choose a reason for hiding this comment

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

few more cases:

  1. termination after termination
  2. termination after end timestamp
  3. combination of termination and acknowledgement time period

test/secret-storage/SecretManager.ts Show resolved Hide resolved
test/secret-storage/SecretManager.ts Outdated Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 16, 2024 05:29

//-------------------------------- TeeManager start ----------------------------------//

modifier onlySecretStore() {
Copy link
Member

Choose a reason for hiding this comment

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

use onlyRole instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Current approach is better as we already have the SECRET_STORE storage var. With onlyRole, we will have to do an extra transaction to grant the role.

Copy link
Member

Choose a reason for hiding this comment

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

what's the pros of using onlyRole that we are missing here? Any security concerns? Also, you can set the ROLE during initialization of contract.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TeeManager contract will be deployed first and then the Executors and SecretStore contracts. So, we cannot assign the role during initialization. I have made setter functions for these two contracts.
We can grant the roles within these setter functions but there isn't any security threat with the existing approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, just in case we have to update the Executors or SecretStore contract, first we will have to revoke the role and then grant it to the new contract, so another overhead.

contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/Executors.sol Outdated Show resolved Hide resolved
contracts/secret-storage/Executors.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 17, 2024 05:48

//-------------------------------- TeeManager start ----------------------------------//

modifier onlySecretStore() {
Copy link
Member

Choose a reason for hiding this comment

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

what's the pros of using onlyRole that we are missing here? Any security concerns? Also, you can set the ROLE during initialization of contract.

contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 17, 2024 09:11
@@ -378,7 +378,9 @@ contract Executors is
uint256[] memory stakeAmounts = TEE_MANAGER.getTeeNodesStake(_enclaveAddresses);
uint256 len = _enclaveAddresses.length;
for (uint256 index = 0; index < len; index++) {
_insert_unchecked(_env, _enclaveAddresses[index], uint64(stakeAmounts[index] / STAKE_ADJUSTMENT_FACTOR));
address enclaveAddress = _enclaveAddresses[index];
if (executors[enclaveAddress].activeJobs < executors[enclaveAddress].jobCapacity)
Copy link
Member

Choose a reason for hiding this comment

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

make sure whoever is calling this method, doesn't put this check of active jobs, otherwise it would be redundant.

contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/TeeManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/mocks/TeeManagerMock.sol Outdated Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 25, 2024 07:33
@@ -21,8 +21,30 @@ contract JobsUser {

event FailedCallback(uint256 indexed jobId, uint256 slashedAmount);

// function createJob(
Copy link
Member

Choose a reason for hiding this comment

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

can remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is still being used in the serverless-v2 contracts, so let's keep it for now.

contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
address _enclaveAddress,
uint256 _storageOccupied
) internal {
secretStores[_enclaveAddress].storageOccupied -= _storageOccupied;
Copy link
Member

Choose a reason for hiding this comment

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

we have to make sure storageOccupied get to the value zero before deregistration and remove stake. i.e. no secrets assigned.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already being checked in the respective functions

contracts/secret-storage/TeeManager.sol Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 31, 2024 09:41
contracts/secret-storage/SecretStore.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
contracts/secret-storage/SecretManager.sol Outdated Show resolved Hide resolved
@rajatlko13 rajatlko13 requested a review from vg-27 December 31, 2024 12:02
Copy link
Member

@vg-27 vg-27 left a comment

Choose a reason for hiding this comment

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

Modification looks good.

Copy link
Member

@vg-27 vg-27 left a comment

Choose a reason for hiding this comment

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

TeeManager test reviewed.

) as unknown as AttestationVerifier;

const USDCoin = await ethers.getContractFactory("USDCoin");
let usdcToken = await upgrades.deployProxy(
Copy link
Member

Choose a reason for hiding this comment

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

this contract is not required.

});

// drain then deregister with no occupied storage
it('can deregister tee node without occupied storage', async function () {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it('can deregister tee node without occupied storage', async function () {
it('can deregister tee node without occupied storage and assigned jobs', async function () {

});

// drain then deregister failed with active jobs != 0
it('cannot deregister secret store with occupied storage', async function () {
Copy link
Member

Choose a reason for hiding this comment

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

update the comment, there is no jobs assigned.

Copy link
Member

Choose a reason for hiding this comment

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

add case of active jobs

// select nodes
await secretManager.selectStores(env, 1, 100);
// drain
await teeManager.connect(signers[1]).drainTeeNode(addrs[15]);
Copy link
Member

Choose a reason for hiding this comment

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

relinquish will happen as part of drain, deregister should pass through after this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here we haven't ack the secret, so it still occupies storage. Only after ack, secret is added to the ackSecretIds list, and then removed during draining.

// select nodes
await secretManager.selectStores(1, 1, 100);
// drain
await teeManager.connect(signers[1]).drainTeeNode(addrs[15]);
Copy link
Member

Choose a reason for hiding this comment

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

drain should have relinquished the hold of secret, please check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

secret is unacknowledged

.to.be.revertedWithCustomError(teeManager, "TeeManagerInvalidEnclaveOwner");
});

it('cannot unstake with occupied storage after draining started', async function () {
Copy link
Member

Choose a reason for hiding this comment

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

add case of assigned jobs

.to.emit(teeManager, "TeeNodeRevived").withArgs(addrs[15]);
});

// it("can revive tee node after draining", async function () {
Copy link
Member

Choose a reason for hiding this comment

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

what's the reason for this commented test function? what's the todo here?

takeSnapshotBeforeAndAfterEveryTest(async () => { });

it("can slash store", async function () {
let stakeAmount = 10n ** 20n,
Copy link
Member

Choose a reason for hiding this comment

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

can you set stake amount to max unit256 and test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The max POND supply is 10 billion (10^28). Updated the test for this value.

let wallet = ethers.HDNodeWallet.fromPhrase("test test test test test test test test test test test junk", undefined, "m/44'/60'/0'/0/" + idx.toString());

return new Wallet(wallet.privateKey);
}
Copy link
Member

Choose a reason for hiding this comment

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

nit: newline at end

Copy link
Member

@vg-27 vg-27 left a comment

Choose a reason for hiding this comment

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

Reviewed Secret Store UTs

let storageCapacity = 1e9,
stakeAmount = 10n ** 19n;
for (let index = 0; index < 2; index++) {
await teeManager.registerSecretStore(
Copy link
Member

Choose a reason for hiding this comment

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

Ideally, mocks should have the exact same function signature as that of the original contract. Like, registerSecretStore is not a function TeeManager contract.


takeSnapshotBeforeAndAfterEveryTest(async () => { });

it("can stake", async function () {
Copy link
Member

Choose a reason for hiding this comment

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

we should check the state of tree after stake is added or removed. Condition of minimum stake.

it('cannot drain secret store twice consecutively', async function () {
let env = 1;
await teeManager.drainSecretStore(addrs[15], env, addrs[0]);
await expect(secretStore.connect(signers[1]).drainSecretStore(addrs[15], env, addrs[0]))
Copy link
Member

Choose a reason for hiding this comment

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

can you validate the reason of revert here? invalid account is trying to call the drain on secret store.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it was incorrect. Btw, we cannot test this case here as it is specific to TeeManager contract, where we already have a test for it. So removed this test from SecretStore and Executors.

});
});

describe("SecretStore - Drain/Revive secret store", function () {
Copy link
Member

Choose a reason for hiding this comment

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

testing of renounce secrets ?

await expect(secretManager.markAliveUpdate(addrs[15], currentCheckTimestamp, 500, addrs[2]))
.to.not.be.reverted;

expect(await secretStore.getSecretStoreLastAliveTimestamp(addrs[15])).to.eq(currentCheckTimestamp);
Copy link
Member

Choose a reason for hiding this comment

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

can you validate that slashing has happened?

.to.not.be.reverted;

expect(await secretStore.getSecretStoreDeadTimestamp(addrs[15])).to.eq(currentCheckTimestamp);
expect(await secretStore.getStoreAckSecretIds(addrs[15])).to.deep.eq([]);
Copy link
Member

Choose a reason for hiding this comment

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

verify that slashing is happening

let wallet = ethers.HDNodeWallet.fromPhrase("test test test test test test test test test test test junk", undefined, "m/44'/60'/0'/0/" + idx.toString());

return new Wallet(wallet.privateKey);
}
Copy link
Member

Choose a reason for hiding this comment

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

nit: newline at end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants