syntax = "proto3"; package coredocument; option go_package = "github.com/centrifuge/centrifuge-protobufs/gen/go/coredocument;coredocumentpb"; option java_multiple_files = true; option java_outer_classname = "CoredocumentProto"; option java_package = "com.coredocument"; import "google/protobuf/any.proto"; import "google/protobuf/timestamp.proto"; import "precise-proofs/proofs/proto/proof.proto"; import "precise-proofs/proofs/proto/salt.proto"; // `CoreDocument` is a document that can be sent to different nodes and anchored // on chain. It handles all the generic features native Centrifuge Documents support: // // * Merkle Roots for the document data // * Signatures on document data // * Access Control message CoreDocument { // # Identifiers // CoreDocument has two kinds of identifiers, the `document_identifier` is assigned // once per document and stays the same for the lifetime of the document. // document_identifier is the first ID ever used to anchor the document on chain and // is used internally to store all future versions. The `previous_version`, `current_version`, and the // `next_version` refer only to a particular version. // // 32 byte value bytes document_identifier = 9 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // previous_version refers to the previous state of the document. // 32 byte value bytes previous_version = 16 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // current_version is the version used to refer to the current state of the document. // 32 byte value bytes current_version = 3 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // current_preimage is the sha256 pre-image of the current_version. It prevents current state commitment id(anchor id) from getting exposed. // 32 byte value bytes current_preimage = 23 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // next_version is the version that is going to be used for the next version if any // party wants to update the state. bytes next_version = 4 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // next_preimage is the sha256 pre-image of the next_version. It prevents next state commitment id(anchor id) from getting exposed. bytes next_preimage = 22 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // Signatures of the signature_root by collaborators on the document. SignatureData signature_data = 6 [(proofs.exclude_from_tree) = true]; // When a document is transmitted over the wire, the type specific fields (e.g. InvoiceData) are // embedded in the document using the google.protobuf.Any type. google.protobuf.Any embedded_data = 13 [(proofs.exclude_from_tree) = true]; repeated proofs.Salt salts = 15; // list of roles repeated Role roles = 1 [ (proofs.field_length) = 32, (proofs.mapping_key) = "role_key" ]; // read_rules define who may read a document and who should sign it repeated ReadRule read_rules = 19; // transition rules define how a document may be manipulated repeated TransitionRule transition_rules = 24; // nft list for uniqueness check repeated NFT nfts = 20 [(proofs.mapping_key) = "collection_id"]; // AccessTokens which have been added to this CoreDocument repeated AccessToken access_tokens = 21 [ (proofs.field_length) = 32, (proofs.mapping_key) = "identifier" ]; // author of the latest update bytes author = 25 [(proofs.field_length) = 32]; // timestamp of the latest update google.protobuf.Timestamp timestamp = 26; // anchor repository address used to anchor this document bytes anchor_repository_used = 27 [(proofs.field_length) = 32]; // custom attributes(user defined fields) for this document repeated Attribute attributes = 28 [ (proofs.field_length) = 32, (proofs.mapping_key) = "key" ]; } // TransitionRulesFingerprint is used to create the 'fingerprint' hash for verifying if the Transition Rules and Roles // of a CoreDocument have changed message TransitionRulesFingerprint { // list of roles repeated Role roles = 1 [ (proofs.field_length) = 32, (proofs.mapping_key) = "role_key", (proofs.no_salt) = true ]; // transition rules define how a document may be manipulated repeated TransitionRule transition_rules = 3 [(proofs.no_salt) = true]; } message AccessToken { // The identifier is an internal 256bit word bytes identifier = 1 [(proofs.field_length) = 32]; // The identity granting access to the document bytes granter = 3 [(proofs.field_length) = 32]; // The identity being granted access to the document bytes grantee = 4 [(proofs.field_length) = 32]; // Role identifier is the identifier on the read rule that this token should be mapped to bytes role_identifier = 5 [ (proofs.field_length) = 32, (proofs.no_salt) = true ]; // Original identifier of the document bytes document_identifier = 2 [(proofs.field_length) = 32]; // Cryptographic signature that an access token is valid bytes signature = 6 [ (proofs.field_length) = 65, (proofs.no_salt) = true ]; // The public key of the signed message bytes key = 7 [(proofs.field_length) = 32]; // The document version refers to a version of the document this token is embedded in. Its timestamp // will be used to verify the validity of the signature of the access token. bytes document_version = 8 [(proofs.field_length) = 32]; } // SignatureData contains the list of signatures identified by the signature_id message SignatureData { repeated Signature signatures = 1 [ (proofs.append_fields) = true, (proofs.field_length) = 64, (proofs.mapping_key) = "signature_id" ]; } // Signature contains the entity ID, public key used and signature) message Signature { // `signature_id` is a composed key signer_id+public_key (20+32) used bytes signature_id = 1 [(proofs.exclude_from_tree) = true]; // `signer_id` is the CentrifugeID of the identity signing the document. bytes signer_id = 2 [(proofs.exclude_from_tree) = true]; // `public_key` is the public key of the `signer` used for signing the `CoreDocument` bytes public_key = 3 [(proofs.exclude_from_tree) = true]; // `signature` is the actual signature of the CoreDocument bytes signature = 4 [ (proofs.field_length) = 65, (proofs.no_salt) = true ]; // `transition_validated` defines if node was able to validate transition rules from document version A -> B bool transition_validated = 5; } // Action defines the set of actions a collaborator can/have per document. enum Action { ACTION_INVALID = 0; // read_sign represents reading as well the sign the documents. We will pick this one when requesting the signatures. ACTION_READ_SIGN = 1; // read represents just reading the doc/fields ACTION_READ = 2; } // Roles holds a list of collaborators, NFTs, and/or access tokens. message Role { // role key which is used to identify the group internally and map the role to rules bytes role_key = 1 [(proofs.field_length) = 32]; // collaborators holds the list of document collaborators repeated bytes collaborators = 3 [(proofs.field_length) = 32]; // nfts is a list of collection and item ID pairs. // For easier verification in merkle proofs, the values are simply concatenated with the first 8 bytes // being the NFT encoded collection ID and the remaining 16 bytes the encoded item ID. repeated bytes nfts = 4 [(proofs.field_length) = 24]; } message ReadRule { repeated bytes roles = 2 [(proofs.field_length) = 32]; Action action = 4; } enum FieldMatchType { FIELD_MATCH_TYPE_INVALID = 0; FIELD_MATCH_TYPE_PREFIX = 1; FIELD_MATCH_TYPE_EXACT = 2; } message TransitionRule { // rule key, to help track of the rule bytes rule_key = 1 [(proofs.field_length) = 32]; // Indicates which roles can make changes or read the fields specified: // this list holds role keys correlated to those in the 'roles' field of the CoreDocument repeated bytes roles = 2 [(proofs.field_length) = 32]; // prefix or exact FieldMatchType match_type = 3; // compact property of the field bytes field = 4; // what kind of action this rule allows TransitionAction action = 5; // compute_fields holds the list of attribute fields that will be passed to WASM repeated bytes compute_fields = 6; // compute_target_field is the attribute label that will hold the result of the WASM execution bytes compute_target_field = 7; // compute_code is the WASM binary that will be executed bytes compute_code = 8; } enum TransitionAction { TRANSITION_ACTION_INVALID = 0; TRANSITION_ACTION_EDIT = 1; TRANSITION_ACTION_COMPUTE = 2; } message NFT { bytes collection_id = 1 [(proofs.field_length) = 8]; bytes item_id = 2 [(proofs.field_length) = 16]; } // Attribute represents a custom attribute message Attribute { bytes key = 1 [(proofs.field_length) = 32]; bytes key_label = 2; AttributeType type = 3; oneof value { string str_val = 4; bytes byte_val = 5; google.protobuf.Timestamp time_val = 6; Signed signed_val = 7; Monetary monetary_val = 8 [(proofs.append_fields) = true]; } } // Signed holds the custom attribute signature type message Signed { bytes doc_version = 1 [(proofs.field_length) = 32]; AttributeType type = 6; bytes value = 2; bytes identity = 3 [(proofs.field_length) = 32]; // signature = sign(identity + doc_id(taken from the document.document_identifier) + doc_version + value) bytes signature = 4 [ (proofs.field_length) = 65, (proofs.no_salt) = true ]; bytes public_key = 5 [(proofs.field_length) = 32]; } // Monetary holds decimal value, id, type and chain context message Monetary { bytes type = 1; // fixed 1 byte bytes chain = 2; // fixed 4 bytes bytes value = 3; // fixed 32 bytes bytes id = 4; // fixed 32 bytes } // AttributeType defines the allowed attribute types. enum AttributeType { ATTRIBUTE_TYPE_INVALID = 0; ATTRIBUTE_TYPE_INTEGER = 1; ATTRIBUTE_TYPE_DECIMAL = 2; ATTRIBUTE_TYPE_STRING = 3; ATTRIBUTE_TYPE_BYTES = 4; ATTRIBUTE_TYPE_TIMESTAMP = 5; ATTRIBUTE_TYPE_SIGNED = 6; ATTRIBUTE_TYPE_MONETARY = 7; }