ZCash bellman版本 Groth16代码解析
1. 引言
Groth 2016年论文《On the Size of Pairing-based Non-interactive Arguments》。
相关代码实现有:
- https://github.com/matter-labs/bellman
- https://github.com/zkcrypto/bellman
- https://github.com/arkworks-rs/groth16
本文主要关注代码:
- https://github.com/zkcrypto/bellman
该代码库中的主要依赖有:
- https://github.com/zkcrypto/ff
- https://github.com/zkcrypto/group
- https://github.com/zkcrypto/pairing
- https://github.com/zkcrypto/bls12_381
- crossbeam:并发编程工具
- subtle:常量执行密码学操作的库
- futures_cpupool:用于excute work on a thread pool。
- futures:为Rust异步编程库。
- num_cpus:用于获取机器CPU的数量。
1.1 ff
https://github.com/zkcrypto/ff 为:
- 使用纯Rust语言编写的 finite field library,其中未使用任何
unsafe{}
代码。
其提供的traits有:
- BitView:Create a
BitSlice
view over some type that supports it. - Field:表示an element of a field.
- PrimeField:表示an element of a prime field。
其提供的函数接口有:
- adc:计算
a+b+carry
,返回the sum以及modify the carry value. - mac_with_carry:计算
a+(b*c)+carry
,返回the least significant digit以及setting carry to the most significant digit. - sbb:计算
a-b-borrow
,返回the result以及modify the borrow value.
其定义的类型有:
- FieldBits:为bit representation of a field element.
若想实现自己的prime field,按如下操作即可:
- 首先启用derive feature
[dependencies]
ff = { version = "0.9", features = ["derive"] }
- 然后按如下顺序设置宏即可:【至此,
Fp
即实现了Field和PrimeField。】
#[macro_use]
extern crate ff;#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
#[PrimeFieldReprEndianness = "little"]
struct Fp([u64; 4]);
1.2 group
https://github.com/zkcrypto/group 为:
- a crate for working with groups over elliptic curves。
其提供的trait主要有:
- Add、Sub、AddAssign、SubAssign等group operation
GroupOps
- group scalar multiplication
ScalarMul
- cryptographic group中an element的表示
Group
- elliptic curve 上point的高效表示
Curve
(如to_affine坐标系表示,以及batch_normalize即批量将projective表示的元素转换为affine表示的元素。) GroupEncoding
以及UncompressedEncoding
PrimeGroup:Group+GroupEncoding
:表示an element of a prime-order cryptographic group.PrimeCurve
:表示an elliptic curve point guaranteed to be in the correct prime order subgroups.PrimeCurveAffine
:为an elliptic curve point guaranteed to be in the correct prime order subgroups的affIne表示。WnafGroup:Group
:为Extension trait on a [Group
] that provides helpers used by [Wnaf
]。
1.3 pairing
https://github.com/zkcrypto/pairing 为:
- a crate for using pairing-friendly elliptic curves.
其提供了构建pairing-friendly elliptic curve所需的基本traits。特定曲线的curve可参见特定的库。如BLS12-381 curve的实现见:https://github.com/zkcrypto/bls12_381。
其提供的trait主要有:
Engine
:为a collection of types (fields, elliptic curve groups, etc.) with well-defined relationships. In particular, the G1/G2 curve groups are of prime orderr
, and are equipped with a bilinear pairing function.PairingCurveAffine
:为 affine representation of an elliptic curve point that can be used to perform pairings.MultiMillerLoop
:为 an engine that can compute sums of pairings in an efficient way.MillerLoopResult
:为pairing运算中最昂贵的部分。Represents results of a Miller loop, one of the most expensive portions of the pairing function.MillerLoopResult
s cannot be compared with each other until [MillerLoopResult::final_exponentiation
] is called, which is also expensive.
1.4 bls12_381
https://github.com/zkcrypto/bls12_381 中构建了BLS12-381 pairing-friendly elliptic curve。该库:
- 未经过代码审计。
- 不需要Rust standard library。
- 除非明确标注,所有的操作都是constant time的。
其支持的主要特征有:
- bits:默认开启。允许通过API获取scalar的bit iterator。
- groups:默认开启。允许通过API进行group arithmetic with G1, G2和GT。
- pairings:默认开启。允许通过API进行pairing运算。
- alloc:默认开启。允许通过API获取allocator。包含了pairing优化。
- nightly:启用
subtle/nightly
,可阻止编译器优化影响constant time operations。需要nightly Rust compiler。 - endo:默认开启。允许借助curve endomorphism进行优化。已deprecated,在未来release将移除本功能。
- experimental:可启用一些测试特性。当前支持的测试特性有:
– Hashing to curves
2. bellman
https://github.com/zkcrypto/bellman 中构建了zk-SNARK circuits。提供了:
- circuit traits
- primitive structures
- basic gadget implementations,如booleans和number abstractions。
其features为:
[features]
groth16 = ["pairing"]
multicore = ["futures-cpupool", "crossbeam", "num_cpus"]
default = ["groth16", "multicore"]
该代码库中各源码主要功能为:
- src/multicore.rs:提供了并行计算接口。当前仅为cpupool和crossbeam的简单封装。未来可能会扩展至支持多种并行策略。
- src/multiexp.rs:为c=a1g1+a2g2+⋯+angnc=a_1g_1+a_2g_2+\cdots+a_ng_nc=a1g1+a2g2+⋯+angn multi-exponentiation运算提供了与多线程(CPU内核数)并行计算函数
pub fn multiexp<Q, D, G, S>
。 - src/domain.rs:主要包含了
EvaluationDomain
,用于表示在scalar field域内的各种多项式运算。(包含各种fft和ifft运算。具体见其中的测试用例。)
像Groth16这样基于pairing的SNARKs,需要计算某多项式 与 代表contraint的roots多项式 的商多项式。为了提升计算效率,对于n阶多项式,通常选择这些root为powers of 2n2^n2n-th root of unity。使得相应的多项式运算为O(n) by performing an O(n log n) FFT over such a domain。 - src/gadget.rs:实现了Assignment trait,对于未分配的赋值,返回AssignmentMissing错误。
- src/lib.rs:定义了:
– Circuit trait,Groth16中的arithmetic circuit以rank-1 quadratic constraint system形式表示。Circuit trait 代表可合成的circuit,其synthesize
函数在生成CRS和Prove过程中会被调用。
合成过程中存在的错误类型有:
/// This is an error that could occur during circuit synthesis contexts,
/// such as CRS generation or proving.
#[derive(Debug)]
pub enum SynthesisError {/// During synthesis, we lacked knowledge of a variable assignment.AssignmentMissing,/// During synthesis, we divided by zero.DivisionByZero,/// During synthesis, we constructed an unsatisfiable constraint system.Unsatisfiable,/// During synthesis, our polynomials ended up being too high of degreePolynomialDegreeTooLarge,/// During proof generation, we encountered an identity in the CRSUnexpectedIdentity,/// During proof generation, we encountered an I/O error with the CRSIoError(io::Error),/// During CRS generation, we observed an unconstrained auxiliary variableUnconstrainedVariable,
}
验证过程中的错误类型有:
/// An error during verification.
#[derive(Debug, Clone)]
pub enum VerificationError {/// Verification was attempted with a malformed verifying key.InvalidVerifyingKey,/// Proof verification failed.InvalidProof,
}
– contraint system中的变量表示:
/// Represents a variable in our constraint system.
#[derive(Copy, Clone, Debug)]
pub struct Variable(Index);
/// Represents the index of either an input variable or
/// auxiliary variable.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Index {Input(usize),Aux(usize),
}
– 基于变量的线性运算表示为:(其中Scalar表示的是变量的系数。)
/// This represents a linear combination of some variables, with coefficients
/// in the scalar field of a pairing-friendly elliptic curve group.
#[derive(Clone)]
pub struct LinearCombination<Scalar: PrimeField>(Vec<(Variable, Scalar)>);
– ContraintSystem:用于表示可allocate new variable和contrain这些variables关系的 constraint system。
– Namespace constraint system:borrow了a constraint system (pushing a namespace context),当drop时,会pop out该namespace context。
需为Namespace struct实现ConstraintSystem trait和drop trait。
同时也为ConstraintSystem<Scalar>
实现ConstraintSystem trait。
2.1 groth16
针对的为src/groth16目录下的代码。
- generators.rs:生成CRS。
(σ⃗,τ⃗)←Setup(R)(\vec{\sigma},\vec{\tau})\leftarrow Setup(R)(σ,τ)←Setup(R):选择α,β,γ,δ,x←F∗\alpha,\beta,\gamma,\delta,x\leftarrow \mathbb{F}^*α,β,γ,δ,x←F∗,设置τ⃗=(α,β,γ,δ,x)\vec{\tau}=(\alpha,\beta,\gamma,\delta,x)τ=(α,β,γ,δ,x),σ⃗=([σ⃗1]1,[σ⃗2]2)\vec{\sigma}=([\vec{\sigma}_1]_1,[\vec{\sigma}_2]_2)σ=([σ1]1,[σ2]2),其中:
σ⃗1=(α,β,γ,δ,{xi}i=0n−1,{βui(x)+αvi(x)+wi(x)γ}i=0l,{βui(x)+αvi(x)+wi(x)δ}i=l+1m,{xit(x)δ}i=0n−2),σ⃗2=(β,γ,δ,{xi}i=0n−1)\vec{\sigma}_1 = (\alpha,\beta,\gamma,\delta,\{x^i\}_{i=0}^{n-1},\{\frac{\beta u_i(x)+\alpha v_i(x)+w_i(x)}{\gamma}\}_{i=0}^{l}, \{\frac{\beta u_i(x)+\alpha v_i(x)+w_i(x)}{\delta}\}_{i=l+1}^{m}, \{\frac{x^it(x)}{\delta}\}_{i=0}^{n-2}), \vec{\sigma}_2=(\beta,\gamma,\delta,\{x^i\}_{i=0}^{n-1})σ1=(α,β,γ,δ,{xi}i=0n−1,{γβui(x)+αvi(x)+wi(x)}i=0l,{δβui(x)+αvi(x)+wi(x)}i=l+1m,{δxit(x)}i=0n−2),σ2=(β,γ,δ,{xi}i=0n−1)
相关结构体有:
/// This is our assembly structure that we'll use to synthesize the
/// circuit into a QAP.
struct KeypairAssembly<Scalar: PrimeField> {num_inputs: usize,num_aux: usize,num_constraints: usize,at_inputs: Vec<Vec<(Scalar, usize)>>,bt_inputs: Vec<Vec<(Scalar, usize)>>,ct_inputs: Vec<Vec<(Scalar, usize)>>,at_aux: Vec<Vec<(Scalar, usize)>>,bt_aux: Vec<Vec<(Scalar, usize)>>,ct_aux: Vec<Vec<(Scalar, usize)>>,
}alloc //构建私有变量
alloc_input //构建公有变量
enforce //约束`A` * `B` =`C`
synthesize //用于将circuit 合成为 rank-1 quadratic constraint system
其中verifier key中的icicic即为:
ic={[βui(x)+αvi(x)+wi(x)γ]1}i=0lic = \{[\frac{\beta u_i(x)+\alpha v_i(x)+w_i(x)}{\gamma}]_1\}_{i=0}^{l}ic={[γβui(x)+αvi(x)+wi(x)]1}i=0l
- prover.rs:生成proof。
π←Prove(R,σ⃗,a1,⋯,am)\pi\leftarrow Prove(R,\vec{\sigma}, a_1,\cdots,a_m)π←Prove(R,σ,a1,⋯,am):选择r,s←Fr,s\leftarrow \mathbb{F}r,s←F,计算π⃗=([A]1,[C]1,[B]2)\vec{\pi}=([A]_1,[C]_1,[B]_2)π=([A]1,[C]1,[B]2),其中:
A=α+∑i=0maiui(x)+rδA=\alpha+\sum_{i=0}^{m}a_iu_i(x)+r\deltaA=α+∑i=0maiui(x)+rδ
B=β+∑i=0maivi(x)+sδB=\beta+\sum_{i=0}^{m}a_iv_i(x)+s\deltaB=β+∑i=0maivi(x)+sδ
C=∑i=l+1mai(βui(x)+αvi(x)+wi(x))+h(x)t(x)δ+As+rB−rsδC=\frac{\sum_{i=l+1}^{m}a_i(\beta u_i(x)+\alpha v_i(x)+w_i(x))+h(x)t(x)}{\delta}+As+rB-rs\deltaC=δ∑i=l+1mai(βui(x)+αvi(x)+wi(x))+h(x)t(x)+As+rB−rsδ
相关结构体有:
struct ProvingAssignment<S: PrimeField> {// Density of queriesa_aux_density: DensityTracker,b_input_density: DensityTracker,b_aux_density: DensityTracker,// Evaluations of A, B, C polynomialsa: Vec<Scalar<S>>,b: Vec<Scalar<S>>,c: Vec<Scalar<S>>,// Assignments of variablesinput_assignment: Vec<S>,aux_assignment: Vec<S>,
}pub struct Proof<E: Engine> {pub a: E::G1Affine,pub b: E::G2Affine,pub c: E::G1Affine,
}
- verifier.rs:验证proof。
0/1←Vfy(R,σ⃗,a1,⋯,al,π⃗)0/1\leftarrow Vfy(R,\vec{\sigma}, a_1,\cdots,a_l, \vec{\pi})0/1←Vfy(R,σ,a1,⋯,al,π):解析π⃗=([A]1,[C]1,[B]2)∈G12×G2\vec{\pi}=([A]_1,[C]_1,[B]_2)\in\mathbb{G}_1^2\times \mathbb{G}_2π=([A]1,[C]1,[B]2)∈G12×G2,对应的test为:
[A]1⋅[B]2=[α]1⋅[β]2+∑i=0lai[(βui(x)+αvi(x)+wi(x))γ]1⋅[γ]2+[C]1⋅[δ]2[A]_1\cdot [B]_2= [\alpha]_1 \cdot [\beta]_2 + \sum_{i=0}^{l}a_i[\frac{(\beta u_i(x)+\alpha v_i(x)+w_i(x))}{\gamma}]_1\cdot [\gamma]_2 + [C]_1\cdot [\delta]_2[A]1⋅[B]2=[α]1⋅[β]2+∑i=0lai[γ(βui(x)+αvi(x)+wi(x))]1⋅[γ]2+[C]1⋅[δ]2
若以上test成立,则accept the proof。
会生成PreparedVerifyingKey:
pub fn prepare_verifying_key<E: MultiMillerLoop>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {let gamma = vk.gamma_g2.neg();let delta = vk.delta_g2.neg();PreparedVerifyingKey {alpha_g1_beta_g2: E::pairing(&vk.alpha_g1, &vk.beta_g2),neg_gamma_g2: gamma.into(),neg_delta_g2: delta.into(),ic: vk.ic.clone(),}
}// The original verification equation is:// A * B = alpha * beta + inputs * gamma + C * delta// ... however, we rearrange it so that it is:// A * B - inputs * gamma - C * delta = alpha * beta// or equivalently:// A * B + inputs * (-gamma) + C * (-delta) = alpha * beta// which allows us to do a single final exponentiation.
2.2 gadgets
1)boolean.rs:
/// Represents a variable in the constraint system which is guaranteed
/// to be either zero or one.
#[derive(Clone)]
pub struct AllocatedBit {variable: Variable,value: Option<bool>,
}
对AllocatedBit 实现了:
- conditionally boolean bit alloc约束
- 普通的boolean bit约束
- bit xor约束
- bit and约束
- bit and not约束
- bit nor约束
u64_into_boolean_vec_le
将u64转为64位little endian bit vec,同时对每个bit做了 普通boolean bit约束;field_into_boolean_vec_le
将PrimeFieldBits转换为F::NUM_BITS位little endian bit vec,同时对每个bit做了 普通boolean bit约束。
Boolean的枚举类型有:
/// This is a boolean value which may be either a constant or
/// an interpretation of an `AllocatedBit`.
#[derive(Clone)]
pub enum Boolean {/// Existential view of the boolean variableIs(AllocatedBit),/// Negated view of the boolean variableNot(AllocatedBit),/// Constant (not an allocated variable)Constant(bool),
}
pub fn get_value(&self) -> Option<bool> {match *self {Boolean::Constant(c) => Some(c),Boolean::Is(ref v) => v.get_value(),Boolean::Not(ref v) => v.get_value().map(|b| !b),}}pub fn lc<Scalar: PrimeField>(&self,one: Variable,coeff: Scalar,) -> LinearCombination<Scalar> {match *self {Boolean::Constant(c) => {if c {LinearCombination::<Scalar>::zero() + (coeff, one)} else {LinearCombination::<Scalar>::zero()}}Boolean::Is(ref v) => LinearCombination::<Scalar>::zero() + (coeff, v.get_variable()),Boolean::Not(ref v) => {LinearCombination::<Scalar>::zero() + (coeff, one) - (coeff, v.get_variable())}}}
对Boolean枚举,实现了:
- equal 约束
- not 运算
- xor 运算及约束
- and 运算及约束
- (a and b) xor ((not a) and c) 运算及约束(sha256_ch)
- (a and b) xor (a and c) xor (b and c) 运算及约束 (sha256_maj)
2)multieq.rs:
pub struct MultiEq<Scalar: PrimeField, CS: ConstraintSystem<Scalar>> {cs: CS,ops: usize,bits_used: usize,lhs: LinearCombination<Scalar>,rhs: LinearCombination<Scalar>, //<变量,系数> vec
}
对MultiEq结构体,实现了:
- equal 约束。其中若
Scalar::CAPACITY as usize) <= (self.bits_used + num_bits
,会先进行accumulate()。 - 为MultiEq实现了ConstraintSystem trait。
3)num.rs:
pub struct AllocatedNum<Scalar: PrimeField> {value: Option<Scalar>, // Scalar维度variable: Variable,
}/// Deconstructs this allocated number into its/// boolean representation in little-endian bit/// order, requiring that the representation/// strictly exists "in the field" (i.e., a/// congruency is not allowed.)pub fn to_bits_le_strict<CS>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError>....../// Convert the allocated number into its little-endian representation./// Note that this does not strongly enforce that the commitment is/// "in the field."pub fn to_bits_le<CS>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError>......
在AllocatedBit和Boolean的基础上,对AllocatedNum实现了:
a*b=ab
约束;a*a=aa
约束;a
不为零约束,即存在1/a1/a1/a,使得a∗1/a=1a*1/a=1a∗1/a=1成立;- conditionally_reverse约束,即:
/// Takes two allocated numbers (a, b) and returns/// (b, a) if the condition is true, and (a, b)/// otherwise.
可将AllocatedNum 转换为 Num:
pub struct Num<Scalar: PrimeField> {value: Option<Scalar>,lc: LinearCombination<Scalar>,
}
4)multipack.rs:
提供了:
- pack_into_inputs:Takes a sequence of booleans and exposes them as compact public inputs。
- bytes_to_bits:将bytes转换为bits。
- bytes_to_bits_le:将bytes转换为little-endian bits。
- compute_multipacking:将bool bits转换为Scalar vec。
5)uint32.rs:
/// Represents an interpretation of 32 `Boolean` objects as an
/// unsigned integer.
#[derive(Clone)]
pub struct UInt32 {// Least significant bit firstbits: Vec<Boolean>,value: Option<u32>,
}
对UInt32实现了:
- 自定义的 triop 三变量运算。
- (a and b) xor (a and c) xor (b and c) 运算及约束 (sha256_maj)。
- (a and b) xor ((not a) and c) 运算及约束(sha256_ch)。
- 两变量xor运算及约束。
- 多个UInt32变量求和取模运算及约束。
6)sha256.rs:
为Circuits for the SHA-256 hash function and its internal compression。
7)blake2s.rs:
为 The BLAKE2s hash function with personalization support.
8)lookup.rs:
为Window table lookup gadgets。
9)test/mod.rs:
为测试目的定义了constraint system。
2.3 mimc
https://github.com/zkcrypto/bellman/tree/main/tests/common/mod.rs中:
基于BLS12-381,实现了Albrecht等人 2016年论文《MiMC: Efficient Encryption and Cryptographic Hashing with Minimal Multiplicative Complexity》中的LongsightF322p3
算法。
相应的测试用例见:https://github.com/zkcrypto/bellman/blob/main/tests/mimc.rs
ZCash bellman版本 Groth16代码解析相关推荐
- 视觉SLAM开源算法ORB-SLAM3 原理与代码解析
来源:深蓝学院,文稿整理者:何常鑫,审核&修改:刘国庆 本文总结于上交感知与导航研究所科研助理--刘国庆关于[视觉SLAM开源算法ORB-SLAM3 原理与代码解析]的公开课. ORB-SLA ...
- 密码算法中iv值是什么_?标检测中的?极?值抑制算法(nms):python代码解析
⾮极⼤值抑制(Non-Maximum Suppression)原理 ⾮极⼤值抑制,顾名思义,找出极⼤值,抑制⾮极⼤值.这种思路和算法在各个领域中应⽤⼴泛,⽐如边缘检测算法canny算⼦中就使⽤了该⽅法 ...
- 对抗思想与强化学习的碰撞-SeqGAN模型原理和代码解析
GAN作为生成模型的一种新型训练方法,通过discriminative model来指导generative model的训练,并在真实数据中取得了很好的效果.尽管如此,当目标是一个待生成的非连续性序 ...
- [转载] --- Fastjson1.2.68版及以下全版本远程代码执行漏洞通告
再这样,真的要放弃fastjson了 [安全通告]Fastjson <=1.2.68全版本远程代码执行漏洞通告 尊敬的腾讯云用户,您好! 近日,腾讯云安全运营中心监测到,Fastjson < ...
- PX4代码解析(5)
一.前言 我所讨论的PX4代码是基于v1.11版本,该版本与之前的版本有不少不同,其中一个比较大的区别在于新版本大部分用到了C++中模板,使得代码没有以前那么容易理解,因此我在后面介绍PX4的姿态估计 ...
- PX4代码解析(1)
前言 做pixhawk飞控有一段时间了,但在学习过程中遇到许多困难,目前网上找不到比较完整的PX4学习笔记,我打算结合自己理解,写写自己对PX4源码的理解,不一定对,只是希望与各位大佬交流交流,同时梳 ...
- nms python代码_?标检测中的?极?值抑制算法(nms):python代码解析
⾮极⼤值抑制(Non-Maximum Suppression)原理 ⾮极⼤值抑制,顾名思义,找出极⼤值,抑制⾮极⼤值.这种思路和算法在各个领域中应⽤⼴泛,⽐如边缘检测算法canny算⼦中就使⽤了该⽅法 ...
- linux文件系统的总体架构,Linux NFS的整体架构与核心代码解析
前面文章我们从应用层面对NFS进行了介绍,接下来的文章我们将进入实现层面.本文首先从整体上对Linux的NFS软件架构进行介绍,然后介绍代码与实际业务逻辑介绍一下NFS的处理流程. NFS文件系统的架 ...
- [GCN] 代码解析 of GitHub:Semi-supervised classification with graph convolutional networks
本文解析的代码是论文Semi-Supervised Classification with Graph Convolutional Networks作者提供的实现代码. 原GitHub:Graph C ...
最新文章
- 基于DCMTK的DICOM相关程序编写攻略
- Ant Design 入门-参照官方文档使用组件
- 漫画:什么是公有云、私有云和混合云?
- Java 7在整数中出现的次数
- 编译服务器home文件夹,离线安装FastDFS-过程填坑
- jpa 实体图查询_JPA实体图
- 数据库事务隔离级别-- 脏读、幻读、不可重复读(清晰解释)
- Vue第二部分(5):编程式的路由导航和实战案例
- [bzoj3140] [Hnoi2013]消毒
- 如何识别计算机病毒,怎样识别计算机病毒
- smtp服务器组件,配置exchange Smtp服务器
- jsp企业员工请假管理系统
- 报表工具九个核心标准
- [Lisp] [Scheme][MacOS]Scheme语言环境搭建
- vue 总结一项目建立及文件夹结构配置
- 【RabbitMQ】RabbitMQ基础
- FineUI秘密花园(七) — 上传控件
- 怎样用html制作动态心,HTML5使用Canvas动态绘制心型线和玫瑰线的教程
- JavaScript中开关灯案例展示
- JVM(7)内存溢出问题(工作中常用、面试也重要的知识点)
热门文章
- go的滚咕噜咕噜滚和点心的龙卷风的实现原理
- 【飞轮储能】基于simulink的飞轮储能发电系统的仿真
- 阿里巴巴启动全面组织升级
- Python编程错误:参数错误([_ctypes.COMError: (-2147024809, ‘参数错误。‘, (None, None, None, 0, ...
- 网站首页js幻灯片代码
- Android中动态生成ListView及SimpleAdapter的使用
- 04 Python基本数据类型
- winfomlabel 从右边_炒菜时,用左边的燃气灶还是右边的燃气灶?燃气师傅提醒,别弄错...
- Recall, Precision, and Average Precision
- 为什么那么多的企业选择上云,上云有哪些优势?