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

Edit Problems Description: 2 - cat gifs, and 3 - delegation #20

Merged
merged 10 commits into from
Aug 15, 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
38 changes: 31 additions & 7 deletions problems/2-cat-gifs/problem.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
# Storing cat gifs for fun and gossip
# Storing cat memes for fun and gossip

These cat gifs are not going to store themselves. Lets hurl them into the permanent web where they can be revered **forever**.
These cat memes of yours are not going to store themselves. Let's catapult them into the permanent web where they can be adored **forever**.

But wait, what did you just say? Permanent web? Yeah, like IPFS.

IPFS uses content addressing (sometimes known as hash addressing) where you refer to data by a "hash" that is created from the data itself. If the data changes, the hash changes. Anyone can store and distribute your data because the hash guarantees the data cannot change. Imagine the caching possibilities!
**What is the Permanent Web?**

In the third web, you hash your content _first_, that way you know the hash you generated refers to the content you generated it from, and if you fetch the content by it's hash, you can verify that the content you receive hasn't been tampered with because it "hashes" to the same value.
Imagine a world where your favorite cat memes are preserved forever. That's the magic of IPFS (InterPlanetary File System). IPFS uses content addressing, a fancy way of saying you refer to data by a "hash" created from the data itself. If the data changes, the hash changes too. This ensures that the data remains unchanged and untampered with. Think of it as a digital fingerprint for your memes!

In IPFS, hashes are referred to as Content Identifiers, or CID for short. In this exercise we're going to transform your data into content addressed data, that you can refer to via a CID, upload it to web3.storage and print out the CID.
**Why Content Addressing?**

Create a _new_ file for your solution e.g. `ex3.mjs`. Import the w3up library and create the client as before. Install the module `files-from-path` from npm (`npm install files-from-path`) and import it like so:
On the third web, you hash your content first. This means the hash you generate is unique to the content you created. If you fetch the content by its hash, you can be sure that the content hasn't been tampered with because it "hashes" to the same value. It's like a super-secure way to keep your cat memes pristine and perfect.

**Let's Get Started!**

Download a meme locally (or use the one that you already have!), upload them to web3.storage, and print out their unique CID (Content Identifier). Once you downloaded the last meme your friend sent you, continue with:

**1. Create a New File**
Create a _new_ file, like `ex3.mjs`.
**2. Import w3up and create the client**
Import the w3up library and create the client as before.
**3. Instal the `files-from-path` module**
It helps read files from your local file system and transforms file paths into a format that can be uploaded to web3.storage. Without this module, you’d be stuck doing all the heavy lifting of file reading and formatting - who has time for that in this economy?
hakierka marked this conversation as resolved.
Show resolved Hide resolved
Install `npm install files-from-path` and import:

```js
import { filesFromPaths } from 'files-from-path'
```
**4. Upload the meme**
Specify the path to the meme:
```js
const files = await filesFromPaths(['path-to-your-meme'])
```
and upload it with using the client's `uploadDirectory` function:
```js
const root = await client.uploadDirectory(files)
```

Use the `uploadDirectory` function on the client to upload you favourite cat gif from your local file system to web3.storage. You'll receive a CID for the content, use `console.log` to print it out.
Finally, print the CID:
```js
console.log(root.toString())
```

─────────────────────────────────────────────────────────────────────────────
* To print these instructions again, run: `$ADVENTURE_NAME print`
Expand Down
50 changes: 43 additions & 7 deletions problems/3-delegation/problem.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ Excellent cat gifs. Well done you.

Now, lets talk UCAN.

UCANs are like JWTs with super powers. They’re an essential component in decentralized authorization. They use public key cryptography - so whenever you create a UCAN you _sign it_ with your private key.
**What are UCANs?**
UCANs (User Controlled Authorization Networks) are like supercharged passwords. They’re used for secure, decentralized authorization. When you create a UCAN, you sign it with your private key, kind of like signing a document with your unique signature.

The best thing about UCANs is that you can provably delegate "capabilities" that allow others to act on your behalf, without ever sharing your private key.
**Why are UCANs cool?**
The best thing about UCANs is that you can securely give permission to others to do things on your behalf without sharing your private key. This is called "delegation".

In this exercise, you're going to delegate an `upload/list` capability to the workshop. Behind the scenes the workshop will create it's own private key, and pass it's public key (it's DID) to you on `stdin`.
**Your Mission**
In this exercise, you're going to delegate an `upload/list` capability to the workshop. The workshop will create its own private key and pass its public key (DID) to you via `stdin` (standard input).

Your program should read from `process.stdin`, create a delegation for the `upload/list` capability and write it to `process.stdout`. So, something like this:

Expand All @@ -18,20 +21,53 @@ DID => your program => delegation

Then the workshop will be able to **invoke** the capability to list the items _you've_ uploaded to _your_ space. It'll verify it can find that cat gif you uploaded in the previous exercise.
hakierka marked this conversation as resolved.
Show resolved Hide resolved

You can read and parse the DID from `stdin` like so:
One last thing, make sure the delegation remains valid for **more than one hour**.


**Steps to complete the task**
**1. Create new file and read a DID from `stdin`**
Create new file, like `ex4.mjs` and then you can read and parse the DID from `process.stdin`:
```js
import fs from 'node:fs'
import * as DID from '@ipld/dag-ucan/did'

const data = fs.readFileSync(process.stdin.fd, 'utf-8')
const principal = DID.parse(data)
```
**2. Create the delegetion**
Use the client to create a delegation for `upload/list` to the provided DID:
```js
import * as Client from '@web3-storage/w3up-client'
```
Create the client and set the expiration time for the delegation:
```js
const client = await Client.create()
const twoHours = 1000 * 60 * 60 * 2 // Two hours in milliseconds
```
In the example above, it is set to two hours.
**3. Generate the delegation**
Create the delegation for the `upload/list` capability:
```js
const delegation = await client.createDelegation(principal, ['upload/list'], {
// Expiration is in seconds from Unix epoch
expiration: Math.round((Date.now() + twoHours) / 1000),
})
```

Create a _new_ file for your solution e.g. `ex4.mjs` and use the client to create a delegation for `upload/list` to the provided DID. Create an archive of the delegation and write it to `process.stdout`.

One last thing, make sure the delegation remains valid for **more than one hour**.
**4. Archive the delegation**
Archive the delegation and handle any errors:
```js
const { ok: archive, error } = await delegation.archive()
if (!archive) {
throw new Error('Failed to create delegation archive', { cause: error })
}
```

**5. Output the delegation**
Write the delegation to `process.stdout`:
```js
process.stdout.write(archive)
```
─────────────────────────────────────────────────────────────────────────────
* To print these instructions again, run: `$ADVENTURE_NAME print`
* To verify your program, run: `$ADVENTURE_NAME verify ex4.mjs`
Expand Down
Loading