'use strict';

const MIN_BASE_FEE = 5000;
const COMMITTEE_SIZE = 1000;
const GAS_LIMIT = 20000000;
const GAS_LIMIT_BOUND_DIVISOR = 1024;
const BASE_FEE_CHANGE_DENOMINATOR = 8;
const ELASTICITY_MULTIPLIER = 2;
const MAX_SCHEDULE_DURATION = 3*365*24*3600; // 3 years in seconds
const EPOCH_PERIOD = 30;
const DELEGATION_RATE = 100;
const UN_BONDING_PERIOD = 60;
const TREASURY_FEE = "10000000000000000";
// because we cannot test inflation in truffle properly, due to the fact that its time of deployment is not same as that of autonity contract
const INITIAL_INFLATION_RESERVE = "0";
const PROPOSER_REWARD_RATE = 1000
const WITHHOLDING_THRESHOLD = 0
const MIN_EPOCH_PERIOD = 30;
const VERSION = 0;
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
const SLASHING_RATE_PRECISION = 10000; // needs to match the slashing rate precision in Slasher.sol
const ORACLE_REWARD_RATE = 0; // tests for oracle rewards are outside of the Truffle tests
const CLUSTERING_THRESHOLD = 64; // 64 validators before clustering kicks in

const ACCOUNTABILITY_CONFIG = {
        "innocenceProofSubmissionWindow": 30,
        "delta": 10,
        "range": 256,
        "baseSlashingRates" : {
            "low": 400,
            "mid": 600,
            "high": 800,
        },
        "factors" : {
            "collusion": 200,
            "history": 500,
            "jail": 48,
        },
    };

const OMISSION_ACCOUNTABILITY_CONFIG = {
    "inactivityThreshold": 1000,     // 10%
    "lookbackWindow":  10,   // 10 blocks
    "pastPerformanceWeight":   1000, // 10%
    "initialJailingPeriod":    300,  // 300 blocks
    "initialProbationPeriod":  24,  // 24 epochs
    "initialSlashingRate":     25, // 0.25%
    "delta": 5, // 5 blocks
}

const GENESIS_ENODES = [
        "enode://d73b857969c86415c0c000371bcebd9ed3cca6c376032b3f65e58e9e2b79276fbc6f59eb1e22fcd6356ab95f42a666f70afd4985933bd8f3e05beb1a2bf8fdde@172.25.0.11:30303",
        "enode://1f207dfb3bcbbd338fbc991ec13e40d204b58fe7275cea48cfeb53c2c24e1071e1b4ef2959325fe48a5893de8ff37c73a24a412f367e505e5dec832813da546a@172.25.0.12:30303",
        "enode://438a5c2cd8fdc2ecbc508bf7362e41c0f0c3754ba1d3267127a3756324caf45e6546b02140e2144b205aeb372c96c5df9641485f721dc7c5b27eb9e35f5d887b@172.25.0.14:30303",
        "enode://3ce6c053cb563bfd94f4e0e248510a07ccee1bc836c9784da1816dba4b10564e7be1ba42e0bd8d73c8f6274f8e9878dc13814adb381c823264265c06048b4b59@172.25.0.15:30303"
    ];

// precomputed using aut validator compute-address
const GENESIS_NODE_ADDRESSES = [
        "0x850C1Eb8D190e05845ad7F84ac95a318C8AaB07f",
        "0x4AD219b58a5b46A1D9662BeAa6a70DB9F570deA5",
        "0xc443C6c6AE98F5110702921138D840e77dA67702",
        "0x09428E8674496e2D1E965402F33A9520c5fCBbE2",
    ];

const GENESIS_CONSENSUS_KEYS = [
    "0xb10a7d9920aca66523e7f30d60cd9da832f5a122882ebe5e973f1e3e8e608dffc69fca62dc93f42a8fa273d1e5af2439",
    "0x83530bec48a262f2ca0231001a29824e9a0de41801742a9634a4d452daaa41fc009fa9d160cb30827741da5ff2db367b",
    "0xb5f30c01a36560d144df1c41ffa0208cd3393c5628ac4957236cf45389d8497bdce90c8d42cf0b3f9c5fcc9944fa0a0b",
    "0x905034a9758670d4881ad36b655e89ab234c21112d225e247ffb5f0108337f5f0ccc0c48a5cad307f4c7f667c48f146d",
];

const BASE_VALIDATOR = {
        "selfBondedStake": 0,
        "selfUnbondingStakeLocked": 0,
        "totalSlashed": 0,
        "jailReleaseBlock": 0,
        "liquidSupply": 0,
        "registrationBlock": 0,
        "state": 0,
        "liquidStateContract": ZERO_ADDRESS,
        "selfUnbondingStake": 0,
        "selfUnbondingShares": 0,
        "unbondingStake": 0,
        "unbondingShares": 0,
        "consensusKey": "0x00",
        "conversionRatio": "1000000000000000000",
    };

const GENESIS_PRIVATE_KEYS = [
    "a4b489752489e0f47e410b8e8cbb1ac1b56770d202ffd45b346ca8355c602c91",
    "aa4b77b1305f8f265e81599587c623d8950624f3e1bd9c121ef2461a7a1e7527",
    "4ec99383dc50aa3f3117fcbfba7b69188ba60d3418185fb353c9a69d066e55d9",
    "0c8698f456533170fe07c6dcb753d47bef8bedd46443efa57a859c989887b56b",
];

const INFLATION_CONTROLLER_CONFIG = {
    "inflationRateInitial": "0x8dc0fa1e",
    "inflationRateTransition": "0x67f3ea9f",
    "inflationCurveConvexity": "0x13d4d3edc8088000",
    "inflationTransitionPeriod": "0x685807f13a9c4278000000",
    "inflationReserveDecayRate": "0x147820d72",
}

const STABILIZATION_CONFIG = {
    "borrowInterestRate" : 0,
    "announcementWindow" : 30,
    "liquidationRatio" : 1,
    "minCollateralizationRatio" : 2,
    "minDebtRequirement" : 0,
    "targetPrice" : 0,
}

function autonityConfig(operator, treasuryAccount) {
    return {
        "policy": {
            "treasuryFee": TREASURY_FEE,
            "minBaseFee": MIN_BASE_FEE,
            "delegationRate": DELEGATION_RATE,
            "unbondingPeriod" : UN_BONDING_PERIOD,
            "initialInflationReserve": INITIAL_INFLATION_RESERVE,
            "withholdingThreshold": WITHHOLDING_THRESHOLD,
            "proposerRewardRate": PROPOSER_REWARD_RATE,
            "withheldRewardsPool": treasuryAccount,
            "treasuryAccount": treasuryAccount,
            "oracleRewardRate": ORACLE_REWARD_RATE,
            "baseFeeChangeDenominator": BASE_FEE_CHANGE_DENOMINATOR,
            "elasticityMultiplier": ELASTICITY_MULTIPLIER,
        },
        "contracts": {
            "oracleContract" : ZERO_ADDRESS, // gets updated in deployContracts()
            "accountabilityContract": ZERO_ADDRESS, // gets updated in deployContracts()
            "acuContract" :ZERO_ADDRESS,
            "supplyControlContract" :ZERO_ADDRESS,
            "stabilizationContract" :ZERO_ADDRESS,
            "upgradeManagerContract" :ZERO_ADDRESS,
            "inflationControllerContract" :ZERO_ADDRESS,
            "omissionAccountabilityContract": ZERO_ADDRESS,
            "auctioneerContract": ZERO_ADDRESS,
        },
        "protocol": {
            "operatorAccount": operator,
            "epochPeriod": EPOCH_PERIOD,
            "blockPeriod": MIN_EPOCH_PERIOD,
            "committeeSize": COMMITTEE_SIZE,
            "gasLimit": GAS_LIMIT,
            "maxScheduleDuration": MAX_SCHEDULE_DURATION,
            "gasLimitBoundDivisor": GAS_LIMIT_BOUND_DIVISOR,
            "clusteringThreshold": CLUSTERING_THRESHOLD,
        },
        "contractVersion": VERSION,
    };
}

// accounts[2] is skipped because it is used as a genesis validator when running against autonity
// this can cause interference in reward distribution tests
function validators(accounts) {
    return [
        { ...BASE_VALIDATOR,
            "treasury": accounts[0],
            "nodeAddress": GENESIS_NODE_ADDRESSES[0],
            "oracleAddress": accounts[0],
            "enode": GENESIS_ENODES[0],
            "consensusKey": GENESIS_CONSENSUS_KEYS[0],
            "commissionRate": 100,
            "bondedStake": 100,
        },
        { ...BASE_VALIDATOR,
            "treasury": accounts[1],
            "nodeAddress": GENESIS_NODE_ADDRESSES[1],
            "oracleAddress": accounts[1],
            "enode": GENESIS_ENODES[1],
            "consensusKey": GENESIS_CONSENSUS_KEYS[1],
            "commissionRate": 100,
            "bondedStake": 90,
        },
        { ...BASE_VALIDATOR,
            "treasury": accounts[3],
            "nodeAddress": GENESIS_NODE_ADDRESSES[2],
            "oracleAddress": accounts[3],
            "enode": GENESIS_ENODES[2],
            "consensusKey": GENESIS_CONSENSUS_KEYS[2],
            "commissionRate": 100,
            "bondedStake": 110,
        },
        { ...BASE_VALIDATOR,
            "treasury": accounts[4],
            "nodeAddress": GENESIS_NODE_ADDRESSES[3],
            "oracleAddress": accounts[4],
            "enode": GENESIS_ENODES[3],
            "consensusKey": GENESIS_CONSENSUS_KEYS[3],
            "commissionRate": 100,
            "bondedStake": 120,
        },
    ];
}

module.exports = {
    MIN_BASE_FEE: MIN_BASE_FEE,
    COMMITTEE_SIZE: COMMITTEE_SIZE,
    VERSION: VERSION,
    ACCOUNTABILITY_CONFIG: ACCOUNTABILITY_CONFIG,
    OMISSION_ACCOUNTABILITY_CONFIG: OMISSION_ACCOUNTABILITY_CONFIG,
    GENESIS_ENODES: GENESIS_ENODES,
    GENESIS_NODE_ADDRESSES: GENESIS_NODE_ADDRESSES,
    BASE_VALIDATOR: BASE_VALIDATOR,
    GENESIS_PRIVATE_KEYS: GENESIS_PRIVATE_KEYS,
    INFLATION_CONTROLLER_CONFIG: INFLATION_CONTROLLER_CONFIG,
    STABILIZATION_CONFIG: STABILIZATION_CONFIG,
    SLASHING_RATE_PRECISION: SLASHING_RATE_PRECISION,
    autonityConfig: autonityConfig,
    validators: validators,
};
