治理合约
在TON中,与TVM、catchain、费用和链拓扑(以及这些参数如何存储和更新)有关的节点操作共识参数由一组特殊的智能合约 控制(与前几代区块链采用的旧式和不灵活的硬编码这些参数的方式不同)。通过这种方式,TON实现了全面透明的链上治理。这组特殊合约本身受参数控制,目前包括选举人、配置合约和DNS合约,将来将通过额外的货币铸币和其他合约进行扩展。
选举人(Elector)
选举人智能合约控制验证轮次的更替方式、谁获得验证区块链的职责以及如何分配验证奖励。如果您想成为验证者并与选举人互动,请查看验证者说明。
选举人存储未提取的Toncoin数据在credits
哈希表中,新的申请在elect
哈希表中,以及关于以往选举的信息在 past*elections 哈希表中(后者存储在关于验证者不当行为的 complaints 和_frozen*-已完成轮次的验证者质押中,这些质押被扣留用于 stake_held_for
(配置参数15))。选举人合约有三个目的:
- 处理验证者选举的申请
- 举行选举
- 处理验证者不当行为的报告
- 分配验证奖励
处理申请
要创建申请,未来的验证者需要形成一个包含相应参数(ADNL地址、公钥、max_factor
等)的特殊消息,将其附加到一定数量的TON(称为质押),并发送给选举人。反过来,选举人检查这些参数,要么注册申请,要么立即将质押退还给发送者。请注意,只接受来自主链地址的申请。
举行选举
选举人是一个特殊的智能合约,可以在每个区块的开始和结束时被强制调用(所谓的Tick和Tock交易)。选举人确实在每个区块上被调用,并检查是否是举行新选举的时候。
选举过程的总体概念是考虑所有申请,特别是它们的TON数量和max_factor
(此申请人同意做的验证工作与最弱验证者做的验证工作相比的最大比例),并按照TON数量为每个验证者设置权重,但要满足所有max_factor
条件。
技术实现如下:
- 选举人取出所有质押金额高于当前网络最低
min_stake
(配置参数17)的申请。 - 按质押金额降序排列。
- 如果参与者多于验证者的最大数量(
max_validators
配置参数16),则舍弃名单尾部。 - 从
1
循环到N
(剩余参与者数量)。
- 取名单中按降序排列的第
i
个元素 - 假设第_i_个候选人将是最后一个被接受的(因此权重最低),并根据
max_factor
计算有效质押(true_stake
)。换句话说,第_j_个(j<i
)申请人的有效质押计算为min(stake[i]*max_factor[j], stake[j])
。 - 计算第1个到第_i_个参与者的总有效质押(TES)。如果这个TES高于先前已知的最大TES,则将其视为当前最佳权重配置。
- 获取当前最佳配置,即最大化利用质押的权重配置,并将其发送给配置合约(下面的配置合约)以成为新的验证者集合。
- 将所有未使用的质押,例如那些没有成为验证者的申请人和多余的部分(如果有的话)
stake[j]-min(stake[i]*max_factor[j], stake[j])
放入credits
表中,申请人可以从中请求拿回它们。
这样,如果我们有9个候选人,每个人有100,000和2.7的因子,最后一个参与者不会被选举:没有他,有效质押将是900,000,有他,只有9 * 27,000 + 10,000 = 253,000。相反,如果我们有一个候选人有100,000和2.7的因子和9个参与者各有10,000,他们都将成为验证者。但是,第一个候选人只会质押10*2.7 = 27,000 TON,多出的73,000 TON进入credits
。
请注意,对结果验证集有一些限制(显然由TON配置参数控制),特别是min_validators
、max_validators
(配置参数16)、min_stake
、max_stake
、min_total_stake
、max_stake_factor
(配置参数17)。如果目前的申请无法满足这些条件,选举将被推迟。
报告验证者不当行为的过程
每个验证者不时被随机分配创建新区块的任务(如果验证者在几秒钟后失败,这个职责将传递给下一个验证者)。这种分配的频率由验证者的权重决定。因此,任何人都可以从上一个验证轮次获取区块,并检查生成的区块数量是否接近实际数量。统计上显著的偏差(生成的区块数量少于预期)意味着验证者的不当行为。在TON上,使用Merkle证明相对容易证明不当行为。选举人合约接受这种证明和所建议的罚款,任何愿意支付其存储费用的人都可以注册投诉。然后,当前轮次的每个验证者检查投诉,如果它是正确的,并且建议的罚款与不当行为的严重性相符,他们会为其投票。获得超过2/3的权重投票后,投诉被接受,罚款从past_elections
对应元素的frozen
哈希表中扣除。
分配验证奖励
与检查是否是进行新选举的时候一样,选举人在每个区块中都会检查是否是释放frozen
中存储的past_elections
的资金的时候。在相应的区块中,选举人将相应验证轮次积累的收益(gas费和区块创建奖励)按验证者权重比例分配给该轮次的验证者。之后,质押和奖励被添加到credits
表中,选举从past_elections
表中删除。
配置(Config)
配置智能合约控制TON配置参数。其逻辑决定了谁以及在什么条件下有权更改这些参数中的一些。它还实现了提案/投票机制和验证者集合滚动更新。
验证者集合滚动更新
一旦配置合约从选举人合约收到特殊消息,通知其新的验证者集合已经被选举出来,配置将新的验证者集合放到配置参数36(下一个验证者)。然后,在每个区块的TickTock交易期间,配置检查是否是应用新验证者集合的时候(验证者集合本身嵌入了时间utime_since
),并将之前的集合从配置参数34(当前验证者)移动到配置参数32(之前的验证者),并从配置参数36设置到配 置参数34。
提案/投票机制
任何愿意支付存储提案费用的人都可以通过向配置合约发送相应消息来提议更改一个或多个配置参数。反过来,当前集合中的任何验证者都可以通过用他们的私钥签署批准消息来为这个提案投票(注意相应的公钥存储在配置参数34中)。在获得或不获得3/4的投票(根据验证者权重)后,提案获胜或输掉一轮。在赢得足够多轮次的关键次数(min_wins
配置参数11)后,提案被接受;在输掉足够多轮次的关键次数(max_losses
配置参数11)后,它被丢弃。
请注意,一些参数被认为是关键的(关键参数集本身是配置参数配置参数10),因此需要更多轮次才能被接受。
配置参数索引-999
、-1000
、-1001
预留用于投票紧急更新机制和更新配置和选举人合约的代码。当相应索引的提案在足够多轮次中获得足够的投票时,配置合约的代码或选举人合约的代码将被更新。
紧急更新
验证者可以投票分配一个特殊的公钥,以便在无法通过投票机制进行时能够更新配置参数。这是网络积极发展期间必要的临时措施。预计随着网络的成熟,这种措施将逐渐淘汰。一旦开发和测试完成,密钥将被转移到多签名解决方案。一旦网络证明了其稳定性,紧急机制将被完全废除。
验证者确实在2021年7月投票将该密钥分配给TON基金会(主链区块12958364
)。请注意,这样的密钥只能用来加速配置更新。它无法干预任何链上的任何合约的代码、存储和余额。
紧急更新的历史:
- 2022年4月17日,申请选举的数量增长到足以使选举在当时的gas限制下无法进行。特别是,选举需要超过1000万的gas,而区块
soft_limit
和hard_limit
被设置为10m
和20m
(配置参数22),special_gas_limit
和block_gas_limit
分别被设置为10m
和10m
(配置参数20)。这样,新的验证者无法被设置,由于达到区块gas限制,处理内部消息的交易无法包含在区块中。因此,紧急密钥被用于更新配置参数22soft_limit
至22m和hard_limit
至25m(在区块19880281
中)以及配置参数20special_gas_limit
至20m和block_gas_limit
至22m(在区块19880300
中)。结果,选举成功进行,下一个区块消耗了10 001 444
gas 。选举的总延迟约为6小时,基本链的功能未受影响。 - 2023年3月2日,申请选举的数量增长到即使
20m
也不足以进行选举。然而,这一次由于更高的hard_limit
,主链继续处理外部消息。紧急密钥被用于更新配置参数20special_gas_limit
至25m和block_gas_limit
至27m(在区块27747086
中)。结果,选举在下一个区块中成功进行。选举的总延迟约为6小时,除选举外,主链和基本链的功能未受影响。 - 2023年11月22日,密钥被用于放弃自己(在区块
34312810
中)。结果,公钥被替换为32个零字节。 - 由于切换到OpenSSL实现的Ed25519签名验证,检查特殊情况所有公钥字节都相同被禁用。因此,针对零公钥的检查按预期停止工作。利用这个问题,紧急密钥在12月9日再次更新(在区块
34665437
,交易),为 nothing-in-my-sleeve字节序列82b17caadb303d53c3286c06a6e1affc517d1bc1d3ef2e4489d18b873f5d7cd1
,这是sha256("Not a valid curve point")
。现在,更新网络配置参数的唯一方法是通过验证者共识。