2022-05-19 19:56:03 +00:00
|
|
|
## Nim-Codex
|
2021-02-26 00:23:22 +00:00
|
|
|
## Copyright (c) 2021 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.
|
|
|
|
|
2022-04-05 00:46:13 +00:00
|
|
|
import std/tables
|
|
|
|
export tables
|
|
|
|
|
2022-03-18 22:17:51 +00:00
|
|
|
import pkg/upraises
|
|
|
|
|
|
|
|
push: {.upraises: [].}
|
2021-02-26 00:23:22 +00:00
|
|
|
|
2023-08-02 00:50:52 +00:00
|
|
|
import pkg/libp2p/[cid, multicodec, multihash]
|
2021-08-30 19:25:20 +00:00
|
|
|
import pkg/stew/byteutils
|
2022-01-11 02:25:13 +00:00
|
|
|
import pkg/questionable
|
|
|
|
import pkg/questionable/results
|
2022-10-27 13:41:34 +00:00
|
|
|
import pkg/chronicles
|
2022-01-11 02:25:13 +00:00
|
|
|
|
2023-07-06 23:23:27 +00:00
|
|
|
import ./units
|
|
|
|
import ./utils
|
2022-10-27 13:41:34 +00:00
|
|
|
import ./formats
|
2022-01-11 02:25:13 +00:00
|
|
|
import ./errors
|
2021-02-26 00:23:22 +00:00
|
|
|
|
2023-07-06 23:23:27 +00:00
|
|
|
export errors, formats, units
|
2022-10-27 13:41:34 +00:00
|
|
|
|
2022-07-28 00:39:17 +00:00
|
|
|
const
|
2022-10-06 20:01:25 +00:00
|
|
|
# Size of blocks for storage / network exchange,
|
|
|
|
# should be divisible by 31 for PoR and by 64 for Leopard ECC
|
2023-07-06 23:23:27 +00:00
|
|
|
DefaultBlockSize* = NBytes 31 * 64 * 33
|
2022-07-28 00:39:17 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
Block* = ref object of RootObj
|
|
|
|
cid*: Cid
|
|
|
|
data*: seq[byte]
|
|
|
|
|
2023-08-02 00:50:52 +00:00
|
|
|
var
|
|
|
|
EmptyCid {.threadvar.}: array[CIDv0..CIDv1, Table[MultiCodec, Cid]]
|
2022-04-05 00:46:13 +00:00
|
|
|
|
2023-08-02 01:02:22 +00:00
|
|
|
proc emptyCid*(version: CidVersion, codex: MultiCodec): ?!Cid =
|
2022-04-05 00:46:13 +00:00
|
|
|
once:
|
2023-03-10 07:02:54 +00:00
|
|
|
EmptyCid = [
|
2022-04-05 00:46:13 +00:00
|
|
|
CIDv0: {
|
|
|
|
multiCodec("sha2-256"): Cid
|
|
|
|
.init("QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n")
|
|
|
|
.get()
|
|
|
|
}.toTable,
|
|
|
|
CIDv1: {
|
|
|
|
multiCodec("sha2-256"): Cid
|
|
|
|
.init("bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku")
|
|
|
|
.get()
|
|
|
|
}.toTable,
|
|
|
|
]
|
|
|
|
|
2023-08-02 00:50:52 +00:00
|
|
|
try:
|
|
|
|
success EmptyCid[version][codex]
|
|
|
|
except CatchableError as exc:
|
|
|
|
err(exc)
|
2022-04-05 00:46:13 +00:00
|
|
|
|
2023-08-02 00:50:52 +00:00
|
|
|
var
|
|
|
|
EmptyDigests {.threadvar.}: array[CIDv0..CIDv1, Table[MultiCodec, MultiHash]]
|
2022-04-05 00:46:13 +00:00
|
|
|
|
2023-08-02 19:44:32 +00:00
|
|
|
proc emptyDigest*(version: CidVersion, codec: MultiCodec): ?!MultiHash =
|
|
|
|
|
2022-04-05 00:46:13 +00:00
|
|
|
once:
|
2023-08-02 19:44:32 +00:00
|
|
|
let cid0 = emptyCid(CIDv0, multiCodec("sha2-256")).get()
|
|
|
|
let cid1 = emptyCid(CIDv1, multiCodec("sha2-256")).get()
|
|
|
|
let mhash0 = cid0.mhash.get
|
|
|
|
let mhash1 = cid1.mhash.get
|
|
|
|
|
2023-03-10 07:02:54 +00:00
|
|
|
EmptyDigests = [
|
2023-08-02 19:44:32 +00:00
|
|
|
CIDv0: { multiCodec("sha2-256"): mhash0 }.toTable,
|
|
|
|
CIDv1: { multiCodec("sha2-256"): mhash1 }.toTable,
|
2023-08-02 00:50:52 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
try:
|
2023-08-02 19:44:32 +00:00
|
|
|
success EmptyDigests[version][codec]
|
2023-08-02 00:50:52 +00:00
|
|
|
except CatchableError as exc:
|
|
|
|
err(exc)
|
|
|
|
|
|
|
|
var
|
|
|
|
EmptyBlock {.threadvar.}: array[CIDv0..CIDv1, Table[MultiCodec, Block]]
|
|
|
|
|
|
|
|
proc emptyBlock*(version: CidVersion, codex: MultiCodec): ?!Block =
|
2022-04-05 00:46:13 +00:00
|
|
|
once:
|
2023-08-02 19:44:32 +00:00
|
|
|
let cid0 = ? emptyCid(CIDv0, multiCodec("sha2-256"))
|
|
|
|
let cid1 = ? emptyCid(CIDv1, multiCodec("sha2-256"))
|
|
|
|
let blk0 = Block(cid: cid0)
|
|
|
|
let blk1 = Block(cid: cid1)
|
2023-08-02 00:50:52 +00:00
|
|
|
|
2023-03-10 07:02:54 +00:00
|
|
|
EmptyBlock = [
|
2023-08-02 19:44:32 +00:00
|
|
|
CIDv0: { multiCodec("sha2-256"): blk0 }.toTable,
|
|
|
|
CIDv1: { multiCodec("sha2-256"): blk1 }.toTable,
|
2022-04-05 00:46:13 +00:00
|
|
|
]
|
|
|
|
|
2023-08-02 00:50:52 +00:00
|
|
|
try:
|
|
|
|
success EmptyBlock[version][codex]
|
|
|
|
except CatchableError as exc:
|
|
|
|
err(exc)
|
|
|
|
|
2022-04-05 00:46:13 +00:00
|
|
|
|
|
|
|
proc isEmpty*(cid: Cid): bool =
|
2023-08-02 01:02:22 +00:00
|
|
|
cid == emptyCid(cid.cidver, cid.mhash.get().mcodec).get()
|
2022-04-05 00:46:13 +00:00
|
|
|
|
|
|
|
proc isEmpty*(blk: Block): bool =
|
|
|
|
blk.cid.isEmpty
|
|
|
|
|
|
|
|
proc emptyBlock*(cid: Cid): Block =
|
2023-08-02 01:07:56 +00:00
|
|
|
emptyBlock(cid.cidver, cid.mhash.get().mcodec).get()
|
2022-04-05 00:46:13 +00:00
|
|
|
|
2021-02-26 00:23:22 +00:00
|
|
|
proc `$`*(b: Block): string =
|
|
|
|
result &= "cid: " & $b.cid
|
|
|
|
result &= "\ndata: " & string.fromBytes(b.data)
|
|
|
|
|
2022-03-18 19:50:53 +00:00
|
|
|
func new*(
|
2023-06-22 15:11:18 +00:00
|
|
|
T: type Block,
|
|
|
|
data: openArray[byte] = [],
|
|
|
|
version = CIDv1,
|
|
|
|
mcodec = multiCodec("sha2-256"),
|
|
|
|
codec = multiCodec("raw")
|
|
|
|
): ?!Block =
|
|
|
|
## creates a new block for both storage and network IO
|
|
|
|
##
|
2022-01-11 02:25:13 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
hash = ? MultiHash.digest($mcodec, data).mapFailure
|
|
|
|
cid = ? Cid.init(version, codec, hash).mapFailure
|
|
|
|
|
2022-03-15 18:47:31 +00:00
|
|
|
# TODO: If the hash is `>=` to the data,
|
|
|
|
# use the Cid as a container!
|
|
|
|
Block(
|
2022-01-11 02:25:13 +00:00
|
|
|
cid: cid,
|
2022-03-15 18:47:31 +00:00
|
|
|
data: @data).success
|
2021-08-30 19:25:20 +00:00
|
|
|
|
2022-03-18 19:50:53 +00:00
|
|
|
func new*(
|
2023-06-22 15:11:18 +00:00
|
|
|
T: type Block,
|
|
|
|
cid: Cid,
|
|
|
|
data: openArray[byte],
|
|
|
|
verify: bool = true
|
|
|
|
): ?!Block =
|
|
|
|
## creates a new block for both storage and network IO
|
|
|
|
##
|
2022-01-11 02:25:13 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
mhash = ? cid.mhash.mapFailure
|
2022-03-18 19:50:53 +00:00
|
|
|
b = ? Block.new(
|
2022-01-11 02:25:13 +00:00
|
|
|
data = @data,
|
|
|
|
version = cid.cidver,
|
|
|
|
codec = cid.mcodec,
|
|
|
|
mcodec = mhash.mcodec)
|
|
|
|
|
|
|
|
if verify and cid != b.cid:
|
2022-04-05 00:46:13 +00:00
|
|
|
return "Cid and content don't match!".failure
|
2022-01-11 02:25:13 +00:00
|
|
|
|
|
|
|
success b
|