syntax = "proto3";
package object;
option go_package = "github.com/nspcc-dev/neofs-proto/object";

import "refs/types.proto";
import "session/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         = 10;
    }
}

message Tombstone {
    // Epoch when tombstone was created
    uint64 Epoch = 1;
}

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 StorageGroup {
    // ValidationDataSize is size of the all object's payloads included into storage group
    uint64 ValidationDataSize = 1;
    // ValidationHash is homomorphic hash of all object's payloads included into storage group
    bytes ValidationHash = 2 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false];

    message Lifetime {
        enum Unit {
            // Unlimited set if storage group always valid
            Unlimited = 0;
            // NeoFSEpoch set if storage group is valid until lifetime NeoFS epoch
            NeoFSEpoch = 1;
            // UnixTime set if storage group is valid until lifetime unix timestamp
            UnixTime = 2;
        }

        // Unit is lifetime type
        Unit unit = 1 [(gogoproto.customname) = "Unit"];
        // Value for lifetime
        int64 Value = 2;
    }

    // Lifetime is time until storage group is valid
    Lifetime lifetime = 3 [(gogoproto.customname) = "Lifetime"];
}