This module provides the basic procedures and types for ERIS encoding and decoding. Encoding and decoding always requires an ErisStore receiver object and store operations are asynchronous.
ErisStore objects are implemented in additional modules.
Example:
import eris import eris/memory_stores import std/[asyncdispatch, streams] let text = "Hello world!" store = newMemoryStore() (capA, _) = waitFor encode(store, newStringStream(text)) (capB, _) = waitFor encode(store, newStringStream(text), convergentMode) (capC, _) = waitFor encode(store, newStringStream(text), convergentMode) assert capA != capB assert capB == capC assert waitFor(decode(store, capA)) == waitFor(decode(store, capB)) assert waitFor(decode(store, capB)) == waitFor(decode(store, capC))An ErisStore is implemented by get and put methods. Both operate on a variant of the FutureBlock type which holds a buffer, parameters, and callbacks.
Example:
import eris import eris/memory_stores import std/[asyncdispatch, streams] type LoggerStore {.final.} = ref object of ErisStore other: ErisStore proc newLogger(s: ErisStore): LoggerStore = LoggerStore(other: s) method get(logger: LoggerStore; fut: FutureGet) = fut.addCallback: if fut.failed: stderr.writeLine("failed to get ", fut.chunkSize.int, " byte chunk ", fut.`ref`) else: stderr.writeLine("got ", fut.chunkSize.int, " byte chunk ", fut.`ref`) get(logger.other, fut) method put(logger: LoggerStore; fut: FuturePut) = fut.addCallback: if fut.failed: stderr.writeLine("failed to put ", fut.chunkSize.int, " byte chunk ", fut.`ref`) else: stderr.writeLine("put ", fut.chunkSize.int, " byte chunk ", fut.`ref`) put(logger.other, fut) let store = newMemoryStore() logger = newLogger(store) (cap, _) = waitFor encode(logger, newStringStream("Hail ERIS!")) discard waitFor decode(logger, cap)
Types
BlockStatus = enum unknown, verified, plaintext
- Source
DiscardStore {.final.} = ref object of ErisStoreObj
- Source
ErisCap = object pair*: Pair level*: uint8 chunkSize*: ChunkSize
- A capability for retrieving ERIS encoded data. Source
ErisIngest = ref ErisIngestObj
- Source
ErisStore = ref ErisStoreObj
- Object for interfacing ERIS storage. Source
ErisStoreObj = object of RootObj nil
- Source
ErisStream = ref ErisStreamObj
- An object representing data streams. Source
FutureBlock = ref FutureBlockObj
- Source
Mode = enum uniqueMode, convergentMode
- Type for specifying if an encoding shall be unique or convergent. See section 2.3 for an explaination of encoding modes. Source
Operations = set[Operation]
- Source
Consts
erisCborTag = 276
- CBOR tag for ERIS binary read capabilities. https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml Source
Procs
proc `$`(cap): string {....raises: [], tags: [].}
- Encode a ErisCap to standard URN form. https://inqlab.net/projects/eris/#_urn Source
func `*`[T: SomeUnsignedInt](x: T; bs: ChunkSize): T
- Convenience function to multiply an integer by a ChunkSize value. Source
func `div`[T: SomeUnsignedInt](x: T; bs: ChunkSize): T
- Convenience function to divide an integer by a ChunkSize value. Source
proc `ref`(blk: FutureBlock): Reference {.inline, ...raises: [], tags: [].}
- Source
proc addCallback(blk: FutureBlock; cb: proc () {.closure, ...gcsafe.}) {. ...raises: [], tags: [].}
- Add a callback to a FutureBlock. Callbacks are called last-in-first-out when complete is called on blk. Source
proc addCallback(fut: Future; blk: FutureBlock; cb: proc () {.closure, ...gcsafe.})
- Source
proc append(ingest: ErisIngest; data: string | seq[byte]): owned( Future[void])
- Ingest content. Source
proc append(ingest: ErisIngest; stream: Stream): owned(Future[void]) {. ...raises: [Exception], tags: [ReadIOEffect, RootEffect].}
- Ingest content from a Stream. Source
proc assertVerified(blk: FutureBlock) {....raises: [], tags: [].}
- Source
proc atEnd(s: ErisStream): bool {....raises: [], tags: [].}
- Check if an ErisStream is positioned at its end. May return false negatives. Source
func buffer(blk: FutureBlock): pointer {.inline, ...raises: [], tags: [].}
- Source
proc bytes(cap): seq[byte] {....raises: [], tags: [].}
- Binary encoding of the read-capability. Source
proc cap(ingest: ErisIngest): Future[ErisCap] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Derive the ErisCap of ingest. The state of ingest is afterwards invalid until reinit or reopen is called. Source
proc cap(s: ErisStream): ErisCap {....raises: [], tags: [].}
- Source
func chunkSize(blk: FutureBlock): ChunkSize {.inline, ...raises: [], tags: [].}
- Source
proc chunkSize(ingest: ErisIngest): ChunkSize {....raises: [], tags: [].}
- Source
proc close(s: ErisStream) {....raises: [], tags: [].}
- Release the resources of an ErisStream. Source
proc complete(blk: FutureBlock) {....raises: [], tags: [RootEffect].}
- Complete a FutureBlock. Source
proc complete(blk: FutureGet; buf: sink seq[byte]; status = unknown) {. ...raises: [], tags: [RootEffect].}
- Source
proc complete(blk: FutureGet; src: pointer; len: Natural; status = unknown) {. ...raises: [], tags: [RootEffect].}
- Complete a Get FutureBlock with the chunk at src. Source
proc complete[T: byte | char](blk: FutureGet; buf: openArray[T]; status = unknown) {.inline.}
- Source
proc copy(blk: FutureBlock; dst: pointer; len: Natural) {....raises: [Exception], tags: [].}
- Copy chunk data out of a FutureBlock. Source
proc crypto(blk: FutureBlock; key; level: TreeLevel) {....raises: [], tags: [].}
- Source
proc decode(store; cap): Future[seq[byte]] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Asynchronously decode cap from store. Source
proc dump(s: ErisStream; stream: Stream): owned(Future[void]) {. ...raises: [Exception], tags: [RootEffect, WriteIOEffect].}
- Source
proc encode(store; chunkSize: ChunkSize; content: Stream; mode = uniqueMode): Future[ (ErisCap, uint64)] {....raises: [Exception, ValueError], tags: [ReadIOEffect, RootEffect].}
- Asychronously encode content into store and derive its ErisCap. Source
proc encode(store; chunkSize: ChunkSize; content: Stream; secret: Secret): Future[ (ErisCap, uint64)] {....raises: [Exception, ValueError], tags: [ReadIOEffect, RootEffect].}
- Asychronously encode content into store and derive its ErisCap. Source
proc encode(store; chunkSize: ChunkSize; content: string; mode = uniqueMode): Future[ (ErisCap, uint64)] {....raises: [Exception, ValueError], tags: [ReadIOEffect, RootEffect].}
- Asychronously encode content into store and derive its ErisCap. Source
proc encode(store; content: Stream; mode = uniqueMode): Future[ (ErisCap, uint64)] {....raises: [Exception, ValueError], tags: [ReadIOEffect, RootEffect].}
- Asychronously encode content into store and derive its ErisCap. The chunk size is 1KiB unless the content is at least 16KiB. Source
proc erisCap(content: string; chunkSize: ChunkSize): ErisCap {. ...raises: [Exception, ValueError, OSError], tags: [RootEffect, TimeEffect, ReadIOEffect].}
-
Derive a convergent ErisCap for content.
Example:
assert: $erisCap("Hello world!", chunk1k) == "urn:eris:BIAD77QDJMFAKZYH2DXBUZYAP3MXZ3DJZVFYQ5DFWC6T65WSFCU5S2IT4YZGJ7AC4SYQMP2DM2ANS2ZTCP3DJJIRV733CRAAHOSWIYZM3M"
Source proc fail(blk: FutureBlock; e: ref Exception) {....raises: [], tags: [RootEffect].}
- Source
func failed(blk: FutureBlock): bool {.inline, ...raises: [], tags: [].}
- Source
proc fromBase32[T: Reference | Key | Secret](v: var T; s: string): bool
- Source
proc get(store; pair: Pair; level: TreeLevel; bs: ChunkSize): Future[seq[byte]] {. ...raises: [ValueError, Exception], tags: [RootEffect].}
- Source
proc getAll(store: ErisStore; cap: ErisCap): Future[void] {....raises: [Exception], tags: [RootEffect].}
- Get all chunks that constitute cap from store. No data is returned, this procedure is for ensuring that all chunks are present at some store. Source
proc getBlock(store: ErisStore; ref: Reference): Future[seq[byte]] {....deprecated, raises: [Exception, ValueError], tags: [RootEffect].}
- Source This requests a small chunk and with a fallback to a large chunk. Do not use it.
proc getPosition(s: ErisStream): BiggestUInt {....raises: [], tags: [].}
- Return the position of an ErisStream. Source
proc hash(r: Reference): Hash {....raises: [], tags: [].}
- Reduce a Reference to a Hash value. Source
proc length(s: ErisStream): Future[BiggestUInt] {. ...raises: [Exception, ValueError], tags: [RootEffect].}
- Estimate the length of an ErisStream. The result is the length of s rounded up to the next chunk boundary. Source
proc loadBlock(s: ErisStream; bNum: BiggestUInt): Future[void] {. ...raises: [Exception], tags: [RootEffect].}
- Source
proc moveBytes(blk: FutureBlock): owned seq[byte] {....raises: [], tags: [].}
- Move the seq[byte] out of a FutureBlock. This is only safe to use in the first callback added to blk because it will be called last. Source
proc newDiscardStore(): DiscardStore {....raises: [], tags: [].}
- Create an ErisStore that discards writes and fails to read. Source
proc newErisIngest(store: ErisStore; chunkSize = chunk32k; mode = uniqueMode): ErisIngest {. ...raises: [], tags: [].}
- Create a new ErisIngest object. If mode is uniqueMode then a random convergence secret will be generated using entropy from the operating system. For convergentMode a zero-secret will be used and the encoding will be deterministic and reproducible. Source
proc newErisIngest(store: ErisStore; chunkSize = chunk32k; secret: Secret): ErisIngest {. ...raises: [], tags: [].}
- Create a new ErisIngest object. Source
proc newErisStream(store; cap): owned ErisStream {....raises: [], tags: [].}
- Open a new stream for reading ERIS data. Source
proc newFutureGet(bs: ChunkSize): FutureGet {....raises: [], tags: [].}
- Source
proc newFutureGet(ref: Reference; bs: ChunkSize): FutureGet {....raises: [], tags: [].}
- Source
proc newFuturePut(bs: ChunkSize): FuturePut {....raises: [], tags: [].}
- Source
proc newFuturePut(ref: Reference; bs: ChunkSize): FuturePut {....raises: [], tags: [].}
- Source
proc newFuturePut[T: byte | char](buffer: openArray[T]): FuturePut
- Source
proc notFound(blk: FutureBlock; msg = "") {.inline, ...raises: [], tags: [RootEffect].}
- Fail f with a KeyError exception. Source
proc padToNextBlock(ingest: ErisIngest; pad = 0x80'u8): Future[void] {. ...raises: [Exception], tags: [RootEffect].}
- Pad the ingest stream with 0x80 until the start of the next chunk. Source
proc parseErisUrn(urn: string): ErisCap {....raises: [ValueError], tags: [].}
- Decode a URN to a ErisCap. Source
proc position(ingest: ErisIngest): BiggestUInt {....raises: [], tags: [].}
- Get the current append position of ingest. This is same as the number of bytes appended. Source
proc read(s: ErisStream; size: int): Future[seq[byte]] {. ...raises: [Exception, ValueError], tags: [RootEffect].}
- Source
proc readAll(s: ErisStream): Future[seq[byte]] {. ...raises: [Exception, ValueError], tags: [RootEffect].}
- Reads all data from the specified ErisStream. Source
proc readBuffer(s: ErisStream; buffer: pointer; bufLen: int): Future[int] {. ...raises: [Exception, ValueError], tags: [RootEffect].}
- Source
proc readDataStr(s: ErisStream; buffer: var string; slice: Slice[int]): Future[ int] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Source
proc readLine(s: ErisStream): Future[string] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Source
func recommendedChunkSize(dataLength: Natural): ChunkSize {....raises: [], tags: [].}
- Return the recommended ChunkSize for encoding data of the given length. The current implementation selects 1KiB chunks for lengths less than 16KiB otherwise 32KiB. The reasoning is that anything less 16KiB is encoded in a tree with a depth of no more than two chunk. A 16KiB chunk would waste nearly half of a 32KiB chunk but only requires a single chunk to be fetched, whereas 16KiB-1 rould require 17 chunk requests. The behavior of this function is not guaranted to remain constant and because of storage efficiency and latency tradeoffs may not yield the best choice for all applications. Source
proc ref=(blk: FutureBlock; r: Reference) {.inline, ...raises: [], tags: [].}
- Source
proc reference[T: byte | char](data: openArray[T]): Reference
- Derive the Reference for a 1KiB or 32KiB buffer. Source
proc references(store: ErisStore; cap: ErisCap): Future[HashSet[Reference]] {. ...raises: [Exception, ValueError], tags: [RootEffect].}
- Collect the set of References that constitute an ErisCap. Source
proc reinit(ingest: ErisIngest) {....raises: [], tags: [].}
- Re-initialize an ErisIngest object. Source
proc reopen(ingest: ErisIngest; cap: ErisCap): owned(Future[void]) {. ...raises: [Exception], tags: [RootEffect].}
- Re-open an ErisIngest for appending to an ErisCap. Source
proc reopenErisIngest(store: ErisStore; cap: ErisCap; mode = uniqueMode): Future[ ErisIngest] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Re-open a ErisCap for appending. Source
proc reopenErisIngest(store: ErisStore; cap: ErisCap; secret: Secret): Future[ ErisIngest] {....raises: [Exception, ValueError], tags: [RootEffect].}
- Re-open a ErisCap for appending. Source
proc setPosition(s: ErisStream; pos: BiggestUInt) {....raises: [], tags: [].}
- Seek an ErisStream. Source
proc toBytes(blk: FutureBlock): owned seq[byte] {....raises: [], tags: [].}
- Source
func verified(blk: FutureBlock): bool {.inline, ...raises: [], tags: [].}
- Source
proc verify(blk: FutureBlock): bool {.discardable, ...raises: [], tags: [].}
- Verify that blk corresponds to ref and set the chunk error otherwise. Source
proc verify(blk: FutureBlock; ref: Reference): bool {.discardable, ...deprecated, raises: [], tags: [].}
- Source
Methods
method get(store; blk: FutureGet) {.base, ...raises: [], tags: [RootEffect].}
- Method for getting a chunk from a Store. The result is not decrypted but should be verified. Source
method hasBlock(store; r: Reference; bs: ChunkSize): Future[bool] {.base, ...raises: [ValueError, Exception], tags: [RootEffect].}
- Test if store has a chunk for a Reference. For some stores this is cheaper than retrieving a chunk. Source
Iterators
iterator chunkPairs(blk: seq[byte]): Pair {....raises: [], tags: [].}
- Source
Templates
template asFuture(blk: FutureBlock): untyped
- Source
template asFuture(blk: FutureBlock; body: untyped): untyped
- Source