syntax = "proto3";
package band.tss.v1beta1;

import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/timestamp.proto";

option go_package            = "github.com/bandprotocol/chain/v3/x/tss/types";
option (gogoproto.equal_all) = true;

// Group is a type representing a participant group in a Distributed Key Generation or signing process.
message Group {
  // id is the unique identifier of the group.
  uint64 id = 1
      [(gogoproto.customname) = "ID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.GroupID"];
  // size is the number of members in the group.
  uint64 size = 2;
  // threshold is the minimum number of members needed to generate a valid signature.
  uint64 threshold = 3;
  // pub_key is the public key generated by the group after successful completion of the DKG process.
  bytes pub_key = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // status represents the current stage of the group in the DKG or signing process.
  GroupStatus status = 5;
  // created_height is the block height when the group was created.
  uint64 created_height = 6;
  // module_owner is the module that creates this group.
  string module_owner = 7;
}

// GroupResult is a tss group result from querying tss group information.
message GroupResult {
  // group defines the group object containing group information.
  Group group = 1 [(gogoproto.nullable) = false];
  // dkg_context defines the DKG context data.
  bytes dkg_context = 2 [
    (gogoproto.customname) = "DKGContext",
    (gogoproto.casttype)   = "github.com/cometbft/cometbft/libs/bytes.HexBytes"
  ];
  // members is the list of members in the group.
  repeated Member members = 3 [(gogoproto.nullable) = false];
  // round1_infos is the list of Round 1 information.
  repeated Round1Info round1_infos = 4 [(gogoproto.nullable) = false];
  // round2_infos is the list of Round 2 information.
  repeated Round2Info round2_infos = 5 [(gogoproto.nullable) = false];
  // complaints_with_status is the list of complaints with status.
  repeated ComplaintsWithStatus complaints_with_status = 6 [(gogoproto.nullable) = false];
  // confirms is the list of confirms.
  repeated Confirm confirms = 7 [(gogoproto.nullable) = false];
}

// Round1Info contains all necessary information for handling round 1 of the DKG process.
message Round1Info {
  // member_id is the unique identifier of a group member.
  uint64 member_id = 1
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // coefficients_commits is a list of commitments to the coefficients of the member's secret polynomial.
  repeated bytes coefficient_commits = 2 [(gogoproto.castrepeated) = "github.com/bandprotocol/chain/v3/pkg/tss.Points"];
  // one_time_pub_key is the one-time public key used by the member to encrypt secret shares.
  bytes one_time_pub_key = 3 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // a0_signature is the member's signature on the first coefficient of its secret polynomial.
  bytes a0_signature = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Signature"];
  // one_time_signature is the member's signature on its one-time public key.
  bytes one_time_signature = 5 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Signature"];
}

// Round2Info contains all necessary information for handling round 2 of the DKG process.
message Round2Info {
  // member_id is the unique identifier of a group member.
  uint64 member_id = 1
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // encrypted_secret_shares is a list of secret shares encrypted under the public keys of other members.
  repeated bytes encrypted_secret_shares = 2
      [(gogoproto.castrepeated) = "github.com/bandprotocol/chain/v3/pkg/tss.EncSecretShares"];
}

// DE contains the public parts of a member's decryption and encryption keys.
message DE {
  // pub_d is the public value of own commitment (D).
  bytes pub_d = 1 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // pub_e is the public value of own commitment (E).
  bytes pub_e = 2 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
}

// DEQueue is a simple queue data structure contains index of existing DE objects of each member.
message DEQueue {
  // head is the current index of the first element in the queue.
  uint64 head = 1;
  // tail is the current index of the last element in the queue.
  uint64 tail = 2;
}

// Signing contains all necessary information for handling a signing request.
message Signing {
  // id is the unique identifier of the signing.
  uint64 id = 1
      [(gogoproto.customname) = "ID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.SigningID"];
  // current_attempt is the latest round number that signing has been attempted.
  uint64 current_attempt = 2;
  // group_id is the unique identifier of the group.
  uint64 group_id = 3
      [(gogoproto.customname) = "GroupID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.GroupID"];
  // group_pub_key is the public key of the group that sign this message.
  bytes group_pub_key = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // message is the message to be signed.
  bytes message = 5 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"];
  // group_pub_nonce is the public nonce generated by the group for this signing process.
  bytes group_pub_nonce = 6 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // signature is the group's signature on the message.
  bytes signature = 7 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Signature"];
  // status represents the current stage of the signing in the signing process.
  SigningStatus status = 8;
  // created_height is the block height when the signing was created.
  uint64 created_height = 9;
  // created_timestamp is the block timestamp when the signing was created.
  google.protobuf.Timestamp created_timestamp = 10 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
}

// SigningAttempt contains a member that has been assigned to and expiration block height of
// the specific attempt.
message SigningAttempt {
  // signing_id is the unique identifier of the signing.
  uint64 signing_id = 1 [
    (gogoproto.customname) = "SigningID",
    (gogoproto.casttype)   = "github.com/bandprotocol/chain/v3/pkg/tss.SigningID"
  ];
  // attempt is the number of round that this signing has been attempted.
  uint64 attempt = 2;
  // expired_height is the block height when this signing attempt was expired.
  uint64 expired_height = 3;
  // assigned_members is a list of members assigned to the signing process.
  repeated AssignedMember assigned_members = 4 [(gogoproto.nullable) = false];
}

// AssignedMember is a type representing a member that has been assigned to a signing process.
message AssignedMember {
  // member_id is the unique identifier of the member.
  uint64 member_id = 1
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // member is the human-readable name of the member.
  string address = 2;
  // pub_key is the public part of a member.
  bytes pub_key = 3 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // pub_d is the public part of a member's decryption key.
  bytes pub_d = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // pub_e is the public part of a member's encryption key.
  bytes pub_e = 5 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // binding_factor is the binding factor of the member for the signing process.
  bytes binding_factor = 6 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Scalar"];
  // pub_nonce is the public nonce of the member for the signing process.
  bytes pub_nonce = 7 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
}

// PendingSignings is a list of all signing processes that are currently pending.
message PendingSignings {
  // signing_ids is a list of identifiers for the signing processes.
  repeated uint64 signing_ids = 1;
}

// SigningStatus is an enumeration of the possible statuses of a signing.
enum SigningStatus {
  option (gogoproto.goproto_enum_prefix) = false;

  // SIGNING_STATUS_UNSPECIFIED is the status of a signing that has not been specified.
  SIGNING_STATUS_UNSPECIFIED = 0;
  // SIGNING_STATUS_WAITING is the status of a signing that is waiting to be signed in the protocol.
  SIGNING_STATUS_WAITING = 1;
  // SIGNING_STATUS_SUCCESS is the status of a signing that has success in the protocol.
  SIGNING_STATUS_SUCCESS = 2;
  // SIGNING_STATUS_FALLEN is the status of a signing that has fallen out of the protocol.
  SIGNING_STATUS_FALLEN = 3;
}

// Member is a type representing a member of the group.
message Member {
  // id is the unique identifier of a member.
  uint64 id = 1
      [(gogoproto.customname) = "ID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // group_id is the group id of this member.
  uint64 group_id = 2
      [(gogoproto.customname) = "GroupID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.GroupID"];
  // address is the address of the member.
  string address = 3;
  // pub_key is the public key of the member.
  bytes pub_key = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // is_malicious is a boolean flag indicating whether the member is considered malicious.
  bool is_malicious = 5;
  // is_active is a boolean flag indicating whether the member is currently active in the protocol.
  bool is_active = 6;
}

// GroupStatus is an enumeration of the possible statuses of a group.
enum GroupStatus {
  option (gogoproto.goproto_enum_prefix) = false;

  // GROUP_STATUS_UNSPECIFIED is the status of a group that has not been specified.
  GROUP_STATUS_UNSPECIFIED = 0;
  // GROUP_STATUS_ROUND_1 is the status of a group that is in the first round of the protocol.
  GROUP_STATUS_ROUND_1 = 1;
  // GROUP_STATUS_ROUND_2 is the status of a group that is in the second round of the protocol.
  GROUP_STATUS_ROUND_2 = 2;
  // GROUP_STATUS_ROUND_3 is the status of a group that is in the third round of the protocol.
  GROUP_STATUS_ROUND_3 = 3;
  // GROUP_STATUS_ACTIVE is the status of a group that is actively participating in the protocol.
  GROUP_STATUS_ACTIVE = 4;
  // GROUP_STATUS_EXPIRED is the status of a group that has expired in the protocol.
  GROUP_STATUS_EXPIRED = 5;
  // GROUP_STATUS_FALLEN is the status of a group that has fallen out of the protocol.
  GROUP_STATUS_FALLEN = 6;
}

// Confirm is a message type used to confirm participation in the protocol.
message Confirm {
  // member_id is the unique identifier of a group member.
  uint64 member_id = 1
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // own_pub_key_sig is a signature over the member's own public key.
  bytes own_pub_key_sig = 2 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Signature"];
}

// Complaint is a message type used to issue a complaint against a member.
message Complaint {
  // complainant is the member issuing the complaint.
  uint64 complainant = 1 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // respondent is the member against whom the complaint is issued.
  uint64 respondent = 2 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // key_sym is a symmetric key between respondent's private key and respondent's public key.
  bytes key_sym = 3 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Point"];
  // signature is the complaint signature that can do a symmetric key validation and complaint verification.
  bytes signature = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.ComplaintSignature"];
}

// ComplaintStatus represents the status of a complaint.
enum ComplaintStatus {
  option (gogoproto.goproto_enum_prefix) = false;

  // COMPLAINT_STATUS_UNSPECIFIED represents an undefined status of the complaint.
  COMPLAINT_STATUS_UNSPECIFIED = 0;
  // COMPLAINT_STATUS_SUCCESS represents a successful complaint.
  COMPLAINT_STATUS_SUCCESS = 1;
  // COMPLAINT_STATUS_FAILED represents a failed complaint.
  COMPLAINT_STATUS_FAILED = 2;
}

// ComplaintWithStatus contains information about a complaint with its status.
message ComplaintWithStatus {
  // complaint is the information about the complaint.
  Complaint complaint = 1 [(gogoproto.nullable) = false];
  // complaint_status is the status of the complaint.
  ComplaintStatus complaint_status = 2;
}

// ComplaintsWithStatus contains information about multiple complaints and their status from a single member.
message ComplaintsWithStatus {
  // member_id is the identifier of the member filing the complaints.
  uint64 member_id = 1
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // complaints_with_status is the list of complaints with their status from this member.
  repeated ComplaintWithStatus complaints_with_status = 2 [(gogoproto.nullable) = false];
}

// PendingProcessGroups is a list of groups that are waiting to be processed.
message PendingProcessGroups {
  // group_ids is a list of group IDs.
  repeated uint64 group_ids = 1
      [(gogoproto.customname) = "GroupIDs", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.GroupID"];
}

// PendingProcessSignings is a list of signings that are waiting to be processed.
message PendingProcessSignings {
  // signing_ids is a list of signing IDs.
  repeated uint64 signing_ids = 1 [
    (gogoproto.customname) = "SigningIDs",
    (gogoproto.casttype)   = "github.com/bandprotocol/chain/v3/pkg/tss.SigningID"
  ];
}

// PartialSignature contains information about a member's partial signature.
message PartialSignature {
  // signing_id is the unique identifier of the signing.
  uint64 signing_id = 1 [
    (gogoproto.customname) = "SigningID",
    (gogoproto.casttype)   = "github.com/bandprotocol/chain/v3/pkg/tss.SigningID"
  ];
  // signing_attempt is the number of attempts for this signing.
  uint64 signing_attempt = 2;
  // member_id is the identifier of the member providing the partial signature.
  uint64 member_id = 3
      [(gogoproto.customname) = "MemberID", (gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.MemberID"];
  // signature is the partial signature provided by this member.
  bytes signature = 4 [(gogoproto.casttype) = "github.com/bandprotocol/chain/v3/pkg/tss.Signature"];
}

// TextSignatureOrder defines a general text signature order.
message TextSignatureOrder {
  option (cosmos_proto.implements_interface) = "Content";

  // message is the data that needs to be signed.
  bytes message = 1 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"];
}

// EVMSignature defines a signature in the EVM format.
message EVMSignature {
  // r_address is the address of the nonce for using in the contract.
  bytes r_address = 1 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"];
  // signature is the signature part for using in the contract.
  bytes signature = 2 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"];
}

// SigningResult is a tss signing result from querying tss signing information.
message SigningResult {
  // signing is the tss signing result.
  Signing signing = 1 [(gogoproto.nullable) = false];
  // current_signing_attempt is the current attempt information of the signing.
  SigningAttempt current_signing_attempt = 2;
  // evm_signature is the signature in the format that can use directly in EVM.
  EVMSignature evm_signature = 3 [(gogoproto.customname) = "EVMSignature"];
  // received_partial_signatures is a list of received partial signatures.
  repeated PartialSignature received_partial_signatures = 4 [(gogoproto.nullable) = false];
}

// SigningExpiration defines the expiration time of the signing.
message SigningExpiration {
  // signing_id is the id of the signing.
  uint64 signing_id = 1 [
    (gogoproto.customname) = "SigningID",
    (gogoproto.casttype)   = "github.com/bandprotocol/chain/v3/pkg/tss.SigningID"
  ];
  // signing_attempt is the number of attempts of the signing.
  uint64 signing_attempt = 2;
}

// SigningExpirations is a list of signing expiration information that are waiting in the queue.
message SigningExpirations {
  // signing_expirations is a list of SigningExpiration object.
  repeated SigningExpiration signing_expirations = 1 [(gogoproto.nullable) = false];
}
