decodeBlob method

Uint8List decodeBlob({
  1. required int nShards,
  2. required int blobSize,
  3. required List<({Uint8List data, int index})> slivers,
})

Decode (reconstruct) a blob from primary slivers via Rust FFI.

Uses walrus-core's RS2 decoder — the same decoder used by the Walrus network for canonical reconstruction. This is dramatically faster than any pure-Dart erasure coding implementation.

nShards: number of shards in the committee. blobSize: the original unencoded blob length in bytes. slivers: list of (index, data) pairs — the shard index and raw primary sliver bytes for each available sliver. Minimum required is primarySymbols (from encodingParams).

Returns the reconstructed original blob data.

Implementation

Uint8List decodeBlob({
  required int nShards,
  required int blobSize,
  required List<({int index, Uint8List data})> slivers,
}) {
  if (slivers.isEmpty) {
    throw WalrusFfiException('decodeBlob: no slivers provided');
  }

  final sliverSize = slivers.first.data.length;
  final sliverCount = slivers.length;

  // Allocate flat buffers for all sliver data + indices.
  final totalSliverBytes = sliverCount * sliverSize;
  final sliverDataPtr = calloc<Uint8>(
    totalSliverBytes == 0 ? 1 : totalSliverBytes,
  );
  final sliverIndicesPtr = calloc<Uint16>(sliverCount);
  final outBlobPtr = calloc<Uint8>(blobSize == 0 ? 1 : blobSize);
  final outBlobLen = calloc<Uint64>(1);

  try {
    // Copy sliver data into the flat buffer.
    final flatView = sliverDataPtr.asTypedList(totalSliverBytes);
    final indicesView = sliverIndicesPtr.asTypedList(sliverCount);
    for (var i = 0; i < sliverCount; i++) {
      flatView.setRange(
        i * sliverSize,
        (i + 1) * sliverSize,
        slivers[i].data,
      );
      indicesView[i] = slivers[i].index;
    }

    final ret = _decodeBlob(
      nShards,
      blobSize,
      sliverDataPtr,
      sliverIndicesPtr,
      sliverCount,
      sliverSize,
      outBlobPtr,
      outBlobLen,
    );

    if (ret != 0) {
      throw WalrusFfiException(
        'walrus_decode_blob failed with code $ret '
        '(slivers=$sliverCount, sliverSize=$sliverSize, blobSize=$blobSize)',
      );
    }

    final decodedLen = outBlobLen.value;
    return Uint8List.fromList(outBlobPtr.asTypedList(decodedLen));
  } finally {
    calloc.free(sliverDataPtr);
    calloc.free(sliverIndicesPtr);
    calloc.free(outBlobPtr);
    calloc.free(outBlobLen);
  }
}