syntax = "proto3";

package protobuf;


// HashOp is the hashing algorithm we use at each level
enum HashOp {
    RIPEMD160 = 0;
    SHA224 = 1;
    SHA256 = 2;
    SHA384 = 3;
    SHA512 = 4;
    SHA3_224 = 5;
    SHA3_256 = 6;
    SHA3_384 = 7;
    SHA3_512 = 8;
    SHA256_X2 = 9;
};

// Op represents one hash in a chain of hashes.
// An operation takes the output of the last level and returns
// a hash for the next level:
// Op(last) => Operation(prefix + last + sufix)
//
// A simple left/right hash would simply set prefix=left or
// suffix=right and leave the other blank. However, one could
// also represent the a Patricia trie proof by setting
// prefix to the rlp encoding of all nodes before the branch
// we select, and suffix to all those after the one we select.
message Op {
    bytes prefix = 1;
    bytes suffix = 2;
    HashOp op = 3;
}

// Data is the end value stored,
// used to generate the initial hash store
message Data {
    // optional prefix allows second preimage resistance
    bytes prefix = 1;
    bytes key = 2;
    bytes value = 3;
    HashOp op = 4;
    // If it is KeyValue, this is the data we want
    // If it is SubTree, key is name of the tree,
    //   value is root hash
    enum DataType {
        KeyValue = 0;
        SubTree = 1;
    }
    DataType dataType = 5;
}

// Branch will hash data and then pass it through operations
// from first to last in order to calculate the root node.
//
// Visualize Branch as representing the data closest to
// root as the first item, and the leaf as the last item.
message Branch {
    // if either are non-empty, enforce this prefix on all
    // leaf/inner nodes to provide second preimage resistence
    bytes prefixLeaf = 1;
    bytes prefixInner = 2;
    // this is the data to get the original hash,
    // and a set of operations to calculate the root hash
    Data data = 3;
    repeated Op operations = 4;
}

message MerkleProof {
    // TODO: root, height, chain_id, etc...

    // branches start from the value, and then may
    // include multiple subtree branches to embed it
    //
    // The first branch must have dataType KeyValue
    // Following branches must have dataType SubTree
    repeated Branch branches = 1;
}
