diff --git a/dagger/dataset.nim b/dagger/dataset.nim new file mode 100644 index 00000000..7656bc06 --- /dev/null +++ b/dagger/dataset.nim @@ -0,0 +1,64 @@ +## Nim-Dagger +## 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. + +{.push raises: [Defect].} + +import std/sequtils + +import pkg/libp2p +import pkg/stew/byteutils +import pkg/questionable +import pkg/questionable/results + +import ./blockstream + +type + BlockSetRef* = ref object of BlockStreamRef + stream*: BlockStreamRef + +proc hashBytes*(mh: MultiHash): seq[byte] = + mh.data.buffer[mh.dpos..(mh.dpos + mh.size - 1)] + +proc hashBytes*(b: Block): seq[byte] = + without mh =? b.cid.mhash: + return + + mh.hashBytes() + +method nextBlock*(d: BlockSetRef): ?!Block = + d.stream.nextBlock() + +proc treeHash*(d: BlockSetRef): ?!MultiHash = + var + stack: seq[seq[byte]] + codec: MultiCodec = InvalidMultiCodec + + while true: + let (blk1, blk2) = (d.nextBlock().option, d.nextBlock().option) + if blk1.isNone and blk2.isNone and stack.len == 1: + let res = MultiHash.init($codec, stack[0]) + if mh =? res: + return success mh + + return failure($res.error) + + if blk1.isSome: stack.add((!blk1).hashBytes()) + if blk2.isSome: stack.add((!blk2).hashBytes()) + + codec = if codec == InvalidMultiCodec: (!blk1).cid.mcodec else: codec + while (stack.len mod 2) == 0: + let (b1, b2) = (stack.pop(), stack.pop()) + let res = MultiHash.init($codec, b1 & b2) + if mh =? res: + stack.add(mh.hashBytes()) + else: + return failure($res.error) + +proc new*(T: type BlockSetRef, blockStream: BlockStreamref) = + discard