module Sidetree module Model # https://identity.foundation/sidetree/spec/#provisional-index-file class ProvisionalIndexFile attr_reader :provisional_proof_file_uri attr_reader :chunks attr_reader :operations # Initialize # @param [String] proof_file_uri Provisional Proof File URI. # @param [Array[Sidetree::Model::Chunk]] chunks # @param [Array[Sidetree::OP::Update]] operations Update operations # @raise [Sidetree::Error] def initialize(proof_file_uri: nil, chunks: [], operations: []) if !chunks.is_a?(Array) || chunks.empty? raise Sidetree::Error, "Provisional Index File chunk property missing or incorrect type" elsif chunks.length > 1 raise Sidetree::Error, "Provisional Index File chunks does not have exactly one element" end @provisional_proof_file_uri = proof_file_uri @chunks = chunks @operations = operations did_suffixes = operations.map(&:did_suffix).compact if did_suffixes.length > 0 unless did_suffixes.length == did_suffixes.uniq.length raise Sidetree::Error, "Provisional Index File has multiple operations for same DID" end else if proof_file_uri raise Sidetree::Error, "Provisional proof file '#{proof_file_uri}' not allowed in a provisional index file with no updates" end end end # Parse provisional index file. # @param [String] index_data provisional index file data. # @param [Boolean] compressed Whether the +index_data+ is compressed or not, default: true. # @return [Sidetree::Model::ProvisionalIndexFile] def self.parse(index_data, compressed: true) decompressed = ( if compressed begin Sidetree::Util::Compressor.decompress( index_data, max_bytes: Sidetree::Params::MAX_PROVISIONAL_INDEX_FILE_SIZE ) rescue Zlib::GzipFile::Error raise Sidetree::Error, "Provisional Index File decompression failure" end else index_data end ) begin json = JSON.parse(decompressed, symbolize_names: true) operations = [] chunks = [] json.each do |k, v| case k when :chunks chunks = v .map do |chunk| chunk.map do |c_k, c_v| case c_k when :chunkFileUri Sidetree::Model::Chunk.new(c_v) else raise Sidetree::Error, "Provisional Index File chunk has missing or unknown property" end end end .flatten when :provisionalProofFileUri when :operations v.each do |o_k, o_v| case o_k when :update unless o_v.is_a?(Array) raise Sidetree::Error, "Provisional Index File update operation not array" end operations = o_v.map do |update| Sidetree::OP::Update.from_json(update.to_json_c14n) end else raise Sidetree::Error, "Unexpected property '#{o_k.to_s}' in update operation" end end else raise Sidetree::Error, "Unexpected property #{k.to_s} in provisional index file" end end ProvisionalIndexFile.new( chunks: chunks, operations: operations, proof_file_uri: json[:provisionalProofFileUri] ) rescue JSON::ParserError raise Sidetree::Error, "Provisional index file is not json" end end # Compress this provisional index file # @return [String] compressed data. def to_compress params = { chunks: chunks.map(&:to_h) } unless operations.empty? params[:operations] = { update: operations.map do |update| { didSuffix: update.did_suffix, revealValue: update.revealed_value } end } params[:provisionalProofFileUri] = provisional_proof_file_uri end Sidetree::Util::Compressor.compress(params.to_json) end end end end