Skip to content

Commit

Permalink
Adding private-storage docs
Browse files Browse the repository at this point in the history
Signed-off-by: dwertent <[email protected]>
  • Loading branch information
dwertent committed Jan 13, 2025
1 parent 541a251 commit df90565
Show file tree
Hide file tree
Showing 17 changed files with 871 additions and 53 deletions.
143 changes: 143 additions & 0 deletions doc-site/docs/tutorials/private-storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Private Storage Contract

In this tutorial, you'll learn how to deploy and interact with a **private storage contract** using Paladin's privacy groups. Unlike the public storage example, here only authorized members of a privacy group can interact with the contract, ensuring secure and private data handling.

---

## Prerequisites

Before starting, make sure you have:

1. Completed the [Public Storage Tutorial](./public-storage.md) and are familiar with:
- Deploying and interacting with contracts.
- Using Paladin SDK for blockchain transactions.
2. A running Paladin network with multiple nodes (at least 3 for this tutorial).

---

## Overview

The `PrivateStorage` tutorial demonstrates how to:

1. Create a **privacy group** with selected members.
2. Deploy a **private Storage contract** within the group.
3. Interact with the contract securely within the group.
4. Test privacy by attempting access from a non-member node.

The example code can be found in the [Paladin example repository](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/example/private-storage).

The Solidity contract remains the same as in the [Public Storage Tutorial](https://github.com/LF-Decentralized-Trust-labs/paladin/blob/main/solidity/contracts/tutorial/Storage.sol). However, the interaction is scoped to the privacy group.

---

## Step 1: Create a Privacy Group

To enable private interactions, start by creating a privacy group with selected members.

```typescript
// Create a privacy group with Node1 and Node2
logger.log("Creating a privacy group for Node1 and Node2...");
const penteFactory = new PenteFactory(paladinNode1, "pente");
const memberPrivacyGroup = await penteFactory.newPrivacyGroup(verifierNode1, {
group: {
salt: newGroupSalt(), // Generate a unique salt for the group
members: [verifierNode1, verifierNode2], // Include Node1 and Node2 as members
},
evmVersion: "shanghai",
endorsementType: "group_scoped_identities",
externalCallsEnabled: true,
});

if (!checkDeploy(memberPrivacyGroup)) {
logger.error("Failed to create the privacy group.");
return false;
}
logger.log("Privacy group created successfully!");
```

---

## Step 2: Deploy the Contract in the Privacy Group

Deploy the `Storage` contract within the created privacy group.

```typescript
logger.log("Deploying a private Storage contract...");
const contractAddress = await memberPrivacyGroup.deploy(
storageJson.abi, // ABI of the Storage contract
storageJson.bytecode, // Bytecode of the Storage contract
verifierNode1 // Deploying as Node1
);

if (!contractAddress) {
logger.error("Failed to deploy the private Storage contract.");
return false;
}
logger.log(`Private Storage contract deployed! Address: ${contractAddress}`);
```

---

## Step 3: Store and Retrieve Values as Group Members

### Store a Value

Group members can store values securely in the private contract.

```typescript
const privateStorage = new PrivateStorage(memberPrivacyGroup, contractAddress);

logger.log("Storing value (125) in the private Storage contract...");
const storeTx = await privateStorage.invoke(verifierNode1, "store", { num: 125 });
logger.log("Value stored successfully! Transaction hash:", storeTx?.transactionHash);
```

---

### Retrieve the Value as a Member

Authorized group members can retrieve the stored value.

```typescript
logger.log("Node1 retrieving the stored value...");
const retrievedValueNode1 = await privateStorage.call(verifierNode1, "retrieve", []);
logger.log("Node1 retrieved the value successfully:", retrievedValueNode1["0"]);

logger.log("Node2 retrieving the stored value...");
const retrievedValueNode2 = await privateStorage
.using(paladinNode2)
.call(verifierNode2, "retrieve", []);
logger.log("Node2 retrieved the value successfully:", retrievedValueNode2["0"]);
```

---

## Step 4: Verify Privacy by Testing Unauthorized Access

When an outsider (Node3) tries to access the private contract, the attempt should fail.

```typescript
try {
logger.log("Node3 (outsider) attempting to retrieve the value...");
await privateStorage.using(paladinNode3).call(verifierNode3, "retrieve", []);
logger.error("Node3 (outsider) should not have access to the private Storage contract!");
return false;
} catch (error) {
logger.info("Node3 (outsider) cannot retrieve data. Access denied.");
}
```

---

## Conclusion

Congratulations! You’ve successfully:

1. Created a privacy group with selected members.
2. Deployed a `Storage` contract in the privacy group.
3. Ensured secure interactions with the contract for group members.
4. Verified that unauthorized access is blocked.

---

## Next Steps
5 changes: 4 additions & 1 deletion doc-site/docs/tutorials/public-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,7 @@ Congratulations! You’ve successfully:
---

## Next Steps


Now that you've mastered deploying and interacting with a **public storage contract**, it's time to take things to the next level. In the next tutorial, you'll learn about **Storage with Privacy**, where you will add a privacy layer to the blockchain.the blockchain!

[Continue to the Privacy Storage Contract Tutorial →](./private-storage.md)
2 changes: 2 additions & 0 deletions doc-site/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ nav:
- Tutorials:
- Introduction: tutorials/index.md
- Hello World: tutorials/hello-world.md
- Public Storage: tutorials/public-storage.md
- Private Storage: tutorials/private-storage.md
- Bond Issuance: tutorials/bond-issuance.md
- Wholesale CBDC: tutorials/zkp-cbdc.md
- Reference:
Expand Down
13 changes: 13 additions & 0 deletions example/privacy-storage/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Run",
"runtimeExecutable": "npm",
"args": ["run", "start"],
"request": "launch",
"type": "node",
"outputCapture": "std"
}
]
}
46 changes: 46 additions & 0 deletions example/privacy-storage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Example: Hello World


See the [tutorial](https://lf-decentralized-trust-labs.github.io/paladin/head/tutorials/private-storage/) for a detailed explanation.

## Pre-requisites

Requires a local Paladin instance running on `localhost:31548`.
Requires a local Paladin instance running on `localhost:31648`.
Requires a local Paladin instance running on `localhost:31748`.

## Run standalone

Compile [Solidity contracts](../../solidity):

```shell
cd ../../solidity
npm install
npm run compile
```

Build [TypeScript SDK](../../sdk/typescript):

```shell
cd ../../sdk/typescript
npm install
npm run abi
npm run build
```

Run example:

```shell
npm install
npm run abi
npm run start
```

## Run with Gradle

The following will perform all pre-requisites and then run the example:

```shell
../../gradlew build
npm run start
```
73 changes: 73 additions & 0 deletions example/privacy-storage/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright © 2024 Kaleido, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

configurations {
// Resolvable configurations
contractCompile {
canBeConsumed = false
canBeResolved = true
}
buildSDK {
canBeConsumed = false
canBeResolved = true
}
}

dependencies {
contractCompile project(path: ':solidity', configuration: 'compiledContracts')
buildSDK project(path: ':sdk:typescript', configuration: 'buildSDK')
}

task install(type: Exec) {
executable 'npm'
args 'install'

inputs.files(configurations.buildSDK)
inputs.files('package.json')
outputs.files('package-lock.json')
outputs.dir('node_modules')
}

task copyABI(type: Exec, dependsOn: install) {
executable 'npm'
args 'run'
args 'abi'

inputs.files(configurations.contractCompile)
inputs.dir('scripts')
outputs.dir('src/abis')
}

task build(type: Exec, dependsOn: [install, copyABI]) {
executable 'npm'
args 'run'
args 'build'

inputs.dir('src')
outputs.dir('build')
}

task e2e(type: Exec, dependsOn: [build]) {
dependsOn ':operator:deploy'

executable 'npm'
args 'run'
args 'start'
}

task clean(type: Delete) {
delete 'node_modules'
delete 'build'
}
Loading

0 comments on commit df90565

Please sign in to comment.