function initializeChallenge( IOneStepProof[] calldata _executors, address _resultReceiver, bytes32 _executionHash, uint256 _maxMessageCount, address _asserter, address _challenger, uint256 _asserterTimeLeft, uint256 _challengerTimeLeft, IBridge _bridge ) external override { ... asserter = _asserter; challenger = _challenger; ... turn = Turn.Challenger; challengeState = _executionHash; ... } initializeChallenge确定挑战者和应战者,并确定需要挑战的状态(存储在challengeState)。challengeState是由一个和多个bisectionChunk状态hash组成的merkle树树根: 整个执行过程可以分割成多个小过程,每个小过程(bisection)由起始和结束的gas和状态来表示。 turn用来记录交互顺序。turn = Turn.Challenger表明在初始化挑战后,首先由Challenger发起分歧点分割。 ![]() bisectExecution bisectExecution挑选之前分割片段,并如可能将片段进行再次分割: bisectExecution的函数定义如下: function bisectExecution( bytes32[] calldata _merkleNodes, uint256 _merkleRoute, uint256 _challengedSegmentStart, uint256 _challengedSegmentLength, bytes32 _oldEndHash, uint256 _gasUsedBefore, bytes32 _assertionRest, bytes32[] calldata _chainHashes ) external onlyOnTurn { _chainHashes是再次分割点的状态。如果需要再次分割,需要满足分割点的个数规定: uint256 private constant EXECUTION_BISECTION_DEGREE = 400; require( _chainHashes.length == bisectionDegree(_challengedSegmentLength, EXECUTION_BISECTION_DEGREE) + 1, “CUT_COUNT” ); 简单的说,每次分割,必须分割成400份。 _oldEndHash是用来验证状态这次分割的分割片段是上一次分割中的某个。需要检查分割的有效性: require(_chainHashes[_chainHashes.length - 1] != _oldEndHash, “SAME_END”); require( _chainHashes[0] == ChallengeLib.assertionHash(_gasUsedBefore, _assertionRest), “segment pre-fields” ); require(_chainHashes[0] != UNREACHABLE_ASSERTION, “UNREACHABLE_START”); require( _gasUsedBefore < _challengedSegmentStart.add(_challengedSegmentLength), “invalid segment length” ); 起始状态正确。这次分割不能超出上次分割范围,并且最后一个状态和上一个分割的结束状态不一样。 bytes32 bisectionHash = (责任编辑:admin) |