// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// You may obtain a copy of the licence at:
//
//     https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
//
// SPDX-License-Identifier: EUPL-1.2

// Package config defines chain parameters for the Lethean blockchain.
//
// All constants are derived from the canonical C++ source files
// currency_config.h.in and default.cmake. Mainnet and Testnet configurations
// are provided as package-level variables.
package config

// ---------------------------------------------------------------------------
// Tokenomics
// ---------------------------------------------------------------------------

// Coin is the number of smallest indivisible units in one LTHN.
// 1 LTHN = 10^12 atomic units.
const Coin uint64 = 1_000_000_000_000

// DisplayDecimalPoint is the number of decimal places used when displaying
// amounts in human-readable form.
const DisplayDecimalPoint = 12

// BlockReward is the fixed reward per block in atomic units (1.0 LTHN).
const BlockReward uint64 = 1_000_000_000_000

// DefaultFee is the standard transaction fee in atomic units (0.01 LTHN).
const DefaultFee uint64 = 10_000_000_000

// MinimumFee is the lowest acceptable transaction fee in atomic units (0.01 LTHN).
const MinimumFee uint64 = 10_000_000_000

// Premine is the total pre-mined supply in atomic units (10,000,000 LTHN).
// This covers the coinswap allocation (13,827,203 LTHN reserved) and the
// initial premine (3,690,000 LTHN). The raw value from cmake is
// 10,000,000,000,000,000,000 but that exceeds uint64 range. The C++ code
// uses an unsigned literal suffix; we store the value faithfully.
const Premine uint64 = 10_000_000_000_000_000_000

// BaseRewardDustThreshold is the minimum meaningful fraction of a block
// reward in atomic units.
const BaseRewardDustThreshold uint64 = 1_000_000

// DefaultDustThreshold is the dust threshold for normal transactions.
const DefaultDustThreshold uint64 = 0

// ---------------------------------------------------------------------------
// Address prefixes
// ---------------------------------------------------------------------------

// Address prefix constants determine the leading characters of base58-encoded
// addresses. Each prefix is varint-encoded before the public keys.
const (
	// AddressPrefix is the standard public address prefix.
	// Produces addresses starting with "iTHN".
	AddressPrefix uint64 = 0x1eaf7

	// IntegratedAddressPrefix is the prefix for integrated addresses
	// (address + embedded payment ID). Produces addresses starting with "iTHn".
	IntegratedAddressPrefix uint64 = 0xdeaf7

	// AuditableAddressPrefix is the prefix for auditable addresses.
	// Produces addresses starting with "iThN".
	AuditableAddressPrefix uint64 = 0x3ceff7

	// AuditableIntegratedAddressPrefix is the prefix for auditable
	// integrated addresses. Produces addresses starting with "iThn".
	AuditableIntegratedAddressPrefix uint64 = 0x8b077
)

// ---------------------------------------------------------------------------
// P2P and RPC ports
// ---------------------------------------------------------------------------

const (
	MainnetP2PPort     uint16 = 36942
	MainnetRPCPort     uint16 = 36941
	MainnetStratumPort uint16 = 36940

	TestnetP2PPort     uint16 = 46942
	TestnetRPCPort     uint16 = 46941
	TestnetStratumPort uint16 = 46940
)

// ---------------------------------------------------------------------------
// Timing and difficulty
// ---------------------------------------------------------------------------

const (
	// DifficultyPowTarget is the target block interval for PoW blocks in seconds.
	DifficultyPowTarget uint64 = 120

	// DifficultyPosTarget is the target block interval for PoS blocks in seconds.
	DifficultyPosTarget uint64 = 120

	// DifficultyTotalTarget is the effective combined target:
	// (PoW + PoS) / 4 = 60 seconds.
	DifficultyTotalTarget uint64 = (DifficultyPowTarget + DifficultyPosTarget) / 4

	// DifficultyWindow is the number of blocks used for difficulty calculation.
	DifficultyWindow uint64 = 720

	// DifficultyLag is the additional lookback beyond the window.
	DifficultyLag uint64 = 15

	// DifficultyCut is the number of timestamps cut from each end after sorting.
	DifficultyCut uint64 = 60

	// DifficultyBlocksCount is the total number of blocks considered
	// (Window + Lag).
	DifficultyBlocksCount uint64 = DifficultyWindow + DifficultyLag

	// DifficultyPowStarter is the initial PoW difficulty.
	DifficultyPowStarter uint64 = 1

	// DifficultyPosStarter is the initial PoS difficulty.
	DifficultyPosStarter uint64 = 1

	// BlockTarget is the desired block interval in seconds.
	// Both PoW and PoS blocks use the same 120-second target.
	BlockTarget uint64 = 120

	// DifficultyPowTargetHF6 is the PoW target after hardfork 6 (240s).
	DifficultyPowTargetHF6 uint64 = 240

	// DifficultyPosTargetHF6 is the PoS target after hardfork 6 (240s).
	DifficultyPosTargetHF6 uint64 = 240

	// DifficultyTotalTargetHF6 is the combined target after HF6.
	DifficultyTotalTargetHF6 uint64 = (DifficultyPowTargetHF6 + DifficultyPosTargetHF6) / 4
)

// ---------------------------------------------------------------------------
// Block and transaction limits
// ---------------------------------------------------------------------------

const (
	// MaxBlockNumber is the absolute maximum block height.
	MaxBlockNumber uint64 = 500_000_000

	// MaxBlockSize is the maximum block header blob size in bytes.
	MaxBlockSize uint64 = 500_000_000

	// TxMaxAllowedInputs is the maximum number of inputs per transaction.
	// Limited primarily by the asset surjection proof.
	TxMaxAllowedInputs uint64 = 256

	// TxMaxAllowedOutputs is the maximum number of outputs per transaction.
	TxMaxAllowedOutputs uint64 = 2000

	// TxMinAllowedOutputs is the minimum number of outputs (effective from HF4 Zarcanum).
	TxMinAllowedOutputs uint64 = 2

	// DefaultDecoySetSize is the ring size for pre-HF4 transactions.
	DefaultDecoySetSize uint64 = 10

	// HF4MandatoryDecoySetSize is the ring size required from HF4 onwards.
	HF4MandatoryDecoySetSize uint64 = 15

	// HF4MandatoryMinCoinage is the minimum coinage in blocks required for HF4.
	HF4MandatoryMinCoinage uint64 = 10

	// MinedMoneyUnlockWindow is the number of blocks before mined coins
	// can be spent.
	MinedMoneyUnlockWindow uint64 = 10

	// BlockGrantedFullRewardZone is the block size threshold in bytes after
	// which block reward is calculated using the actual block size.
	BlockGrantedFullRewardZone uint64 = 125_000

	// CoinbaseBlobReservedSize is the reserved space for the coinbase
	// transaction blob in bytes.
	CoinbaseBlobReservedSize uint64 = 1100

	// MaxTransactionBlobSize is the maximum serialised transaction size in bytes.
	// Derived from BlockGrantedFullRewardZone - 2*CoinbaseBlobReservedSize
	// but the canonical C++ value is 374,600.
	MaxTransactionBlobSize uint64 = 374_600

	// BlockFutureTimeLimit is the maximum acceptable future timestamp for
	// PoW blocks in seconds (2 hours).
	BlockFutureTimeLimit uint64 = 60 * 60 * 2

	// PosBlockFutureTimeLimit is the maximum acceptable future timestamp
	// for PoS blocks in seconds (20 minutes).
	PosBlockFutureTimeLimit uint64 = 60 * 20

	// TimestampCheckWindow is the number of blocks used when checking
	// whether a block timestamp is valid.
	TimestampCheckWindow uint64 = 60

	// PosStartHeight is the block height from which PoS is enabled.
	PosStartHeight uint64 = 0

	// RewardBlocksWindow is the number of recent blocks used to calculate
	// the reward median.
	RewardBlocksWindow uint64 = 400

	// FreeTxMaxBlobSize is the soft txpool-based limit for free transactions
	// in bytes.
	FreeTxMaxBlobSize uint64 = 1024

	// PreHardforkTxFreezePeriod is the number of blocks before hardfork
	// activation when no new transactions are accepted (effective from HF5).
	PreHardforkTxFreezePeriod uint64 = 60
)

// ---------------------------------------------------------------------------
// Block version constants
// ---------------------------------------------------------------------------

const (
	BlockMajorVersionGenesis  uint8 = 1
	BlockMinorVersionGenesis  uint8 = 0
	BlockMajorVersionInitial  uint8 = 0
	HF1BlockMajorVersion      uint8 = 1
	HF3BlockMajorVersion      uint8 = 2
	HF3BlockMinorVersion      uint8 = 0
	CurrentBlockMajorVersion  uint8 = 3
	CurrentBlockMinorVersion  uint8 = 0
)

// ---------------------------------------------------------------------------
// Transaction version constants
// ---------------------------------------------------------------------------

const (
	TransactionVersionInitial  uint8 = 0
	TransactionVersionPreHF4   uint8 = 1
	TransactionVersionPostHF4  uint8 = 2
	TransactionVersionPostHF5  uint8 = 3
	CurrentTransactionVersion  uint8 = 3
)

// ---------------------------------------------------------------------------
// PoS constants
// ---------------------------------------------------------------------------

const (
	PosScanWindow                  uint64 = 60 * 10 // 10 minutes in seconds
	PosScanStep                    uint64 = 15      // seconds
	PosModifierInterval            uint64 = 10
	PosMinimumCoinstakeAge         uint64 = 10 // blocks
	PosStrictSequenceLimit         uint64 = 20
	PosStarterKernelHash                  = "00000000000000000006382a8d8f94588ce93a1351924f6ccb9e07dd287c6e4b"
)

// ---------------------------------------------------------------------------
// P2P constants
// ---------------------------------------------------------------------------

const (
	P2PLocalWhitePeerlistLimit uint64 = 1000
	P2PLocalGrayPeerlistLimit  uint64 = 5000
	P2PDefaultConnectionsCount uint64 = 8
	P2PDefaultHandshakeInterval uint64 = 60      // seconds
	P2PDefaultPacketMaxSize    uint64 = 50_000_000
	P2PIPBlockTime             uint64 = 60 * 60 * 24 // 24 hours
	P2PIPFailsBeforeBlock      uint64 = 10
)

// ---------------------------------------------------------------------------
// Network identity
// ---------------------------------------------------------------------------

const (
	// CurrencyFormationVersion identifies the mainnet network.
	CurrencyFormationVersion uint64 = 84

	// CurrencyFormationVersionTestnet identifies the testnet network.
	CurrencyFormationVersionTestnet uint64 = 100

	// P2PNetworkIDVer is derived from CurrencyFormationVersion + 0.
	P2PNetworkIDVer uint64 = CurrencyFormationVersion + 0
)

// NetworkIDMainnet is the 16-byte network UUID for mainnet P2P handshake.
// From net_node.inl: bytes 0-9 are fixed, byte 10 = P2P_NETWORK_ID_TESTNET_FLAG,
// bytes 11-14 fixed, byte 15 = formation version (84 = 0x54).
// NOTE: In the C++ source, the #ifndef TESTNET branch (i.e. mainnet) sets
// P2P_NETWORK_ID_TESTNET_FLAG = 1 and the #else (testnet) sets it to 0.
// The naming is counter-intuitive but matches the compiled binaries.
var NetworkIDMainnet = [16]byte{
	0x11, 0x10, 0x01, 0x11, 0x01, 0x01, 0x11, 0x01,
	0x10, 0x11, 0x01, 0x11, 0x01, 0x11, 0x21, 0x54,
}

// NetworkIDTestnet is the 16-byte network UUID for testnet P2P handshake.
// Byte 10 = 0x00 (P2P_NETWORK_ID_TESTNET_FLAG in testnet build),
// byte 15 = formation version (100 = 0x64).
var NetworkIDTestnet = [16]byte{
	0x11, 0x10, 0x01, 0x11, 0x01, 0x01, 0x11, 0x01,
	0x10, 0x11, 0x00, 0x11, 0x01, 0x11, 0x21, 0x64,
}

// ClientVersion is the version string sent in CORE_SYNC_DATA.
// The C++ daemon parses this as "major.minor.revision.build[commit]"
// and rejects connections where it cannot parse or the build number
// is below the minimum for the current hard-fork era.
const ClientVersion = "6.0.1.2[go-blockchain]"


// ---------------------------------------------------------------------------
// Currency identity
// ---------------------------------------------------------------------------

const (
	CurrencyNameAbbreviation = "LTHN"
	CurrencyNameBase         = "Lethean"
	CurrencyNameShort        = "Lethean"
)

// ---------------------------------------------------------------------------
// Alias constants
// ---------------------------------------------------------------------------

const (
	AliasMinimumPublicShortNameAllowed uint64 = 6
	AliasNameMaxLen                    uint64 = 255
	AliasValidChars                           = "0123456789abcdefghijklmnopqrstuvwxyz-."
	AliasCommentMaxSizeBytes           uint64 = 400
	MaxAliasPerBlock                   uint64 = 1000
)

// ---------------------------------------------------------------------------
// ChainConfig aggregates all chain parameters into a single struct.
// ---------------------------------------------------------------------------

// ChainConfig holds the complete set of parameters for a particular chain
// (mainnet or testnet).
type ChainConfig struct {
	// Name is the human-readable chain name.
	Name string

	// Abbreviation is the ticker symbol.
	Abbreviation string

	// IsTestnet indicates whether this is a test network.
	IsTestnet bool

	// CurrencyFormationVersion identifies the network.
	CurrencyFormationVersion uint64

	// Coin is the number of atomic units per coin.
	Coin uint64

	// DisplayDecimalPoint is the number of decimal places.
	DisplayDecimalPoint uint8

	// BlockReward is the fixed block reward in atomic units.
	BlockReward uint64

	// DefaultFee is the default transaction fee in atomic units.
	DefaultFee uint64

	// MinimumFee is the minimum acceptable fee in atomic units.
	MinimumFee uint64

	// Premine is the pre-mined amount in atomic units.
	Premine uint64

	// AddressPrefix is the base58 prefix for standard addresses.
	AddressPrefix uint64

	// IntegratedAddressPrefix is the base58 prefix for integrated addresses.
	IntegratedAddressPrefix uint64

	// AuditableAddressPrefix is the base58 prefix for auditable addresses.
	AuditableAddressPrefix uint64

	// AuditableIntegratedAddressPrefix is the base58 prefix for auditable
	// integrated addresses.
	AuditableIntegratedAddressPrefix uint64

	// P2PPort is the default peer-to-peer port.
	P2PPort uint16

	// RPCPort is the default RPC port.
	RPCPort uint16

	// StratumPort is the default stratum mining port.
	StratumPort uint16

	// DifficultyPowTarget is the target PoW block interval in seconds.
	DifficultyPowTarget uint64

	// DifficultyPosTarget is the target PoS block interval in seconds.
	DifficultyPosTarget uint64

	// DifficultyWindow is the number of blocks in the difficulty window.
	DifficultyWindow uint64

	// DifficultyLag is the additional lookback beyond the window.
	DifficultyLag uint64

	// DifficultyCut is the number of timestamps cut after sorting.
	DifficultyCut uint64

	// DifficultyPowStarter is the initial PoW difficulty.
	DifficultyPowStarter uint64

	// DifficultyPosStarter is the initial PoS difficulty.
	DifficultyPosStarter uint64

	// MaxBlockNumber is the absolute maximum block height.
	MaxBlockNumber uint64

	// TxMaxAllowedInputs is the maximum inputs per transaction.
	TxMaxAllowedInputs uint64

	// TxMaxAllowedOutputs is the maximum outputs per transaction.
	TxMaxAllowedOutputs uint64

	// DefaultDecoySetSize is the default ring size.
	DefaultDecoySetSize uint64

	// HF4MandatoryDecoySetSize is the mandatory ring size from HF4.
	HF4MandatoryDecoySetSize uint64

	// MinedMoneyUnlockWindow is the maturity period for mined coins.
	MinedMoneyUnlockWindow uint64

	// P2PMaintainersPubKey is the hex-encoded maintainers public key.
	P2PMaintainersPubKey string

	// NetworkID is the 16-byte network UUID for P2P handshake.
	NetworkID [16]byte
}

// Mainnet holds the chain configuration for the Lethean mainnet.
var Mainnet = ChainConfig{
	Name:                             CurrencyNameBase,
	Abbreviation:                     CurrencyNameAbbreviation,
	IsTestnet:                        false,
	CurrencyFormationVersion:         CurrencyFormationVersion,
	Coin:                             Coin,
	DisplayDecimalPoint:              DisplayDecimalPoint,
	BlockReward:                      BlockReward,
	DefaultFee:                       DefaultFee,
	MinimumFee:                       MinimumFee,
	Premine:                          Premine,
	AddressPrefix:                    AddressPrefix,
	IntegratedAddressPrefix:          IntegratedAddressPrefix,
	AuditableAddressPrefix:           AuditableAddressPrefix,
	AuditableIntegratedAddressPrefix: AuditableIntegratedAddressPrefix,
	P2PPort:                          MainnetP2PPort,
	RPCPort:                          MainnetRPCPort,
	StratumPort:                      MainnetStratumPort,
	DifficultyPowTarget:              DifficultyPowTarget,
	DifficultyPosTarget:              DifficultyPosTarget,
	DifficultyWindow:                 DifficultyWindow,
	DifficultyLag:                    DifficultyLag,
	DifficultyCut:                    DifficultyCut,
	DifficultyPowStarter:             DifficultyPowStarter,
	DifficultyPosStarter:             DifficultyPosStarter,
	MaxBlockNumber:                   MaxBlockNumber,
	TxMaxAllowedInputs:               TxMaxAllowedInputs,
	TxMaxAllowedOutputs:              TxMaxAllowedOutputs,
	DefaultDecoySetSize:              DefaultDecoySetSize,
	HF4MandatoryDecoySetSize:         HF4MandatoryDecoySetSize,
	MinedMoneyUnlockWindow:           MinedMoneyUnlockWindow,
	P2PMaintainersPubKey:             "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607",
	NetworkID:                       NetworkIDMainnet,
}

// Testnet holds the chain configuration for the Lethean testnet.
var Testnet = ChainConfig{
	Name:                             CurrencyNameBase + "_testnet",
	Abbreviation:                     CurrencyNameAbbreviation,
	IsTestnet:                        true,
	CurrencyFormationVersion:         CurrencyFormationVersionTestnet,
	Coin:                             Coin,
	DisplayDecimalPoint:              DisplayDecimalPoint,
	BlockReward:                      BlockReward,
	DefaultFee:                       DefaultFee,
	MinimumFee:                       MinimumFee,
	Premine:                          Premine,
	AddressPrefix:                    AddressPrefix,
	IntegratedAddressPrefix:          IntegratedAddressPrefix,
	AuditableAddressPrefix:           AuditableAddressPrefix,
	AuditableIntegratedAddressPrefix: AuditableIntegratedAddressPrefix,
	P2PPort:                          TestnetP2PPort,
	RPCPort:                          TestnetRPCPort,
	StratumPort:                      TestnetStratumPort,
	DifficultyPowTarget:              DifficultyPowTarget,
	DifficultyPosTarget:              DifficultyPosTarget,
	DifficultyWindow:                 DifficultyWindow,
	DifficultyLag:                    DifficultyLag,
	DifficultyCut:                    DifficultyCut,
	DifficultyPowStarter:             DifficultyPowStarter,
	DifficultyPosStarter:             DifficultyPosStarter,
	MaxBlockNumber:                   MaxBlockNumber,
	TxMaxAllowedInputs:               TxMaxAllowedInputs,
	TxMaxAllowedOutputs:              TxMaxAllowedOutputs,
	DefaultDecoySetSize:              DefaultDecoySetSize,
	HF4MandatoryDecoySetSize:         HF4MandatoryDecoySetSize,
	MinedMoneyUnlockWindow:           MinedMoneyUnlockWindow,
	P2PMaintainersPubKey:             "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607",
	NetworkID:                       NetworkIDTestnet,
}
