Add multicodec to table and make it single source of multiformat codes.

Adapt multiaddress and multihash to use multicodec.
This commit is contained in:
cheatfate 2018-12-05 17:24:07 +02:00
parent bdcfa1f189
commit b486410ac0
4 changed files with 518 additions and 256 deletions

View File

@ -9,43 +9,16 @@
## This module implements MultiAddress. ## This module implements MultiAddress.
import tables, strutils, net import tables, strutils, net
import multihash, transcoder, base58, base32, vbuffer import multicodec, multihash, transcoder, base58, base32, vbuffer
{.deadCodeElim:on.} {.deadCodeElim:on.}
const
P_IP4* = 0x0004
P_TCP* = 0x0006
P_UDP* = 0x0111
P_DCCP* = 0x0021
P_IP6* = 0x0029
P_IP6ZONE* = 0x002A
P_DNS4* = 0x0036
P_DNS6* = 0x0037
P_DNSADDR* = 0x0038
P_QUIC* = 0x01CC
P_SCTP* = 0x0084
P_UDT* = 0x012D
P_UTP* = 0x012E
P_UNIX* = 0x0190
P_P2P* = 0x01A5
P_IPFS* = 0x01A5 # alias for backwards compatability
P_HTTP* = 0x01E0
P_HTTPS* = 0x01BB
P_ONION* = 0x01BC
P_WS* = 0x01DD
LP2P_WSSTAR* = 0x01DF
LP2P_WRTCSTAR* = 0x0113
LP2P_WRTCDIR* = 0x0114
P_P2PCIRCUIT* = 0x0122
type type
MAKind* = enum MAKind* = enum
None, Fixed, Length, Path, Marker None, Fixed, Length, Path, Marker
MAProtocol* = object MAProtocol* = object
name*: string mcodec*: MultiCodec
code*: int
size*: int size*: int
kind: MAKind kind: MAKind
coder*: Transcoder coder*: Transcoder
@ -288,109 +261,101 @@ const
) )
ProtocolsList = [ ProtocolsList = [
MAProtocol( MAProtocol(
name: "ip4", code: P_IP4, kind: Fixed, size: 4, mcodec: multiCodec("ip4"), kind: Fixed, size: 4,
coder: TranscoderIP4 coder: TranscoderIP4
), ),
MAProtocol( MAProtocol(
name: "tcp", code: P_TCP, kind: Fixed, size: 2, mcodec: multiCodec("tcp"), kind: Fixed, size: 2,
coder: TranscoderPort coder: TranscoderPort
), ),
MAProtocol( MAProtocol(
name: "udp", code: P_UDP, kind: Fixed, size: 2, mcodec: multiCodec("udp"), kind: Fixed, size: 2,
coder: TranscoderPort coder: TranscoderPort
), ),
MAProtocol( MAProtocol(
name: "ip6", code: P_IP6, kind: Fixed, size: 16, mcodec: multiCodec("ip6"), kind: Fixed, size: 16,
coder: TranscoderIP6 coder: TranscoderIP6
), ),
MAProtocol( MAProtocol(
name: "dccp", code: P_DCCP, kind: Fixed, size: 2, mcodec: multiCodec("dccp"), kind: Fixed, size: 2,
coder: TranscoderPort coder: TranscoderPort
), ),
MAProtocol( MAProtocol(
name: "sctp", code: P_SCTP, kind: Fixed, size: 2, mcodec: multiCodec("sctp"), kind: Fixed, size: 2,
coder: TranscoderPort coder: TranscoderPort
), ),
MAProtocol( MAProtocol(
name: "udt", code: P_UDT, kind: Marker, size: 0 mcodec: multiCodec("udt"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "utp", code: P_UTP, kind: Marker, size: 0 mcodec: multiCodec("utp"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "http", code: P_HTTP, kind: Marker, size: 0 mcodec: multiCodec("http"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "https", code: P_HTTPS, kind: Marker, size: 0 mcodec: multiCodec("https"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "quic", code: P_QUIC, kind: Marker, size: 0 mcodec: multiCodec("quic"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "ip6zone", code: P_IP6ZONE, kind: Length, size: 0, mcodec: multiCodec("ip6zone"), kind: Length, size: 0,
coder: TranscoderIP6Zone coder: TranscoderIP6Zone
), ),
MAProtocol( MAProtocol(
name: "onion", code: P_ONION, kind: Fixed, size: 10, mcodec: multiCodec("onion"), kind: Fixed, size: 10,
coder: TranscoderOnion coder: TranscoderOnion
), ),
MAProtocol( MAProtocol(
name: "ws", code: P_WS, kind: Marker, size: 0 mcodec: multiCodec("ws"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "ws", code: P_WS, kind: Marker, size: 0 mcodec: multiCodec("ipfs"), kind: Length, size: 0,
),
MAProtocol(
name: "ipfs", code: P_IPFS, kind: Length, size: 0,
coder: TranscoderP2P coder: TranscoderP2P
), ),
MAProtocol( MAProtocol(
name: "p2p", code: P_P2P, kind: Length, size: 0, mcodec: multiCodec("p2p"), kind: Length, size: 0,
coder: TranscoderP2P coder: TranscoderP2P
), ),
MAProtocol( MAProtocol(
name: "unix", code: P_UNIX, kind: Path, size: 0, mcodec: multiCodec("unix"), kind: Path, size: 0,
coder: TranscoderUnix coder: TranscoderUnix
), ),
MAProtocol( MAProtocol(
name: "dns4", code: P_DNS4, kind: Length, size: 0, mcodec: multiCodec("dns4"), kind: Length, size: 0,
coder: TranscoderDNS coder: TranscoderDNS
), ),
MAProtocol( MAProtocol(
name: "dns6", code: P_DNS6, kind: Length, size: 0, mcodec: multiCodec("dns6"), kind: Length, size: 0,
coder: TranscoderDNS coder: TranscoderDNS
), ),
MAProtocol( MAProtocol(
name: "dnsaddr", code: P_DNS6, kind: Length, size: 0, mcodec: multiCodec("dnsaddr"), kind: Length, size: 0,
coder: TranscoderDNS coder: TranscoderDNS
), ),
MAProtocol( MAProtocol(
name: "p2p-circuit", code: P_P2PCIRCUIT, kind: Marker, size: 0 mcodec: multiCodec("p2p-circuit"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "p2p-websocket-star", code: LP2P_WSSTAR, kind: Marker, size: 0 mcodec: multiCodec("p2p-websocket-star"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "p2p-webrtc-star", code: LP2P_WRTCSTAR, kind: Marker, size: 0 mcodec: multiCodec("p2p-webrtc-star"), kind: Marker, size: 0
), ),
MAProtocol( MAProtocol(
name: "p2p-webrtc-direct", code: LP2P_WRTCDIR, kind: Marker, size: 0 mcodec: multiCodec("p2p-webrtc-direct"), kind: Marker, size: 0
) )
] ]
proc initMultiAddressNameTable(): Table[string, MAProtocol] {.compileTime.} = proc initMultiAddressCodeTable(): Table[MultiCodec,
result = initTable[string, MAProtocol]() MAProtocol] {.compileTime.} =
result = initTable[MultiCodec, MAProtocol]()
for item in ProtocolsList: for item in ProtocolsList:
result[item.name] = item result[item.mcodec] = item
proc initMultiAddressCodeTable(): Table[int, MAProtocol] {.compileTime.} =
result = initTable[int, MAProtocol]()
for item in ProtocolsList:
result[item.code] = item
const const
CodeAddresses = initMultiAddressCodeTable() CodeAddresses = initMultiAddressCodeTable()
NameAddresses = initMultiAddressNameTable()
proc trimRight(s: string, ch: char): string = proc trimRight(s: string, ch: char): string =
## Consume trailing characters ``ch`` from string ``s`` and return result. ## Consume trailing characters ``ch`` from string ``s`` and return result.
@ -407,32 +372,18 @@ proc shcopy*(m1: var MultiAddress, m2: MultiAddress) =
m1.data.offset = m2.data.offset m1.data.offset = m2.data.offset
m1.data.length = m2.data.length m1.data.length = m2.data.length
proc protoCode*(mtype: typedesc[MultiAddress], protocol: string): int = proc protoCode*(ma: MultiAddress): MultiCodec =
## Returns protocol code from protocol name ``protocol``.
let proto = NameAddresses.getOrDefault(protocol)
if proto.kind == None:
raise newException(MultiAddressError, "Protocol not found")
result = proto.code
proc protoName*(mtype: typedesc[MultiAddress], protocol: int): string =
## Returns protocol name from protocol code ``protocol``.
let proto = CodeAddresses.getOrDefault(protocol)
if proto.kind == None:
raise newException(MultiAddressError, "Protocol not found")
result = proto.name
proc protoCode*(ma: MultiAddress): int =
## Returns MultiAddress ``ma`` protocol code. ## Returns MultiAddress ``ma`` protocol code.
var header: uint64 var header: uint64
var vb: MultiAddress var vb: MultiAddress
shcopy(vb, ma) shcopy(vb, ma)
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
result = proto.code result = proto.mcodec
proc protoName*(ma: MultiAddress): string = proc protoName*(ma: MultiAddress): string =
## Returns MultiAddress ``ma`` protocol name. ## Returns MultiAddress ``ma`` protocol name.
@ -441,11 +392,11 @@ proc protoName*(ma: MultiAddress): string =
shcopy(vb, ma) shcopy(vb, ma)
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
result = proto.name result = $(proto.mcodec)
proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): int = proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): int =
## Returns MultiAddress ``ma`` protocol argument value. ## Returns MultiAddress ``ma`` protocol argument value.
@ -458,7 +409,7 @@ proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): int =
shcopy(vb, ma) shcopy(vb, ma)
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
@ -483,7 +434,7 @@ proc getPart(ma: MultiAddress, index: int): MultiAddress =
while offset <= index: while offset <= index:
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
@ -522,7 +473,7 @@ iterator items*(ma: MultiAddress): MultiAddress =
var res = MultiAddress(data: initVBuffer()) var res = MultiAddress(data: initVBuffer())
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
@ -554,20 +505,20 @@ proc `$`*(value: MultiAddress): string =
break break
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
raise newException(MultiAddressError, "Malformed binary address!") raise newException(MultiAddressError, "Malformed binary address!")
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & $header & "'") "Unsupported protocol '" & $header & "'")
if proto.kind in {Fixed, Length, Path}: if proto.kind in {Fixed, Length, Path}:
if isNil(proto.coder.bufferToString): if isNil(proto.coder.bufferToString):
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Missing protocol '" & proto.name & "' transcoder") "Missing protocol '" & $(proto.mcodec) & "' coder")
if not proto.coder.bufferToString(vb.data, part): if not proto.coder.bufferToString(vb.data, part):
raise newException(MultiAddressError, "Decoding protocol error") raise newException(MultiAddressError, "Decoding protocol error")
parts.add(proto.name) parts.add($(proto.mcodec))
parts.add(part) parts.add(part)
elif proto.kind == Marker: elif proto.kind == Marker:
parts.add(proto.name) parts.add($(proto.mcodec))
if len(parts) > 0: if len(parts) > 0:
result = "/" & parts.join("/") result = "/" & parts.join("/")
@ -585,7 +536,7 @@ proc validate*(ma: MultiAddress): bool =
break break
if vb.data.readVarint(header) == -1: if vb.data.readVarint(header) == -1:
return false return false
let proto = CodeAddresses.getOrDefault(int(header)) let proto = CodeAddresses.getOrDefault(MultiCodec(header))
if proto.kind == None: if proto.kind == None:
return false return false
if proto.kind in {Fixed, Length, Path}: if proto.kind in {Fixed, Length, Path}:
@ -628,6 +579,11 @@ proc init*(mtype: typedesc[MultiAddress], protocol: int): MultiAddress =
result.data.writeVarint(cast[uint64](proto.code)) result.data.writeVarint(cast[uint64](proto.code))
result.data.finish() result.data.finish()
proc getProtocol(name: string): MAProtocol {.inline.} =
let mc = MultiCodec.codec(name)
if mc != InvalidMultiCodec:
result = CodeAddresses.getOrDefault(mc)
proc init*(mtype: typedesc[MultiAddress], value: string): MultiAddress = proc init*(mtype: typedesc[MultiAddress], value: string): MultiAddress =
## Initialize MultiAddress object from string representation ``value``. ## Initialize MultiAddress object from string representation ``value``.
var parts = value.trimRight('/').split('/') var parts = value.trimRight('/').split('/')
@ -638,7 +594,7 @@ proc init*(mtype: typedesc[MultiAddress], value: string): MultiAddress =
result.data = initVBuffer() result.data = initVBuffer()
while offset < len(parts): while offset < len(parts):
let part = parts[offset] let part = parts[offset]
let proto = NameAddresses.getOrDefault(part) let proto = getProtocol(part)
if proto.kind == None: if proto.kind == None:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Unsupported protocol '" & part & "'") "Unsupported protocol '" & part & "'")
@ -651,20 +607,21 @@ proc init*(mtype: typedesc[MultiAddress], value: string): MultiAddress =
"Missing protocol '" & part & "' argument") "Missing protocol '" & part & "' argument")
if proto.kind in {Fixed, Length}: if proto.kind in {Fixed, Length}:
result.data.writeVarint(cast[uint](proto.code)) result.data.writeCodec(proto.mcodec)
if not proto.coder.stringToBuffer(parts[offset + 1], result.data): let res = proto.coder.stringToBuffer(parts[offset + 1], result.data)
if not res:
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Error encoding `$1/$2`" % [part, parts[offset + 1]]) "Error encoding `$1/$2`" % [part, parts[offset + 1]])
offset += 2 offset += 2
elif proto.kind == Path: elif proto.kind == Path:
var path = "/" & (parts[(offset + 1)..^1].join("/")) var path = "/" & (parts[(offset + 1)..^1].join("/"))
result.data.writeVarint(cast[uint](proto.code)) result.data.writeCodec(proto.mcodec)
if not proto.coder.stringToBuffer(path, result.data): if not proto.coder.stringToBuffer(path, result.data):
raise newException(MultiAddressError, raise newException(MultiAddressError,
"Error encoding `$1/$2`" % [part, path]) "Error encoding `$1/$2`" % [part, path])
break break
elif proto.kind == Marker: elif proto.kind == Marker:
result.data.writeVarint(cast[uint](proto.code)) result.data.writeCodec(proto.mcodec)
offset += 1 offset += 1
result.data.finish() result.data.finish()

316
libp2p/multicodec.nim Normal file
View File

@ -0,0 +1,316 @@
## Nim-Libp2p
## Copyright (c) 2018 Status Research & Development GmbH
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not BE copied, modified, or distributed except according to
## those terms.
## This module implements MultiCodec.
import tables, hashes
import varint, vbuffer
{.deadCodeElim: on.}
## List of officially supported codecs can BE found here
## https://github.com/multiformats/multicodec/blob/master/table.csv
const MultiCodecList = [
("raw", 0x55),
# serialization formats
("cbor", 0x51),
("protobuf", 0x50),
("rlp", 0x60),
("bencode", 0x63),
# multiformats
("multicodec", 0x30),
("multihash", 0x31),
("multiaddr", 0x32),
("multibase", 0x33),
# multihashes
("identity", 0x00),
("md4", 0xD4),
("md5", 0xD5),
("sha1", 0x11),
("sha2-256", 0x12),
("sha2-512", 0x13),
("dbl-sha2-256", 0x56),
("sha3-224", 0x17),
("sha3-256", 0x16),
("sha3-384", 0x15),
("sha3-512", 0x14),
("shake-128", 0x18),
("shake-256", 0x19),
("keccak-224", 0x1A),
("keccak-256", 0x1B),
("keccak-384", 0x1C),
("keccak-512", 0x1D),
("murmur3", 0x22),
("blake2b-8", 0xB201), ("blake2b-16", 0xB202), ("blake2b-24", 0xB203),
("blake2b-32", 0xB204), ("blake2b-40", 0xB205), ("blake2b-48", 0xB206),
("blake2b-56", 0xB207), ("blake2b-64", 0xB208), ("blake2b-72", 0xB209),
("blake2b-80", 0xB20A), ("blake2b-88", 0xB20B), ("blake2b-96", 0xB20C),
("blake2b-104", 0xB20D), ("blake2b-112", 0xB20E), ("blake2b-120", 0xB20F),
("blake2b-128", 0xB210), ("blake2b-136", 0xB211), ("blake2b-144", 0xB212),
("blake2b-152", 0xB213), ("blake2b-160", 0xB214), ("blake2b-168", 0xB215),
("blake2b-176", 0xB216), ("blake2b-184", 0xB217), ("blake2b-192", 0xB218),
("blake2b-200", 0xB219), ("blake2b-208", 0xB21A), ("blake2b-216", 0xB21B),
("blake2b-224", 0xB21C), ("blake2b-232", 0xB21D), ("blake2b-240", 0xB21E),
("blake2b-248", 0xB21F), ("blake2b-256", 0xB220), ("blake2b-264", 0xB221),
("blake2b-272", 0xB222), ("blake2b-280", 0xB223), ("blake2b-288", 0xB224),
("blake2b-296", 0xB225), ("blake2b-304", 0xB226), ("blake2b-312", 0xB227),
("blake2b-320", 0xB228), ("blake2b-328", 0xB229), ("blake2b-336", 0xB22A),
("blake2b-344", 0xB22B), ("blake2b-352", 0xB22C), ("blake2b-360", 0xB22D),
("blake2b-368", 0xB22E), ("blake2b-376", 0xB22F), ("blake2b-384", 0xB230),
("blake2b-392", 0xB231), ("blake2b-400", 0xB232), ("blake2b-408", 0xB233),
("blake2b-416", 0xB234), ("blake2b-424", 0xB235), ("blake2b-432", 0xB236),
("blake2b-440", 0xB237), ("blake2b-448", 0xB238), ("blake2b-456", 0xB239),
("blake2b-464", 0xB23A), ("blake2b-472", 0xB23B), ("blake2b-480", 0xB23C),
("blake2b-488", 0xB23D), ("blake2b-496", 0xB23E), ("blake2b-504", 0xB23F),
("blake2b-512", 0xB240), ("blake2s-8", 0xB241), ("blake2s-16", 0xB242),
("blake2s-24", 0xB243), ("blake2s-32", 0xB244), ("blake2s-40", 0xB245),
("blake2s-48", 0xB246), ("blake2s-56", 0xB247), ("blake2s-64", 0xB248),
("blake2s-72", 0xB249), ("blake2s-80", 0xB24A), ("blake2s-88", 0xB24B),
("blake2s-96", 0xB24C), ("blake2s-104", 0xB24D), ("blake2s-112", 0xB24E),
("blake2s-120", 0xB24F), ("blake2s-128", 0xB250), ("blake2s-136", 0xB251),
("blake2s-144", 0xB252), ("blake2s-152", 0xB253), ("blake2s-160", 0xB254),
("blake2s-168", 0xB255), ("blake2s-176", 0xB256), ("blake2s-184", 0xB257),
("blake2s-192", 0xB258), ("blake2s-200", 0xB259), ("blake2s-208", 0xB25A),
("blake2s-216", 0xB25B), ("blake2s-224", 0xB25C), ("blake2s-232", 0xB25D),
("blake2s-240", 0xB25E), ("blake2s-248", 0xB25F), ("blake2s-256", 0xB260),
("skein256-8", 0xB301), ("skein256-16", 0xB302), ("skein256-24", 0xB303),
("skein256-32", 0xB304), ("skein256-40", 0xB305), ("skein256-48", 0xB306),
("skein256-56", 0xB307), ("skein256-64", 0xB308), ("skein256-72", 0xB309),
("skein256-80", 0xB30A), ("skein256-88", 0xB30B), ("skein256-96", 0xB30C),
("skein256-104", 0xB30D), ("skein256-112", 0xB30E), ("skein256-120", 0xB30F),
("skein256-128", 0xB310), ("skein256-136", 0xB311), ("skein256-144", 0xB312),
("skein256-152", 0xB313), ("skein256-160", 0xB314), ("skein256-168", 0xB315),
("skein256-176", 0xB316), ("skein256-184", 0xB317), ("skein256-192", 0xB318),
("skein256-200", 0xB319), ("skein256-208", 0xB31A), ("skein256-216", 0xB31B),
("skein256-224", 0xB31C), ("skein256-232", 0xB31D), ("skein256-240", 0xB31E),
("skein256-248", 0xB31F), ("skein256-256", 0xB320),
("skein512-8", 0xB321), ("skein512-16", 0xB322), ("skein512-24", 0xB323),
("skein512-32", 0xB324), ("skein512-40", 0xB325), ("skein512-48", 0xB326),
("skein512-56", 0xB327), ("skein512-64", 0xB328), ("skein512-72", 0xB329),
("skein512-80", 0xB32A), ("skein512-88", 0xB32B), ("skein512-96", 0xB32C),
("skein512-104", 0xB32D), ("skein512-112", 0xB32E), ("skein512-120", 0xB32F),
("skein512-128", 0xB330), ("skein512-136", 0xB331), ("skein512-144", 0xB332),
("skein512-152", 0xB333), ("skein512-160", 0xB334), ("skein512-168", 0xB335),
("skein512-176", 0xB336), ("skein512-184", 0xB337), ("skein512-192", 0xB338),
("skein512-200", 0xB339), ("skein512-208", 0xB33A), ("skein512-216", 0xB33B),
("skein512-224", 0xB33C), ("skein512-232", 0xB33D), ("skein512-240", 0xB33E),
("skein512-248", 0xB33F), ("skein512-256", 0xB340), ("skein512-264", 0xB341),
("skein512-272", 0xB342), ("skein512-280", 0xB343), ("skein512-288", 0xB344),
("skein512-296", 0xB345), ("skein512-304", 0xB346), ("skein512-312", 0xB347),
("skein512-320", 0xB348), ("skein512-328", 0xB349), ("skein512-336", 0xB34A),
("skein512-344", 0xB34B), ("skein512-352", 0xB34C), ("skein512-360", 0xB34D),
("skein512-368", 0xB34E), ("skein512-376", 0xB34F), ("skein512-384", 0xB350),
("skein512-392", 0xB351), ("skein512-400", 0xB352), ("skein512-408", 0xB353),
("skein512-416", 0xB354), ("skein512-424", 0xB355), ("skein512-432", 0xB356),
("skein512-440", 0xB357), ("skein512-448", 0xB358), ("skein512-456", 0xB359),
("skein512-464", 0xB35A), ("skein512-472", 0xB35B), ("skein512-480", 0xB35C),
("skein512-488", 0xB35D), ("skein512-496", 0xB35E), ("skein512-504", 0xB35F),
("skein512-512", 0xB360), ("skein1024-8", 0xB361), ("skein1024-16", 0xB362),
("skein1024-24", 0xB363), ("skein1024-32", 0xB364), ("skein1024-40", 0xB365),
("skein1024-48", 0xB366), ("skein1024-56", 0xB367), ("skein1024-64", 0xB368),
("skein1024-72", 0xB369), ("skein1024-80", 0xB36A), ("skein1024-88", 0xB36B),
("skein1024-96", 0xB36C), ("skein1024-104", 0xB36D),
("skein1024-112", 0xB36E), ("skein1024-120", 0xB36F),
("skein1024-128", 0xB370), ("skein1024-136", 0xB371),
("skein1024-144", 0xB372), ("skein1024-152", 0xB373),
("skein1024-160", 0xB374), ("skein1024-168", 0xB375),
("skein1024-176", 0xB376), ("skein1024-184", 0xB377),
("skein1024-192", 0xB378), ("skein1024-200", 0xB379),
("skein1024-208", 0xB37A), ("skein1024-216", 0xB37B),
("skein1024-224", 0xB37C), ("skein1024-232", 0xB37D),
("skein1024-240", 0xB37E), ("skein1024-248", 0xB37F),
("skein1024-256", 0xB380), ("skein1024-264", 0xB381),
("skein1024-272", 0xB382), ("skein1024-280", 0xB383),
("skein1024-288", 0xB384), ("skein1024-296", 0xB385),
("skein1024-304", 0xB386), ("skein1024-312", 0xB387),
("skein1024-320", 0xB388), ("skein1024-328", 0xB389),
("skein1024-336", 0xB38A), ("skein1024-344", 0xB38B),
("skein1024-352", 0xB38C), ("skein1024-360", 0xB38D),
("skein1024-368", 0xB38E), ("skein1024-376", 0xB38F),
("skein1024-384", 0xB390), ("skein1024-392", 0xB391),
("skein1024-400", 0xB392), ("skein1024-408", 0xB393),
("skein1024-416", 0xB394), ("skein1024-424", 0xB395),
("skein1024-432", 0xB396), ("skein1024-440", 0xB397),
("skein1024-448", 0xB398), ("skein1024-456", 0xB399),
("skein1024-464", 0xB39A), ("skein1024-472", 0xB39B),
("skein1024-480", 0xB39C), ("skein1024-488", 0xB39D),
("skein1024-496", 0xB39E), ("skein1024-504", 0xB39F),
("skein1024-512", 0xB3A0), ("skein1024-520", 0xB3A1),
("skein1024-528", 0xB3A2), ("skein1024-536", 0xB3A3),
("skein1024-544", 0xB3A4), ("skein1024-552", 0xB3A5),
("skein1024-560", 0xB3A6), ("skein1024-568", 0xB3A7),
("skein1024-576", 0xB3A8), ("skein1024-584", 0xB3A9),
("skein1024-592", 0xB3AA), ("skein1024-600", 0xB3AB),
("skein1024-608", 0xB3AC), ("skein1024-616", 0xB3AD),
("skein1024-624", 0xB3AE), ("skein1024-632", 0xB3AF),
("skein1024-640", 0xB3B0), ("skein1024-648", 0xB3B1),
("skein1024-656", 0xB3B2), ("skein1024-664", 0xB3B3),
("skein1024-672", 0xB3B4), ("skein1024-680", 0xB3B5),
("skein1024-688", 0xB3B6), ("skein1024-696", 0xB3B7),
("skein1024-704", 0xB3B8), ("skein1024-712", 0xB3B9),
("skein1024-720", 0xB3BA), ("skein1024-728", 0xB3BB),
("skein1024-736", 0xB3BC), ("skein1024-744", 0xB3BD),
("skein1024-752", 0xB3BE), ("skein1024-760", 0xB3BF),
("skein1024-768", 0xB3C0), ("skein1024-776", 0xB3C1),
("skein1024-784", 0xB3C2), ("skein1024-792", 0xB3C3),
("skein1024-800", 0xB3C4), ("skein1024-808", 0xB3C5),
("skein1024-816", 0xB3C6), ("skein1024-824", 0xB3C7),
("skein1024-832", 0xB3C8), ("skein1024-840", 0xB3C9),
("skein1024-848", 0xB3CA), ("skein1024-856", 0xB3CB),
("skein1024-864", 0xB3CC), ("skein1024-872", 0xB3CD),
("skein1024-880", 0xB3CE), ("skein1024-888", 0xB3CF),
("skein1024-896", 0xB3D0), ("skein1024-904", 0xB3D1),
("skein1024-912", 0xB3D2), ("skein1024-920", 0xB3D3),
("skein1024-928", 0xB3D4), ("skein1024-936", 0xB3D5),
("skein1024-944", 0xB3D6), ("skein1024-952", 0xB3D7),
("skein1024-960", 0xB3D8), ("skein1024-968", 0xB3D9),
("skein1024-976", 0xB3DA), ("skein1024-984", 0xB3DB),
("skein1024-992", 0xB3DC), ("skein1024-1000", 0xB3DD),
("skein1024-1008", 0xB3DE), ("skein1024-1016", 0xB3DF),
("skein1024-1024", 0xB3E0),
# multiaddrs
("ip4", 0x04),
("ip6", 0x29),
("ip6zone", 0x2A),
("tcp", 0x06),
("udp", 0x0111),
("dccp", 0x21),
("sctp", 0x84),
("udt", 0x012D),
("utp", 0x012E),
("unix", 0x0190), # not in multicodec list
("ipfs", 0x01A5),
("p2p", 0x01A5),
("http", 0x01E0),
("https", 0x01BB),
("quic", 0x01CC),
("ws", 0x01DD),
("wss", 0x01DE), # not in multicodec list
("p2p-websocket-star", 0x01DF), # not in multicodec list
("p2p-webrtc-star", 0x0113), # not in multicodec list
("p2p-webrtc-direct", 0x0114), # not in multicodec list
("onion", 0x01BC),
("p2p-circuit", 0x0122),
("dns4", 0x36),
("dns6", 0x37),
("dnsaddr", 0x38),
# IPLD formats
("dag-pb", 0x70),
("dag-cbor", 0x71),
("dag-json", 0x129),
("git-raw", 0x78),
("eth-block", 0x90),
("eth-block-list", 0x91),
("eth-tx-trie", 0x92),
("eth-tx", 0x93),
("eth-tx-receipt-trie", 0x94),
("eth-tx-receipt", 0x95),
("eth-state-trie", 0x96),
("eth-account-snapshot", 0x97),
("eth-storage-trie", 0x98),
("bitcoin-block", 0xB0),
("bitcoin-tx", 0xB1),
("zcash-block", 0xC0),
("zcash-tx", 0xC1),
("stellar-block", 0xD0),
("stellar-tx", 0xD1),
("decred-block", 0xE0),
("decred-tx", 0xE1),
("dash-block", 0xF0),
("dash-tx", 0xF1),
("torrent-info", 0x7B),
("torrent-file", 0x7C),
("ed25519-pub", 0xED)
]
type
MultiCodec* = distinct int
MultiCodecError* = object of Exception
const
InvalidMultiCodec* = MultiCodec(-1)
proc initMultiCodecNameTable(): Table[string, int] {.compileTime.} =
result = initTable[string, int]()
for item in MultiCodecList:
result[item[0]] = item[1]
proc initMultiCodecCodeTable(): Table[int, string] {.compileTime.} =
result = initTable[int, string]()
for item in MultiCodecList:
result[item[1]] = item[0]
const
CodeCodecs = initMultiCodecCodeTable()
NameCodecs = initMultiCodecNameTable()
proc multiCodec*(name: string): MultiCodec {.compileTime.} =
## Generate MultiCodec from string ``name`` at compile time.
var code = NameCodecs.getOrDefault(name, -1)
if code == -1:
raise newException(MultiCodecError,
"MultiCodec `" & name & "` not supported!")
result = MultiCodec(code)
proc multiCodec*(code: int): MultiCodec {.compileTime.} =
## Generate MultiCodec from integer ``code`` at compile time.
var name = CodeCodecs.getOrDefault(code, "")
if name == "":
raise newException(MultiCodecError,
"MultiCodec with code " & $code & " not supported!")
result = MultiCodec(code)
proc `$`*(mc: MultiCodec): string =
## Returns string representation of MultiCodec ``mc``.
result = CodeCodecs.getOrDefault(int(mc), "")
if result == "":
raise newException(MultiCodecError,
"MultiCodec with code " & $int(mc) & " not supported!")
proc `==`*(mc: MultiCodec, name: string): bool {.inline.} =
## Compares MultiCodec ``mc`` with string ``name``.
var mcname = CodeCodecs.getOrDefault(int(mc), "")
if mcname == "":
return false
result = (mcname == name)
proc `==`*(mc: MultiCodec, code: int): bool {.inline.} =
## Compares MultiCodec ``mc`` with integer ``code``.
result = (int(mc) == code)
proc `==`*(a, b: MultiCodec): bool =
## Returns ``true`` if MultiCodecs ``a`` and ``b`` are equal.
int(a) == int(b)
proc `!=`*(a, b: MultiCodec): bool =
## Returns ``true`` if MultiCodecs ``a`` and ``b`` are not equal.
int(a) != int(b)
proc hash*(m: MultiCodec): Hash {.inline.} =
## Hash procedure for tables.
result = hash(int(m))
proc codec*(mt: typedesc[MultiCodec], name: string): MultiCodec {.inline.} =
## Return MultiCodec from string representation ``name``.
## If ``name`` is not valid multicodec name, then ``InvalidMultiCodec`` will
## be returned.
result = MultiCodec(NameCodecs.getOrDefault(name, -1))
proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} =
## Return MultiCodec from integer representation ``code``.
## If ``code`` is not valid multicodec code, then ``InvalidMultiCodec`` will
## be returned.
let res = CodeCodecs.getOrDefault(code, "")
if res == "":
result = InvalidMultiCodec
else:
result = MultiCodec(code)
proc writeCodec*(vb: var VBuffer, mc: MultiCodec) {.inline.} =
## Write MultiCodec to buffer ``vb``.
vb.writeVarint(cast[uint](mc))

View File

@ -22,7 +22,7 @@
## 3. MURMUR ## 3. MURMUR
import tables import tables
import nimcrypto/[sha2, keccak, blake2, hash, utils] import nimcrypto/[sha2, keccak, blake2, hash, utils]
import varint, vbuffer, base58 import varint, vbuffer, base58, multicodec
const const
MaxHashSize* = 128 MaxHashSize* = 128
@ -31,14 +31,13 @@ type
MHashCoderProc* = proc(data: openarray[byte], MHashCoderProc* = proc(data: openarray[byte],
output: var openarray[byte]) {.nimcall, gcsafe.} output: var openarray[byte]) {.nimcall, gcsafe.}
MHash* = object MHash* = object
name*: string mcodec*: MultiCodec
code*: int
size*: int size*: int
coder*: MHashCoderProc coder*: MHashCoderProc
MultiHash* = object MultiHash* = object
data*: VBuffer data*: VBuffer
code*: int mcodec*: MultiCodec
size*: int size*: int
dpos*: int dpos*: int
@ -162,175 +161,154 @@ proc shake_256hash(data: openarray[byte], output: var openarray[byte]) =
const const
HashesList = [ HashesList = [
MHash(name: "identity", code: 0x00, size: 0, coder: identhash), MHash(mcodec: multiCodec("identity"), size: 0,
MHash(name: "dbl-sha2-256", code: 0x56, size: sha256.sizeDigest, coder: identhash),
MHash(mcodec: multiCodec("dbl-sha2-256"), size: sha256.sizeDigest,
coder: dblsha2_256hash coder: dblsha2_256hash
), ),
MHash(name: "sha2-256", code: 0x12, size: sha256.sizeDigest, MHash(mcodec: multiCodec("sha2-256"), size: sha256.sizeDigest,
coder: sha2_256hash coder: sha2_256hash
), ),
MHash(name: "sha2-512", code: 0x13, size: sha512.sizeDigest, MHash(mcodec: multiCodec("sha2-512"), size: sha512.sizeDigest,
coder: sha2_512hash coder: sha2_512hash
), ),
MHash(name: "sha3-224", code: 0x17, size: sha3_224.sizeDigest, MHash(mcodec: multiCodec("sha3-224"), size: sha3_224.sizeDigest,
coder: sha3_224hash coder: sha3_224hash
), ),
MHash(name: "sha3-256", code: 0x16, size: sha3_256.sizeDigest, MHash(mcodec: multiCodec("sha3-256"), size: sha3_256.sizeDigest,
coder: sha3_256hash coder: sha3_256hash
), ),
MHash(name: "sha3-384", code: 0x15, size: sha3_384.sizeDigest, MHash(mcodec: multiCodec("sha3-384"), size: sha3_384.sizeDigest,
coder: sha3_384hash coder: sha3_384hash
), ),
MHash(name: "sha3-512", code: 0x14, size: sha3_512.sizeDigest, MHash(mcodec: multiCodec("sha3-512"), size: sha3_512.sizeDigest,
coder: sha3_512hash coder: sha3_512hash
), ),
MHash(name: "shake-128", code: 0x18, size: 32, coder: shake_128hash), MHash(mcodec: multiCodec("shake-128"), size: 32, coder: shake_128hash),
MHash(name: "shake-256", code: 0x19, size: 64, coder: shake_256hash), MHash(mcodec: multiCodec("shake-256"), size: 64, coder: shake_256hash),
MHash(name: "keccak-224", code: 0x1A, size: keccak_224.sizeDigest, MHash(mcodec: multiCodec("keccak-224"), size: keccak_224.sizeDigest,
coder: keccak_224hash coder: keccak_224hash
), ),
MHash(name: "keccak-256", code: 0x1B, size: keccak_256.sizeDigest, MHash(mcodec: multiCodec("keccak-256"), size: keccak_256.sizeDigest,
coder: keccak_256hash coder: keccak_256hash
), ),
MHash(name: "keccak-384", code: 0x1C, size: keccak_384.sizeDigest, MHash(mcodec: multiCodec("keccak-384"), size: keccak_384.sizeDigest,
coder: keccak_384hash coder: keccak_384hash
), ),
MHash(name: "keccak-512", code: 0x1D, size: keccak_512.sizeDigest, MHash(mcodec: multiCodec("keccak-512"), size: keccak_512.sizeDigest,
coder: keccak_512hash coder: keccak_512hash
), ),
MHash(name: "blake2b-8", code: 0xB201, size: 1, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-8"), size: 1, coder: blake2Bhash),
MHash(name: "blake2b-16", code: 0xB202, size: 2, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-16"), size: 2, coder: blake2Bhash),
MHash(name: "blake2b-24", code: 0xB203, size: 3, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-24"), size: 3, coder: blake2Bhash),
MHash(name: "blake2b-32", code: 0xB204, size: 4, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-32"), size: 4, coder: blake2Bhash),
MHash(name: "blake2b-40", code: 0xB205, size: 5, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-40"), size: 5, coder: blake2Bhash),
MHash(name: "blake2b-48", code: 0xB206, size: 6, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-48"), size: 6, coder: blake2Bhash),
MHash(name: "blake2b-56", code: 0xB207, size: 7, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-56"), size: 7, coder: blake2Bhash),
MHash(name: "blake2b-64", code: 0xB208, size: 8, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-64"), size: 8, coder: blake2Bhash),
MHash(name: "blake2b-72", code: 0xB209, size: 9, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-72"), size: 9, coder: blake2Bhash),
MHash(name: "blake2b-80", code: 0xB20A, size: 10, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-80"), size: 10, coder: blake2Bhash),
MHash(name: "blake2b-88", code: 0xB20B, size: 11, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-88"), size: 11, coder: blake2Bhash),
MHash(name: "blake2b-96", code: 0xB20C, size: 12, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-96"), size: 12, coder: blake2Bhash),
MHash(name: "blake2b-104", code: 0xB20D, size: 13, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-104"), size: 13, coder: blake2Bhash),
MHash(name: "blake2b-112", code: 0xB20E, size: 14, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-112"), size: 14, coder: blake2Bhash),
MHash(name: "blake2b-120", code: 0xB20F, size: 15, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-120"), size: 15, coder: blake2Bhash),
MHash(name: "blake2b-128", code: 0xB210, size: 16, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-128"), size: 16, coder: blake2Bhash),
MHash(name: "blake2b-136", code: 0xB211, size: 17, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-136"), size: 17, coder: blake2Bhash),
MHash(name: "blake2b-144", code: 0xB212, size: 18, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-144"), size: 18, coder: blake2Bhash),
MHash(name: "blake2b-152", code: 0xB213, size: 19, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-152"), size: 19, coder: blake2Bhash),
MHash(name: "blake2b-160", code: 0xB214, size: 20, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-160"), size: 20, coder: blake2Bhash),
MHash(name: "blake2b-168", code: 0xB215, size: 21, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-168"), size: 21, coder: blake2Bhash),
MHash(name: "blake2b-176", code: 0xB216, size: 22, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-176"), size: 22, coder: blake2Bhash),
MHash(name: "blake2b-184", code: 0xB217, size: 23, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-184"), size: 23, coder: blake2Bhash),
MHash(name: "blake2b-192", code: 0xB218, size: 24, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-192"), size: 24, coder: blake2Bhash),
MHash(name: "blake2b-200", code: 0xB219, size: 25, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-200"), size: 25, coder: blake2Bhash),
MHash(name: "blake2b-208", code: 0xB21A, size: 26, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-208"), size: 26, coder: blake2Bhash),
MHash(name: "blake2b-216", code: 0xB21B, size: 27, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-216"), size: 27, coder: blake2Bhash),
MHash(name: "blake2b-224", code: 0xB21C, size: 28, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-224"), size: 28, coder: blake2Bhash),
MHash(name: "blake2b-232", code: 0xB21D, size: 29, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-232"), size: 29, coder: blake2Bhash),
MHash(name: "blake2b-240", code: 0xB21E, size: 30, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-240"), size: 30, coder: blake2Bhash),
MHash(name: "blake2b-248", code: 0xB21F, size: 31, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-248"), size: 31, coder: blake2Bhash),
MHash(name: "blake2b-256", code: 0xB220, size: 32, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-256"), size: 32, coder: blake2Bhash),
MHash(name: "blake2b-264", code: 0xB221, size: 33, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-264"), size: 33, coder: blake2Bhash),
MHash(name: "blake2b-272", code: 0xB222, size: 34, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-272"), size: 34, coder: blake2Bhash),
MHash(name: "blake2b-280", code: 0xB223, size: 35, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-280"), size: 35, coder: blake2Bhash),
MHash(name: "blake2b-288", code: 0xB224, size: 36, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-288"), size: 36, coder: blake2Bhash),
MHash(name: "blake2b-296", code: 0xB225, size: 37, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-296"), size: 37, coder: blake2Bhash),
MHash(name: "blake2b-304", code: 0xB226, size: 38, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-304"), size: 38, coder: blake2Bhash),
MHash(name: "blake2b-312", code: 0xB227, size: 39, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-312"), size: 39, coder: blake2Bhash),
MHash(name: "blake2b-320", code: 0xB228, size: 40, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-320"), size: 40, coder: blake2Bhash),
MHash(name: "blake2b-328", code: 0xB229, size: 41, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-328"), size: 41, coder: blake2Bhash),
MHash(name: "blake2b-336", code: 0xB22A, size: 42, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-336"), size: 42, coder: blake2Bhash),
MHash(name: "blake2b-344", code: 0xB22B, size: 43, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-344"), size: 43, coder: blake2Bhash),
MHash(name: "blake2b-352", code: 0xB22C, size: 44, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-352"), size: 44, coder: blake2Bhash),
MHash(name: "blake2b-360", code: 0xB22D, size: 45, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-360"), size: 45, coder: blake2Bhash),
MHash(name: "blake2b-368", code: 0xB22E, size: 46, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-368"), size: 46, coder: blake2Bhash),
MHash(name: "blake2b-376", code: 0xB22F, size: 47, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-376"), size: 47, coder: blake2Bhash),
MHash(name: "blake2b-384", code: 0xB230, size: 48, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-384"), size: 48, coder: blake2Bhash),
MHash(name: "blake2b-392", code: 0xB231, size: 49, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-392"), size: 49, coder: blake2Bhash),
MHash(name: "blake2b-400", code: 0xB232, size: 50, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-400"), size: 50, coder: blake2Bhash),
MHash(name: "blake2b-408", code: 0xB233, size: 51, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-408"), size: 51, coder: blake2Bhash),
MHash(name: "blake2b-416", code: 0xB234, size: 52, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-416"), size: 52, coder: blake2Bhash),
MHash(name: "blake2b-424", code: 0xB235, size: 53, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-424"), size: 53, coder: blake2Bhash),
MHash(name: "blake2b-432", code: 0xB236, size: 54, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-432"), size: 54, coder: blake2Bhash),
MHash(name: "blake2b-440", code: 0xB237, size: 55, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-440"), size: 55, coder: blake2Bhash),
MHash(name: "blake2b-448", code: 0xB238, size: 56, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-448"), size: 56, coder: blake2Bhash),
MHash(name: "blake2b-456", code: 0xB239, size: 57, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-456"), size: 57, coder: blake2Bhash),
MHash(name: "blake2b-464", code: 0xB23A, size: 58, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-464"), size: 58, coder: blake2Bhash),
MHash(name: "blake2b-472", code: 0xB23B, size: 59, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-472"), size: 59, coder: blake2Bhash),
MHash(name: "blake2b-480", code: 0xB23C, size: 60, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-480"), size: 60, coder: blake2Bhash),
MHash(name: "blake2b-488", code: 0xB23D, size: 61, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-488"), size: 61, coder: blake2Bhash),
MHash(name: "blake2b-496", code: 0xB23E, size: 62, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-496"), size: 62, coder: blake2Bhash),
MHash(name: "blake2b-504", code: 0xB23F, size: 63, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-504"), size: 63, coder: blake2Bhash),
MHash(name: "blake2b-512", code: 0xB240, size: 64, coder: blake2Bhash), MHash(mcodec: multiCodec("blake2b-512"), size: 64, coder: blake2Bhash),
MHash(name: "blake2s-8", code: 0xB241, size: 1, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-8"), size: 1, coder: blake2Shash),
MHash(name: "blake2s-16", code: 0xB242, size: 2, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-16"), size: 2, coder: blake2Shash),
MHash(name: "blake2s-24", code: 0xB243, size: 3, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-24"), size: 3, coder: blake2Shash),
MHash(name: "blake2s-32", code: 0xB244, size: 4, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-32"), size: 4, coder: blake2Shash),
MHash(name: "blake2s-40", code: 0xB245, size: 5, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-40"), size: 5, coder: blake2Shash),
MHash(name: "blake2s-48", code: 0xB246, size: 6, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-48"), size: 6, coder: blake2Shash),
MHash(name: "blake2s-56", code: 0xB247, size: 7, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-56"), size: 7, coder: blake2Shash),
MHash(name: "blake2s-64", code: 0xB248, size: 8, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-64"), size: 8, coder: blake2Shash),
MHash(name: "blake2s-72", code: 0xB249, size: 9, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-72"), size: 9, coder: blake2Shash),
MHash(name: "blake2s-80", code: 0xB24A, size: 10, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-80"), size: 10, coder: blake2Shash),
MHash(name: "blake2s-88", code: 0xB24B, size: 11, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-88"), size: 11, coder: blake2Shash),
MHash(name: "blake2s-96", code: 0xB24C, size: 12, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-96"), size: 12, coder: blake2Shash),
MHash(name: "blake2s-104", code: 0xB24D, size: 13, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-104"), size: 13, coder: blake2Shash),
MHash(name: "blake2s-112", code: 0xB24E, size: 14, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-112"), size: 14, coder: blake2Shash),
MHash(name: "blake2s-120", code: 0xB24F, size: 15, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-120"), size: 15, coder: blake2Shash),
MHash(name: "blake2s-128", code: 0xB250, size: 16, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-128"), size: 16, coder: blake2Shash),
MHash(name: "blake2s-136", code: 0xB251, size: 17, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-136"), size: 17, coder: blake2Shash),
MHash(name: "blake2s-144", code: 0xB252, size: 18, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-144"), size: 18, coder: blake2Shash),
MHash(name: "blake2s-152", code: 0xB253, size: 19, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-152"), size: 19, coder: blake2Shash),
MHash(name: "blake2s-160", code: 0xB254, size: 20, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-160"), size: 20, coder: blake2Shash),
MHash(name: "blake2s-168", code: 0xB255, size: 21, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-168"), size: 21, coder: blake2Shash),
MHash(name: "blake2s-176", code: 0xB256, size: 22, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-176"), size: 22, coder: blake2Shash),
MHash(name: "blake2s-184", code: 0xB257, size: 23, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-184"), size: 23, coder: blake2Shash),
MHash(name: "blake2s-192", code: 0xB258, size: 24, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-192"), size: 24, coder: blake2Shash),
MHash(name: "blake2s-200", code: 0xB259, size: 25, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-200"), size: 25, coder: blake2Shash),
MHash(name: "blake2s-208", code: 0xB25A, size: 26, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-208"), size: 26, coder: blake2Shash),
MHash(name: "blake2s-216", code: 0xB25B, size: 27, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-216"), size: 27, coder: blake2Shash),
MHash(name: "blake2s-224", code: 0xB25C, size: 28, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-224"), size: 28, coder: blake2Shash),
MHash(name: "blake2s-232", code: 0xB25D, size: 29, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-232"), size: 29, coder: blake2Shash),
MHash(name: "blake2s-240", code: 0xB25E, size: 30, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-240"), size: 30, coder: blake2Shash),
MHash(name: "blake2s-248", code: 0xB25F, size: 31, coder: blake2Shash), MHash(mcodec: multiCodec("blake2s-248"), size: 31, coder: blake2Shash),
MHash(name: "blake2s-256", code: 0xB260, size: 32, coder: blake2Shash) MHash(mcodec: multiCodec("blake2s-256"), size: 32, coder: blake2Shash)
] ]
proc initMultiHashNameTable(): Table[string, MHash] {.compileTime.} = proc initMultiHashCodeTable(): Table[MultiCodec, MHash] {.compileTime.} =
result = initTable[string, MHash]() result = initTable[MultiCodec, MHash]()
for item in HashesList: for item in HashesList:
result[item.name] = item result[item.mcodec] = item
proc initMultiHashCodeTable(): Table[int, MHash] {.compileTime.} =
result = initTable[int, MHash]()
for item in HashesList:
result[item.code] = item
const const
CodeHashes = initMultiHashCodeTable() CodeHashes = initMultiHashCodeTable()
NameHashes = initMultiHashNameTable()
proc multihashName*(code: int): string =
## Returns MultiHash digest name from its code.
let hash = CodeHashes.getOrDefault(code)
if isNil(hash.coder):
raise newException(MultiHashError, "Hash not supported")
else:
result = hash.name
proc multihashCode*(name: string): int =
## Returns MultiHash digest code from its name.
let hash = NameHashes.getOrDefault(name)
if isNil(hash.coder):
raise newException(MultiHashError, "Hash not supported")
else:
result = hash.code
proc digestImplWithHash(hash: MHash, data: openarray[byte]): MultiHash = proc digestImplWithHash(hash: MHash, data: openarray[byte]): MultiHash =
var buffer: array[MaxHashSize, byte] var buffer: array[MaxHashSize, byte]
result.data = initVBuffer() result.data = initVBuffer()
result.code = hash.code result.mcodec = hash.mcodec
result.data.writeVarint(uint(hash.code)) result.data.writeCodec(hash.mcodec)
if hash.size == 0: if hash.size == 0:
result.data.writeVarint(uint(len(data))) result.data.writeVarint(uint(len(data)))
result.dpos = len(result.data.buffer) result.dpos = len(result.data.buffer)
@ -345,9 +323,9 @@ proc digestImplWithHash(hash: MHash, data: openarray[byte]): MultiHash =
proc digestImplWithoutHash(hash: MHash, data: openarray[byte]): MultiHash = proc digestImplWithoutHash(hash: MHash, data: openarray[byte]): MultiHash =
result.data = initVBuffer() result.data = initVBuffer()
result.code = hash.code result.mcodec = hash.mcodec
result.size = len(data) result.size = len(data)
result.data.writeVarint(uint(hash.code)) result.data.writeCodec(hash.mcodec)
result.data.writeVarint(uint(len(data))) result.data.writeVarint(uint(len(data)))
result.dpos = len(result.data.buffer) result.dpos = len(result.data.buffer)
result.data.writeArray(data) result.data.writeArray(data)
@ -356,7 +334,10 @@ proc digest*(mhtype: typedesc[MultiHash], hashname: string,
data: openarray[byte]): MultiHash {.inline.} = data: openarray[byte]): MultiHash {.inline.} =
## Perform digest calculation using hash algorithm with name ``hashname`` on ## Perform digest calculation using hash algorithm with name ``hashname`` on
## data array ``data``. ## data array ``data``.
let hash = NameHashes.getOrDefault(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name")
let hash = CodeHashes.getOrDefault(mc)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") raise newException(MultihashError, "Hash not supported")
result = digestImplWithHash(hash, data) result = digestImplWithHash(hash, data)
@ -374,14 +355,17 @@ proc init*[T](mhtype: typedesc[MultiHash], hashname: string,
mdigest: MDigest[T]): MultiHash {.inline.} = mdigest: MDigest[T]): MultiHash {.inline.} =
## Create MultiHash from nimcrypto's `MDigest` object and hash algorithm name ## Create MultiHash from nimcrypto's `MDigest` object and hash algorithm name
## ``hashname``. ## ``hashname``.
let hash = NameHashes.getOrDefault(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name")
let hash = CodeHashes.getOrDefault(mc)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") raise newException(MultihashError, "Hash not supported")
if hash.size != len(mdigest.data): if hash.size != len(mdigest.data):
raise newException(MultiHashError, "Incorrect MDigest[T] size") raise newException(MultiHashError, "Incorrect MDigest[T] size")
result = digestImplWithoutHash(hash, mdigest.data) result = digestImplWithoutHash(hash, mdigest.data)
proc init*[T](mhtype: typedesc[MultiHash], hashcode: int, proc init*[T](mhtype: typedesc[MultiHash], hashcode: MultiCodec,
mdigest: MDigest[T]): MultiHash {.inline.} = mdigest: MDigest[T]): MultiHash {.inline.} =
## Create MultiHash from nimcrypto's `MDigest` and hash algorithm code ## Create MultiHash from nimcrypto's `MDigest` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
@ -396,14 +380,17 @@ proc init*(mhtype: typedesc[MultiHash], hashname: string,
bdigest: openarray[byte]): MultiHash {.inline.} = bdigest: openarray[byte]): MultiHash {.inline.} =
## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code ## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
let hash = NameHashes.getOrDefault(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name")
let hash = CodeHashes.getOrDefault(mc)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") raise newException(MultihashError, "Hash not supported")
if (hash.size != 0) and (hash.size != len(bdigest)): if (hash.size != 0) and (hash.size != len(bdigest)):
raise newException(MultiHashError, "Incorrect bdigest size") raise newException(MultiHashError, "Incorrect bdigest size")
result = digestImplWithoutHash(hash, bdigest) result = digestImplWithoutHash(hash, bdigest)
proc init*(mhtype: typedesc[MultiHash], hashcode: int, proc init*(mhtype: typedesc[MultiHash], hashcode: MultiCodec,
bdigest: openarray[byte]): MultiHash {.inline.} = bdigest: openarray[byte]): MultiHash {.inline.} =
## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code ## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
@ -439,14 +426,14 @@ proc decode*(mhtype: typedesc[MultiHash], data: openarray[byte],
dpos += res dpos += res
if size > 0x7FFF_FFFF'u64: if size > 0x7FFF_FFFF'u64:
return -1 return -1
let hash = CodeHashes.getOrDefault(int(code)) let hash = CodeHashes.getOrDefault(MultiCodec(code))
if isNil(hash.coder): if isNil(hash.coder):
return -1 return -1
if (hash.size != 0) and (hash.size != int(size)): if (hash.size != 0) and (hash.size != int(size)):
return -1 return -1
if not vb.isEnough(int(size)): if not vb.isEnough(int(size)):
return -1 return -1
mhash = MultiHash.init(int(code), mhash = MultiHash.init(MultiCodec(code),
vb.buffer.toOpenArray(vb.offset, vb.buffer.toOpenArray(vb.offset,
vb.offset + int(size) - 1)) vb.offset + int(size) - 1))
result = vb.offset + int(size) result = vb.offset + int(size)
@ -494,12 +481,12 @@ proc `==`*[T](mdigest: MDigest[T], mh: MultiHash): bool {.inline.} =
## hashes are equal, ``false`` otherwise. ## hashes are equal, ``false`` otherwise.
result = `==`(mh, mdigest) result = `==`(mh, mdigest)
proc `==`*(a, b: MultiHash): bool = proc `==`*(a: MultiHash, b: MultiHash): bool =
## Compares MultiHashes ``a`` and ``b``, returns ``true`` if ## Compares MultiHashes ``a`` and ``b``, returns ``true`` if
## hashes are equal, ``false`` otherwise. ## hashes are equal, ``false`` otherwise.
if a.dpos == 0 and b.dpos == 0: if a.dpos == 0 and b.dpos == 0:
return true return true
if a.code != b.code: if a.mcodec != b.mcodec:
return false return false
if a.size != b.size: if a.size != b.size:
return false return false
@ -514,8 +501,8 @@ proc base58*(value: MultiHash): string =
## Return Base58 encoded string representation of MultiHash ``value``. ## Return Base58 encoded string representation of MultiHash ``value``.
result = Base58.encode(value.data.buffer) result = Base58.encode(value.data.buffer)
proc `$`*(value: MultiHash): string = proc `$`*(mh: MultiHash): string =
## Return string representation of MultiHash ``value``. ## Return string representation of MultiHash ``value``.
let digest = toHex(value.data.buffer.toOpenArray(value.dpos, let digest = toHex(mh.data.buffer.toOpenArray(mh.dpos,
value.dpos + value.size - 1)) mh.dpos + mh.size - 1))
result = multihashName(value.code) & "/" & digest result = $(mh.mcodec) & "/" & digest

View File

@ -12,6 +12,8 @@ import vbuffer
type type
Transcoder* = object Transcoder* = object
stringToBuffer*: proc(s: string, vb: var VBuffer): bool {.nimcall.} stringToBuffer*: proc(s: string,
bufferToString*: proc(vb: var VBuffer, s: var string): bool {.nimcall.} vb: var VBuffer): bool {.nimcall, gcsafe.}
validateBuffer*: proc(vb: var VBuffer): bool {.nimcall.} bufferToString*: proc(vb: var VBuffer,
s: var string): bool {.nimcall, gcsafe.}
validateBuffer*: proc(vb: var VBuffer): bool {.nimcall, gcsafe.}