Skip to content

Configuration free implementation #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Sep 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a04a8f6
pkg: drop period
mikeal Aug 20, 2020
fd0ce17
invalidate cache
Gozala Sep 9, 2020
edbc56c
fix: vendor varint for pure ESM
mikeal Sep 16, 2020
b7aa2a6
fix: pass encode offset
Gozala Sep 16, 2020
70cd8ce
fix: remove unecessary ImplicitSha256Digest
Gozala Sep 16, 2020
66682df
chore: add links, tree and get APIs to Block
Gozala Sep 16, 2020
04030cb
fix: typo in template literal
Gozala Sep 16, 2020
655860e
fix: vendor base-x for pure ESM
Gozala Sep 17, 2020
783bce4
feat: bundle base58btc and base32 encoders
Gozala Sep 17, 2020
5e9a433
chore: add code type info
Gozala Sep 18, 2020
8bcdb5d
fix: switch to field base check over instanceof
Gozala Sep 19, 2020
0c2ac57
core: export ByteView type
Gozala Sep 19, 2020
005cb52
fix: browser polyfill for deepStrictEquals doesn't supprot Uint8Arrays
mikeal Sep 23, 2020
e43c0d3
fix: coverage for cid
Gozala Sep 23, 2020
262ba31
fix: hashes coverage
Gozala Sep 23, 2020
a2d6763
chore: disable coverage for vendor
Gozala Sep 23, 2020
64d3977
chore: improve test coverage
Gozala Sep 23, 2020
4baa102
chore: remove dead code
Gozala Sep 23, 2020
7d2fda3
chore: remove block.js
Gozala Sep 23, 2020
d9b92be
fix: drop old npm ignore
mikeal Sep 23, 2020
a5d58ac
fix: moving excludes to package.json
mikeal Sep 23, 2020
cd3ffc6
fix: browser same handles uint8arrays terribly
mikeal Sep 23, 2020
49c0fc6
fix: clearing out old docs
mikeal Sep 23, 2020
c012a2f
chore: update readme
Gozala Sep 24, 2020
2654958
doc: fix typo
mikeal Sep 25, 2020
a826851
fix: drop basics exports
mikeal Sep 25, 2020
6f633a3
fix: tests off of basics interface
mikeal Sep 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .npmignore

This file was deleted.

233 changes: 113 additions & 120 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,161 +1,154 @@
# multiformats

This library is for building an interface for working with various
inter-related multiformat technologies (multicodec, multihash, multibase,
and CID).
This library defines common interfaces and low level building blocks for varios inter-related multiformat technologies (multicodec, multihash, multibase,
and CID). They can be used to implement custom custom base
encoders / decoders / codecs, codec encoders /decoders and multihash hashers that comply to the interface that layers above assume.

The interface contains all you need for encoding and decoding the basic
structures with no codec information, codec encoder/decoders, base encodings
or hashing functions. You can then add codec info, codec encoders/decoders,
base encodings, and hashing functions to the interface.
Library provides implementations for most basics and many others can be found in linked repositories.

This allows you to pass around an interface containing only the code you need
which can greatly reduce dependencies and bundle size.
## Interfaces

```js
import { create } from 'multiformats'
import sha2 from 'multiformats/hashes/sha2'
import dagcbor from '@ipld/dag-cbor'
const { multihash, multicodec, CID } = create()
multihash.add(sha2)
multicodec.add(dagcbor)

const buffer = multicodec.encode({ hello, 'world' }, 'dag-cbor')
const hash = await multihash.hash(buffer, 'sha2-256')
// raw codec is the only codec that is there by default
const cid = new CID(1, 'raw', hash)
import CID from 'multiformats/cid'
import json from 'multiformats/codecs/json'
import { sha256 } from 'multiformats/hashes/sha2'

const bytes = json.encode({ hello: 'world' })

const hash = await sha256.digest(bytes)
const cid = CID.create(1, json.code, hash)
//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea)
```

However, if you're doing this much you should probably use multiformats
with the `Block` API.
### Multibase Encoders / Decoders / Codecs

CIDs can be serialized to string representation using multibase encoders that
implement [`MultibaseEncoder`](https://github.com/multiformats/js-multiformats/blob/master/src/bases/interface.ts) interface. Library
provides quite a few implementations that can be imported:

```js
// Import basics package with dep-free codecs, hashes, and base encodings
import multiformats from 'multiformats/basics'
import dagcbor from '@ipld/dag-cbor'
import { create } from '@ipld/block' // Yet to be released Block interface
multiformats.multicodec.add(dagcbor)
const Block = create(multiformats)
const block = Block.encoder({ hello: world }, 'dag-cbor')
const cid = await block.cid()
import { base64 } from "multiformats/bases/base64"
cid.toString(base64.encoder)
//> 'mAYAEEiCTojlxqRTl6svwqNJRVM2jCcPBxy+7mRTUfGDzy2gViA'
```

# Plugins
Parsing CID string serialized CIDs requires multibase decoder that implements
[`MultibaseDecoder`](https://github.com/multiformats/js-multiformats/blob/master/src/bases/interface.ts) interface. Library provides a
decoder for every encoder it provides:

By default, no base encodings, hash functions, or codec implementations are included with `multiformats`.
However, you can import the following bundles to get a `multiformats` interface with them already configured.
```js
CID.parse('mAYAEEiCTojlxqRTl6svwqNJRVM2jCcPBxy+7mRTUfGDzy2gViA', base64.decoder)
//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea)
```

| bundle | bases | hashes | codecs |
|---|---|---|---|
| `multiformats/basics` | `base32`, `base64` | `sha2-256`, `sha2-512` | `json`, `raw` |
Dual of multibase encoder & decoder is defined as multibase codec and it exposes
them as `encoder` and `decoder` properties. For added convenience codecs also
implement `MultibaseEncoder` and `MultibaseDecoder` interfaces so they could be
used as either or both:

## Base Encodings (multibase)

| bases | import | repo |
--- | --- | --- |
`base16` | `multiformats/bases/base16` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base32`, `base32pad`, `base32hex`, `base32hexpad`, `base32z` | `multiformats/bases/base32` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base64`, `base64pad`, `base64url`, `base64urlpad` | `multiformats/bases/base64` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base58btc`, `base58flick4` | `multiformats/bases/base58` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
```js
cid.toString(base64)
CID.parse(cid.toString(base64), base64)
```

## Hash Functions (multihash)
**Note:** CID implementation comes bundled with `base32` and `base58btc`
multibase codecs so that CIDs can be base serialized to (version specific)
default base encoding and parsed without having to supply base encoders/decoders:

| hashes | import | repo |
| --- | --- | --- |
| `sha2-256`, `sha2-512` | `multiformats/hashes/sha2` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/hashes) |
| `sha3-224`, `sha3-256`, `sha3-384`,`sha3-512`, `shake-128`, `shake-256`, `keccak-224`, `keccak-256`, `keccak-384`, `keccak-512` | `@multiformats/sha3` | [multiformats/js-sha3](https://github.com/multiformats/js-sha3) |
| `murmur3-128`, `murmur3-32` | `@multiformats/murmur3` | [multiformats/js-murmur3](https://github.com/multiformats/js-murmur3) |
```js
const v1 = CID.parse('bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea')
v1.toString()
//> 'bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea'

const v0 = CID.parse('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n')
v0.toString()
//> 'QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n'
v0.toV1().toString()
//> 'bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku'
```

## Codec Implementations (multicodec)
### Multicodec Encoders / Decoders / Codecs

| codec | import | repo |
| --- | --- | --- |
| `raw` | `multiformats/codecs/raw` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/codecs) |
| `json` | `multiformats/codecs/json` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/codecs) |
| `dag-cbor` | `@ipld/dag-cbor` | [ipld/js-dag-cbor](https://github.com/ipld/js-dag-cbor) |
| `dag-json` | `@ipld/dag-json` | [ipld/js-dag-json](https://github.com/ipld/js-dag-json) |
Library defines [`BlockEncoder`, `BlockDecoder` and `BlockCodec` interfaces](https://github.com/multiformats/js-multiformats/blob/master/src/codecs/interface.ts)
and utility function to take care of the boilerplate when implementing them:

# API
```js
import { codec } from 'multiformats/codecs/codec'

const json = codec({
name: 'json',
// As per multiformats table
// https://github.com/multiformats/multicodec/blob/master/table.csv#L113
code: 0x0200,
encode: json => new TextEncoder().encode(JSON.stringify(json)),
decode: bytes => JSON.parse(new TextDecoder().decode(bytes))
})
```

# multiformats([table])
Just like with multibase, here codecs are duals of `encoder` and `decoder` parts,
but they also implement both interfaces for convenience:

Returns a new multiformats interface.
```js
const hello = json.encoder.encode({ hello: 'world' })
json.decode(b1)
//> { hello: 'world' }
```

Can optionally pass in a table of multiformat entries.
### Multihash Hashers

# multihash
This library defines [`MultihashHasher` and `MultihashDigest` interfaces](https://github.com/multiformats/js-multiformats/blob/master/src/hashes/interface.ts)
and convinient function for implementing them:

## multihash.encode
```js
import * as hasher from 'multiformats/hashes/hasher')

## multihash.decode
const sha256 = hasher.from({
// As per multiformats table
// https://github.com/multiformats/multicodec/blob/master/table.csv#L9
name: 'sha2-256',
code: 0x12,

## multihash.validate
encode: (input) => new Uint8Array(crypto.createHash('sha256').update(input).digest())
})

## multihash.add
const hash = await sha256.digest(json.encode({ hello: 'world' }))
CID.create(1, json.code, hash)

## multihash.hash
//> CID(bagaaierasords4njcts6vs7qvdjfcvgnume4hqohf65zsfguprqphs3icwea)
```

# multicodec

## multicodec.encode

## multicodec.decode
# Implementations

## multicodec.add
By default, no base encodings (other than base32 & base58btc), hash functions,
or codec implementations are included exposed by `multiformats`, you need to
import the ones you need yourself.

# multibase
## Multibase codecs

## multibase.encode
| bases | import | repo |
--- | --- | --- |
`base16` | `multiformats/bases/base16` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base32`, `base32pad`, `base32hex`, `base32hexpad`, `base32z` | `multiformats/bases/base32` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base64`, `base64pad`, `base64url`, `base64urlpad` | `multiformats/bases/base64` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |
`base58btc`, `base58flick4` | `multiformats/bases/base58` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/bases) |

## multibase.decode
## Multihash hashers

## multibase.add
| hashes | import | repo |
| --- | --- | --- |
| `sha2-256`, `sha2-512` | `multiformats/hashes/sha2` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/hashes) |
| `sha3-224`, `sha3-256`, `sha3-384`,`sha3-512`, `shake-128`, `shake-256`, `keccak-224`, `keccak-256`, `keccak-384`, `keccak-512` | `@multiformats/sha3` | [multiformats/js-sha3](https://github.com/multiformats/js-sha3) |
| `murmur3-128`, `murmur3-32` | `@multiformats/murmur3` | [multiformats/js-murmur3](https://github.com/multiformats/js-murmur3) |

## multiformats/bases
## Codec Implementations (multicodec)

```js
import { create } from 'multiformats'
import base16 from 'multiformats/bases/base16'
import base32 from 'multiformats/bases/base32'
import base58 from 'multiformats/bases/base58'
import base64 from 'multiformats/bases/base64'
const multiformats = create()
multiformats.add([base16, base32, base58, base64])
```
| codec | import | repo |
| --- | --- | --- |
| `raw` | `multiformats/codecs/raw` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/codecs) |
| `json` | `multiformats/codecs/json` | [multiformats/js-multiformats](https://github.com/multiformats/js-multiformats/tree/master/codecs) |
| `dag-cbor` | `@ipld/dag-cbor` | [ipld/js-dag-cbor](https://github.com/ipld/js-dag-cbor) |
| `dag-json` | `@ipld/dag-json` | [ipld/js-dag-json](https://github.com/ipld/js-dag-json) |

## multiformats/hashes

## multiformats/codecs

# CID

Changes from `cids`:

* All base encodings are cached indefinitely.
* CID's can be created without any multiformat data.
* The new API is entirely based on parsing the varints
so it doesn't need the table metadata in order to associate
string names.

There are also numerous deprecations. These deprecations all stem from the
fact that we no longer know the full set of available multicodec information.
It's actually quite possible to provide a CID interface without this, you can
still do everything you used to do, you just need to use ints instead of strings
and do some of the fancier V0 coercions outside this library.

Deprecation List:
* the multibase encoding is no longer cached during instantiation.
* this being indeterministic was causing some nasty problems downstream
since `toString()` needs to be used as a cache key and it's not possible
to encode V0 into anything but base58btc. this means that you can't have
deterministic hash keys without also requiring base58btc support, so we
removed this feature.
* no more .toBaseEncodedString(), just toString()
* no more .multibaseName
* no more .prefix()
* no more .codec
* new property ".code" is the multiformat integer.
* this is going to be a painful transition but we have to get off of using
the string if we ever want to drop the full table. while the DX for this is
nice it forces into bloating the bundle and makes using new codecs very
painful.
28 changes: 20 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@
"type": "module",
"scripts": {
"build": "npm_config_yes=true npx ipjs@latest build --tests",
"build:vendor": "npm run build:vendor:varint && npm run build:vendor:base-x",
"build:vendor:varint": "npx brrp -x varint > vendor/varint.js",
"build:vendor:base-x": "npx brrp -x @multiformats/base-x > vendor/base-x.js",
"publish": "npm_config_yes=true npx ipjs@latest publish",
"lint": "standard",
"test:cjs": "npm run build && mocha dist/cjs/node-test/test-*.js && npm run test:cjs:browser",
"test:node": "hundreds mocha test/test-*.js",
"test:cjs:browser": "polendina --cleanup dist/cjs/browser-test/test-*.js",
"test": "npm run lint && npm run test:node && npm run test:cjs",
"test:node-v12": "mocha test/test-*.js && npm run test:cjs",
"coverage": "c8 --reporter=html mocha test/test-*.js && npm_config_yes=true npx st -d coverage -p 8080"
"coverage": "c8 --exclude vendor --reporter=html mocha test/test-*.js && npm_config_yes=true npx st -d coverage -p 8080"
},
"c8": {
"exclude": [
"test/**",
"vendor/**"
]
},
"keywords": [],
"author": "Mikeal Rogers <[email protected]> (https://www.mikealrogers.com/)",
Expand All @@ -22,10 +31,6 @@
".": {
"import": "./src/index.js"
},
"./basics": {
"import": "./src/basics-import.js",
"browser": "./src/basics-browser.js"
},
"./cid": {
"import": "./src/cid.js"
},
Expand All @@ -45,10 +50,19 @@
"import": "./src/bases/base64-import.js",
"browser": "./src/bases/base64-browser.js"
},
"./hashes/hasher": {
"import": "./src/hashes/hasher.js"
},
"./hashes/digest": {
"import": "./src/hashes/digest.js"
},
"./hashes/sha2": {
"browser": "./src/hashes/sha2-browser.js",
"import": "./src/hashes/sha2.js"
},
"./codecs/codec": {
"import": "./src/codecs/codec.js"
},
"./codecs/json": {
"import": "./src/codecs/json.js"
},
Expand All @@ -69,10 +83,8 @@
]
},
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.6.0",
"cids": "^1.0.0",
"varint": "^5.0.0"
"cids": "^1.0.0"
},
"directories": {
"test": "test"
Expand Down
Loading