2022-05-19 19:56:03 +00:00
|
|
|
## Nim-Codex
|
2022-03-14 16:06:36 +00:00
|
|
|
## Copyright (c) 2022 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-08-24 12:15:59 +00:00
|
|
|
# This module implements serialization and deserialization of Manifest
|
|
|
|
|
2022-03-18 22:17:51 +00:00
|
|
|
import pkg/upraises
|
|
|
|
|
|
|
|
push: {.upraises: [].}
|
2022-03-14 16:06:36 +00:00
|
|
|
|
|
|
|
import std/tables
|
|
|
|
|
|
|
|
import pkg/libp2p
|
|
|
|
import pkg/questionable
|
|
|
|
import pkg/questionable/results
|
|
|
|
import pkg/chronicles
|
|
|
|
import pkg/chronos
|
|
|
|
|
2022-03-15 18:47:31 +00:00
|
|
|
import ./manifest
|
2022-03-14 16:06:36 +00:00
|
|
|
import ../errors
|
2022-07-29 20:04:12 +00:00
|
|
|
import ../blocktype
|
2022-04-06 00:34:29 +00:00
|
|
|
import ./types
|
2022-03-15 18:47:31 +00:00
|
|
|
|
2023-11-09 11:47:41 +00:00
|
|
|
proc encode*(coder: DagPBCoder, manifest: Manifest): ?!seq[byte] =
|
2022-03-14 16:06:36 +00:00
|
|
|
## Encode the manifest into a ``ManifestCodec``
|
|
|
|
## multicodec container (Dag-pb) for now
|
|
|
|
##
|
|
|
|
|
2022-08-24 12:15:59 +00:00
|
|
|
? manifest.verify()
|
2022-03-14 16:06:36 +00:00
|
|
|
var pbNode = initProtoBuffer()
|
|
|
|
|
2022-03-15 18:47:31 +00:00
|
|
|
# NOTE: The `Data` field in the the `dag-pb`
|
|
|
|
# contains the following protobuf `Message`
|
|
|
|
#
|
|
|
|
# ```protobuf
|
2022-04-05 00:46:13 +00:00
|
|
|
# Message ErasureInfo {
|
2023-11-14 12:02:17 +00:00
|
|
|
# optional uint32 ecK = 1; # number of encoded blocks
|
|
|
|
# optional uint32 ecM = 2; # number of parity blocks
|
2023-11-09 11:47:41 +00:00
|
|
|
# optional bytes originalManifest = 3; # manifest of the original dataset
|
2022-04-05 00:46:13 +00:00
|
|
|
# }
|
2022-03-15 18:47:31 +00:00
|
|
|
# Message Header {
|
2023-11-14 12:02:17 +00:00
|
|
|
# optional bytes treeCid = 1; # cid (root) of the tree
|
2022-04-05 00:46:13 +00:00
|
|
|
# optional uint32 blockSize = 2; # size of a single block
|
2023-11-14 12:02:17 +00:00
|
|
|
# optional uint64 datasetSize = 3; # size of the dataset
|
2022-04-05 00:46:13 +00:00
|
|
|
# optional ErasureInfo erasure = 4; # erasure coding info
|
2022-03-15 18:47:31 +00:00
|
|
|
# }
|
|
|
|
# ```
|
|
|
|
#
|
2023-11-14 12:02:17 +00:00
|
|
|
# var treeRootVBuf = initVBuffer()
|
2022-03-15 18:47:31 +00:00
|
|
|
var header = initProtoBuffer()
|
2023-11-14 12:02:17 +00:00
|
|
|
header.write(1, manifest.treeCid.data.buffer)
|
2022-03-15 18:47:31 +00:00
|
|
|
header.write(2, manifest.blockSize.uint32)
|
2023-11-14 12:02:17 +00:00
|
|
|
header.write(3, manifest.datasetSize.uint32)
|
2022-04-05 00:46:13 +00:00
|
|
|
if manifest.protected:
|
|
|
|
var erasureInfo = initProtoBuffer()
|
2023-03-10 07:02:54 +00:00
|
|
|
erasureInfo.write(1, manifest.ecK.uint32)
|
|
|
|
erasureInfo.write(2, manifest.ecM.uint32)
|
2023-11-14 17:28:24 +00:00
|
|
|
erasureInfo.write(3, manifest.interleave.uint32)
|
|
|
|
erasureInfo.write(4, ? coder.encode(manifest.originalManifest)) # TODO: fix check
|
2022-04-05 00:46:13 +00:00
|
|
|
erasureInfo.finish()
|
|
|
|
|
|
|
|
header.write(4, erasureInfo)
|
2022-03-15 18:47:31 +00:00
|
|
|
|
2023-11-14 12:02:17 +00:00
|
|
|
pbNode.write(1, header) # set the treeCid as the data field
|
2022-03-14 16:06:36 +00:00
|
|
|
pbNode.finish()
|
|
|
|
|
|
|
|
return pbNode.buffer.success
|
|
|
|
|
2023-11-09 11:47:41 +00:00
|
|
|
proc decode*(coder: DagPBCoder, data: openArray[byte]): ?!Manifest =
|
2022-03-14 16:06:36 +00:00
|
|
|
## Decode a manifest from a data blob
|
|
|
|
##
|
|
|
|
|
|
|
|
var
|
|
|
|
pbNode = initProtoBuffer(data)
|
2022-03-15 18:47:31 +00:00
|
|
|
pbHeader: ProtoBuffer
|
2022-04-05 00:46:13 +00:00
|
|
|
pbErasureInfo: ProtoBuffer
|
2023-11-14 12:02:17 +00:00
|
|
|
treeCidBuf: seq[byte]
|
2023-11-09 11:47:41 +00:00
|
|
|
originalManifest: Manifest
|
2023-11-14 12:02:17 +00:00
|
|
|
datasetSize: uint32
|
2022-03-15 18:47:31 +00:00
|
|
|
blockSize: uint32
|
2023-11-14 17:28:24 +00:00
|
|
|
ecK, ecM, interleave: uint32
|
2022-03-14 16:06:36 +00:00
|
|
|
|
2022-03-15 18:47:31 +00:00
|
|
|
# Decode `Header` message
|
|
|
|
if pbNode.getField(1, pbHeader).isErr:
|
|
|
|
return failure("Unable to decode `Header` from dag-pb manifest!")
|
|
|
|
|
|
|
|
# Decode `Header` contents
|
2023-11-14 12:02:17 +00:00
|
|
|
if pbHeader.getField(1, treeCidBuf).isErr:
|
|
|
|
return failure("Unable to decode `treeCid` from manifest!")
|
2022-03-15 18:47:31 +00:00
|
|
|
|
|
|
|
if pbHeader.getField(2, blockSize).isErr:
|
|
|
|
return failure("Unable to decode `blockSize` from manifest!")
|
2022-03-14 16:06:36 +00:00
|
|
|
|
2023-11-14 12:02:17 +00:00
|
|
|
if pbHeader.getField(3, datasetSize).isErr:
|
|
|
|
return failure("Unable to decode `datasetSize` from manifest!")
|
2022-08-24 12:15:59 +00:00
|
|
|
|
2022-04-05 00:46:13 +00:00
|
|
|
if pbHeader.getField(4, pbErasureInfo).isErr:
|
|
|
|
return failure("Unable to decode `erasureInfo` from manifest!")
|
|
|
|
|
2023-11-14 12:02:17 +00:00
|
|
|
let protected = pbErasureInfo.buffer.len > 0
|
|
|
|
if protected:
|
2023-03-10 07:02:54 +00:00
|
|
|
if pbErasureInfo.getField(1, ecK).isErr:
|
2022-04-05 00:46:13 +00:00
|
|
|
return failure("Unable to decode `K` from manifest!")
|
|
|
|
|
2023-03-10 07:02:54 +00:00
|
|
|
if pbErasureInfo.getField(2, ecM).isErr:
|
2022-04-05 00:46:13 +00:00
|
|
|
return failure("Unable to decode `M` from manifest!")
|
|
|
|
|
2023-11-14 17:28:24 +00:00
|
|
|
if pbErasureInfo.getField(3, interleave).isErr:
|
|
|
|
return failure("Unable to decode `interleave` from manifest!")
|
|
|
|
|
2023-11-09 11:47:41 +00:00
|
|
|
var buffer = newSeq[byte]()
|
2023-11-14 17:28:24 +00:00
|
|
|
if pbErasureInfo.getField(4, buffer).isErr:
|
2023-11-09 11:47:41 +00:00
|
|
|
return failure("Unable to decode `originalManifest` from manifest!")
|
|
|
|
originalManifest = coder.decode(buffer).get # TODO: fix check
|
2022-03-14 16:06:36 +00:00
|
|
|
|
2023-11-14 12:02:17 +00:00
|
|
|
let
|
|
|
|
treeCid = ? Cid.init(treeCidBuf).mapFailure
|
2022-03-15 18:47:31 +00:00
|
|
|
|
2023-07-19 14:06:59 +00:00
|
|
|
let
|
2023-11-14 12:02:17 +00:00
|
|
|
self = if protected:
|
2023-07-19 14:06:59 +00:00
|
|
|
Manifest.new(
|
2023-11-14 12:02:17 +00:00
|
|
|
treeCid = treeCid,
|
|
|
|
datasetSize = datasetSize.NBytes,
|
2023-07-19 14:06:59 +00:00
|
|
|
blockSize = blockSize.NBytes,
|
2023-11-14 12:02:17 +00:00
|
|
|
version = treeCid.cidver,
|
|
|
|
hcodec = (? treeCid.mhash.mapFailure).mcodec,
|
|
|
|
codec = treeCid.mcodec,
|
2023-07-19 14:06:59 +00:00
|
|
|
ecK = ecK.int,
|
|
|
|
ecM = ecM.int,
|
2023-11-14 17:28:24 +00:00
|
|
|
interleave = interleave.int, #TODO
|
|
|
|
originalManifest = originalManifest
|
2023-07-19 14:06:59 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
Manifest.new(
|
2023-11-14 12:02:17 +00:00
|
|
|
treeCid = treeCid,
|
|
|
|
datasetSize = datasetSize.NBytes,
|
2023-07-19 14:06:59 +00:00
|
|
|
blockSize = blockSize.NBytes,
|
2023-11-14 12:02:17 +00:00
|
|
|
version = treeCid.cidver,
|
|
|
|
hcodec = (? treeCid.mhash.mapFailure).mcodec,
|
|
|
|
codec = treeCid.mcodec
|
2023-07-19 14:06:59 +00:00
|
|
|
)
|
2022-04-05 00:46:13 +00:00
|
|
|
|
2022-08-24 12:15:59 +00:00
|
|
|
? self.verify()
|
2022-04-05 00:46:13 +00:00
|
|
|
self.success
|
|
|
|
|
|
|
|
proc encode*(
|
2023-06-22 15:11:18 +00:00
|
|
|
self: Manifest,
|
|
|
|
encoder = ManifestContainers[$DagPBCodec]
|
|
|
|
): ?!seq[byte] =
|
2022-03-15 18:47:31 +00:00
|
|
|
## Encode a manifest using `encoder`
|
|
|
|
##
|
|
|
|
|
|
|
|
encoder.encode(self)
|
|
|
|
|
|
|
|
func decode*(
|
2023-06-22 15:11:18 +00:00
|
|
|
_: type Manifest,
|
|
|
|
data: openArray[byte],
|
|
|
|
decoder = ManifestContainers[$DagPBCodec]
|
|
|
|
): ?!Manifest =
|
2022-03-15 18:47:31 +00:00
|
|
|
## Decode a manifest using `decoder`
|
|
|
|
##
|
|
|
|
|
|
|
|
decoder.decode(data)
|
2022-07-07 13:00:08 +00:00
|
|
|
|
2022-07-29 20:04:12 +00:00
|
|
|
func decode*(_: type Manifest, blk: Block): ?!Manifest =
|
2022-12-03 00:00:55 +00:00
|
|
|
## Decode a manifest using `decoder`
|
|
|
|
##
|
|
|
|
|
|
|
|
if not ? blk.cid.isManifest:
|
|
|
|
return failure "Cid not a manifest codec"
|
|
|
|
|
|
|
|
Manifest.decode(
|
|
|
|
blk.data,
|
|
|
|
? ManifestContainers[$(?blk.cid.contentType().mapFailure)].catch)
|