package
2.1.0+incompatible
Repository: https://github.com/jackallabs/canine-chain.git
Documentation: pkg.go.dev

# README

◀ modules

filetree

Contents

  1. Concept
  2. Merkle Paths
  3. Client
  4. Transaction Messages
  5. Query Requests

Concept

The filetree module is responsible for keeping records of a user's files and organizing them in a way that is accessible. When a user uploads a file using the Storage module, the file is only accessible from the File ID (fid) which makes the process clunky and obtuse to remember every file uploaded to Jackal. Furthermore, every single upload would be required to be public, or the user would need to keep track of every symmetric key used to encrypt the files and manually map them to the fids. The solution to this is a tree structure storing each file as an entry in the tree. Organizing this structure is also trivial as we can assign children to pseudo files that we call folders. Finally to keep track of encryption keys, the protocol maps every file to its respective key.

Merkle Paths

To keep files hidden from the public eye, we fully hash the file paths for every file. Usually just hashing the entire path would result in two file paths having no relationship even if in the plaintext path, one of the files would be a child of the other.

Ex: /home/path/ & /home/path/child are very clearly related.

Through our system we call Merkle Paths, we can keep these relations intact while still pushing for privacy through one-way hash functions.

let path := 'home/path/'
let child := 'child'

let H := func() return hash(item)

// we split `path` by `/`
let h1 := 'home'
let h2 := 'path'

// we hash each value of split(path)
let hh1 := H(h1)
let hh2 := H(h2)

// we also hash the child
let hh3 := H(child)

// this leaves us with each chunk hashed and protected from prying eyes already, 
// but it's clear this has 3 items in its path (NOT GOOD)

// we can then hash every item in this list with the proceeding item

let s := H(hh1)
ps := H(s + hh2)
cs := H(ps + hh3)

// what we are left with is the merkle path of the child (cs) and the path of the parent (ps)

// at any time we can check if cs is a child of ps if we have H(child)

func checkChild(parent ps, child cs, hc H(child)) {
    return H(parent + hc) == child
}

// this gives us the ability to keep the usefulness of plaintext paths but add a 
// level of privacy that would be impossible to achieve with plaintext.

Client

Below are CLI query and transaction commands to interact with canined.

Query

The query commands allow users to query filetree state.

canined q filetree --help

Transactions

The tx commands allow users to interact with the filetree module.

canined tx filetree --help

Transaction Messages

Below is a full description of valid transaction messages that can be broadcasted to affect state change. These descriptions aim to be "implementation agnostic", i.e., they make sense to both the CLI/Golang and TS implementations.

Postkey

Post a ecies.PublicKey on chain for the encryption scheme

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in Bech32 address
keyStringecies.PublicKey

Response

Coming soon

Makeroot

Create an absolute root folder for a storage account.

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in Bech32 address
accountStringHex[ hash( Bech32 address of user that will own this account)].
Please note that the broadcaster of this message will always be making a storage account for themselves, but there are other filetree transaction messages that can be called by userA to affect a change in userB's account. It is for this purpose that the Account field exists.
rootHashPathStringMerklePath("s")
contentsStringFID
editorsStringstring(json encoded map) with:
let c = concatenate( "e", trackingNumber, Bech32 address )
map_key: hex[ hash("c") ]
map_value: ECIES.encrypt( aesIV + aesKey )
Note that map_key and map_value must be strings or else unmarshalling in the keeper will fail.
viewersStringPass in "NONE." Do not pass in an emptry string else message validation will fail. Root folder has no viewers. Unknown at this time if this field will be needed in the future so we leave it in for now.
trackingNumberStringUUID. This trackingNumber is one and the same as what is used in editors map

Response

Coming soon

PostFile

Create and save a new 'Files' struct on chain. The distinction between a folder and a file is very clear in jackalJS, but the filetree module does not care whether a Files struct is being used to save data for a folder or a file.

Let it be that alice wants to create a home folder

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in alice's Bech32 address
accountStringHex[ hash( alice's Bech32 address )]
hashParentStringMerklePath("s")
hashChildStringHex[ hash("home") ]
contentsStringFID
viewersStringstring(json encoded map) with:
let c = concatenate( "v", trackingNumber, Bech32 address )
map_key: hex[ hash("c") ]
map_value: ECIES.encrypt( aesIV + aesKey )
Note that map_key and map_value must be strings or else unmarshalling in the keeper will fail.
editorsStringsame as above but with c = concatenate( "e", trackingNumber, Bech32 address )
trackingNumberStringUUID. This trackingNumber is one and the same as what is used in editors AND viewers map

alice can add other users to her viewers and editors map aswell.

Response

let fullMerklePath = MerklePath("s/home")

{
  
    "path": "fullMerklePath"

}

AddViewers

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in alice's Bech32 address
viewerIdsStringA comma separated string of viewer addresses. A viewer address is: hex[ hash("c") ] where c = concatenate( "v", "trackingNumber", "Bech32 address" )
viewerKeysStringA comma separated string of keys that have been protected with the scheme used to protect the owner's viewing key
addressStringThe full chain address of the file, i.e., the merklePath
ownerStringLet c = Hex[ hash(owner Bech32 address) ]. Full chain address is: Hex[ hash("o"+"merklePath"+"c") ]

Response

Coming soon

RemoveViewers

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in alice's Bech32 address
viewerIdsStringA comma separated string of viewer addresses. A viewer address is: hex[ hash("c") ] where c = concatenate( "v", "trackingNumber", "Bech32 address" )
addressStringThe full chain address of the file, i.e., the merklePath
ownerStringLet c = Hex[ hash(owner Bech32 address) ]. Full chain address is: Hex[ hash("o"+"merklePath"+"c") ]

Response

Coming soon

Delete

Let it be that alice wants to delete her "s/home" folder

NameTypeDescription
creatorStringThe creator and broadcaster of this message. Pass in alice's Bech32 address
hashPathStringMerklePath("s/home")
accountStringHex[ hash( alice's Bech32 address )]

Response

Coming soon

Query Requests

Below is a full description of valid query requests that can be made to retrieve state information. These descriptions aim to be "implementation agnostic", i.e., they make sense to both the CLI/Golang and TS implementations.

GetPubkey

Retrieve a user's ecies.PublicKey

NameTypeDescription
addressStringuser's Bech32 address

Response

types.PubKey

GetFiles

Retrieve a Files struct. Let it be that alice want's to retrieve "s/home/bunny.jpg"

NameTypeDescription
addressStringMerklePath("s/home/bunny.jpg")
ownerAddressStringaccountHash = Hex[hash(alice's bech32 address)]
let c = concatenate("o", MerklePath("s/home/bunny.jpg"), accountHash)
OwnerAddress = hex[hash(c)]

Response

types.Files

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Package types is a reverse proxy.

# Functions

ExportGenesis returns the capability module's exported genesis.
InitGenesis initializes the capability module's state from a provided genesis state.
No description provided by the author
No description provided by the author
NewHandler ...

# Structs

AppModule implements the AppModule interface for the capability module.
AppModuleBasic implements the AppModuleBasic interface for the capability module.