• 周四. 12月 1st, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

L2 – deep understanding of arbitrum

[db:作者]

1月 6, 2022

Arbitrum yes Layer2 Rollup A scheme of . and Optimism similar , The finality of State adopts “ Challenge ”(challenge) Mechanism to ensure .Optimism The challenge is to put a deal entirely in Layer1 Simulation execution , Judge whether the status of the transaction after execution is correct . This method needs to be in Layer1 simulation EVM Execution environment , Relatively complex .Arbitrum The challenge is relatively light , stay Layer1 Perform an operation (AVM), Determine if the operation is performed correctly .Arbitrum The introduction document mentions , The whole challenge needs to be about 500 Bytes of data and 9w Left and right gas. For this lightweight challenge mechanism ,Arbitrum Realized AVM virtual machine , And in AVM In the virtual machine EVM Implementation .AVM The advantage of virtual machine is that the underlying structure is convenient for state proving .

Arbitrum The developer documentation for Arbitrum Architecture and Design . Yes AVM as well as L1/L2 Small partners who are interested in interaction details can patiently check “Inside Arbitrum” chapter :

https://developer.offchainlabs.com/docs/developer_quickstart

The overall framework

Arbitrum The developer’s document gives the relationship of each module :

Arbitrum The system consists of three parts ( The right part of the picture , From bottom to top ):EthBridge,AVM Execution environment and ArbOS.EthBridge Mainly achieved inbox/outbox Management, and Rollup agreement .EthBridge Realize in Layer1.ArbOS stay AVM On a virtual machine EVM. To put it simply ,Arbitrum stay Layer2 Realized AVM virtual machine , Simulate again on a virtual machine EVM execution environment . use AVM Simulate again EVM The reason is that AVM It’s better to express , Easy Layer1 Challenge .

EthBridge and AVM Source code corresponding to execution environment :

https://github.com/OffchainLabs/arbitrum.git

ArbOS Corresponding source code :

https://github.com/OffchainLabs/arb-os.git

This module diagram is too general , Let’s break it down a little bit :

EthBridge It mainly realizes three functions :inbox,outbox as well as Rollup agreement .inbox in “ Deposit ” Transaction information , The trading information will “ Sync ” To ArbOS And implement .outbox in “ Deposit ” from L2 To L1 Transactions , Mainly withdrawl transaction .Rollup The agreement is mainly L2 State preservation and challenges . Special note ,Arbitrum All transactions are submitted to L1, Until then ArbOS perform .ArbOS In addition to some external interfaces , Mainly achieved EVM Simulator . The whole simulator is implemented in AVM above . Whole EVM The simulator uses mini Language implementation ,Arbitrum Realized AVM Upper mini Language compiler . To put it simply ,Arbitrum New hardware is defined (machine) And instruction set , And realized a kind of upper language mini. adopt mini Language ,Arbitrum Realized EVM Simulator , The corresponding transaction can be executed .

AVM State

Because all the deals are in AVM perform , The execution status of the transaction can be used AVM State means .AVM The implementation code is in arbitrum/packages/arb-avm-cpp in .

AVM The status of the PC,Stack,Register And so on .AVM The state of is the state of hash The value of the stitched hash result .

AVM Use c++ Realization ,AVM The logic of representation is implemented in MachineStateKeys Class machineHash function (machinestate.cpp) in .AVM What’s special about it is that in addition to execution , It can also be more convenient to express ( prove ) Execution status . In depth understanding of AVM The basic data structure ,AVM The basic data types of include :

using value = std::variant<Tuple, uint256_t, CodePointStub, HashPreImage, Buffer>; enum ValueTypes { NUM, CODEPT, HASH_PRE_IMAGE, TUPLE, BUFFER = 12, CODE_POINT_STUB = 13 };
  • uint256_t – Integer types
  • CodePoint – The current code instruction represents
  • Tuple – Tuples , from 8 individual Value form . An element in a tuple can still be a tuple
  • Buffer – Array , The longest is 2^64
  • HashPreImage – fixed hash type ,hashValue = hash(value, prevHashValue)

For each data type, in addition to data representation , And it’s very convenient to calculate hash Value as state . Take a closer look CodePoint and Tuple Basic data type .

CodePoint

CodePoint Type will have multiple operations “ binding ” together , Every CodePoint In addition to recording the current Operation Outside , Including the previous one CodePoint Of hash Information . So all of Operation It can be concatenated , Current CodePoint In addition to expressing the current Operation Outside , It’s also clear that Operation Dependency of .CodePoint Is defined in :packages/arb-avm-cpp/avm_values/include/avm_values/codepoint.hpp.

struct CodePoint { Operation op; uint256_t nextHash; CodePoint(Operation op_, uint256_t nextHash_) : op(op_), nextHash(nextHash_) {} bool isError() const { return nextHash == 0 && op == Operation{static_cast<OpCode>(0)}; } };

Tuple

Tuple Type by RawTuple Realization .RawTuple It’s a group. value form .Tuple The limit is at most 8 individual value.

struct RawTuple { HashPreImage cachedPreImage; std::vector<value> data; bool deferredHashing = true; RawTuple() : cachedPreImage({}, 0), deferredHashing(true) {} };

Tuple Is defined in :packages/arb-avm-cpp/avm_values/include/avm_values/tuple.hpp.

On the basis of understanding the basic types ,DataStack It can be made up of a series of Tuple Realization :

To sum up ,AVM Medium PC,Stack,Register And so on hash The result shows .AVM The whole state is made up of these hash Value of the stitching data of hash Express .

Rollup Challenge

In submission to L1 When there are differences in the state of , Challenge both sides (Asserter and Challenger) First, split the State , find “ The difference is ”. Once the differences are clear , Both sides of the challenge can provide an implementation environment ,L1 Perform actions to determine if the previously submitted status is correct .L1 The challenge handling logic is implemented in arb-bridge-eth/contracts/challenge/Challenge.sol. The whole challenge mechanism is guaranteed by a time-out mechanism , To highlight the core process , The simplified process is shown in the figure below :

Challenger through initializeChallenge Function challenges . Next, the Challenger (Challenger) And the Challenger (Asserter) adopt bisectExecution Make sure that it’s indivisible “ The difference is ”. After determining the point of divergence , Challenger through oneStepProveExecution The function determines Assert Whether the status of the previous submission is correct .

  • initializeChallenge
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 Identify challengers and challengers , And determine the state of the challenge ( Stored in challengeState).challengeState It’s made up of one and more bisectionChunk state hash Composed of merkle Tree root :

The whole execution process can be divided into several small processes , Every little process (bisection) From the beginning to the end gas And state .

turn Used to record the order of interaction .turn = Turn.Challenger Indicates that after initializing the challenge , First of all Challenger Initiate a breakup .

  • bisectExecution

    bisectExecution Segment before selecting , And if possible, segment it again :

    bisectExecution The function of is defined as follows :

function bisectExecution( bytes32[] calldata _merkleNodes, uint256 _merkleRoute, uint256 _challengedSegmentStart, uint256 _challengedSegmentLength, bytes32 _oldEndHash, uint256 _gasUsedBefore, bytes32 _assertionRest, bytes32[] calldata _chainHashes ) external onlyOnTurn {

_chainHashes It’s the state of the split point again . If it needs to be split again , It needs to meet the number of segmentation points :

uint256 private constant EXECUTION_BISECTION_DEGREE = 400; require( _chainHashes.length == bisectionDegree(_challengedSegmentLength, EXECUTION_BISECTION_DEGREE) + 1, "CUT_COUNT" );

To put it simply , Every time you split , It has to be divided into 400 Share .

_oldEndHash It is used to verify the state. The segmentation segment of this segmentation is one of the previous segmentation . You need to check the validity of the segmentation :

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" );

The starting state is correct . This partition can’t go beyond the last one , And the last state is different from the end state of the previous partition .

bytes32 bisectionHash = ChallengeLib.bisectionChunkHash( _challengedSegmentStart, _challengedSegmentLength, _chainHashes[0], _oldEndHash ); verifySegmentProof(bisectionHash, _merkleNodes, _merkleRoute);

adopt merkle The path check of the tree determines that the start and end states are the last partition .

updateBisectionRoot(_chainHashes, _challengedSegmentStart, _challengedSegmentLength);

Update the corresponding challengeState.

  • oneStepProveExecution

    When it can’t be divided , Challengers provide the initial state ( prove ), And by the L1 Make the corresponding calculation . The result of the calculation should be the same as that provided _oldEndHash atypism . The inconsistency means that the Challenger succeeded in proving that the previous calculation was wrong .

(uint64 gasUsed, uint256 totalMessagesRead, bytes32[4] memory proofFields) = executors[prover].executeStep( bridge, _initialMessagesRead, [_initialSendAcc, _initialLogAcc], _executionProof, _bufferProof );

adopt executeStep Calculate the correct end state .executeStep Realize in packages/arb-bridge-eth/contracts/arch/OneStepProofCommon.sol in . The core is executeOp function , For the moment context Read op, Execute and update status . Interested partners can check by themselves .

rootHash = ChallengeLib.bisectionChunkHash( _challengedSegmentStart, _challengedSegmentLength, oneStepProofExecutionBefore( _initialMessagesRead, _initialSendAcc, _initialLogAcc, _initialState, proofFields ), _oldEndHash ); } verifySegmentProof(rootHash, _merkleNodes, _merkleRoute);

Make sure that the initial state and the end state are some segments of the last challenge state . The initial state is proved by (proof) Obtained by calculation .

require( _oldEndHash != oneStepProofExecutionAfter( _initialSendAcc, _initialLogAcc, _initialState, gasUsed, totalMessagesRead, proofFields ), "WRONG_END" );

confirm _oldEndHash It’s not the same as calculating the end state . The difference indicates that the end status of the previous submission is wrong .

_currentWin();

After calculation , Determine the winner .

summary :

Arbitrum yes Layer2 Rollup A scheme of . Use the challenge mechanism to determine Rollup The finality of state . In order to introduce a light challenge mechanism ,Arbitrum Defined AVM, A virtual machine that can easily prove the execution state , And designed mini Languages and compilers . stay AVM It’s simulated on the Internet EVM Execution environment , compatible EVM. The challenge will be to carry out the process 400 Divide , from L1 Execute a small number of instructions to determine if the state is correct .

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注