Skip to content

Commit

Permalink
Merge pull request #20 from hakierka/amy-edit
Browse files Browse the repository at this point in the history
Edit Problems Description: 2 - cat gifs, and 3 - delegation
  • Loading branch information
hakierka authored Aug 15, 2024
2 parents 73e5283 + 4bea3b8 commit 269ef09
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 19 deletions.
4 changes: 2 additions & 2 deletions bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import adventure from 'adventure'
import * as IntroductionProblem from './problems/0-introduction/index.js'
import * as SpaceOutProblem from './problems/1-space-out/index.js'
import * as CatGifsProblem from './problems/2-cat-gifs/index.js'
import * as CatMemesProblem from './problems/2-cat-gifs/index.js'
import * as DelegationProblem from './problems/3-delegation/index.js'
import * as InfiniteCompressionProblem from './problems/4-infinite-compression/index.js'
import * as MemesProblem from './problems/5-memes/index.js'
Expand All @@ -18,7 +18,7 @@ const shop = adventure({

shop.add('Introduction: UCAN do it!', () => IntroductionProblem)
shop.add('Lets space out', () => SpaceOutProblem)
shop.add('Storing cat gifs for fun and gossip', () => CatGifsProblem)
shop.add('Storing cat memes for fun and gossip', () => CatMemesProblem)
shop.add('Delegation, invocation and procrastination', () => DelegationProblem)
shop.add('Infinite avatar compression!', () => InfiniteCompressionProblem)
shop.add('Memes for my eyes', () => MemesProblem)
Expand Down
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. Install 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?
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
54 changes: 45 additions & 9 deletions problems/3-delegation/problem.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,73 @@
# Delegation, invocation and procrastination

Excellent cat gifs. Well done you.
Excellent cat memes. 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:

```
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.
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 meme you uploaded in the previous exercise.

One last thing, make sure the delegation remains valid for **more than one hour**.

You can read and parse the DID from `stdin` like so:

**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
2 changes: 1 addition & 1 deletion problems/4-infinite-compression/problem.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ In web3.storage, we content address CARs as well! So we generate a hash for the

I know loads of text, but one more thing, sometimes y'all got big datas. If the datas are big, we split the DAG across multiple CAR files. In this exercise we're going to store something else and log out the CAR CIDs a.k.a. the CID of the CAR _shards_.

Create a _new_ file for your solution e.g. `ex5.mjs` and upload something like you did in the cat gifs exercise. This time though, print out the CIDs of the CAR shards as they are sent, and then _finally_ the CID of the root of the DAG. Your output is expected to be newline delimited.
Create a _new_ file for your solution e.g. `ex5.mjs` and upload something like you did in the cat memes exercise. This time though, print out the CIDs of the CAR shards as they are sent, and then _finally_ the CID of the root of the DAG. Your output is expected to be newline delimited.

Good luck!

Expand Down

0 comments on commit 269ef09

Please sign in to comment.