syntax = "proto3";

package quilibrium.node.channel.pb;

option go_package = "source.quilibrium.com/quilibrium/monorepo/node/protobufs";

import "keys.proto";

// Describes a general channel envelope for a message.
message P2PChannelEnvelope {
  // A general protocol identifier as a uint32 – this is expected to rarely
  // iterate, and should be uniquely identifying both protocol and version.
  // Pragmatically speaking, this implies that the least significant byte
  // specifies version (which should iterate most minimally), and the three most
  // significant bytes should specify protocol. Recipients SHOULD ignore
  // messages with incompatible protocol identifiers, but also SHOULD warn on
  // identifiers with versions higher than the supported protocol. A large
  // number of unsupported protocol messages may indicate spam/some other
  // attack, whereas a large number of unsupported protocol versions may
  // indicate an out of date client, respective to which side is the maximum of
  // the version number.
  uint32 protocol_identifier = 1;

  // The encrypted message header. Message header encryption is mandatory –
  // P2P channels in some cases pre-empt the mixnet and leaky information from
  // unencrypted message headers could de-anonymize the recipient. It is thus
  // also mandatory at the protocol implementation level that header sizes are
  // consistent within a protocol so as to not leak metadata. An example of this
  // is in Double and Triple-Ratchet, where the sequence identifiers MUST be
  // encoded as fixed-length integers, as variable encoding can indicate a
  // message being in the first 256, 65,536, etc. if an exchange is highly
  // asymmetrical in sends/receives. This is especially critical in long
  // running protocols with a need for fixed length messages (see message_body
  // notes).
  MessageCiphertext message_header = 2;

  // The encrypted message body. Message bodies are variable length – ciphertext
  // could range widely, however if this metadata is pertinent to determining
  // protocol state, such as knowing what round an encapsulated protocol is in,
  // or potentially what might be transferred over the protocol, protocol
  // implementers SHOULD utilize chunking and send fixed length messages.
  // Additionally, if rounds themselves are highly asymmetric or have
  // long-standing processing times that could dangerously leak information of
  // round state, implementers SHOULD defer protocol use to leverage the mixnet.
  // If this is not feasible, the implementation details are left up to the
  // exercise of the protocol author.
  MessageCiphertext message_body = 3;
}

// Describes a general ciphertext payload.
message MessageCiphertext {
  // The intialization vector used for encryption. While cipher specific,
  // typically this should be a unique value for every ciphertext. If this is
  // not the case for a protocol where it should be, this SHOULD be considered
  // an invalid message and warned, as it could either indicate compromise,
  // or a faulty cryptographic implementation – such as a faulty PKCS#11
  // implementation that has a code path to handle HSM vendors which mandate
  // zeroed IVs before passing into encryption methods, as they will update the
  // IV within the HSM through hardware-supplied entropy.
  bytes initialization_vector = 1;

  // The raw ciphertext byte string. This will be cipher specific, however some
  // general attributes are expected to be followed. If there is a common
  // layout expected, such as AES-GCM having the GCM tag appended to the
  // ciphertext, please follow the common layout.
  bytes ciphertext = 2;
  
  // The associated data byte string, if available. This will be highly protocol
  // specific, but SHOULD NOT leak metadata.
  bytes associated_data = 3;
}

// Describes the announcement of a new proving key.
message ProvingKeyAnnouncement {
  // The commitment to a Schnorr proof of the Identity Key. The commitment is
  // produced by taking a hash of the C and S components of the proof.
  bytes identity_commitment = 1;
  // The commitment to a Schnorr proof of the Signed Pre Key. The commitment is
  // produced by taking a hash of the C and S components of the proof.
  bytes prekey_commitment = 2;

  oneof proving_key_signature {
    quilibrium.node.keys.pb.Ed448Signature proving_key_signature_ed448 = 3;
  }
}

// Represents a request for a proving key.
message ProvingKeyRequest {
  bytes proving_key_bytes = 1;
}

// Describes the aggregation of inclusion commitments for a given clock frame
message InclusionAggregateProof {
  // The filter in which the inclusion proof was produced.
  bytes filter = 1;
  // The frame number in which the inclusion proof was added.
  uint64 frame_number = 2;
  // The collection of inclusion commitments, in order.
  repeated InclusionCommitment inclusion_commitments = 3;
  // The raw serialized proof, mirroring the type of commitment scheme used
  // within the inclusion proofs.
  bytes proof = 4;
}

// Describes the commitment of a data's inclusion in a given clock frame
message InclusionCommitment {
  // The filter in which the inclusion aggregate proof was produced.
  bytes filter = 1;
  // The frame number in which the inclusion aggregate proof was added.
  uint64 frame_number = 2;
  // The position of the data in the proof.
  uint32 position = 3;
  // The specific type url represented by the data.
  string type_url = 4;
  // The raw serialized data as incorporated into the inclusion proof. Due to
  // the non-deterministic nature of protobuf serialization, this data is an
  // opaque binary string so that inclusion proofs can be accurately assessed
  // between various node implementations, and retain forwards-compatibility
  // with additional properties in future revisions to types.
  bytes data = 5;
  // The raw serialized commitment. Similar to data, this commitment data is an
  // opaque binary string so that future commitment types can be added without
  // having to break the underlying inclusion structure.
  bytes commitment = 6;
}

// Describes the announcement of both an identity key and signed pre key. This
// is expected to be used for the initial announcement of a key bundle, and
// subsequent full revocations if identity key and signed pre keys are both
// suspected of/known to be compromised. Signatures under KeyBundleAnnouncement
// are expected to be cross-signed, such that the signature on the identity key
// is produced through the prover key, the signature on the signed pre key is
// produced through the identity key. ProvingKeyAnnouncements may be repeated
// whenever a key bundle update is expected – only the first proving key
// announcement is retained in inclusion proofs, but the announcements
// necessarily are required for key bundle updates, as they provide a commitment
// to the updated keys' Schnorr proofs. An updated KeyBundleAnnouncement must
// be captured in an inclusion proof before it may be used for communication
// channels, and may only be used in communication channels once a lobby has
// opened _after_ the inclusion proof. If a lobby is open during the time the
// inclusion proof has been created, the announcement is not yet considered
// valid.
message KeyBundleAnnouncement {
  IdentityKey identity_key = 1;
  SignedPreKey signed_pre_key = 2;
  bytes proving_key_bytes = 3;
}

// Describes the Identity Key and corresponding Schnorr proof. Schnorr proofs
// are expected to mirror the EC parameters of the proving and identity key. If
// they do not, validation will fail.
message IdentityKey {
  // The C component of the Schnorr proof, serialized as big endian.
  bytes challenge = 1;
  // The S component of the Schnorr proof, serialized as big endian.
  bytes response = 2;
  // The Statement component of the Schnorr proof, serialized as an (compressed,
  // if possible) affine representation of the point.
  bytes statement = 3;

  oneof identity_key_signature {
    quilibrium.node.keys.pb.Ed448Signature public_key_signature_ed448 = 4;
  }
}

// Describes the Signed Pre Key and corresponding Schnorr proof. Schnorr proofs
// are expected to mirror the EC parameters of the identity and signed pre key.
// If they do not, validation will fail.
message SignedPreKey {
  // The C component of the Schnorr proof, serialized as big endian.
  bytes challenge = 1;
  // The S component of the Schnorr proof, serialized as big endian.
  bytes response = 2;
  // The Statement component of the Schnorr proof, serialized as an (compressed,
  // if possible) affine representation of the point.
  bytes statement = 3;

  oneof signed_pre_key_signature {
    quilibrium.node.keys.pb.Ed448Signature public_key_signature_ed448 = 4;
  }
}