// Copyright (c) 2018 IoTeX
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

// To compile the proto, run:
//      protoc --go_out=plugins=grpc:$GOPATH/src *.proto
syntax = "proto3";
package iotextypes;
option go_package = "github.com/iotexproject/iotex-proto/golang/iotextypes";
option java_multiple_files = true;
option java_package = "com.github.iotexproject.grpc.types";

message Transfer {
  // used by state-based model
  string amount = 1;
  string recipient = 2;
  bytes payload = 3;
}

// Candidates and list of candidates
message Candidate {
  string address = 1;
  bytes votes = 2;
  bytes pubKey = 3;
  string rewardAddress = 4;
  bytes blsPubKey = 5; // BLS public key for the candidate
}

message CandidateList {
  repeated Candidate candidates = 1;
}

message PutPollResult {
  uint64 height = 1;
  CandidateList candidates = 2;
}

message TxContainer {
  bytes raw = 1;
}

message Execution {
  string amount = 1;
  string contract = 2;
  bytes data = 3;
}

message AccessTuple {
  string address = 1;
  repeated string storageKeys = 2;
}

message BlobTxSidecar {
  repeated bytes blobs = 1;       // Blobs needed by the blob pool
  repeated bytes commitments = 2; // Commitments needed by the blob pool
  repeated bytes proofs = 3;      // Proofs needed by the blob pool
}

message BlobTxData {
  string blobFeeCap = 1;
  repeated bytes blobHashes = 2;
  BlobTxSidecar blobTxSidecar = 3;
}

message BlobTxSidecars {
  repeated bytes txHash = 1;
  repeated BlobTxSidecar sidecars = 2;
}

// create stake
message StakeCreate {
  string candidateName = 1;
  string stakedAmount = 2;
  uint32 stakedDuration = 3;
  bool autoStake = 4;
  bytes payload = 5;
}

// migrate stake
message StakeMigrate {
  uint64 bucketIndex = 1;
}

// unstake or withdraw
message StakeReclaim {
  uint64 bucketIndex = 1;
  bytes payload = 2;
}

// add the amount of bucket 
message StakeAddDeposit {
  uint64 bucketIndex = 1;
  string amount = 2;
  bytes payload = 3;
}

// restake the duration and autoStake flag of bucket 
message StakeRestake {
  uint64 bucketIndex = 1;
  uint32 stakedDuration = 2;
  bool autoStake = 3;
  bytes payload = 4;
}

// move the bucket to vote for another candidate or transfer the ownership of bucket to another voters
message StakeChangeCandidate {
  uint64 bucketIndex = 1;
  string candidateName = 2;
  bytes payload = 3;
}

message StakeTransferOwnership {
  uint64 bucketIndex = 1;
  string voterAddress = 2;
  bytes payload = 3;
}

message CandidateBasicInfo {
  string name = 1;
  string operatorAddress = 2;
  string rewardAddress = 3;
  bytes blsPubKey = 4;
}

message CandidateRegister {
  CandidateBasicInfo candidate = 1;
  string stakedAmount = 2;
  uint32 stakedDuration = 3;
  bool autoStake = 4;
  string ownerAddress = 5; // if ownerAddress is absent, owner of candidate is the sender
  bytes payload = 6;
}

message CandidateTransferOwnership {
  string newOwnerAddress = 1;
  bytes payload = 2;
}

message CandidateActivate {
  uint64 bucketIndex = 1;
}

message CandidateEndorsement {
  uint64 bucketIndex = 1;
  bool endorse = 2; // deprecated
  uint32 op = 3;
}

message StartSubChain {
  // TODO: chainID chould be assigned by system and returned via a receipt
  uint32 chainID = 1;
  string securityDeposit = 2;
  string operationDeposit = 3;
  uint64 startHeight = 4;
  uint64 parentHeightOffset = 5;
}

message StopSubChain {
  uint32 chainID = 1;
  uint64 stopHeight = 2;
  string subChainAddress = 3;
}

message MerkleRoot {
  string name = 1;
  bytes value = 2;
}

message PutBlock {
  string subChainAddress = 1;
  uint64 height = 2;
  repeated MerkleRoot roots = 3;
}

message CreateDeposit {
  uint32 chainID = 1;
  string amount  = 2;
  string recipient = 3;
}

message SettleDeposit {
  string amount  = 1;
  string recipient = 2;
  uint64 index = 3;
}

// plum main chain APIs
message CreatePlumChain {
}

message TerminatePlumChain {
  string subChainAddress = 1;
}

message PlumPutBlock {
  string subChainAddress = 1;
  uint64 height = 2;
  map<string, bytes> roots = 3;
}

message PlumCreateDeposit {
  string subChainAddress = 1;
  string amount = 2;
  string recipient = 3;
}

message PlumStartExit {
  string subChainAddress = 1;
  bytes previousTransfer = 2;
  bytes previousTransferBlockProof = 3;
  uint64 previousTransferBlockHeight = 4;
  bytes exitTransfer = 5;
  bytes exitTransferBlockProof = 6;
  uint64 exitTransferBlockHeight = 7;
}

message PlumChallengeExit {
  string subChainAddress = 1;
  uint64 coinID = 2;
  bytes challengeTransfer = 3;
  bytes challengeTransferBlockProof = 4;
  uint64 challengeTransferBlockHeight = 5;
}

message PlumResponseChallengeExit {
  string subChainAddress = 1;
  uint64 coinID = 2;
  bytes challengeTransfer = 3;
  bytes responseTransfer = 4;
  bytes responseTransferBlockProof = 5;
  uint64 previousTransferBlockHeight = 6;
}

message PlumFinalizeExit {
  string subChainAddress = 1;
  uint64 coinID = 2;
}

// plum sub chain APIs
message PlumSettleDeposit {
  uint64 coinID = 1;
}

message PlumTransfer {
  uint64 coinID = 1;
  bytes denomination = 2;
  string owner = 3;
  string recipient = 4;
}

message ActionCore {
  uint32 version = 1;
  uint64 nonce = 2;
  uint64 gasLimit = 3;
  string gasPrice = 4;
  uint32 chainID = 5;
  string gasTipCap = 6;
  string gasFeeCap = 7;
  BlobTxData blobTxData = 8;
  repeated AccessTuple accessList = 9;
  uint32 txType = 28;
  oneof action {
    Transfer transfer = 10;
    TxContainer txContainer = 11;
    Execution execution = 12;
    // FedChain
    StartSubChain startSubChain = 13;
    StopSubChain stopSubChain = 14;
    PutBlock putBlock = 15;
    CreateDeposit createDeposit = 16;
    SettleDeposit settleDeposit = 17;

    // PlumChain
    CreatePlumChain createPlumChain = 18;
    TerminatePlumChain terminatePlumChain = 19;
    PlumPutBlock plumPutBlock = 20;
    PlumCreateDeposit plumCreateDeposit = 21;
    PlumStartExit plumStartExit = 22;
    PlumChallengeExit plumChallengeExit = 23;
    PlumResponseChallengeExit plumResponseChallengeExit = 24;
    PlumFinalizeExit plumFinalizeExit = 25;
    PlumSettleDeposit plumSettleDeposit = 26;
    PlumTransfer plumTransfer = 27;

    // Rewarding protocol actions
    DepositToRewardingFund depositToRewardingFund = 30;
    ClaimFromRewardingFund claimFromRewardingFund = 31;
    GrantReward grantReward = 32;

    // Native staking
    StakeCreate stakeCreate = 40;
    StakeReclaim stakeUnstake = 41;
    StakeReclaim stakeWithdraw = 42;
    StakeAddDeposit stakeAddDeposit = 43;
    StakeRestake stakeRestake = 44;
    StakeChangeCandidate stakeChangeCandidate = 45;
    StakeTransferOwnership stakeTransferOwnership = 46;
    CandidateRegister candidateRegister = 47;
    CandidateBasicInfo candidateUpdate = 48;
    CandidateActivate candidateActivate = 49;
    CandidateEndorsement candidateEndorsement = 51;
    CandidateTransferOwnership candidateTransferOwnership = 52;
    StakeMigrate stakeMigrate = 53;

    PutPollResult putPollResult = 50;
  }
}

enum Encoding {
  option allow_alias = true;
  IOTEX_PROTOBUF = 0;
  ETHEREUM_EIP155 = 1;
  ETHEREUM_RLP = 1;
  ETHEREUM_UNPROTECTED = 2;
  TX_CONTAINER = 128;
}

message Action {
  ActionCore core = 1;
  bytes senderPubKey = 2;
  bytes signature = 3;
  Encoding encoding = 4;
}

// a pack of actions
message Actions {
  repeated Action actions = 1;
}

message ActionHash {
  bytes hash = 1;
}

message Receipt {
  uint64 status = 1;
  uint64 blkHeight = 2;
  bytes actHash = 3;
  uint64 gasConsumed = 4;
  string contractAddress = 5;
  repeated Log logs = 6;
  string executionRevertMsg = 7;
  uint32 txIndex = 8;
  uint64 blobGasUsed = 9;
  string blobGasPrice = 10;
  string effectiveGasPrice = 11;
}

message Log {
  string contractAddress = 1;
  repeated bytes topics = 2;
  bytes data = 3;
  uint64 blkHeight = 4;
  bytes actHash = 5;
  uint32 index = 6;
  bytes blkHash = 7;
  uint32 txIndex = 8;
}

message Logs {
  repeated Log logs = 1;
}

// Deprecated
message EvmTransfer {
  bytes amount = 1;
  string from = 2;
  string to = 3;
}

// Deprecated
message EvmTransferList {
  repeated EvmTransfer evmTransfers = 1;
}

// Deprecated
message ActionEvmTransfer {
  bytes actionHash = 1;
  uint64 numEvmTransfers = 2;
  repeated EvmTransfer evmTransfers = 3;
}

// Deprecated
message BlockEvmTransfer {
  uint64 blockHeight = 1;
  uint64 numEvmTransfers = 2;
  repeated ActionEvmTransfer actionEvmTransfers = 3;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// BELOW ARE DEFINITIONS FOR BLOCK PRODUCER PROTOCOL
////////////////////////////////////////////////////////////////////////////////////////////////////

message DepositToRewardingFund {
  string amount = 1;
  bytes data = 2;
}

message ClaimFromRewardingFund {
  string amount = 1;
  bytes data = 2;
  // address the claim of rewards for, if empty denoting the sender's address
  // more information see iip27: https://iotex.larksuite.com/wiki/EtDewVEz6i5BeCkyj6vudtdHsCh
  string address = 3;
}

enum RewardType {
  BlockReward = 0;
  EpochReward = 1;
}

message GrantReward {
  RewardType type = 1;
  uint64 height = 2;
}
