Skip to main content

ADR-003: Buckets

Summary

Associate data on the Sonr network together with the addition of a new resource type: buckets.

Abstract

The canonical storage resource inside the Sonr network is the Bucket - an encrypted, schemaless, storage container. By using buckets, developers may leverage a secure and private decentralized storage layer for their applications.

Objectives

  • Private and secure storage mechanism
  • Support Access Control Lists
  • Support CRUD operations for buckets and bucket content
  • Support revokation of access

Use Cases

  • Store multiple associated files (application assets)
  • Store staticly served files

Concept

Conceptually, buckets behave similarly to a key-value store, where the keys are developer-created and mapped one-to-one with a CID. The content is encrypted using the shared member's JWKs (JSON Web Keys).

Creating and managing buckets require updates to the underlying blockchain. This includes deleting the bucket, adding new resources, or updating permissions. The bucket model itself is stored in IPFS, but the CID for the model will be stored on-chain; this significantly reduces the usage of on-chain space.

Bucket Model

The model for a bucket, which will be stored in IPFS, is as follows.

type Bucket struct {
Did string
Label string
IsActive bool
EncryptedJwks map[CID]map[PublicKey]EncryptedJWK
Content map[string]CID
}

type CID string
type PublicKey string
type EncryptedJWK []byte

DID

A DID which uniquely identifies the bucket.

Label

A label for conveniently referencing the bucket.

IsActive

Reflects whether or not the bucket is active. Inactive buckets cannot be modified.

EncryptedJwks

A map that stores the encrypted keys for each party who should have access to the content referenced by a CID. Each CID entry contains a map of public keys (those of the members being granted access) to the JWK encrypted with that public key (PK). This allows the user to find the JWK they need to decrypt the data found with CID.

Content

Maps developer-defined keys to the CID for content. Content is posted via the APIs described below and can be found again via this map.

Bucket API

At a high-level, the supported Bucket operations are:

CreateBucket(label)

Parameters

label (string) : The label for the bucket. A convenient way to reference the bucket in addition to the generated DID.

Description

Provisions a new bucket with the given label. New buckets will be initialized with a corresponding DID and DID Document. The content and encryptedJwks fields will be empty.

The bucket model itself will be persisted via IPFS, while the DID Document and a record which references the newly created bucket will be stored on-chain.

Data persisted via IPFS will incur a storage cost relative to the size of the data storage. Additonal costs will be incurred for storing the bucket reference on the chain.

UpdateLabel(did, new_label)

Parameters

did (string) : The DID of the bucket to update.

new_label (string) : The new label for the bucket.

Description

Updates the label for the given bucket DID. Updating a label requires updating the bucket model in IPFS, which in turn will require an on-chain transaction to update the DID-CID pair.

Data persisted to IPFS as part of an update will incur a storage cost that is linked to the size of the changed files. IPFS will persist all files, so any files with changes will need to be re-uploaded, as well as the bucket model. The changes will need to persist to the chain incurring an additional cost.

AddContent(did, name, encryptedContent, sharedMembersEncryptedKey)

Parameters

did (string) : The did of the bucket to add content to.

name (string) : The key used to reference the content being added. This will be addressable via DID URL.

encryptedContent (string) : The content to be added, encrypted with a JWK. The JWK should be one known only to the parties included in sharedMembersEncryptedKeys.

sharedMembersEncryptedKeys (map[string]string) : A map containing the JWK used for encrypting the content, encrypted with the public key of each party to share with.

Description

Adds encrypted content to an existing bucket. A JWK is used to encrypt the content, and that JWK is encrypted once for every user who should have access to it. This enables data to be securely stored and access to be securely distributed.

This call will require a new DID-CID pair to be added to the chain and as such will incur a cost. Additionally, this will charge for the cost of the file storage on IPFS

UpdateContent(did, name, encryptedContent, sharedMembersEncryptedKeys)

Parameters

did (string) : The did of the bucket to update content on.

name (string) : The key used to reference the content being updated. The updated CID will replace the value found at this name.

encryptedContent (string) : The new content, encrypted with a JWK. The JWK should be one known only to the parties included in sharedMembersEncryptedKeys.

sharedMembersEncryptedKey (map[string]string) : A map containing the JWK used for encrypting the content, encrypted with the public key of each party to share with.

Description

Updates a bucket's content at the given name. The CID generated for the updated content will replace the CID found under name in the content map. A new entry into the encrypted key map for sharedMembersEncryptedKey.

This update will require a new DID-CID pair written to the chain. This change will charge for the size of the new entry on IPFS as well as CID on-chain update

RemoveContent(did, name)

Parameters

did (string) : The did of the bucket to update content on.

name (string) : The content name.

Description

Removes content from a bucket. This does not delete content from IPFS, but it removes the entry in the content map and encryptedJwks and map.

Removing content, like updating, requires a single transaction on chain for updating the DID-CID pair for this bucket.

DeactivateBucket(did)

Parameters

did (string) : The bucket's DID.

Description

Sets the bucket's IsActive field to false. Requires a transaction on-chain to update the DID-CID pair.

GetBucket(did)

Parameters

did (string) : The bucket's DID.

Description

Returns the bucket model for the given DID. No transactions on-chain are required.

BucketExists(did)

Parameters

did (string) : The bucket's DID.

Description

Checks if a bucket exists for a given DID. No transactions on-chain are required.