• Stars
    star
    104
  • Rank 330,604 (Top 7 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Proof of Liabilities (PoL) is a scheme designed to let companies that accept monetary deposits from consumers (e.g. Bitcoin exchanges, gambling websites, online Bitcoin wallets, etc.) prove their total amount of deposits (their liabilities) without compromising the privacy of individual users.

Proof of Liabilities

Build Status

Proof of Liabilities specification and Javascript implementation.

Proof of Liabilities (PoL) is a scheme designed to let companies that accept monetary deposits from consumers (e.g. Bitcoin exchanges, gambling websites, online Bitcoin wallets, etc.) prove their total amount of deposits (their liabilities) without compromising the privacy of individual users.

The Proof of Liabilities scheme can be used as part of the broader Proof of Solvency scheme.

Proof of Liabilities online tools

Table of Contents

Install

npm install -g lproof

Usage

Simple usage:

# Generate a partial tree for all users in accounts.json.
# Partial trees will be saved to partial_trees/ directory.
# complete_tree.json and root.json will be saved to current directory.
# For a sample accounts file, refer to test/accounts.json.

$ lproof generate -f accounts.json

# Verify a partial tree 

$ lproof verify --root root.json -f partial_trees/satoshi.json

# or (where hash is the root hash and sum is the root sum)

$ lproof verify --hash "1ded5478d0116b30aca091f8d5ddd2340d9391dca47a41d9271e61ede51c0f6b" --sum 37618 -f mark.json

Advanced usage:

# Create complete proof tree from an accounts file (see
# test/account.json for format)

$ lproof completetree -f test/accounts.json --human
$ lproof completetree -f test/accounts.json > complete.out.json

# Extract partial tree for user mark.

$ lproof partialtree mark -f complete.out.json --human
$ lproof partialtree mark -f complete.out.json > mark.out.json

# Display root node hash and sum

$ lproof root -f complete.out.json --human

# Verify partial tree

$  verify --hash "1ded5478d0116b30aca091f8d5ddd2340d9391dca47a41d9271e61ede51c0f6b" --sum 37618 -f mark.out.json

Library usage

See cli.js.

Browser build: browserify index.js --standalone lproof > build/lproof.js.

Implementations

Non interoperable implementations:

Specification

Definitions

Complete proof tree

The complete proof tree is a binary tree where the leaf nodes represent all the user accounts and the internal nodes generated using the NodeCombiner function described below.

The complete tree should be kept private by the operator in order to protect the privacy of its users. Only the root node should be published publicly and each individual user should have private access to their own partial proof tree.

Ideally the tree layout should be random.

Leaf node

Leaf nodes represent user accounts. They possess the following values:

  • user: A unique identifier for the user. The user must ensure the uniqueness of this value so using their username or e-mail is recommended (it is never revealed by this scheme).
  • nonce: A random secret assigned by the operator to prevent neighbours from accidentally or deliberately discovering the value of user or sum (balance).
  • sum: The user's balance (called sum for consistency with internal nodes).
  • hash: SHA256(user + '|' + sum + '|' + nonce)

Internal node

Internal nodes are generated using the NodeCombiner function described below.

The node's sum is the result of adding of its children's sums.

The node's hash is its sum concatenated with its children's hashes, fed to SHA256.

function NodeCombiner (left_child, right_child) {
  var n = {};
  n.sum = left_child.sum + right_child.sum;
  n.hash = sha256(string(n.sum) + '|' + left_child.hash + '|' + right_child.hash);
  return n;
}

Root node

The root node of the, tree like all internal nodes, possesses a hash and a sum. This data must be published publicly so that all users can ensure they're verifying against the same proof tree.

Partial proof tree

A partial proof tree contains only the nodes from the complete tree which a given user needs in order to verify he was included in the tree.

It can be generated by starting with the user's leaf node and including every parent node up the tree, up to and including the root node (the root path). Then the sibling of each node on the path must be added to the tree.

  • All internal nodes should be completely stripped of their data to encourage verifiers to compute it themselves.

  • All leaf nodes except for the leaf representing the given user should be stripped of their user and nonce properties to ensure privacy.

  • The leaf representing the given user should be stripped of its hash property to encourage verifiers to compute it themselves.

Partial trees should be disclosed privately to each individual user so they can verify the proof, learning an absolute minimum about their neigbours.

Serialized data formats (work in progress / draft)

This section is intended to standardize the way root nodes and trees are generated and represented in order to make implementations compatible.

Hashing leaf nodes

To be accepted by conforming verifier tools, leaf (account) node hashes must be computed using:

SHA256(user + '|' + string(sum) + '|' + nonce)

where user, sum and nonce have the same meanings as above, but specifically:

  • strings are trimmed of any whitespace then joined using the pipe character (ASCII 0x7C) as a separator; no ASCII NULs are included in the SHA256 input
  • string(sum) is a string representation of the balance for the corresponding account, matching the regular expression ^(0|[1-9][0-9]*)(\.[0-9]+)?$ (or informally, the JSON 'number' format but no negative numbers and no 'e' notation). This representation must be in the shortest possible form allowed by the regular expression, achieved by stripping trailing zero digits from the fractional part[1]. The representation should not use more decimal places than required to represent the currency's smallest subunit; if the operator's system uses more decimal places, the value should be rounded towards +∞ to the next subunit before any use (addition/hashing/serialisation) in this scheme. Any conversion performed to produce or consume it should be done very carefully. Examples:
    • given $0, use 0, not 0.0 or 0.000
    • given $1.23 use 1.23, not 1.230 or 1.23000000
    • given $1.20 use 1.2, not 1.20 or 1.20000
    • given $20.00 use 20, not 20.00 or 20.000000
    • prefer to round $1234.5678 to $1234.57 before any use in this scheme
  • nonce is encoded as a hexadecimal string.

Example: if user [email protected] had a balance of 3.1415 bitcoins and had been been assigned nonce e3b0c44298fc1c149afbf4c8996fb924 by the operator, the hash would take the following string as input:

[email protected]|3.1415|e3b0c44298fc1c149afbf4c8996fb924

producing (hexadecimal-encoded) hash:

7856aa35ddcf71ab84d18c16d5ac1b90b19e6d54e932d972595235d343c17461

Hashing internal nodes

Internal (non-account) node hashes must be computed using:

SHA256(string(sum) + '|' + left_child.hash + '|' + right_child.hash)

where sum, left_child.hash and right_child.hash have the same meanings as above, but specifically:

  • strings are trimmed of any whitespace then joined using the pipe character (ASCII 0x7C) as a separator; no ASCII NULs are included in the SHA256 input
  • string(sum) is as above for leaf nodes, except represents the liabilities sum for the subtree.
  • left_child.hash(/right_child.hash) is the 64-digit hexadecimal string encoding (with lowercase letters) of the left(/right) child's hash

Example: if an internal node had a subtree liability sum of 71.31 bitcoins and child nodes with (hexadecimal-encoded) hashes of 000d5478d0116b30aca091f8d5ddd2340d9391dca47a41d9271e61ede51c0f6b (left) and 20aa3f466728a58182a9b7733fcb70044ab489a27554d9fb7ed520936759bf96 (right), the hash would take the following string as input:

71.31|000d5478d0116b30aca091f8d5ddd2340d9391dca47a41d9271e61ede51c0f6b|20aa3f466728a58182a9b7733fcb70044ab489a27554d9fb7ed520936759bf96

producing (hexadecimal-encoded) hash:

81dbc2416e7ead6a4ac1db605c56e293119a7ed65f3c80fdf1abbceeef22ac15

Root node

A JSON object:

{
  "root": {
    "sum": <JSON string, as described above>,
    "hash": <JSON string, as described above>
  },
  "currency": <JSON string>,
  "timestamp": <JSON number>
}

hash and sum are calculated as described above; both are JSON strings. hash is encoded as a 64-digit hexadecimal string with lowercase letters. The contents of string sum should be identical to the representation used in hashing, but equivalents (which add a fractional part with zeros in all decimal places, or which add trailing zeros to an existing fractional part) that still match the regex are allowed.

currency is the 3 letter ISO 4217 currency code (e.g. USD for United States dollar). If there is no ISO 4217 currency code for the currency, use the code that Bloomberg uses (e.g. XBT for Bitcoin) and otherwise, spell out the full currency name in lowercase (e.g. namecoin).

timestamp is a UNIX timestamp, which is the number of milliseconds between Epoch and the time at which the user balances were retrieved.

Example:

{
  "root": {
    "sum": "37618",
    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
  },
  "currency": "XBT",
  "timestamp": 1395718369805
}

Partial trees

Partial trees are represented as a JSON object graph made up of nodes. Each node has the following format:

{
  "left": <node>,
  "right": <node>,
  "data": <node_data>
}

<node_data> is a JSON object containing some subset of the following name/value pairs:

  • sum (JSON string): as described above. The contents should be identical to the representation used in hashing, but equivalents (which add a fractional part with zeros in all decimal places, or which add trailing zeros to an existing fractional part) that still match the regex are allowed.
    • Immediate children of nodes on the root path must have this key set.
    • Other nodes should not have this key set.
  • hash (JSON string): generated as described above, encoded as a 64-digit hexadecimal string with lowercase letters.
    • Immediate children of nodes on the root path must have this key set.
    • Other nodes should not have this key set.
  • user (JSON string): The unique string chosen by the user.
    • The node belonging to the user this partial tree was generated for must have this key set.
    • All other nodes must not have this key set.
  • nonce (JSON string): The nonce assigned to the user, encoded as a hexadecimal string with lowercase letters.
    • Should be at least 128 bits of cryptographically strong entropy.
    • The node belonging to the user this partial tree was generated for must have this key set.
    • All other nodes must not have this key set.

If redundant keys are omitted as suggested, the "data": <node_data> key/value pair will have an empty object ({}) for <node_data>, in which case the key/value pair should be omitted.

Example leaf node's <node_data>:

{
  "user": "[email protected]",
  "sum": "3.1415",
  "nonce": "e3b0c44298fc1c149afbf4c8996fb924",
}

Example <node_data> for an immediate child of a node on the root path:

{
  "sum": "71.31",
  "hash": "81dbc2416e7ead6a4ac1db605c56e293119a7ed65f3c80fdf1abbceeef22ac15"
}

Account lists

For the purposes of sharing test input and to help pin down inconsistencies between implementations, it would help if your implementation accepted an account list in the following form. This need not be its usual or only means of accepting account lists.

An account list is a JSON array of JSON objects:

[
  {
    "user": <JSON string, as described above>,
    "balance": <JSON string as described above>,
    "nonce": <JSON string as described above>
  }
  {
    "user": <JSON string, as described above>,
    "balance": <JSON string as described above>,
    "nonce": <JSON string as described above>
  }
  ...
]

Trees should ideally be given random layouts normally but when accepting this form for testing you should produce the tree with a deterministic algorithm:

  • pad out the accounts list size to the next power of two, using accounts with user "dummy", balance "0.00000000" and nonce "0"
  • produce a perfect binary tree
  • ensure that a traversal of the tree would visit the leaf nodes in the same order they appeared

This ensures that the root hash for the tree is deterministic and predictable which makes tests shareable.

[1]: Note that there's a bug in BigDecimal.stripTrailingZeros in JDK <8 where 0.000 doesn't change.

Publishing protocol

See olalonde/proof-of-solvency.

Acknowledgements

References

More Repositories

1

node-yelp

Javascript client for Yelp's API (v2.0)
JavaScript
208
star
2

connectr

Connectr allows the insertion/removal of Express middlewares at "runtime". LOOKING FOR MAINTAINER
JavaScript
88
star
3

better-require

Augments require() with support for multiple file formats. Node.js / NPM package
JavaScript
75
star
4

pgtools

Pure Node.js implementation of PostgreSQL's createdb and dropdb tools.
JavaScript
75
star
5

deisdash

Deis Dash is a web based UI for the Deis PaaS. LOOKING FOR MAINTAINER
JavaScript
73
star
6

proof-of-solvency

Proof of Solvency (PoS) is a scheme designed to let users verify the solvency of online websites which accept Bitcoin (or other similar currency) deposits (e.g. exchange websites, online wallets, gambling websites, etc.) in a way that doesn't compromise the privacy of users.
JavaScript
70
star
7

node-notify

Native Node.js C++ extension for displaying desktop notifications using GNOME's libnotify (libnotifymm) library.
C++
65
star
8

handlebars-paginate

Pagination helper for Handlebars.
JavaScript
59
star
9

jsnotify

Sample code to bind Javascript alert() to a GTK+ notification using V8
C++
55
star
10

boolasync

Async boolean logic for Node.js / Javascript.
JavaScript
30
star
11

awesome-microservice-archs

Examples of real world software built with a microservice architecture
26
star
12

proof-of-assets

Proof of Assets (PoA) is a scheme designed to let entitites (operators) prove that they control a given amount of Bitcoin or other blockchain based cryptocurrency.
JavaScript
25
star
13

eslint-import-resolver-babel-root-import

A babel-root-import resolver for eslint-plugin-import
JavaScript
23
star
14

mtgox-socket-client

Node.js client for the MtGox Streaming API (using Socket.io)
JavaScript
21
star
15

kmeans.js

K-means algorithm implementation in Javascript.
JavaScript
17
star
16

tsc-module-loader

Custom Node.js ESM loader that uses TypeScript's module resolution under the hood.
TypeScript
16
star
17

minios

Minimal OS that prints "Hello world" to the screen. Also an OS X "starter kit" for http://littleosbook.github.io/
Assembly
14
star
18

phemex-puzzle

Attempt at solving https://twitter.com/Phemex_official/status/1217808220703473664 , PRs welcome
Jupyter Notebook
14
star
19

advisory-lock

advisory-lock
JavaScript
13
star
20

jest-quickfix-reporter

Jest reporter for Vim's QuickFix
JavaScript
11
star
21

retry-promise

Retry is a small utility function that allows to retry a promise automatically.
JavaScript
10
star
22

resourcemap

Resourceful routing for Express 4.x
JavaScript
10
star
23

express-websocket

Use Express middleware before initiating Websocket connection.
JavaScript
9
star
24

dashell

Minimalist shell for educational purposes.
C
9
star
25

dORM

ORM for PHP 5. [DEPRECATED: I no longer maintain this repo]
PHP
9
star
26

fixer

Setup your test database using fixtures in a breeze.
JavaScript
9
star
27

connect-acceptoverride

Override `Accept` to `application/json` header if URL ends with .json (Connect/Express middleware)
JavaScript
9
star
28

google-plusone-posterous

Small script to add Google +1 to a Posterous theme using an iframe.
PHP
8
star
29

coinscript

An experimental language that compiles to Bitcoin scripts.
JavaScript
7
star
30

require-yaml

require('require-yaml') lets you load YAML/YML files using require syntax. For example: var config = require('./config.yaml');
JavaScript
6
star
31

deis-node

Deis API client for Node and the browser.
JavaScript
6
star
32

notif

Node.js library for handling notifications (in web apps).
6
star
33

worm

WORK IN PROGRESS
JavaScript
5
star
34

require-csv

require('require-csv') lets you load CSV files using require syntax. For example: var data = require('./data.csv');
JavaScript
4
star
35

coreos-bitcoind

tiny bitcoind docker image and coreos unit files
Shell
4
star
36

chungking

Controllers for Node.js (originally built to be used with Connect / Express.js)
JavaScript
4
star
37

docker-fake-s3

Fake AWS S3 server for local development based on fake-s3
4
star
38

require-typescript

require('require-typescript') lets you load typescript files directly from Node.js. For example: var mymodule = require('./mymodule.ts');
JavaScript
4
star
39

node-ttychat

ttychat is a Node.js app that let's you chat with other users on your machine from within the terminal
JavaScript
4
star
40

shc-protocol

Library for decoding and verifying Smart Health Cards data (e.g. the Quebec Covid Vaccine QR code).
TypeScript
4
star
41

express-transform

Express middleware to transform responses using streams
JavaScript
4
star
42

express-bandwidth

Express middleware to monitor the bandwidth of requests/responses.
JavaScript
3
star
43

olalonde.github.com

https://syskall.com
SCSS
3
star
44

csv2array

Sync CSV parser for Node.js
JavaScript
3
star
45

require-xml

require('require-xml') lets you load XML files using require syntax. For example: var config = require('./config.xml');
JavaScript
3
star
46

dotfiles

Personal dotfiles
Lua
3
star
47

solvency-verifier-extension

Proof Of Solvency Chrome extension. See https://github.com/olalonde/proof-of-solvency
JavaScript
2
star
48

getuid

Get the UID of a user by their username. (Node.js NPM package)
JavaScript
2
star
49

open-html

Open HTML strings in your web browser from Node.js
JavaScript
2
star
50

HN-Crunch

Greasemonkey script for Hacker News. Adds a profile picture next to users who have their own CrunchBase profile.
PHP
2
star
51

jsonselect

Filter out JSON fields using Mongoose's select syntax and JSONPaths.
JavaScript
2
star
52

muxide

A tiny IDE written in bash, built on tmux + vim and inspired by tmuxinator.
Shell
2
star
53

gh-globalsearch

Chrome extension that makes Github search all repositories by default instead of the current repository.
JavaScript
2
star
54

wait-events

Turn a complex event emitter into a simple Promise.
JavaScript
1
star
55

docker-ebs

docker-ebs attaches an AWS EBS volume to the EC2 instance where the container is started
Shell
1
star
56

es6-npm-package-scaffold

Opinionated npm package scaffold / template
Shell
1
star
57

docker-insight-api

Dockerfile for insight-api.
Shell
1
star
58

s3-simple-blob-store

Amazon S3 abstract-blob-store
JavaScript
1
star
59

node-ipinfodb

Node.js wrapper for ipinfodb.com API (IP to timezone)
JavaScript
1
star
60

abstract-bitcoin-wallet

Interface and test suite for standardized bitcoin wallet libraries
JavaScript
1
star
61

chatgpt-roles

1
star
62

liability-proof

A ruby implementation of Greg Maxwell's Merkle approach to prove Bitcoin liabilities.
Ruby
1
star
63

daobao

Dispatcher for Railway-routes (use with Express or Connect and Node.js)
JavaScript
1
star
64

expressionist

Programmatically generate expression trees in Node.js or plain browser Javascript.
JavaScript
1
star
65

node-postgres-namedparams

Add named params support to node-postgres
JavaScript
1
star