syntax = "proto3";
package object;
option go_package = "github.com/nspcc-dev/neofs-api-go/object";
option csharp_namespace = "NeoFS.API.Object";

import "refs/types.proto";
import "session/types.proto";
import "storagegroup/types.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";

option (gogoproto.stable_marshaler_all) = true;

message Range {
    // Offset of the data range
    uint64 Offset = 1;
    // Length of the data range
    uint64 Length = 2;
}

message UserHeader {
    // Key of the user's header
    string Key   = 1;
    // Value of the user's header
    string Value = 2;
}

message Header {
    oneof Value {
        // Link to other objects
        Link Link                              = 1;
        // Redirect not used yet
        refs.Address Redirect                  = 2;
        // UserHeader is a set of KV headers defined by user
        UserHeader UserHeader                  = 3;
        // Transform defines transform operation (e.g. payload split)
        Transform Transform                    = 4;
        // Tombstone header that set up in deleted objects
        Tombstone Tombstone                    = 5;
        // Verify header that contains session public key and user's signature
        session.VerificationHeader Verify      = 6;
        // HomoHash is a homomorphic hash of original object payload
        bytes HomoHash                         = 7 [(gogoproto.customtype) = "Hash"];
        // PayloadChecksum of actual object's payload
        bytes PayloadChecksum                  = 8;
        // Integrity header with checksum of all above headers in the object
        IntegrityHeader Integrity              = 9;
        // StorageGroup contains meta information for the data audit
        storagegroup.StorageGroup StorageGroup = 10;
        // PublicKey of owner of the object. Key is used for verification and can be based on NeoID or x509 cert.
        PublicKey PublicKey                    = 11;
    }
}

message Tombstone {}

message SystemHeader {
    // Version of the object structure
    uint64 Version       = 1;
    // PayloadLength is an object payload length
    uint64 PayloadLength = 2;

    // ID is an object identifier, is a valid UUIDv4
    bytes ID        = 3 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false];
    // OwnerID is a wallet address
    bytes OwnerID   = 4 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false];
    // CID is a SHA256 hash of the container structure (container identifier)
    bytes CID       = 5 [(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false];
    // CreatedAt is a timestamp of object creation
    CreationPoint CreatedAt = 6 [(gogoproto.nullable) = false];
}

message CreationPoint {
    // UnixTime is a date of creation in unixtime format
    int64 UnixTime = 1;
    // Epoch is a date of creation in NeoFS epochs
    uint64 Epoch   = 2;
}

message IntegrityHeader {
    // HeadersChecksum is a checksum of all above headers in the object
    bytes HeadersChecksum   = 1;
    // ChecksumSignature is an user's signature of checksum to verify if it is correct
    bytes ChecksumSignature = 2;
}

message Link {
    enum Type {
        Unknown      = 0;
        // Parent object created during object transformation
        Parent       = 1;
        // Previous object in the linked list created during object transformation
        Previous     = 2;
        // Next object in the linked list created during object transformation
        Next         = 3;
        // Child object created during object transformation
        Child        = 4;
        // Object that included into this storage group
        StorageGroup = 5;
    }
    // Type of link
    Type type  = 1;
    // ID is an object identifier, is a valid UUIDv4
    bytes ID = 2 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false];
}

message Transform {
    enum Type {
        Unknown = 0;
        // Split sets when object created after payload split
        Split   = 1;
        // Sign sets when object created after re-signing (doesn't used)
        Sign    = 2;
        // Mould sets when object created after filling missing headers in the object
        Mould   = 3;
    }
    // Type of object transformation
    Type type  = 1;
}

message Object {
    // SystemHeader describes system header
    SystemHeader SystemHeader = 1 [(gogoproto.nullable) = false];
    // Headers describes a set of an extended headers
    repeated Header Headers   = 2 [(gogoproto.nullable) = false];
    // Payload is an object's payload
    bytes Payload             = 3;
}

message PublicKey {
    // Value contains marshaled ecdsa public key
    bytes Value = 1;
}