syntax = "proto3";

package logic.v1beta3;

import "gogoproto/gogo.proto";

option go_package = "github.com/axone-protocol/axoned/x/logic/types";

// Params defines all the configuration parameters of the "logic" module.
message Params {
  option (gogoproto.goproto_stringer) = false;

  // Interpreter specifies the parameter for the logic interpreter.
  Interpreter interpreter = 1 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"interpreter\""
  ];

  // Limits defines the limits of the logic module.
  // The limits are used to prevent the interpreter from running for too long.
  // If the interpreter runs for too long, the execution will be aborted.
  Limits limits = 2 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"limits\""
  ];

  // GasPolicy defines the parameters for calculating predicate invocation costs.
  GasPolicy gas_policy = 3 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"gas_policy\""
  ];
}

// Limits defines the limits of the logic module.
message Limits {
  option (gogoproto.goproto_stringer) = true;

  // max_size specifies the maximum size, in bytes, that is accepted for a program.
  // A value of 0 means that there is no limit on the size of the program.
  uint64 max_size = 3 [(gogoproto.moretags) = "yaml:\"max_size\""];

  // max_result_count specifies the maximum number of results that can be requested for a query.
  // A value of 0 means that there is no limit on the number of results.
  uint64 max_result_count = 2 [(gogoproto.moretags) = "yaml:\"max_result_count\""];

  // max_user_output_size specifies the maximum number of bytes to keep in the user output. If the user output exceeds
  // this size, the interpreter will overwrite the oldest bytes with the new ones to keep the size constant.
  // A value of 0 means the user output is disabled.
  uint64 max_user_output_size = 4 [(gogoproto.moretags) = "yaml:\"max_user_output_size\""];

  // max_variables specifies the maximum number of variables that can be create by the interpreter.
  // A value of 0 means that there is no limit on the number of variables.
  uint64 max_variables = 5 [(gogoproto.moretags) = "yaml:\"max_variables\""];
}

// Filter defines the parameters for filtering the set of strings which can designate anything.
// The filter is used to whitelist or blacklist strings.
message Filter {
  // whitelist specifies a list of strings that are allowed.
  // If this field is not specified, all strings (in the context of the filter) are allowed.
  repeated string whitelist = 1 [
    (gogoproto.nullable) = true,
    (gogoproto.moretags) = "yaml:\"whitelist\""
  ];

  // blacklist specifies a list of strings that are excluded from the set of allowed strings.
  // If a string is included in both whitelist and blacklist, it will be excluded. This means that
  // blacklisted strings prevails over whitelisted ones.
  // If this field is not specified, no strings are excluded.
  repeated string blacklist = 2 [
    (gogoproto.nullable) = true,
    (gogoproto.moretags) = "yaml:\"blacklist\""
  ];
}

// Interpreter defines the various parameters for the interpreter.
message Interpreter {
  option (gogoproto.goproto_stringer) = true;

  // predicates_filter specifies the filter for the predicates that are allowed to be used by the interpreter.
  // The filter is used to whitelist or blacklist predicates represented as `<predicate_name>/[<arity>]`, for example:
  // `findall/3`, or `call`. If a predicate name without arity is included in the filter, then all predicates with that
  // name will be considered regardless of arity. For example, if `call` is included in the filter, then all predicates
  // `call/1`, `call/2`, `call/3`... will be allowed.
  Filter predicates_filter = 1 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"predicates_filter\""
  ];

  // bootstrap specifies the initial program to run when booting the logic interpreter.
  // If not specified, the default boot sequence will be executed.
  string bootstrap = 3 [
    (gogoproto.nullable) = true,
    (gogoproto.moretags) = "yaml:\"bootstrap\""
  ];

  // virtual_files_filter specifies the filter for the virtual files that are allowed to be used by the interpreter.
  // The filter is used to whitelist or blacklist virtual files represented as URI, for example:
  // `file:///path/to/file`, `cosmwasm:cw-storage:axone...?query=foo`
  // The filter is applied to the components of the URI, for example:
  // `file:///path/to/file` -> `file`, `/path/to/file`
  // `cosmwasm:cw-storage:axone...?query=foo` -> `cosmwasm`, `cw-storage`, `axone...`, `query=foo`
  // If a component is included in the filter, then all components with that name will be considered, starting from the
  // beginning of the URI. For example, if `file` is included in the filter, then all URIs that start with `file` will be
  // allowed, regardless of the rest of the components. But `file2` will not be allowed.
  // If the component is not included in the filter, then the component is ignored and the next component is considered.
  Filter virtual_files_filter = 4 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"filesystem_filter\""
  ];
}

// GasPolicy defines the policy for calculating predicate invocation costs and the resulting gas consumption.
// The gas policy is defined as a list of predicates and their associated unit costs, a default unit cost for predicates
// if not specified in the list, and a weighting factor that is applied to the unit cost of each predicate to yield.
message GasPolicy {
  // WeightingFactor is the factor that is applied to the unit cost of each predicate
  // to yield the gas value.
  // If set to 0, the value considered is 1.
  uint64 weighting_factor = 1 [ (gogoproto.moretags) = "yaml:\"weighting_factor\"" ];

  // DefaultPredicateCost is the default unit cost of a predicate when not specified in the PredicateCosts list.
  // If set to 0, the value considered is 1.
  uint64 default_predicate_cost = 2 [ (gogoproto.moretags) = "yaml:\"default_predicate_cost\"" ];

  // PredicateCosts is the list of predicates and their associated unit costs.
  repeated PredicateCost predicate_costs = 3 [
    (gogoproto.nullable) = false,
    (gogoproto.moretags) = "yaml:\"predicate_cost\""
  ];
}

// PredicateCost defines the unit cost of a predicate during its invocation by the interpreter.
message PredicateCost {
  // Predicate is the name of the predicate, optionally followed by its arity (e.g. "findall/3").
  // If no arity is specified, the unit cost is applied to all predicates with the same name.
  string predicate = 1 [
    (gogoproto.nullable) = true,
    (gogoproto.moretags) = "yaml:\"predicate\""
  ];

  // Cost is the unit cost of the predicate.
  // If set to 0, the value considered is 1.
  uint64 cost = 2 [ (gogoproto.moretags) = "yaml:\"cost\"" ];
}
