nim-codex/codex/merkletree/codexmerkletree/coders.nim

105 lines
2.9 KiB
Nim
Raw Normal View History

2023-12-14 01:17:54 +00:00
## Nim-Codex
## Copyright (c) 2023 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.
import pkg/upraises
push: {.upraises: [].}
import std/sequtils
import pkg/libp2p
import pkg/questionable
import pkg/questionable/results
import ../../units
import ../../errors
import ./codexmerkletree
const MaxMerkleTreeSize = 100.MiBs.uint
const MaxMerkleProofSize = 1.MiBs.uint
proc encode*(self: CodexMerkleTree): seq[byte] =
var pb = initProtoBuffer(maxSize = MaxMerkleTreeSize)
pb.write(1, self.mcodec.uint64)
2023-12-14 03:28:13 +00:00
pb.write(2, self.leavesCount.uint64)
2023-12-14 01:17:54 +00:00
for node in self.nodes:
2023-12-14 03:28:13 +00:00
var nodesPb = initProtoBuffer(maxSize = MaxMerkleTreeSize)
2023-12-14 01:17:54 +00:00
nodesPb.write(1, node)
2023-12-14 03:28:13 +00:00
nodesPb.finish()
pb.write(3, nodesPb)
2023-12-14 01:17:54 +00:00
pb.finish
pb.buffer
proc decode*(_: type CodexMerkleTree, data: seq[byte]): ?!CodexMerkleTree =
var pb = initProtoBuffer(data, maxSize = MaxMerkleTreeSize)
var mcodecCode: uint64
var leavesCount: uint64
discard ? pb.getField(1, mcodecCode).mapFailure
2023-12-14 03:28:13 +00:00
discard ? pb.getField(2, leavesCount).mapFailure
2023-12-14 01:17:54 +00:00
let mcodec = MultiCodec.codec(mcodecCode.int)
if mcodec == InvalidMultiCodec:
return failure("Invalid MultiCodec code " & $mcodecCode)
var
nodesBuff: seq[seq[byte]]
nodes: seq[ByteHash]
2023-12-14 03:28:13 +00:00
if ? pb.getRepeatedField(3, nodesBuff).mapFailure:
2023-12-14 01:17:54 +00:00
for nodeBuff in nodesBuff:
var node: ByteHash
2023-12-14 03:28:13 +00:00
discard ? initProtoBuffer(nodeBuff).getField(1, node).mapFailure
2023-12-14 01:17:54 +00:00
nodes.add node
2023-12-14 03:28:13 +00:00
CodexMerkleTree.fromNodes(mcodec, nodes, leavesCount.int)
2023-12-14 01:17:54 +00:00
proc encode*(self: CodexMerkleProof): seq[byte] =
var pb = initProtoBuffer(maxSize = MaxMerkleProofSize)
pb.write(1, self.mcodec.uint64)
2023-12-14 03:28:13 +00:00
pb.write(2, self.index.uint64)
pb.write(3, self.nleaves.uint64)
2023-12-14 01:17:54 +00:00
for node in self.path:
2023-12-14 03:28:13 +00:00
var nodesPb = initProtoBuffer(maxSize = MaxMerkleTreeSize)
2023-12-14 01:17:54 +00:00
nodesPb.write(1, node)
2023-12-14 03:28:13 +00:00
nodesPb.finish()
pb.write(4, nodesPb)
2023-12-14 01:17:54 +00:00
pb.finish
pb.buffer
proc decode*(_: type CodexMerkleProof, data: seq[byte]): ?!CodexMerkleProof =
var pb = initProtoBuffer(data, maxSize = MaxMerkleProofSize)
var mcodecCode: uint64
var index: uint64
2023-12-14 03:28:13 +00:00
var nleaves: uint64
2023-12-14 01:17:54 +00:00
discard ? pb.getField(1, mcodecCode).mapFailure
let mcodec = MultiCodec.codec(mcodecCode.int)
if mcodec == InvalidMultiCodec:
return failure("Invalid MultiCodec code " & $mcodecCode)
2023-12-14 03:28:13 +00:00
discard ? pb.getField(2, index).mapFailure
discard ? pb.getField(3, nleaves).mapFailure
2023-12-14 01:17:54 +00:00
var
nodesBuff: seq[seq[byte]]
nodes: seq[ByteHash]
if ? pb.getRepeatedField(4, nodesBuff).mapFailure:
for nodeBuff in nodesBuff:
var node: ByteHash
let nodePb = initProtoBuffer(nodeBuff)
discard ? nodePb.getField(1, node).mapFailure
nodes.add node
2023-12-14 03:28:13 +00:00
CodexMerkleProof.init(mcodec, index.int, nleaves.int, nodes)