UNPKG

@gamechanger-finance/unimatrix

Version:

Unimatrix Sync is a decentralized, privacy preserving, transaction witness sharing and pairing solution for multisignatures or deferred signatures. It was originally created for GameChanger Wallet to improve it's multisignature user experience and boost t

198 lines (197 loc) 7.93 kB
/** * Decentralized, encrypted, privacy preserving, self-integrity aware protocol * using GunDb as shared key-value cache. * @module unimatrix * * @remarks * * There are 2 types of data that can be stored in JSON objects: **Items** or (Item) **Announcements** * * The key-value store design consists on: * - a key that is a hash of a concatenated list of private and/or public strings. The order of the list builds a 'path' * - a value that is a store of private encrypted and public serialized data. * - encryption (and hash) usually reuse the secret in the path among the public strings and the validation method name. * - data validation on read and write events links and checks data against the path and the validation method used. * - to read or write a value you must know its full path, and it must comply the validation method used. * - the strings, or secrets used for the path are considered a private channel. * * Security: * - usually every stored data on key-value store is encrypted with a secret id * - usually if you know the id you can read/write encrypted data * - every key of the key-value store is a hash of the secret id, the (type) validator involved and the unique path of the item * - encryption and data lookup depends on knowing the secret id, the validator and the path of the item. * - non valid data types, invalid data structures, data with hash mismatch, or miss-encrypted data is automatically discarded by a reading peer * - id behaves like a session token, and it should be renewed after usage, for ex: after a finalized multisig operation * - new private channels cannot be expected for when you don't know channel parameters, good for avoiding DDoS attacks * - at scale all key-value pairs populate under a common root, making listening for all pairs difficult * - fake value injection attacks are filtered by encryption and validators * - **Items**: * - Items are checked against type validity tests and hash-matching tests against provided path, * - therefore provide the strongest security, * - knowing the right id for reading/writing encrypted data means nothing if data does not match required path. * - **Announcements**: * - are only checked against type validity, * - therefore provide the weakest security, * - anyone with the right id can read/write the encrypted data. * - but this is acceptable because of data validation * - for example, announcing a sign request of injected transactions can be easily discarded by signer validators checking against transaction body validity * - usually users should announce signing requests and validators in dapps should check transaction body * * * Basic operations: * - `setData`: encrypts and writes data at a path * - `getData`: reads and decrypt first valid data from a path with a timeout * - `onData`: reads all incoming data at a path and tries to validate and decrypt it * */ import { UnimatrixDB } from "./common"; import { IGunChain } from 'gun'; /** * root node name on GunDB */ export declare const ROOT_NODE_KEY = "root"; /** * default timeout in milliseconds for getters like `getData` */ export declare const GET_TIMEOUT_MS: number; /** * Validator name or tag * * @remarks * * Validators naming convention: * * - those starting in uppercase are for (Item) **Announcements**, where path is not used to verify data integrity * - those starting in lowercase are for **Items**, where standardized path is used to verify data integrity * */ export type UnimatrixValidatorTag = string; /** * Custom user errors reported by Unimatrix nodes */ export type UnimatrixUserError = string; /** * Unimatrix data structure. Usually or data or error is stored. */ export type UnimatrixData = { data: any | undefined; error: undefined; } | { data: undefined; error: UnimatrixUserError; }; /** * An un-encrypted and decoded representation of a `UnimatrixData` file and some metadata. */ export type UnimatrixDataStore = { file: UnimatrixData; updatedAt: number; }; /** * An encrypted and encoded representation of a `UnimatrixDataStore`. Some parts like metadata can be public, some parts like `UnimatrixData` file are encrypted. */ export type UnimatrixEncryptedDataStore = string; /** * Arguments for a `UnimatrixValidatorFn`, basically channel parameters and the `UnimatrixDataStore` data to validate. */ export type UnimatrixValidatorFnArgs = { id: string; validator: UnimatrixValidatorTag; path: string[]; store: UnimatrixDataStore; }; /** * Unimatrix data validator function. It validates `UnimatrixDataStore` data based on channel parameters. */ export type UnimatrixValidatorFn = (args: UnimatrixValidatorFnArgs) => true | string; /** * Modules built on top of Unimatrix can define validator maps, well known key-value structures with `UnimatrixValidatorTag` keys and `UnimatrixValidatorFn` as values. */ export type UnimatrixValidatorMap = { [validatorTag: string]: UnimatrixValidatorFn; }; /** * Functions that encrypt and encode private and public data from a `UnimatrixDataStore` using channel parameters and returns a `UnimatrixEncryptedDataStore` */ export type UnimatrixEncryptFn = (args: { id: string; validator: UnimatrixValidatorTag; path: string[]; store: UnimatrixDataStore; }) => UnimatrixEncryptedDataStore; /** * Functions that decode and decrypt private and public data from a `UnimatrixEncryptedDataStore` using channel parameters and returns a `UnimatrixDataStore` */ export type UnimatrixDecryptFn = (args: { id: string; validator: UnimatrixValidatorTag; path: string[]; store: UnimatrixEncryptedDataStore; }) => UnimatrixDataStore; /** * Function that generates a Unimatrix hash string based on channel parameters that will be used as key for storing a `UnimatrixEncryptedDataStore` on a GunDb node key-value structure * @param args */ export declare const genDataKey: (args: { id: string; validator: UnimatrixValidatorTag; path: string[]; }) => { key: string; path: string; }; /** * Listener function that triggers the `on()` callback every time an **Item** or an **Announcement** (`UnimatrixDataStore`) is received on a specific channel. * @param args */ export declare const onData: (args: { db: UnimatrixDB; id: string; validator: UnimatrixValidatorTag; validators: UnimatrixValidatorMap; path: string[]; change?: boolean | undefined; timeout?: number | undefined; encryptData: UnimatrixEncryptFn; decryptData: UnimatrixDecryptFn; on: (args: { store?: UnimatrixDataStore | undefined; validationError?: string | undefined; userError?: string | undefined; timeoutError?: boolean | undefined; node: IGunChain<string>; stop: () => void; }) => void; }) => void; /** * Getter promise that gets a specific **Item** or **Announcement** (`UnimatrixDataStore`) from a specific channel. * @param args */ export declare const getData: (args: { db: UnimatrixDB; id: string; validator: UnimatrixValidatorTag; validators: UnimatrixValidatorMap; path: string[]; throwValidationErrors?: boolean; throwUserErrors?: boolean; throwTimeoutErrors?: boolean; timeout?: number; encryptData: UnimatrixEncryptFn; decryptData: UnimatrixDecryptFn; }) => Promise<UnimatrixDataStore | undefined>; /** * Setter promise that puts an **Item** or **Announcement** (`UnimatrixDataStore`) on a specific channel. * @param args */ export declare const setData: (args: { db: UnimatrixDB; id: string; validator: UnimatrixValidatorTag; validators: UnimatrixValidatorMap; path: string[]; store: UnimatrixDataStore; checkByFetching?: boolean; encryptData: UnimatrixEncryptFn; decryptData: UnimatrixDecryptFn; }) => Promise<UnimatrixDataStore | undefined>;