/*
Copyright IBM Corp. 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

syntax = "proto3";

option go_package = "github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset";
option java_package = "org.hyperledger.fabric.protos.ledger.rwset.kvrwset";

package kvrwset;

// KVRWSet encapsulates the read-write set for a chaincode that operates upon a KV or Document data model
// This structure is used for both the public data and the private data
message KVRWSet {
    repeated KVRead reads = 1;
    repeated RangeQueryInfo range_queries_info = 2;
    repeated KVWrite writes = 3;
}

// HashedRWSet encapsulates hashed representation of a private read-write set for KV or Document data model
message HashedRWSet {
    repeated KVReadHash hashed_reads = 1;
    repeated KVWriteHash hashed_writes = 2;
}

// KVRead captures a read operation performed during transaction simulation
// A 'nil' version indicates a non-existing key read by the transaction
message KVRead {
    string key = 1;
    Version version = 2;
}

// KVWrite captures a write (update/delete) operation performed during transaction simulation
message KVWrite {
    string key = 1;
    bool is_delete = 2;
    bytes value = 3;
}

// KVReadHash is similar to the KVRead in spirit. However, it captures the hash of the key instead of the key itself
// version is kept as is for now. However, if the version also needs to be privacy-protected, it would need to be the
// hash of the version and hence of 'bytes' type
message KVReadHash {
    bytes key_hash = 1;
    Version version = 2;
}

// KVWriteHash is similar to the KVWrite in spiritcaptures a write (update/delete) operation performed during transaction simulation
message KVWriteHash {
    bytes key_hash = 1;
    bool is_delete = 2;
    bytes value_hash = 3;
}

// Version encapsulates the version of a Key
// A version of a committed key is maintained as the height of the transaction that committed the key.
// The height is represenetd as a tuple <blockNum, txNum> where the txNum is the position of the transaction
// (starting with 0) within block
message Version {
    uint64 block_num = 1;
    uint64 tx_num = 2;
}

// RangeQueryInfo encapsulates the details of a range query performed by a transaction during simulation.
// This helps protect transactions from phantom reads by varifying during validation whether any new items
// got committed within the given range between transaction simuation and validation
// (in addition to regular checks for updates/deletes of the existing items).
// readInfo field contains either the KVReads (for the items read by the range query) or a merkle-tree hash
// if the KVReads exceeds a pre-configured numbers
message RangeQueryInfo {
    string start_key = 1;
    string end_key = 2;
    bool itr_exhausted = 3;
    oneof reads_info {
        QueryReads raw_reads = 4;
        QueryReadsMerkleSummary reads_merkle_hashes = 5;
    }
}

// QueryReads encapsulates the KVReads for the items read by a transaction as a result of a query execution
message QueryReads {
    repeated KVRead kv_reads = 1;
}

// QueryReadsMerkleSummary encapsulates the Merkle-tree hashes for the QueryReads
// This allows to reduce the size of RWSet in the presence of query results
// by storing certain hashes instead of actual results.
// maxDegree field refers to the maximum number of children in the tree at any level
// maxLevel field contains the lowest level which has lesser nodes than maxDegree (starting from leaf level)
message QueryReadsMerkleSummary {
    uint32 max_degree = 1;
    uint32 max_level = 2;
    repeated bytes max_level_hashes = 3;
}
