您正在查看: Polygon 分类下的文章

cdk-data-availability之TrackSequence参数分析

https://github.com/0xPolygon/cdk-data-availability/blob/e17fe08a81dee451636cadce04e568563d992d38/sequencer/tracker.go#L84-L113

// Start starts the SequencerTracker
func (st *Tracker) Start(parentCtx context.Context) {
    st.startOnce.Do(func() {
        ctx, cancel := context.WithTimeout(parentCtx, st.timeout)
        defer cancel()

        addr, err := st.em.TrustedSequencer(ctx)
        if err != nil {
            log.Fatalf("failed to get sequencer addr: %v", err)
            return
        }

        log.Infof("current sequencer addr: %s", addr.Hex())
        st.setAddr(addr)

        url, err := st.em.TrustedSequencerURL(ctx)
        if err != nil {
            log.Fatalf("failed to get sequencer addr: %v", err)
            return
        }

        log.Infof("current sequencer url: %s", url)
        st.setUrl(url)

        if st.trackChanges {
            log.Info("sequencer tracking enabled")

            go st.trackAddrChanges(parentCtx)
            go st.trackUrlChanges(parentCtx)
        }
    })
}

分析

当TrackSequence设置为true时,会在TrackSequencerPollInterval间隔内,检查L1合约内的TrustedSequencer地址和URL是否有变更,并更新本地

场景

因为TrustedSequencer地址和URL变更频率很低,默认情况下TrackSequence可以设置为false,对比变更比较频繁的场景,可以将TrackSequence改为true
注:当cdk-data-availability服务重启时,会自动对齐配置

使用Kurtosis快速验证Polygon CDK新版本

前置介绍

官方部署:https://docs.polygon.technology/cdk/getting-started/local-deployment/
Polygon CDK Kurtosis 包允许您轻松自定义和实例化 CDK 链的所有组件。它使用Kurtosis工具来协调 Docker 容器中链组件的设置,并使用Starlark脚本(一种 Python 方言)中定义的逻辑来定义设置链的分步过程。

Polygon CDK Kurtosis Package

https://github.com/0xPolygon/kurtosis-cdk
通过kurtosis{用于打包和启动临时后端堆栈的平台},通过Docker和k8s 部署私有、可移植、模块化的Polygon CDK开发网络

软件包将部署:

  1. 本地 L1 链,使用ethereum-package ,完全可定制并支持多客户端。
  2. 本地 L2 链,使用Polygon Chain 开发套件(CDK),具有可定制的组件,例如序列器、序列发送器、聚合器、rpc、证明器、dac 等。它将首先在 L1 链上部署Polygon zkEVM 智能合约,然后再部署不同的组件。
  3. zkEVM桥接基础设施,促进 L1 和 L2 链之间的资产桥接,反之亦然。
  4. Agglayer一种正在开发中的互操作性协议,它允许进行无需信任的跨链代币传输和消息传递,以及 L2 链之间的更复杂操作,并由 zk 证明保护。
  5. 附加服务,如交易垃圾邮件发送者、监控工具、无需权限的节点等。

模块版本对应关系

Fork ID CDK Erigon ZkEVM Prover ZkEVM Contracts Data Availability Bridge
13 v2.60.0-beta4 v9.0.0-RC1-fork.13 v8.1.0-rc.1-fork.13 0.0.10 v0.6.0-RC1
12 v2.1.2 v8.0.0-RC14-fork.12 v8.0.0-rc.4-fork.12 0.0.10 v0.6.0-RC1
11 v2.1.2 v7.0.4-fork.11 v7.0.0-rc.2-fork.11 0.0.10 v0.6.0-RC1
9 v2.1.2 v6.0.8 v6.0.0-rc.1-fork.9 0.0.10 v0.6.0-RC1

当前测试时,默认测试 fork12

部署测试

Kurtosis部署

环境准备

  • Docker
  • Kurtosis
    • echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list
      sudo apt update
      sudo apt install kurtosis-cli
  • jq
  • yq (v3)
  • cast
    • curl -L https://foundry.paradigm.xyz | bash
      source ~/.bashrc
      foundryup
  • polycli
    • git clone https://github.com/0xPolygon/polygon-cli.git
      make install
      export PATH="$HOME/go/bin:$PATH"

部署

git clone https://github.com/0xPolygon/kurtosis-cdk.git
sudo su
kurtosis clean --all
ulimit -n 1000000
kurtosis run --enclave cdk .

默认部署包括cdk-erigon作为序列器,以及cdk-node作为序列发送器和聚合器。您可以通过查看 input_parser.star 来验证这些组件的默认版本和默认 fork ID。您可以通过查看input_parser.star来检查已部署组件的默认版本和默认 fork ID
当前cdk-erigon为v2.1.2版本,对应fork ID 12

查看网络布局

kurtosis enclave inspect cdk

L2 RPC 测试调用

export ETH_RPC_URL="$(kurtosis port print cdk cdk-erigon-rpc-001 rpc)"
cast block-number

默认情况下,CDK 处于test模式配置,这意味着地址为 的管理员账户中有一些预先存入的价值

cast balance --ether 0xE34aaF64b29273B7D567FCFc40544c014EEe9970

测试交易

private_key="0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"
cast send --legacy --private-key "$private_key" --value 0.01ether 0x0000000000000000000000000000000000000000
blockHash               0xec514afabfa829f1b4e9339fd72e31fb2a1888a18046fe21743fe38b55bd24c3
blockNumber             45
contractAddress         
cumulativeGasUsed       21000
effectiveGasPrice       1000000000
from                    0xE34aaF64b29273B7D567FCFc40544c014EEe9970
gasUsed                 21000
logs                    []
logsBloom               0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root                    
status                  1 (success)
transactionHash         0xa58b3383c1b1f53369723fdc537c88daa03585cb6a89aa49ebd493953d519fdf
transactionIndex        0
type                    0
blobGasPrice            
blobGasUsed             
authorizationList       
to                      0x0000000000000000000000000000000000000000

批量交易,需要安装polygon-cli

polycli loadtest --rpc-url "$ETH_RPC_URL" --legacy --private-key "$private_key" --verbosity 700 --requests 50000 --rate-limit 50 --concurrency 5 --mode t
polycli loadtest --rpc-url "$ETH_RPC_URL" --legacy --private-key "$private_key" --verbosity 700 --requests 500 --rate-limit 10 --mode 2
polycli loadtest --rpc-url "$ETH_RPC_URL" --legacy --private-key "$private_key" --verbosity 700 --requests 500 --rate-limit 3  --mode uniswapv3

获取输出日志

kurtosis service logs cdk agglayer --follow

排查错误

kurtosis service shell cdk contracts-001
jq . /opt/zkevm/combined.json

检查系统状态

cast rpc zkevm_batchNumber
cast rpc zkevm_virtualBatchNumber
cast rpc zkevm_verifiedBatchNumber

如果验证批次的数量不断增加,则表明系统运行正常

访问zkevm-bridge用户界面

open "$(kurtosis port print cdk zkevm-bridge-proxy-001 web-ui)"

查看cdk-erigon-rpc-001日志

kurtosis service logs cdk cdk-erigon-rpc-001 --follow

停止本地开发网络并将其删除

kurtosis clean --all

ZK-COUNTERS TABLE

ZK-COUNTERS TABLE

opcode name cnt_arith cnt_binary cnt_mem_align cnt_keccak_f cnt_padding_pg cnt_poseidon_g is_dynamic
0x00 STOP 0 0 0 0 0 0 false
0x01 ADD 0 1 0 0 0 0 false
0x02 MUL 1 0 0 0 0 0 false
0x03 SUB 0 1 0 0 0 0 false
0x04 DIV 1 2 0 0 0 0 false
0x05 SDIV 1 8 0 0 0 0 false
0x06 MOD 1 2 0 0 0 0 false
0x07 SMOD 1 8 0 0 0 0 false
0x08 ADDMOD 1 3 0 0 0 0 false
0x09 MULMOD 2 2 0 0 0 0 false
0x0a EXP 512 1025 0 0 0 0 true
0x0b SIGNEXTEND 0 6 0 0 0 0 false
0x10 LT 0 1 0 0 0 0 false
0x11 GT 0 1 0 0 0 0 false
0x12 SLT 0 1 0 0 0 0 false
0x13 SGT 0 1 0 0 0 0 false
0x14 EQ 0 1 0 0 0 0 false
0x15 ISZERO 0 1 0 0 0 0 false
0x16 AND 0 1 0 0 0 0 false
0x17 OR 0 1 0 0 0 0 false
0x18 XOR 0 1 0 0 0 0 false
0x19 NOT 0 1 0 0 0 0 false
0x1a BYTE 2 4 0 0 0 0 false
0x1b SHL 1 2 0 0 0 0 false
0x1c SHR 1 3 0 0 0 0 false
0x1d SAR 2 10 0 0 0 0 false
0x20 SHA3 192 193 2 2 0 10 true
0x30 ADDRESS 0 0 0 0 0 0 false
0x31 BALANCE 0 0 0 0 0 9 false
0x32 ORIGIN 0 0 0 0 0 0 false
0x33 CALLER 0 0 0 0 0 0 false
0x34 CALLVALUE 0 0 0 0 0 0 false
0x35 CALLDATALOAD 64 66 0 0 0 0 true
0x36 CALLDATASIZE 0 0 0 0 0 0 false
0x37 CALLDATACOPY - - - 0 0 0 true
0x38 CODESIZE 0 0 0 0 0 252 true
0x39 CODECOPY 0 - - 0 0 255 true
0x3a GASPRICE 0 0 0 0 0 0 false
0x3b EXTCODESIZE 0 0 0 0 0 255 true
0x3c EXTCODECOPY 0 - - 0 11 510 true
0x3d RETURNDATASIZE 0 1 0 0 0 0 false
0x3e RETURNDATACOPY - - 2 0 0 0 true
0x3f EXTCODEHASH 0 0 0 0 0 255 true
0x40 BLOCKHASH 0 0 0 1 0 9 false
0x41 COINBASE 0 0 0 0 0 0 false
0x42 TIMESTAMP 0 0 0 0 0 0 false
0x43 NUMBER 0 0 0 0 0 0 false
0x44 DIFFICULTY 0 0 0 0 0 0 false
0x45 GASLIMIT 0 0 0 0 0 0 false
0x46 CHAINID 0 0 0 0 0 0 false
0x47 SELFBALANCE 0 0 0 0 0 255 true
0x50 POP 0 0 0 0 0 0 false
0x51 MLOAD 32 32 1 0 0 255 true
0x52 MSTORE 32 32 1 0 0 255 true
0x53 MSTORE8 32 1 1 0 0 255 false
0x54 SLOAD 0 0 0 0 0 255 true
0x55 SSTORE 0 - 0 0 0 255 true
0x56 JUMP 0 - 0 0 0 0 true
0x57 JUMPI 0 - 0 0 0 0 true
0x59 MSIZE 1 3 0 0 0 0 false
0x5a GAS 0 0 0 0 0 0 false
0x5b JUMPDEST 0 0 0 0 0 0 false
0x60 PUSH1 0 3 0 0 0 0 true
0x61 PUSH2 0 4 0 0 0 0 true
0x62 PUSH3 0 5 0 0 0 0 false
0x63 PUSH4 0 2 0 0 0 0 false
0x64 PUSH5 0 4 0 0 0 0 false
0x65 PUSH6 0 5 0 0 0 0 false
0x66 PUSH7 0 6 0 0 0 0 false
0x67 PUSH8 0 3 0 0 0 0 false
0x68 PUSH9 0 5 0 0 0 0 false
0x69 PUSH10 0 6 0 0 0 0 false
0x6a PUSH11 0 7 0 0 0 0 false
0x6b PUSH12 0 4 0 0 0 0 false
0x6c PUSH13 0 6 0 0 0 0 false
0x6d PUSH14 0 7 0 0 0 0 false
0x6e PUSH15 0 8 0 0 0 0 false
0x6f PUSH16 0 5 0 0 0 0 false
0x70 PUSH17 0 7 0 0 0 0 false
0x71 PUSH18 0 8 0 0 0 0 false
0x72 PUSH19 0 9 0 0 0 0 false
0x73 PUSH20 0 6 0 0 0 0 false
0x74 PUSH21 0 8 0 0 0 0 false
0x75 PUSH22 0 9 0 0 0 0 false
0x76 PUSH23 0 10 0 0 0 0 false
0x77 PUSH24 0 7 0 0 0 0 false
0x78 PUSH25 0 9 0 0 0 0 false
0x79 PUSH26 0 10 0 0 0 0 false
0x7a PUSH27 0 11 0 0 0 0 false
0x7b PUSH28 0 8 0 0 0 0 false
0x7c PUSH29 0 10 0 0 0 0 false
0x7d PUSH30 0 11 0 0 0 0 false
0x7e PUSH31 0 12 0 0 0 0 false
0x7f PUSH32 0 9 0 0 0 0 false
0x80 DUP1 0 0 0 0 0 0 false
0x81 DUP2 0 0 0 0 0 0 false
0x82 DUP3 0 0 0 0 0 0 false
0x83 DUP4 0 0 0 0 0 0 false
0x84 DUP5 0 0 0 0 0 0 false
0x85 DUP6 0 0 0 0 0 0 false
0x86 DUP7 0 0 0 0 0 0 false
0x87 DUP8 0 0 0 0 0 0 false
0x88 DUP9 0 0 0 0 0 0 false
0x90 SWAP1 0 0 0 0 0 0 false
0x91 SWAP2 0 0 0 0 0 0 false
0x92 SWAP3 0 0 0 0 0 0 false
0x93 SWAP4 0 0 0 0 0 0 false
0x94 SWAP5 0 0 0 0 0 0 false
0x95 SWAP6 0 0 0 0 0 0 false
0x96 SWAP7 0 0 0 0 0 0 false
0xa0 LOG0 0 - 0 0 0 0 true
0xa1 LOG1 0 - 0 0 0 0 true
0xa2 LOG2 0 - 0 0 0 0 true
0xa3 LOG3 0 - 0 0 0 0 true
0xa4 LOG4 0 - 0 0 0 0 true
0xf0 CREATE - - 0 - 0 - true
0xf1 CALL - - 0 0 - - true
0xf2 CALLCODE - - 0 0 - - true
0xf3 RETURN 0 0 0 0 0 0 false
0xf4 DELEGATECALL - - 0 0 - - true
0xf5 CREATE2 - - 0 - 0 - true
0xfa STATICCALL - - 0 0 - - true
0xfd REVERT 0 0 0 0 0 0 false
0xfe INVALID 0 1 0 0 0 0 false

Dynamic zk-counters

In the following doc, we calculate the cost of processing the opcode. It's important to also add the cost of calculating the cost

EXP

Inputs:
1- a: integer base.
2- exponent: integer exponent.

dynamic_gas = 50 * exponent_byte_size
We need to calculate the exponent byte size to get the gas cost. The counters cost is dynamic but we can't calculate the cost without consuming counters in a dynamic way. We need to find a way to get the size of the exponent in a constant manner or handle the counters limitations from the zkasm.
Maximum setted: Maxmimun byte syze = 256 bytes. Max counters = 256 * (2A + 4B) + 1B = 512A + 1025B

SHA3

L = input length
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0

cnt_arith = 2 + B6
cnt_binary = 2 + A + B
9
cnt_keccak = 1

CALLDATALOAD

L = byte offset in the calldata.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0

counters = divARITH + B*(SHLarith + SHRarith)

CALLDATACOPY

L = Length to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0

counters = A(divARITH + SHLarith + SHRarith + MSTORE32) + SHLarith2 + SHRarith + MSTOREX

CODESIZE

counters = SLOAD

CODECOPY

L = bytes to copy.
if is createContract -> counters = CALLDATACOPY
else -> counters = LT + L*(LT + MEM_ALIGN_WR8)

EXTCODESIZE

counters = SLOAD

EXTCODECOPY

L = bytes to copy.
if is createContract -> counters = CALLDATACOPY
else -> counters = LT + L*(LT + MEM_ALIGN_WR8)

RETURNDATACOPY

L = Length to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = 2EQ + LT + divARITH + mulARITH + A(MLOAD32 + MSTORE32) + B*(MLOADX + MSTOREX)

EXTCODEHASH

counters = SLOAD

SELFBALANCE

counters = SLOAD

MLOAD

counters = MLOAD32

MSTORE

counters = MSTORE32

SLOAD

counters = SLOAD

SSTORE

Cant calculate

JUMPI

isCreateContract ? true -> A = 1, false -> A = 0
isCreate ? true -> B = 1, false -> B = 0

counters = EQ + A(B(MLOADX + SHRarith) + (1-B)(EQ)) + (1-A)(EQ)

JUMP

isCreateContract ? true -> A = 1, false -> A = 0
isCreate ? true -> B = 1, false -> B = 0

counters = EQ + A(B(MLOADX + SHRarith) + (1-B)(EQ)) + (1-A)(EQ)

LOG

L = byte size to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = AMLOAD32 + BMLOADX

CREATE

counters = computeGasSendCall + copySP + SLOAD + SSTORE + getLenBytes

CALL

argsLengthCall + retLength == 0 ? true -> A = 1, false -> A = 0
argsOffsetCall > memLength ? true -> B = 1, false -> B = 0
counters = addARITH + EQ + (1-A)(LT +BsaveMem ) + LT + isEmptyAccount + computeGasSendCall + copySP

CALLCODE

counters = 2EQ + LT2 + computeGasSendCall + copySP

DELEGATECALL

counters = 2EQ + LT2 + computeGasSendCall + copySP

CREATE2

counters = computeGasSendCall + copySP + SLOAD + SSTORE + getLenBytes

STATICCALL

counters = 2EQ + LT2 + computeGasSendCall + copySP

REGS TABLE

REG Name cnt_arith cnt_binary cnt_mem_align cnt_keccak_f cnt_padding_pg cnt_poseidon_g is_dynamic
LT 0 1 0 0 0 0 false
EQ 0 1 0 0 0 0 false
ARITH 1 0 0 0 0 0 false
SLOAD 0 0 0 0 0 11 true
SSTORE 0 0 0 0 0 11 true
MEM_ALIGN_WR8 0 0 1 0 0 0 false

Dynamic regs

SSTORE

SLOAD

Should check how SLOAD is implemented

Functions TABLE

FUNC Name cnt_arith cnt_binary cnt_mem_align cnt_keccak_f cnt_padding_pg cnt_poseidon_g is_dynamic
addARITH 0 1 0 0 0 0 false
divARITH 1 2 0 0 0 0 false
subARITH 0 1 0 0 0 0 false
mulARITH 1 0 0 0 0 0 false
saveMem 0 0 0 0 0 0 false
computeGasSendCall 0 1 0 0 0 0 false
copySP - - 0 0 0 0 true
MLOAD32 0 0 0 0 0 0 true
MLOADX 0 0 0 0 0 0 true
MSTORE32 0 0 0 0 0 0 true
MSTOREX 0 0 0 0 0 0 true
sliceA 0 0 0 0 0 0 false
SHRarith - - 0 0 0 0 true
SHLarith - - 0 0 0 0 true
opCODECOPYLoadBytes 0 1 0 0 0 0 false
isEmptyAccount - - 0 0 0 0 true

Dynamic functions

copySP

It depends on the stack size.
L = stack length
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = MLOAD32 * (A + B)

MLOAD32

MSTORE32

MSTOREX

MLOADX

L = bytes length
L > 0 ? true -> A = 1, false -> A = 0
isMSTOREX ? true -> B = 1, false -> B = 0
counters = LT + B(2SHRarith + 2SHLarith) + (1-B)(C(2SHLarith + 4SHRarith) + (1-C)(2SHRarith + 2SHLarith) + MEM_ALIGN_WR)
MAX:
counters = 192A + 193B + 2MA

SHRarith

SHLarith

A -> bytes to shift
D -> times to shift (A << D)
E -> D > 256? true = 1, false = 0
counters= ARITH + EQ + (1-E) (D(LT + ARITH)) = 1A + 1B + (1-E)(D(1A + 1B)
MAX:
counters = 32A + 32B

isEmptyAccount

isNotPrecompiled ? true -> A = 1, false -> A = 0
zeroBalance ? true -> B = 1, false -> B = 0
zeroNonce ? true -> C = 1, false -> C = 0

counters = LT + A(SLOAD + LT + B(SLOAD + LT + C*(SLOAD + LT)))

https://github.com/0xPolygonHermez/zkevm-rom/blob/main/docs/opcode-cost-zk-counters.md

Polygon zkEvm链区块不可逆判断

区块会经过两个步骤
eth_blockNumber->zkevm_isBlockVirtualized->zkevm_isBlockConsolidated

zkevm_isBlockVirtualized 到达该阶段说明数据已提交到L1层,当到达后,出现不一致概率极低,比如版本升级异常等,才会出现数据不一致
zkevm_isBlockConsolidated zkp 证明已生成,不会再发生数据不一致

每个阶段具体时间隔间,要看具体节点配置,比如当前测试环境
zkevm_isBlockVirtualized:15s
zkevm_isBlockConsolidated:10-20分 (算力充足情况下)

查询RPC
https://www.quicknode.com/docs/polygon-zkevm/zkevm_isBlockVirtualized
https://www.quicknode.com/docs/polygon-zkevm/zkevm_isBlockConsolidated