Microledger
A single file ledger with crypto features for append only objects
Why
I needed a way to store Append Only Objects history, and i used other of my libraries (Faythe to add some crypto and encoding features. The main idea is to have all the the data in only one file (Easy to store anywhere)
Features
- Uses random access storage and works in memory, file and browser (automatically choose the fastest option)
- Can encrypt the content with a
secretKey
- Can sign the
nodes
with a ed25519 keypair - Can use SGL to manage
authorization
- Each node have the current state (append->state)
Installation
Available through the
npm registry. It can be installed using the
npm
or
yarn
command line tools.
npm install microledger --save
Usage
const log = genesis: me: 'Javi' log
API
new Microledger([filename],[options])
This class creates an append only object, where you can only append
and "delete"
.
filename
if is a string, a filename is created in node. In the browser uses chrome filesystem api, creates an idb database, or uses localstorage. Can send any random local storage implementation as a function. If filename doesn't exist, uses ram.
Note: I'm normally use .mlg
extension './myledger.mlg'
options
includes:
genesis: {} // The initial object.keyPair: null // set an object with publicKey and privateKey to sign the appended nodes.secretKey: null // set a secretKey to encrypt each node.sgl: null // set an object to manage authorization (more info above)cache: 65536 // cache gets ands sets to improve performance
append(delta, [options])
This method appends the delta to the previos status
AppendOnlyObject
.
options
check AppendOnlyObject
get(seq)
Returns the node in the seq
sequence/index. Number incremented on each append.
last()
Returns the last node in the microledger.
verify(seq)
Verifies the hash related with the previos node (verifies the signature if exist). Returns true or false.
verified()
Verifies all the nodes from the beginning. Returns true or false.
Tests
npm installnpm run test
SGL (Simple Grant Language)
SGL is a simple but flexible DSL for granting and testing privileges (authorization). It is like XACML but simpler and JSON-oriented. You can use it to write rules about who should be able to do what, and then to compare circumstances to the rules to enforce custom logic. This lets you create your own Role-Based Access Control mechanisms, as well as authorizations based on other criteria.
To add this functionality you need to pass an object to verify each append:
Example:
sgl = path: '/publicKey' grant: 'key_admin' path: '/authorization/profiles' grant: 'key_admin' path: '/authorization/rules' grant: 'rule_admin' path: '/services' grant: 'se_admin' path: '/authentication' grant: 'key_admin'
This verifies the grant privileges for each path
Your microledger genesis MUST have publicKey
and authorization
properties:
Example:
const genesis = publicKey: keyPair authorization: profiles: key: `#` roles: 'edge' rules: grant: 'register' 'key_admin' 'se_admin' 'rule_admin' when: id: `#` grant: 'authcrypt' 'plaintext' 'sign' when: roles: 'edge' grant: 'route' 'authcrypt' when: roles: 'cloud'
See sgl.js
for more information. (Example Note: keyPair uses Faythe identity class,and is exposed by Microledger.Identity
)
Protocol
Microledger is created to allow manage appends only objects in one single file. The header of the file:
version 2 bytes | mode 2 bytes | genesislength 8 bytes
and then sequencially:
CBOR(Node) | nodelength | CBOR(Node) | nodelength ... etc
version
is 01
mode
can be:
00
no encryption | no signatures
10
encryption | no signature
01
no encryption | signature
02
no encryption | signature and sgl
12
encryption | signature and sgl
The length of each node is an uint64be
8 bytes representation of Buffer length.
Dependencies
- append-only-object: A way to append objects (deltas) to objects
- buffer: Node.js Buffer API, for the browser
- esm: Tomorrow's ECMAScript modules today!
- faythe: An easy crypto library to send messages using key encapsulation. A courier for Alice and Bob.
- quick-lru: Simple “Least Recently Used” (LRU) cache
- random-access-file: Continuous reading or writing to a file using random offsets and lengths
- random-access-memory: Exposes the same interface as random-access-file but instead of writing/reading data to a file it maintains it in memory
- random-access-web: Chooses the fastest random access backend based on the user's browser
- simple-grant-lang: Simple Grant Language (SGL)
- uint64be: Encode / decode big endian unsigned 64 bit integers
- util.promisify: Polyfill/shim for util.promisify in node versions < v8
Dev Dependencies
- @rollup/plugin-commonjs: Convert CommonJS modules to ES2015
- @rollup/plugin-replace: Replace strings in files while bundling
- del-cli: Delete files and directories - Cross-platform
- eslint: An AST-based pattern checker for JavaScript.
- eslint-config-standard: JavaScript Standard Style - ESLint Shareable Config
- eslint-plugin-import: Import with sanity.
- eslint-plugin-node: Additional ESLint's rules for Node.js
- eslint-plugin-promise: Enforce best practices for JavaScript promises
- eslint-plugin-standard: ESlint Plugin for the Standard Linter
- husky: Prevents bad commit or push (git hooks, pre-commit/precommit, pre-push/prepush, post-merge/postmerge and all that stuff...)
- nodemon: Simple monitor script for use during development of a node.js app.
- rollup: Next-generation ES module bundler
- rollup-plugin-commonjs-alternate: Alternative CommonJS Rollup plugin.
- rollup-plugin-node-polyfills: rollup-plugin-node-polyfills ===
- rollup-plugin-node-resolve: Bundle third-party dependencies in node_modules
- rollup-plugin-terser: Rollup plugin to minify generated es bundle
- tap-spec: Formatted TAP output like Mocha's spec reporter
- tape: tap-producing test harness for node and browsers
License
MIT
Copyright (c) 2020 Javi Santos
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.