omo检测冲突指令过程
0. 整体步骤
下面的内容是 simple_challenge 合约与 OMO 的交互过程,因为我们先不关注区块的构建和执行,只保留核心的二分查找冲突指令,以及 L1 仲裁的核心过程。
总体上分为三个步骤:
执行 OMO 拿到 初始状态和最终状态
OMO 配合 L1 合约找到冲突的mips指令
调用 L1 合约仲裁,判断是 challenge 还是 defender 作恶
1. 执行 OMO 得到初始状态和最终状态
OMO 将 mips elf 加载到 unicorn,但是不执行,拿到一个初始状态 (initial_state)。
OMO 将 mips elf 加载到 unicorn 并且完全执行,得到一个最终状态 和最终执行到 mips 指令的哪一步(final_state, step_count)。
L2 要依靠 L1 合约,做二分查找来帮助找到冲突指令,所以整个整个 mips elf 程序的执行开始和执行结束的状态都需要。
因为如果恰好是第二条 mips 指令,或者倒数第二条 mips 指令是冲突指令,如果没有开始和结束的内存状态,就无法依靠二分查找来找到冲突指令。
而且完整执行一遍 mips elf 程序之后,还可以在 L1 合约中判断 L2 执行 mips 指令的过程是否正确,以及内存写入的位置是否正确等校验性质的工作。
2. 找到冲突的mips指令
下面就是链下查找冲突指令的过程,不过在此之前,先介绍几个重要的 L1 合约函数:
init_challenge()
使用 initial_state 和 final_state + step_count,初始化一个challenge 。is_searching()
判断是否找到了冲突指令。step_number()
返回当前二分查找所在的步骤。propose_state()
challenger 多次调用,每次都将 L2 执行到某个 step 的 state_root 保存到 L1 合约。respond_state()
defender 多次调用,每次都将 L2 执行到某个 step 的 state_root 保存到 L1 合约,并且会对比本轮(一轮两次:challenge和defender在同样的step_number各执行一次) 双方的 state_root 是否一致,并更新二分搜索的边界。confirm_state_transition()
challenger 调用,执行step_state = mips.run(c.chanllenge_state[c.L])
,再判断stepState == c.chanllenge_state[c.R]
如果是 true,说明 challenge 获胜。因为按照二分查找法,冲突指令是c.L+1 = c.R
。deny_state_transition()
defender 调用,执行step_state = mips.run(c.defender_state[c.L])
,再判断stepState == c.defender_state[c.R]
如果是 true,说明 defender 获胜。
而在链下,需要一些列过程,调用OMO并将与 L1 交互。
下面的伪代码,是链下的过程:
challenge_id = init_challenge(initial_state, final_state, step_count)
// 找到的冲突指令
conflicted_step = 0
// 25次查找,最大支持包含 32M条指令的 mips 可执行程序
for i=0; i<25; i++ {
// 当前二分搜索的步骤
step = contract.get_step_number(challenge_id)
// 找到了冲突的指令步骤,跳出循环
if !contract.is_searching(challenge_id) {
// 冲突指令同样保存在 L1 合约中
conflicted_step = step
break
}
// 执行 omo 得到某个 step 的 内存状态
step_state = get_state_at_step(step)
// 将内存状态,保存到 L1 合约中 challenge 和 defender 保存状态的地方
if is_challenge() {
contract.propose_state(challenge_id, step_state)
} else {
contract.respond_state(challenge_id, step_state)
}
}
3. 发起链上仲裁
// 找到了冲突指令,让 L1 合约的仲裁
is_challenge_win = contract.confirm_state_transition(challenge_id)
is_defender_win = contract.deny_state_transition(challenge_id)
confirm_state_transition()
和 deny_state_transition()
这两个合约函数中,如果某一方获胜,就执行扣除 challenger 或 defender 押金的动作,作为对作恶行为的处罚。