Polygon zkEVM Spearbit审计报告解读(2022年12月版本)

1. 引言

前序博客:

  • Polygon zkEVM Hexens审计报告解读(2022年12月至2023年2月版本)

主要见:

  • Polygon zkEVM Security Review: December 2022 Engagement

Polygon zkEVM为提供(opcode层面兼容的)EVM等价zk-rollup,具有良好的用户体验并兼容现有以太坊生态和工具。

主要关注:

  • 1)检查Ethereum state tests和evm-benchmarks测试覆盖率。
  • 2)手工和工具辅助review一些(PIL)状态机。为辅助审计,开发了PIL状态机的形式化分析工具:
    • https://github.com/Schaeff/pilspector(Rust)
  • 3)手工review EVM指令的zkASM实现。

Spearbit研究人员分为2组:

  • 1)一组专注于状态机和PIL。
  • 2)另一组专注于指令实现和测试评估。

经过10天(共12人周)的培训,Spearbit在(2022年12月5日至2022年12月16日)审计周期中,共发现了32个问题,其中致命漏洞7个,高风险漏洞1个,中等风险漏洞1个,不兼容漏洞1个,信息提示类22个,当前已解决了其中的27个问题。
在这里插入图片描述
在本审计报告中,风险分级为:

风险级别影响:高影响:中等影响:低
可能性:高致命中等
可能性:中等中等
可能性:低中等

其中:

  • 1)影响:
    • 高:会导致丢失协议中 > 10 % >10\% >10%资产,或对大多数用户有重大危害。
    • 中等:丢失 < 10 % <10\% <10%资产,或仅丢失一部分用户的资产,但仍不可接受。
    • 低:丢失很烦人但可接收。适用于可以很容易修复的网格攻击,甚至是gas不足。
  • 2)概率:
    • 高:几乎确定会发生,易于操作,或不易于操作但激励诱人。
    • 中等:仅有可行性可能或动机,但相对有可能发生。
    • 低:需要stars to align,或者几乎没有动机。
  • 3)风险级别:
    • 致命:(若已部署)必须尽快修复。
    • 高:(若未部署),需在部署前修复。
    • 中等:应该修复。
    • 低:可修复。

1.1 测试

本轮review重点关注:

  • zkevm-testvectors#v0.5.1.0。

除外的测试用例列表长度约为2200个entries,可分为如下类别:

  • 预编译测试
  • 交易测试(EIP-2930访问列表相关)
  • selfdestruct测试
  • 应使用 > 30 M >30M >30Mgas、OOC(out of counters)或资源耗尽,而失败的测试。

已研究了一些预编译测试,因为有些支持的预编译(如ecrecover)失败,原因在于其结合了多个预编译(通常是sha256)。实际并不对这些测试做调整。

当前专注于研究因资源限制,且与EVM指定相关限制导致失败的测试用例。其中包括MemoryTests、VMTests、StackTests,但因时间有限,未覆盖每个测试用例。

1.2 zkASM

本轮review重点关注:

  • zkevm-rom#v0.5.2.0

该ROM中包含如下内容:

  • ecrecover
  • opcodes
  • precompiles
  • utilities
  • transaction processing

因时间有限,重点关注:

  • 交易验证
  • flow-control.zkasm中的:
    • 跳转
    • 专注于Keccak-256的CREATE2
  • comparison.zkasm中的:LT、GT、SLT、SGT、EQ、ISZERO、AND、OR、XOR、NOT、BYTE、SHR、SHL、SAR。
  • stak-operations.zkasm中的:DUPx、SWAPx、POP、PUSH。
  • utils.zkasm中:被以上组件使用的utilities。

1.3 PIL状态机

本轮review重点关注:

  • zkevm-proverjs#cc474493
  • zkevm-proverjs#ee7f7862

以PIL编写的所有zkEVM状态机有:

  • arith状态机,部分覆盖(除曲线方程式正确性之外的所有)
  • binary状态机,完全覆盖
  • mem状态机,完全覆盖
  • mem_align状态机,完全覆盖
  • keccakf状态机,部分覆盖
  • padding_kk状态机,部分覆盖
  • padding_kkbit状态机,部分覆盖
  • nine2one状态机,完全覆盖
  • padding_pg状态机,部分覆盖
  • poseidon状态机,部分覆盖
  • main/rom状态机,部分覆盖
  • global状态机,完全覆盖
  • storage状态机,未覆盖

为辅助审计,开发了PIL状态机的形式化分析工具:

  • https://github.com/Schaeff/pilspector(Rust)

该PoC工具可做:

  • 静态分析
  • 非确定性检查
  • PIL状态机正确性证明

1.3.1 arith.pil形式化分析

arith.pil状态机,形式化为,所有多项式以整数值表示。只要所有值和所有算术运算均在所用域内,则该形式化表示是正确的。
arith.pil状态机,展开为32行,初始行号为0,证明了其如下属性:

  • 第0行中的Arith.x1值,总是与第31行的值相同。可通过arith_check_x1_constant_accross_window.smt2 来证明。
  • 若选中equation 0且在第一行,则设置了如下变量:
    Arith.y1=1
    Arith.y2=0
    Arith.x2=0
    Arith.x1=0
    Arith.y3=10
    然后,第一行中的Arith.x1必须等于10。可通过arith_eq0_b1_c0_d0_e10_implies_a10.smt2 来证明。

1.3.2 mem.pil形式化分析

1.3.2.1 mem.pil中read形式化分析

mem.pil状态机内,read,表示为 m O p ′ = 1 ∧ m W r ′ = 0 mOp'=1\land mWr'=0 mOp=1mWr=0,输出值 v a l i ′ , i ∈ [ 0 , 7 ] val_i',i\in[0,7] vali,i[0,7]取决于 l a s t A c c e s s lastAccess lastAccess是否为 1 1 1 l a s t A c c e s s lastAccess lastAccess为请求read之前的address access:

  • 1)Lemma 1: m O p ′ = 1 ∧ m W r ′ = 0 ∧ l a s t A c c e s s = 1 mOp'=1\land mWr'=0\land lastAccess=1 mOp=1mWr=0lastAccess=1,输出为 v a l i ′ = 0 val'_i=0 vali=0。若 l a s t A c c e s s = 1 lastAccess=1 lastAccess=1,则表示为首次访问新读取的地址,因此 v a l i ′ = 0 val'_i=0 vali=0。其在mem_read_last_access.smt2中证明,应返回unsat。
  • 2)Lemma 2: m O p ′ = 1 ∧ m W r ′ = 0 ∧ l a s t A c c e s s = 0 mOp'=1\land mWr'=0\land lastAccess=0 mOp=1mWr=0lastAccess=0,输出为 v a l i ′ = v a l i val'_i=val_i vali=vali。若 l a s t A c c e s s = 0 lastAccess=0 lastAccess=0,则表示所读取的地址之前已被读过或写过,因此 v a l i ′ = v a l i val'_i=val_i vali=vali。其在mem_read_not_last_access.smt2中证明,应返回unsat。
  • 3)Lemma 3: m O p ′ = 1 ∧ m W r ′ = 0 mOp'=1\land mWr'=0 mOp=1mWr=0,输出 v a l i ′ val'_i vali为确定性的。无论 l a s t A c c e s s lastAccess lastAccess为何值。其在mem_read_are_deterministic.smt2中证明,应返回unsat。
1.3.2.2 mem.pil中write形式化分析

mem.pil状态机内,writes,可将任意值写入 v a l i ′ val_i' vali内。这些值未在Mem状态机内约束,因此当有write时,其query是非确定性的:

  • 4)Lemma 4: m W r ′ mWr' mWr,则 v a l i ′ val_i' vali是诶确定性的。其在mme_writes_are_not_deterministic.smt2中证明,返回sat。

writes和内存操作之间关系的另一简单但有用的定理为:

  • 5)Lemma 5: m W r ′ mWr' mWr,则 m O p ′ mOp' mOp,即永远没有内存之外的write。见mem_write_implies_mem_op.smt2,返回unsat。
1.3.2.3 mem.pil中address和step形式化分析

mem.pil中,内存访问表,先按地址排序,然后按step排序。从而要求下一行的地址要么是增加的,要么地址值不变,但step是增加的。除第一行和最后一行之外,其它相邻行都需满足该要求:

  • 6)Lemma 6: I S N O T L A S T = 1 ISNOTLAST=1 ISNOTLAST=1,表示 ( a d d r ′ > a d d r ) ∨ ( a d d r ′ = a d d r ′ ∧ s t e p ′ > s t e p ) (addr'>addr)\vee (addr'=addr'\land step'>step) (addr>addr)(addr=addrstep>step)。具体见mem_isnot_last_implies_inc_addr_step.smt2,返回unsat。

addr和lastAccess之间感兴趣的另一关系为,若当前行的lastAccess为0,则下一行的地址保持不变:

  • 7)Lemma 7: l a s t A c c e s s = 0 lastAccess=0 lastAccess=0,表示 a d d r ′ = a d d r addr'=addr addr=addr。具体见mem_not_last_access_implies_same_addr.smt2,返回unsat。

2. 致命漏洞

2.1 致命漏洞1:频繁使用unchecked free变量来计算gas

具体上下文见:

  • zkevm-rom:calldata-returndata-code.zkasm#L73
  • zkevm-rom:calldata-returndata-code.zkasm#L225
  • zkevm-rom:calldata-returndata-code.zkasm#L329
  • zkevm-rom:utils.zkasm#L395
  • 等等

这些均会影响memory expansion。

以opCALLDATACOPY为例,其未对用于计算wordsize cost的free变量进行约束:

 	GAS - 3 => GAS  :JMPN(outOfGas)GAS - ${3*((C+31)/32)} => GAS    :JMPN(outOfGas) ; Arith

在某些地方,如opRETURNDATACOPY中使用arith状态机来计算:

	;${3*((C+31)/32)}C+31 => A;(C+31)/32A               :MSTORE(arithA)32              :MSTORE(arithB):CALL(divARITH)$ => A          :MLOAD(arithRes1); Mul operation with Arith; 3*((C+31)/32)3               :MSTORE(arithA)A               :MSTORE(arithB):CALL(mulARITH)$ => A          :MLOAD(arithRes1)GAS - A => GAS  :JMPN(outOfGas)

具体修复PR见:

  • $ to $$ & fix unsecure code #199
  • Fix computeGasSendCall #221

2.2 致命漏洞2:内存对齐延展性

上下文见:

  • zkevm-proverjs:sm_mem_align.js#L14

常量多项式BYTE_C4096,未对255之后的值做wrap around,支持inV值大于一个字节,从而可能carry over,并引起MSTORE8在写入指定byte到内存之前,写入一个 1 1 1

背景知识为:

  • Solidity代码生成器通常会试图对齐内存便宜,通过word-boundaries来分配,且许多其它项目也鼓励写内联汇编来实现对齐。但是,某些人为优化gas,可不做对齐,而且也不能确定Solidity的代码生成器中不存在未对齐的情况。
    想象下,若可能在未对齐的MLOADS中插入“fake value”,则意味着恶意产块者可让某用户在某AMM交易或其它类型的swaps中损失钱或赚钱。这些交易可被三明治以提取价值。未对齐读取情况下,可很容易地通过交易追踪来map out,且“searchers”可搭建proof样式的数据库来修改自动执行类似交易。

推荐修复策略:

  • 对大于255的值做wrap around。
@@ -11,7 +11,7 @@ const CONST_F = {
BYTE2B: (i) => (i & 0xFF), // [0..255]
// 0 (x4096), 1 (x4096), ..., 255 (x4096), 0 (x4096), ...
- BYTE_C4096: (i) => (i >> 12), // [0:4096..255:4096]
+ BYTE_C4096: (i) => (i >> 12) & 0xFF, // [0:4096..255:4096]
// 0 - 1023 WR256 = 0 WR8 = 0 i & 0xC00 = 0x000
// 1024 - 2047 WR256 = 0 WR8 = 0 i & 0xC00 = 0x400

修复PR见:

  • fix constant pol BYTE_C4096 #116

2.3 致命漏洞3:不正确的BYTE实现

上下文见:

  • zkevm-rom:comparison.zkasm#L345

在opBYTE中,范围检查 31 - B => D :JMPN(opBYTE0) 是不正确的,因为其仅检查了B0,若任意的B1-B7为非零值,则opBYTE应为0值时,可能为其它值。
如:

  • A=0xa0a1a2a3a4a5a6a7a8a9b0b1b2b3b4b5b6b7b8b9c0c1c2c3c4c5c6c7c8c9d0d1
  • B=0x100000001,即B0=1,B1=1
  • 则结果应为0值,但现在为0xa0值。

类似用例未在Ethereum State Tests中覆盖,但多种不同版本的实现通过单元测试(如evmone)进行了覆盖。

推荐修复措施为:

  • 使用 :SUB

修复PR见:

  • fixes opSAR, opBYTE & remove check poseidon counters #211
    在这里插入图片描述
  • add test comparison: byte & sar #165 为针对性的测试用例

2.4 致命漏洞4:VMTests/vmPerformance/loopExp中的测试失败(可能问题在于EXP)

上下文:

  • zkevm-testvectors

VMTests/vmPerformance/loopExp.json中的某些以太坊测试用例有如下错误:

Input: /0xPolygonHermez/zkevm-testvectors/tools/ethereum-tests/eth-inputs/GeneralStateTests/VMTests/loo c
pExp_1.json↪→
Start executor JS...
Error
Error: Program terminated with registers A, D, E, SR, CTX, PC, MAXMEM, zkPC not set to zero

失败的测试用例列表为:

loopExp_1
loopExp_2
loopExp_3

具体测试用例见:

  • https://github.com/spearbit-audits/ethereum-state-tests/commit/46967ebcec124fb77043aa6d8e19d29537f31550

相比于Ethereum tests,其修改为具有更低交易gas limit,并降低了loop迭代次数,以满足3000万 gas limit的限制。

很难诊断具体原因,因测试框架并不保存类似错误情况下的trace log文件,具体见后面的“Trace log is not saved in case of “register not set to zero” error”信息类漏洞。
可能是EXP实现中存在bug。

建议:

  • 确保可执行这些loopExp测试,并验证EXP表现正确。

修复PR见:

  • fixes opSAR, opBYTE & remove check poseidon counters #211
  • update tmpvars & expAD counters #212 改进了zk-counters check。

2.5 致命漏洞5:不正确的SAR实现

上下文见:

  • zkevm-rom:comparison.zkasm#L488

该opSAR实现是不正确的。当A为“negative”(符号位为1)时,SHRarithBit错误为(0-A)。

如:sar(0x80…01, 1),结果为0xc0…01,而不是c0…00:

sign(A) == 1
abs(A) == 0x7f..ff
abs(A) >> 1 == 0x3f..ff
0 - (abs(A) >> 1) == 0xc0..01

如下测试用例应可发现该bug,但其被禁用了:

[ FAILED ] stShift.shiftCombinations
[ FAILED ] stShift.shiftSignedCombinations

建议:

  • 当A为负数时,SAR的正确实现可为:NOT(SHR(NOT(A), D)),其中A为shift数,D为要移动的位数,当前实现中,NOT为bit wise negation,而不是算术negation。
  • 可使用XOR和符号位,来做有条件negate。若E包含了符号位,则可为:
MASK = SUB(0, E)
RESULT = XOR(SHR(XOR(A, MASK), D), MASK)

修复PR见:

  • fixes opSAR, opBYTE & remove check poseidon counters #211
  • add test comparison: byte & sar #165 为针对性的测试用例

2.6 致命漏洞6:对division余数的check不足

上下文见:

  • zkevm-rom:utils.zkasm#L469

divARITH子程序中,使用arith状态机来做除法。使用的为A * B + C = D * 2**256 +E 方程式,所有变量均为256位无符号数字,但该方程式是整数运算方程式。

该子程序会同时计算 E/A 和 E%A,E和A为该子程序的输入,并按状态机变量的方式赋值。

在调用arith状态机之前,该子程序会做如下2个checks:

  • 1)除0,若A==0,则直接返回(0, 0)。
  • 2)若E<A,则直接返回(0, E)。

然后当其调用arith状态机时,会设置:D=0, B=$(E/A)(free input), C=$(E%A)(free input)。选择这些free inputs,会让该状态机成功。

问题在于:

  • 仅当余数${E%A}值小于A时,其才是正确的余数。当以B=${E/A-1}, C=${(E%A)+A}来触发arith状态机时,其仍然满足该方程式——只要E/A>=1且无算术溢出。

在第469行,其注释声称在调用完arith状态机后,会检查“remainder < divisor”,但实际代码做的是不同的检查:

  • 其调用LT状态机来检查C<E,而不是C<A。

这就意味着,恶意prover可伪造无效的除法和模运算。

注意,由于在调用arith状态机之前检查了E<A,仅在A<=E的情况下才调用arith状态机,从而使得C<E的无效检查,永远不会比正确的C<A检查更严格,从而导致在测试中未发现该问题。

推荐:

  • 修改469行代码:
   - ; check divisor > reminder- C => A ; reminder-  E => B ; divisor+ ; check divisor > reminder+  C => A ; reminder+  E => B ; divisor

修复PR见:

  • Fix divARITH, smod, sdiv #205

2.7 致命漏洞7:binary状态机内未约束的carry值

上下文见:

  • zkevm-proverjs:binary.pil#L72
cIn' * ( 1 - RESET' ) = cOut * ( 1 - RESET' );

当RESET为1时,prover可任意设置cIn中的值。这样,prover可设置cIn为1,来证明0+0==1。
如对于binary状态机的收割运算,该漏洞可被利用为:

// sm_binary.js:337
+ pols.cIn[0] = 1n;

建议:

  • 修改对cIn的PIL约束为:【这样当RESET==1时,有cIn==0。】
// binary.pil:82
- cIn' * (1 - RESET) = cOut * ( 1 - RESET' )
+ cIn' = cOut * ( 1 - RESET' )

修复PR见:

  • binary - carry constraint #137

3. 不兼容性漏洞

3.1 不兼容性漏洞1:可跳转进push-data,与以太坊主网背离

上下文见:

  • zkevm-rom:flow-control.zkasm#L58-L59
	; check if is a jumpDest (0x5B)0x5B => B$                               :EQ, JMPC(readCode, invalidJump)

其仅检查目标是0x5b(JUMPDEST)byte,但不检查0x5b是否为之前PUSH指令的一部分。
以太坊jumpdest-analysis规定,不应跳转到push-data,这是执行过程中代码和数据的有力分离。

虽然JUMPDEST opcode初始需求是为了让EVM代码更容易转换到机器代码(通过启用基本执行块探测),但后来开发人员和工具都期望使用此功能,以避免(恶意)错误隐藏在代码的数据部分。

如果zkEVM允许此类代码有效,则分析部署的代码将需要改进的工具,安全研究人员社区必须意识到这一差异。

如下字节码0x6001600055600A56615B5B5B应fail:

# Bytes Opcode
# Location
# -------- ----------
# 00-01 PUSH1 0x01
# 02-03 PUSH1 0x00
# 04 SSTORE
# 05-06 PUSH1 0x0A (End of PUSH data location)
# 07 JUMP
# 08-0A PUSH2 0x5B5B
# 0B JUMPDEST

建议:

  • 若跳转目标为push-data内的0x5b byte,则异常终止。

当前Polygon-Hermez认为:

  • 这是EVM和zkEVM实现的一个已知的不同之处。在runtime是做code JUMPDEST分析,意味着zkEVM的高开销,因此决定不做该check。

4. 高风险漏洞

4.1 高风险漏洞1:交易处理未拒绝可延展签名

上下文见:

  • load-tx-rlp.zkasm
  • process-tx.zkasm
  • ecrecover.zkasm

在EIP-2: Homestead Hard-fork Changes中,限制了高S值的签名。

当前,s值大于secp256k1n/2的所有交易签名,都认为是无效的。该ECDSA recover预编译合约保持不变,且将仍保持接受高s值,这样做的好处有——在合约内恢复old Bitcoin签名。

processTx中的交易处理代码,会将raw签名细节传递给ecrecover,其仅验证r值在[1, secp256k1n-1]范围内,且s值在[1, secp256k1n-1]范围内。由于ecrecover代码用于预编译,其是合理的。但用于交易处理时,有效的范围应为[1, secp256k1n/2]。

详情也可参看以太坊黄皮书附录F。

建议:

  • 拒绝类似交易。

修复PR见:

  • ecrecover optimizations #201

5. 中等风险漏洞

5.1 中等风险漏洞1:Ethereum Test Suite设计运行多个版本而不是单个版本

上下文:

  • zkevm-testvectors

Ethereum Test Suite设计为支持多个协议版本(称为Network),可自genesis(称为Frontier)递增至最新release。

某些测试用例启用于:

  • 某特定老版本,如今Frontier,因无人更新它们。
  • 自某特定新版本开始,如London,因其依赖于某些新的EVM feature来让测试更简单,但该feature实际设计为自更早的upgrades启用测试。

Polygon zkEVM仅与Berlin release紧密关联,可能会错过某些测试用例。https://github.com/spearbit-audits/ethereum-state-tests/tree/ecrecover-all-forks中更新了一些Berlin中启用的测试用例,但需要更深入地review该test suite。

建议:

  • 确保所有测试用例均运行于Berlin版本

修复的PR有:【Polygon zkEVM团队将review整个Ethereum test suite来识别与Berlin版本想过的missing test,以提升测试覆盖率】

  • generate Berlin tests from non-berlin tests #178

6. 信息类风险

6.1 信息类风险1:源码中仍有TODO和question注释

在源码中,仍有不少TODO和question注释。这些可能导致行为是否是故意的不确定性。再加上许多以太坊状态测试案例被禁用,它们很可能掩盖了真正的问题。

建议:

  • review所有注释,标识并移除。

相关修复PR:

  • remove obsolete TODO comment #222
  • review and clean some TODO #117

6.2 信息类风险2:“register not set to zero”错误时,未保存trace log

当Ethereum测试执行结束有错误:Error: Program terminated with registers A, D, E, SR, CTX, PC, MAXMEM, zkPC not set to zero时,在zkevm-proverjs/src/sm/sm_main/logs-full-trace 目录下并未创建trace文件,使得难于deug该错误。类似loopExp错误也存在没有trace文件,难于debug的问题。

建议:

  • 若test执行以错误结束,总是创建trace log文件。

修复PR见:

  • Update FT and other improvements #110

6.3 信息类风险3:identity预编译内部循环检查了未使用变量

上下文见:

  • zkevm-rom:identity.zkasm#L24
  • zkevm-rom:identity.zkasm#L61

identity内部循环——名为IDENTITYreturnLoop,会做STEPS、BINARY、POSEIDON_G counters减法,但这些并未在该loop内使用,因为没有发生任何arithmetic计算或哈希计算。

这些减法是浪费的,同时会导致区块内包含更少的交易数。

建议:

  • 不要调整这些counters

修复PR见:【将在更底层的函数做zk-counters检查】

  • Feature/counter tests #223 改进了zk-counters处理。
  • Feature/counters and comments #227 添加了一个安全的zk-counter band,以避免不受控的out-of-counters。

6.4 信息类风险4:可能的opPUSH优化

上下文见:

  • zkevm-rom:stack-operations.zkasm#L212-L216

在opPUSH实现中,检查了push data是否在code boundaries:

$ => B :MLOAD(bytecodeLength)
PC + D => A
$ :LT,JMPC(opAuxPUSHA2)
PC => A
B - A => D

无需做256位精度的比较,因为这些值均在32位范围内。因此,可将LT替换为常规减法:

$ => B :MLOAD(bytecodeLength)
B - PC - D :JMPN(opAuxPUSHA2)
B - PC => D

此外,对于push data仅部分位于code boundaries内的病态情况,将D调整为B-PC。特别是,D可以为0,因此请检查readPush是否能正确处理。

最后,可以注意到,在病态情况下,推送到stack的值永远不会被访问(因为PUSH是最后一条指令)。因此,在这种情况下,可始终设置0=>D。

相关修复PR:

  • Optimize opPush and SHL #242

6.5 信息类风险5:应有选项来运行独立测试

上下文见:

  • zkevm-testvectors:eth-tests-folder.sh#L20

eth-tests-folder.sh脚本总是重新生成输入,甚至没有update选项。这与eth-tests.sh脚本逻辑不一致,eth-tests.sh脚本支持不重新生成,仅运行测试用例。

建议:

  • 修改eth-tests-folder.sh脚本,使其与eth-tests.sh类似:
if [ -f "eth-inputs/$group/$folder/info.txt" ] && [ "$1" != "update" ]
then
echo "Exist"
else
npx mocha --max-old-space-size=12000 gen-inputs.js --group $group --folder $folder --output
eth-inputs↪→
fi

同时,建议有可选项,来运行指定folder内的单个测试。

相关修复PR:

  • update README, add test gasPrice*gasLimit #161,改进了README.md来解释每个脚本的目的,并可运行单个测试。

6.6 信息类风险6:test运行时不易于使用debug选项

上下文:

  • zkevm-testvectors

README中提及了一些额外的选项,但如何激活这些选项并不清晰:

  • zkevm-testvectors:ethereum-tests#options

如,可能想要对gen-inputs.js运行添加–evm-debug选项。
同时,生成的traces置于未说明的难以发现的路径,如:

  • 当激活–evm-debug选项时,ethereumjs traces存储在zkevm-testvectors/tools/ethereum-tests/evm-stack-logs目录下。
  • 无需任何flags,zkevm traces存储在zkevm-proverjs/src/sm/sm_main/logs-full-trace 目录下。

建议:

  • 更好的说明如何从test execution中收集EVM traces。

相关修复PR:

  • update README, add test gasPrice*gasLimit #161,更好的文档说明。

6.7 信息类风险7:可能的SHL简化

上下文:

  • zkevm-rom:utils.zkasm#L609

左移操作分为2种情况:

  • 1)zero overflow
  • 2)nonzero overflow

这2种情况,都以完全相同的值来调用ARITH状态机,唯一的区别仅在于其中一种情况使用D=0(ARITH状态机内D为overflow),而另一种情况,D为包含该overflow的free input。

根据该overflow是否为0,会多次调用BINARY和exponentiation机制。最后,2种情况均可将D用作free input。

建议:

  • 仅使用SHLarithBig:
    • 若D(shift amount)小于256,则返回0
    • 计算B=2**D
    • 使用ARITH,验证A*B=* 2**256+<result>是否成立。

相关PR见:

  • Optimize opPush and SHL #242

6.8 信息类风险8:同一文件内的测试索引号是随机的

上下文:

  • zkevm-testvectors:gen-inputs.js#L185

当单个Ethereum test文件内有多个测试时,gen-inputs.js 生成不同的具有<testFileName_index>样式的输入,其中index看起来是“随机”的。该index为Javascript引擎对object内部keys排序,见zkevm-testvectors:gen-inputs.js#L174。这样就难于找到所生成的input对应的原始test。

建议:

  • 根据原始测试文件中的key名称,来对所生成的test input文件命名,如sha3_dllg0v0_Berlin.json,而不是sha3_4.json。dll是指test filler文件transaction.data数组内的index。

Polygon-Hermez回复:

  • 将添加更好的文件命名,以易于表示为zkevm-rom生成的inputs。

6.9 信息类风险9:PaddingKK中重复constant多项式

上下文:

  • zkevm-proverjs:sm_padding_kk.js

PaddingKK.crValid和PaddingKK.r8Valid具有相同的值。这不同于“Binary/MemAlign中的重复constant多项式”,因为这不是2个不相关状态机的偶然情况,而是在同一状态机内。2个多项式均在哈希相关状态机paper内被引用。
引入crValid:

  • 将可创建常量列crValid,当且仅当不在最后一个block时,其值为1

r8Valid:

  • 仅在lookup page 16中被提及。

建议:

  • 首先先区分这2个多项式是否应有相同的值:
    • 若是,则使用单个多项式,并据此更新paper
    • 若不是,则在paper内定义r8Valid,并修复相应的值

相关修复PR:

  • reduce duplicated constant pols #107,仅使用单个多项式r8Valid,并更新了相关文档。

6.10 信息类风险10:当state root不匹配时,测试框架报OOC execution错误

上下文:

  • zkevm-proverjs:sm_main_exec.js#L1852

当运行evm_benchmarks中某些计算量重的测试用例时,观察到的结果输出是state root不匹配:

Input: 0xPolygonHermez2/zkevm-testvectors/tools/ethereum-tests/eth-inputs/GeneralStateTests/evm_benchma c
rks/JUMPDEST_n0.json↪→
Start executor JS...
Error
Error: Assert Error: newStateRoot does not match

但是启用tracer output显示实际的 execution error 为 OOCS (out of counters):

{
tx_hash: '0xdb9be29bc49dd4615aae90d141869d51b320fb938e896bd3be9c240bd1fa18be',
rlp_tx: '0xf8638001843000000094be7c43a58000000000000000000000000000000180808207f3a0c77643128f488ea15b c
0d6ed338b8f99ad155a0f5a2eb8d5f3efc4c0ac1782a39a043f032bde2bd2b5fbdc154d32886bae6fd6664f↪→
f5f307d9adbf843b60dcd451f',
type: 0,
return_value: '',
gas_left: '29453541',
gas_used: '546459',
gas_refunded: '0',
error: 'OOCS',
create_address: '',
state_root: '0x786576b88c34f7812afdb7eb7a9a188948843e8361dd53deb376b895f21927aa',
logs: [],
call_trace: {
context: {
to: '0xbe7c43a580000000000000000000000000000001',
type: 'CALL',
data: '0x',
gas: '30000000',
value: '0',
batch: '0x00',
output: '',
gas_used: '546459',
execution_time: '',
old_state_root: '0x786576b88c34f7812afdb7eb7a9a188948843e8361dd53deb376b895f21927aa',
nonce: 0,
gasPrice: '1',
chainId: 1000,
from: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
return_value: ''
},
steps: [
...

建议:

  • 对于OOC情况,测试应不比对state roots,因执行已失败。输出错误应更好地反应实际原因。

相关修复PR:【更好的终端和详细输出】

  • print zkrom error in debug mode #105
  • Feature/last changes #114

6.11 信息类风险11:测试框架onboarding指南不清晰

上下文:

  • zkevm-testvectors
  • zkevm-proverjs

ethereum/tests测试套件的设置很容易出错,尤其是考虑到不清楚要使用哪些分支,以及最近对其中一些分支的更改会中断运行,否则直到最近才能正常运行。

updated readme 有帮助,至少在验证所运行的测试套件是否正确时,是有帮助的,虽然偶尔有错误的分支。

当前的setup总结为:

  • zkevm-testvectors:71926534(当前develop)
  • zkevm-rom: v0.5.2.0
  • zkevm-proverjs: 1252c73(在新的readme中说明)

主要障碍在于,zkevm-proverjs在其root目录下生成文件cache-main-pil.json。当切换该repo分支时,需手工删除该文件,或其有与新分支不兼容的风险。
但首次clone代码库时,不容易注意到该行为,但在现有setup中切换分支时,应说明该问题。

修复PR:

  • update README, add test gasPrice*gasLimit #161,改进了测试框架脚本。

6.12 信息类风险12:opSDIV仅需调用binary状态机内的XOR一次而不是2次

上下文:

  • zkevm-rom:arithmetic.zkasm#L143

opSDIV可实现为对binary状态机更少的调用次数。
opSDIV调用abs来分别获取绝对值和符号位。若符号位相同,则使用绝对值的unsigned除法。若符号位不同,则取绝对值的unsigned除法的负值。

其使用XOR(XOR(sgnA, sgnB), 1)这种复杂的方式来计算“2个符号位是否不同”。实际上可使用EQ(sgnA, sgnB)来实现相同的效果。
或者有其它更简单的方式来计算,从而压根不需要调用binary状态机。

建议:

  • 将2次XOR调用,替换为1次EQ调用。

修复PR:

  • Fix divARITH, smod, sdiv #205

6.13 信息类风险13:opNOT的无效注释

上下文:

  • zkevm-rom:comparison.zkasm#L311

opNOT中注释说2226,实际应为2256

建议:

  • 将注释修改为2**256

修复PR:

  • RLP checks & clean code #224

6.14 信息类风险14:若某测试文件的input生产内存不足,则跳过该测试文件夹

上下文:

  • zkevm-testvectors:eth-tests-get-info.sh#L29

当测试执行结束出现如下错误:

./eth-tests-get-info.sh: line 36: let: err_gen_perc=(100*0+0/2)/0: division by 0 (error token is "0")
./eth-tests-get-info.sh: line 37: let: err_exec_perc=(100*0+0/2)/0: division by 0 (error token is "0")
./eth-tests-get-info.sh: line 38: let: ok_perc=(100*0+0/2)/0: division by 0 (error token is "0")

看起来似乎是某个input generatiosn内存不足。如下日志指出:

Test name: Return50000_2_0.json
WRITE: /0xPolygonHermez/zkevm-testvectors/tools/ethereum-tests/eth-inputs/GeneralStateTests/stQuadratic c
ComplexityTest/Return50000_2_0.json↪→
Test name: Return50000_2_1.json
Killed

最后,stQuadraticComplexity文件夹没有info.txt总结文件,且eth-tests-get-info.sh无法找到该test。
这可能会影响passed/failed/generation错误的统计分析。OOM错误掩埋在log中,当其实际被跳过时,很难注意到这些测试。

建议:

  • 考虑将文件夹内缺失info.txt文件,标记为test generation错误,这样便于注意。

Polygon-Hermez回复:

  • 某些测试需要高端指定硬件来运行。具体为,Return50000_2_0.json文件被标记为忽略,因其在大型机器上运行后会触发zkevm-rom out-of-counters。当前,将所有会触发out-of-counters错误的测试,都已知,不做zk-counters限制而passed。

6.15 信息类风险15:未说明测试框架要求

上下文:

  • zkevm-testvectors:eth-tests.sh#L55

以eth-tests.sh脚本来运行ethereum tests,要求clone zkevm-rom库,并构建rom.json文件,当首次设置tests时,这些并不明确。同时,还需要zkevm-proverjs repo。

建议:

  • 修改文档,说明运行测试需复制zkevm-proverjs、zkevm-rom、npm install、npm run build,或在setup脚本中包含这些。

修复PR:

  • update README, add test gasPrice*gasLimit #161

6.16 信息类风险16:若交易 gaslimit > 30M,则跳过或忽略该测试

上下文:

  • zkevm-testvectors:gen-inputs.js#L223-L226

当gas limit超过30M时,则不做尝试,甚至其实际可能花费更少的gas。测试中的交易gas limit可为人一直,且并不代表其实际要花费的gas量。

建议:

  • 考虑修改测试执行工具,要么以更大的limit(如80M为一个常见的gas limit),或者尝试执行large limit test看其是否可行。可选择使用真实的limit来改进独立测试用例。

Polygon-Hermez回复:

  • Tests considered ignored regarding two topics has been addressed and are executed in the zkevm-rom to increase test coverage. Those tests are the following ones:
    • gasUsed > 30M gas
      • 最大gas limit可增加至2**32-1,因zkevm-rom可处理GAS寄存器。
      • 将检查测试大于2**32-1 gas Limit,以及在以太坊测试套件内交易生成定制filler modifying。
    • out of counters:
      • zero-knowledge资源被浪费了。因此,test无法在zkevm-rom内运行。
      • 添加不考虑zk资源的模式,然后test可在zkevm-rom内运行。

6.17 信息类风险17:Binary/MemAlign中的重复常量多项式

上下文:

  • zkevm-proverjs:sm_binary.js#L83
  • zkevm-proverjs:sm_mem_align.js#L8

Binary.P_A和MemAlign.BYTE2A是相同的,Binary.P_B和MemAlign.BYTE2B是相同的。

建议:

  • 通过将其提取到Global中,可节约2个常量多项式,并在Binary和MemAlign中使用相同的常量多项式。

修复:

  • zkevm-proverjs:binary.pil#L86-L87
  • zkevm-proverjs:mem_align.pil#L110-L116

6.18 信息类风险18:test生成器解析stEOF tests(以及其他过于嵌套路径)失败

上下文:

  • zkevm-testvectors:gen-inputs.js#L106-L172

该框架循环从以太坊测试套件中读取各个目录树下的每个JSON tests,以生成eth-inputs。但是,其遍历代码默认最大深度为3,而新的stEOF/stEIP3540文件深度超过了3。

在提取test suit时,由于eth-test.sh不强化指定的commit hash,当首次尝试setup tests时,可创建随机的新的失败。

建议:

  • 强化明确所支持的以太坊测试套件版本,通过更新eth-tests.sh中的clone逻辑,或使用git submodule来表示该依赖。

相关PR:

  • fix ethereum/tests version & update package.json and no-exec #164,冻结了以太坊测试套件的某commit
  • update README, add test gasPrice*gasLimit #161,改进了tests解析。

6.19 信息类风险19:很多opcodes中不必要的stack overflow检查

上下文:

  • zkevm-rom:opcodes.zkasm#L42

EVM中的很多指令不会引起stack overflow。zkEVM中的某些指令实现,具有不必要的stack overflow检查,如opNOT和opDUPx中的%CALLDATA_OFFSET - SP :JMPN(stackOverflow)。

建议:

  • 移除所列指令中的stack overflow检查

修复PR:

  • remove unnecessary checks #202
  • remove duplicate stack overflow #240

6.20 信息类风险20:应支持EIP-3541

上下文:

  • zkevm-rom

调用FirstByte的测试用例 被禁用,具体见develop分支中的execption列表和main分支中的execption列表。这些会检查新合约的创建code不能以0xEF字节开头。

缺少EIP-3541的支持可以理解,因zkEVM支持Berlin,且该修改是在London upgrade中引入。但是,这是一个future兼容性修改,可回滚多个网络,实际支持是有用的。

建议:

  • 支持EIP-3541

修复PR:

  • comments & eip-3541 #210,添加了EIP-3541
  • add test eip-3541 #163,添加了定制测试

6.21 信息类风险21:package.json库中npm/yarn使用不兼容Semver版本

上下文:

  • zkevm-testvectors
  • zkevm-commonjs
  • zkevm-contracts
  • zkevm-rom
  • 等等

无需手工干预的情况下,当前无法复制和安装zkevm-testvectors。如,checkout v0.4.0.0,和运行npm install 或 yarn install,有:

% yarn install
yarn install v1.22.11
warning package.json: License should be a valid SPDX license expression
warning package.json: "dependencies" has dependency "chai" with range "^4.3.6" that collides with a
dependency in "devDependencies" of the same name with version "^4.3.4"↪→
info No lockfile found.
warning @0xpolygonhermez/test-vectors@0.4.0.0: License should be a valid SPDX license expression
warning @0xpolygonhermez/test-vectors@0.4.0.0: "dependencies" has dependency "chai" with range "^4.3.6"
that collides with a dependency in "devDependencies" of the same name with version "^4.3.4"↪→
[1/4] Resolving packages...
error Can't add "@0xpolygonhermez/zkevm-commonjs": invalid package version "0.4.0.1".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

在zkevm-commonjs/package.json中引用了无效的package版本:

"version": "0.4.0.1",

该问题的原因在于,最新的npm/yarn期待version版本是Semver兼容的,相关问题见:Private github repository returns invalid package version #6195。

当前的解决方案是,创建所有依赖的赋值版本,并替换其版本号为仅包含3个点(如0.4.0、0.4.1、0.4.0-patch1)。此外,需同时在testvectors和修改后的commonjs中运行install命令。

注意:

  • 将该问题定性为低,是因为版本问题阻止了building,和某些npm/yarn版本使用zkevm。这不构成安全问题。

建议:

  • 使用Semver兼容版本

修复:

  • 在README.md中明确了版本和所用软件。

6.22 信息类风险22:PIL hello world multiplier不可编译

上下文:

  • zkevm-doc:Hello-World-Examples.md#L76

以pilcom编译该文件返回错误,显然该约束degree太高(3)。

namespace Multiplier(%N);
pol constant SET;
pol commit freeIn;
pol commit out;
out' = SET*freeIn + (1 - SET)*(out * freeIn);
node src/pil.js multiplier.pil
Error: ERROR multiplier.pil:undefined: Degre too high

建议:

  • 要么引入中间多项式,要么修改该例子为adder:
namespace Adder(%N);
pol constant SET;
pol commit freeIn;
pol commit out;
out' = SET*freeIn + (1 - SET)*(out + freeIn);

附录:Polygon Hermez 2.0 zkEVM系列博客

  • ZK-Rollups工作原理
  • Polygon zkEVM——Hermez 2.0简介
  • Polygon zkEVM网络节点
  • Polygon zkEVM 基本概念
  • Polygon zkEVM Prover
  • Polygon zkEVM工具——PIL和CIRCOM
  • Polygon zkEVM节点代码解析
  • Polygon zkEVM的pil-stark Fibonacci状态机初体验
  • Polygon zkEVM的pil-stark Fibonacci状态机代码解析
  • Polygon zkEVM PIL编译器——pilcom 代码解析
  • Polygon zkEVM Arithmetic状态机
  • Polygon zkEVM中的常量多项式
  • Polygon zkEVM Binary状态机
  • Polygon zkEVM Memory状态机
  • Polygon zkEVM Memory Align状态机
  • Polygon zkEVM zkASM编译器——zkasmcom
  • Polygon zkEVM哈希状态机——Keccak-256和Poseidon
  • Polygon zkEVM zkASM语法
  • Polygon zkEVM可验证计算简单状态机示例
  • Polygon zkEVM zkASM 与 以太坊虚拟机opcode 对应集合
  • Polygon zkEVM zkROM代码解析(1)
  • Polygon zkEVM zkASM中的函数集合
  • Polygon zkEVM zkROM代码解析(2)
  • Polygon zkEVM zkROM代码解析(3)
  • Polygon zkEVM公式梳理
  • Polygon zkEVM中的Merkle tree
  • Polygon zkEVM中Goldilocks域元素circom约束
  • Polygon zkEVM Merkle tree的circom约束
  • Polygon zkEVM FFT和多项式evaluate计算的circom约束
  • Polygon zkEVM R1CS与Plonk电路转换
  • Polygon zkEVM中的子约束系统
  • Polygon zkEVM交易解析
  • Polygon zkEVM 审计及递归证明
  • Polygon zkEVM发布公开测试网2.0
  • Polygon zkEVM测试集——创建合约交易
  • Polygon zkEVM中的Recursive STARKs
  • Polygon zkEVM的gas定价
  • Polygon zkEVM zkProver基本设计原则 以及 Storage状态机
  • Polygon zkEVM bridge技术文档
  • Polygon zkEVM Trustless L2 State Management 技术文档
  • Polygon zkEVM中的自定义errors
  • Polygon zkEVM RPC服务
  • Polygon zkEVM Prover的 RPC功能
  • Polygon zkEVM PIL技术文档
  • Polygon zkEVM递归证明技术文档(1)【主要描述了相关工具 和 证明的组合、递归以及聚合】
  • Polygon zkEVM递归证明技术文档(2)—— Polygon zkEVM架构设计
  • Polygon zkEVM递归证明技术文档(3)——代码编译及运行
  • Polygon zkEVM递归证明技术文档(4)—— C12 PIL Description
  • Polygon zkEVM递归证明技术文档(5)——附录:借助SNARKjs和PIL-STARK实现proof composition
  • eSTARK:Polygon zkEVM的扩展STARK协议——支持lookup、permutation、copy等arguments(1)
  • eSTARK:Polygon zkEVM的扩展STARK协议——支持lookup、permutation、copy等arguments(2)
  • eSTARK:Polygon zkEVM的扩展STARK协议——支持lookup、permutation、copy等arguments(3)
  • Polygon zkEVM的Dragon Fruit和Inca Berry升级
  • Polygon zkEVM协议治理、升级及其流程
  • Polygon zkEVM 节点软件release日志
  • Polygon zkEVM bridge服务 release日志
  • Polygon zkEVM DataStreamer
  • Polygon zkEVM Goldilocks域各项运算性能
  • Polygon zkEVM Hexens审计报告解读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/223180.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux学习小结

目录结构 tree -L 1 / # /root #root用户的家目录 /home #存储普通用户家目录 lostfound #这个目录平时是空的&#xff0c;存储系统非正常关机而留下“无家可归”的文件 /usr #系统文件&#xff0c;相当于C:\Windows /usr/local #软件安装的目录&#xff0c;相当于C:\Progra…

Ubuntu-20.04.2 mate 上安装、配置、测试 qtcreator

一、从repo中安装 Ubuntu-20.04.2的repo中&#xff0c;qtcreator安装包挺全乎的&#xff0c;敲完 sudo apt install qtcreator 看一下同时安装和新软件包将被安装列表&#xff0c;压缩包252MB&#xff0c;解压安装后933MB&#xff0c;集大成的一包。 sudo apt install qtcrea…

使用Java语言解决古典猴子分桃问题

一、主要思想 五只猴子分桃 第一只猴子呀 平均分成五分 挤出来多一个 多的扔入海中 拿了其中一份 来了五只猴子 均是如此操作 第五只猴子呀 还存有多少只 二、基本代码 public class MonkeyPeach {public static void main(String[] args){int n 1;int m 0;int flag1;int…

uniapp如何原生app-云打包

首先第一步&#xff0c;需要大家在HBuilder X中找到一个项目&#xff0c;然后呢在找到上面的发行选项 发行->原生App-云打包 选择完该选中的直接大包就ok。 大包完毕后呢&#xff0c;会出现一个apk包&#xff0c;这是后将这个包拖动发给随便一个人就行了。 然后接收到的那…

【5G PHY】NR参考信号功率和小区总传输功率的计算

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

初识Docker-什么是docker

Docker是一个快速交付应用、运行应用的技术 目录 一、Docker 二、运用场景 一、什么是Docker&#xff1f;它的作用是什么&#xff1f; Docker如何解决大型项目依赖关系复杂&#xff0c;不同组件依赖的兼容性问题? Docker允许开发中将应用、依赖、函数库、配置一起打包&…

MySQL中CASE when 实战

CASE 语法 CASEWHEN condition1 THEN result1WHEN condition2 THEN result2WHEN conditionN THEN resultNELSE result END; 将表中的内容转换为右边的形式&#xff1a; 1、创建表&#xff0c;创建数据 CREATE TABLEchapter10_7 (order_id VARCHAR(255) NULL,price VARCHAR(25…

阿里云经济型、通用算力型、计算型、通用型、内存型云服务器最新活动报价

阿里云作为国内领先的云计算服务提供商&#xff0c;提供了多种规格的云服务器供用户选择。为了满足不同用户的需求&#xff0c;阿里云推出了经济型、通用算力型、计算型、通用型和内存型等不同类型的云服务器。下面将详细介绍这些云服务器的最新活动报价。 一、阿里云特惠云服…

实验一传统的结构化的软件工程方法、实验二面向对象的软件工程、实验三软件测试

背景&#xff1a; 实验一 传统的结构化的软件工程方法 1实验目的 了解传统的软件工程方法的基本原理&#xff0c;掌握软件生命周期的全过程依次划分为需求分析、总体设计、详细设计、编码、测试、维护等几个重要阶段。每个阶段所要完成的任务以及提交的文档。 2实验内容 …

25、新加坡南洋理工、新加坡国立大学提出FBCNet:完美融合FBCSP的CNN,EEG解码SOTA水准![抱歉老师,我太想进步了!]

前言&#xff1a; 阴阳差错&#xff0c;因工作需要&#xff0c;需要查阅有关如何将FBCSP融入CNN中的文献&#xff0c;查阅全网&#xff0c;发现只此一篇文章&#xff0c;心中大喜&#xff0c;心想作者哪家单位&#xff0c;读之&#xff0c;原来是自己大导&#xff08;新加坡工…

OpenAI 官方 Prompt 工程指南:写好 Prompt 的六个策略

其实一直有很多人问我&#xff0c;Prompt 要怎么写效果才好&#xff0c;有没有模板。 我每次都会说&#xff0c;能清晰的表达你的想法&#xff0c;才是最重要的&#xff0c;各种技巧都是其次。但是&#xff0c;我还是希望发给他们一些靠谱的文档。 但是&#xff0c;网上各种所…

渗透实验 XSS和SQL注入(Lab3.0)

windows server2003IIS搭建 配置2003的虚拟机 1、利用AWVS扫描留言簿网站&#xff08;安装见参考文档0.AWVS安装与使用.docx&#xff09;&#xff0c;发现其存在XSS漏洞&#xff0c;截图。 2、 Kali使用beef生成恶意代码 cd /usr/share/beef-xss./beef执行上面两条命令 …

DBA-MySql面试问题及答案-上

文章目录 1.什么是数据库?2.如何查看某个操作的语法?3.MySql的存储引擎有哪些?4.常用的2种存储引擎&#xff1f;6.可以针对表设置引擎吗&#xff1f;如何设置&#xff1f;6.选择合适的存储引擎&#xff1f;7.选择合适的数据类型8.char & varchar9.Mysql字符集10.如何选择…

【优化】XXLJOB修改为使用虚拟线程

【优化】XXLJOB修改为使用虚拟线程 新建这几个目录 类&#xff0c; 去找项目对应的xxljob的源码 主要是将 new Thread 改为 虚拟线程 Thread.ofVirtual().name("VT").unstarted 以下代码是 xxljob 2.3.0版本 举一反三 去修改对应版本的代码 <!-- 定…

Wordpress插件WP-Statistics无法识别来访IP国家和城市处理方法

Wordpress插件WP-Statistics&#xff0c;可以识别网站访问者的IP物理地址&#xff0c;统计出城市、国家&#xff0c;但最近发现都显示unknown/未知&#xff1a; 更新GeoIP数据库到最新还是不行&#xff1a; 偶然找到了之前能用的数据库&#xff0c;恢复回去&#xff0c;竟然大…

安全认证【八】

文章目录 8. 安全认证8.1 访问控制概述8.2 认证管理8.3 授权管理8.4 准入控制 8. 安全认证 8.1 访问控制概述 Kubernetes作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作…

使用华为云 CodeArts 自动化部署 Discuz实验指导

本实验将介绍基于华为云 CodeArts&#xff0c;更方便地编写 playbook 代码&#xff0c;甚至可以拷贝他人分享的代码仓库&#xff0c;同时基于自身 Ansible 组件实现快速运维部署&#xff0c;减轻工作负担&#xff0c;减少不必要的问题排查环节。 实验后台&#xff1a;开发者云…

pytorch-模型预测概率值为负数

在进行ocr识别模型预测的时候&#xff0c;发现预测的结果是正确的&#xff0c;但是概率值是负数&#xff1a; net_out net(img) #torch.Size([70, 1, 41]) logit, preds net_out.max(2) #41是类别 需要对类别取最大值 preds preds.transpose(1, 0).contiguous().view(-1) …

浏览器原理篇—渲染优化

渲染优化 通常一个页面有三个阶段&#xff1a;加载阶段、交互阶段和关闭阶段 加载阶段&#xff0c;是指从发出请求到渲染出完整页面的过程&#xff0c;影响到这个阶段的主要因素有网络和 JavaScript 脚本。交互阶段&#xff0c;主要是从页面加载完成到用户交互的整合过程&…