README
¶
filetree
Contents
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
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in Bech32 address |
key | String | ecies.PublicKey |
Response
Coming soon
Makeroot
Create an absolute root folder for a storage account.
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in Bech32 address |
account | String | Hex[ 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. |
rootHashPath | String | MerklePath("s") |
contents | String | FID |
editors | String | string(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. |
viewers | String | Pass 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. |
trackingNumber | String | UUID. 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
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in alice's Bech32 address |
account | String | Hex[ hash( alice's Bech32 address )] |
hashParent | String | MerklePath("s") |
hashChild | String | Hex[ hash("home") ] |
contents | String | FID |
viewers | String | string(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. |
editors | String | same as above but with c = concatenate( "e", trackingNumber, Bech32 address ) |
trackingNumber | String | UUID. 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
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in alice's Bech32 address |
viewerIds | String | A comma separated string of viewer addresses. A viewer address is: hex[ hash("c") ] where c = concatenate( "v", "trackingNumber", "Bech32 address" ) |
viewerKeys | String | A comma separated string of keys that have been protected with the scheme used to protect the owner's viewing key |
address | String | The full chain address of the file, i.e., the merklePath |
owner | String | Let c = Hex[ hash(owner Bech32 address) ]. Full chain address is: Hex[ hash("o"+"merklePath"+"c") ] |
Response
Coming soon
RemoveViewers
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in alice's Bech32 address |
viewerIds | String | A comma separated string of viewer addresses. A viewer address is: hex[ hash("c") ] where c = concatenate( "v", "trackingNumber", "Bech32 address" ) |
address | String | The full chain address of the file, i.e., the merklePath |
owner | String | Let 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
Name | Type | Description |
---|---|---|
creator | String | The creator and broadcaster of this message. Pass in alice's Bech32 address |
hashPath | String | MerklePath("s/home") |
account | String | Hex[ 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
Name | Type | Description |
---|---|---|
address | String | user's Bech32 address |
Response
types.PubKey
GetFiles
Retrieve a Files struct. Let it be that alice want's to retrieve "s/home/bunny.jpg"
Name | Type | Description |
---|---|---|
address | String | MerklePath("s/home/bunny.jpg") |
ownerAddress | String | accountHash = Hex[hash(alice's bech32 address)] let c = concatenate("o", MerklePath("s/home/bunny.jpg"), accountHash) OwnerAddress = hex[hash(c)] |
Response
types.Files
Documentation
¶
Index ¶
- func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState
- func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
- func NewHandler(k keeper.Keeper) sdk.Handler
- type AppModule
- func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock)
- func (AppModule) ConsensusVersion() uint64
- func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate
- func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage
- func (AppModule) GenerateGenesisState(simState *module.SimulationState)
- func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate
- func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier
- func (am AppModule) Name() string
- func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent
- func (AppModule) QuerierRoute() string
- func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange
- func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry)
- func (am AppModule) RegisterServices(cfg module.Configurator)
- func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry)
- func (am AppModule) Route() sdk.Route
- func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation
- type AppModuleBasic
- func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage
- func (AppModuleBasic) GetQueryCmd() *cobra.Command
- func (a AppModuleBasic) GetTxCmd() *cobra.Command
- func (AppModuleBasic) Name() string
- func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux)
- func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry)
- func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)
- func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router)
- func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExportGenesis ¶
ExportGenesis returns the capability module's exported genesis.
func InitGenesis ¶
InitGenesis initializes the capability module's state from a provided genesis state.
Types ¶
type AppModule ¶
type AppModule struct { AppModuleBasic // contains filtered or unexported fields }
AppModule implements the AppModule interface for the capability module.
func NewAppModule ¶
func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper, ) AppModule
func (AppModule) BeginBlock ¶
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock)
BeginBlock executes all ABCI BeginBlock logic respective to the capability module.
func (AppModule) ConsensusVersion ¶
ConsensusVersion implements ConsensusVersion.
func (AppModule) EndBlock ¶
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate
EndBlock executes all ABCI EndBlock logic respective to the capability module. It returns no validator updates.
func (AppModule) ExportGenesis ¶
ExportGenesis returns the capability module's exported genesis state as raw JSON bytes.
func (AppModule) GenerateGenesisState ¶
func (AppModule) GenerateGenesisState(simState *module.SimulationState)
GenerateGenesisState creates a randomized GenState of the module
func (AppModule) InitGenesis ¶
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate
InitGenesis performs the capability module's genesis initialization It returns no validator updates.
func (AppModule) LegacyQuerierHandler ¶
func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier
LegacyQuerierHandler returns the capability module's Querier.
func (AppModule) ProposalContents ¶
func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent
ProposalContents doesn't return any content functions for governance proposals
func (AppModule) QuerierRoute ¶
QuerierRoute returns the capability module's query routing key.
func (AppModule) RandomizedParams ¶
func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange
RandomizedParams creates randomized param changes for the simulator
func (AppModule) RegisterInvariants ¶
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry)
RegisterInvariants registers the capability module's invariants.
func (AppModule) RegisterServices ¶
func (am AppModule) RegisterServices(cfg module.Configurator)
RegisterServices registers a GRPC query service to respond to the module-specific GRPC queries.
func (AppModule) RegisterStoreDecoder ¶
func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry)
RegisterStoreDecoder registers a decoder
func (AppModule) WeightedOperations ¶
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation
WeightedOperations returns the all the gov module operations with their respective weights.
type AppModuleBasic ¶
type AppModuleBasic struct {
// contains filtered or unexported fields
}
AppModuleBasic implements the AppModuleBasic interface for the capability module.
func NewAppModuleBasic ¶
func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic
func (AppModuleBasic) DefaultGenesis ¶
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage
DefaultGenesis returns the capability module's default genesis state.
func (AppModuleBasic) GetQueryCmd ¶
func (AppModuleBasic) GetQueryCmd() *cobra.Command
GetQueryCmd returns the capability module's root query command.
func (AppModuleBasic) GetTxCmd ¶
func (a AppModuleBasic) GetTxCmd() *cobra.Command
GetTxCmd returns the capability module's root tx command.
func (AppModuleBasic) Name ¶
func (AppModuleBasic) Name() string
Name returns the capability module's name.
func (AppModuleBasic) RegisterGRPCGatewayRoutes ¶
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux)
RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.
func (AppModuleBasic) RegisterInterfaces ¶
func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry)
RegisterInterfaces registers the module's interface types
func (AppModuleBasic) RegisterLegacyAminoCodec ¶
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)
func (AppModuleBasic) RegisterRESTRoutes ¶
func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router)
RegisterRESTRoutes registers the capability module's REST service handlers.
func (AppModuleBasic) ValidateGenesis ¶
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error
ValidateGenesis performs genesis state validation for the capability module.