零知识证明(zk-SNARK)(一)

全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge,简洁非交互式零知识证明,简洁性使得运行该协议时,即便statement非常大,它的proof大小也仅有几百个bytes,并且验证一个proof的时间可以达到毫秒级别。
主要解决的场景就是,Prover 向 Verifier 证明某个共同认可的计算难题的计算结果是正确的,需要零知识,不能泄露任何信息。
核心方法是通过R1CS,QAP等方法将计算难题变为多项式,将计算结果正确性巧妙转化为了多项式的有特殊解的问题,生成对应proof,然后再运用多项式证明方法,来完成证明与验证。

Non-Interactive Argument of Knowledge of a Polynomial

(注意 计算和参数选取是在域内,即有模运算)

一般多项式的证明

场景如下:Verifier 有一个多项式 f ( x ) f(x) f(x),Prover 向 Verifer 证明他知道这一个多项式。
假设 Prover 知道的多项式为 p ( x ) p(x) p(x),那么现在要证明的就是 f ( x ) = p ( x ) f(x)=p(x) f(x)=p(x),如果这两个多项式的阶数最高为 d d d,那么两个多项式代表的曲线将最多有 d d d个交点,当 Verifier 随机在一个很大的范围内取一个值 s s s的时候,那么 s s s d d d相同的概率会非常低,所以有以下协议

  • Verifier 在大范围里随机选择一个值 s s s,并且在本地计算 f ( s ) f(s) f(s),然后把 s s s发送给 Prover
  • Prover 计算 p ( s ) p(s) p(s),然后发送给Verifier
  • Verifier 验证 f ( s ) = ? p ( s ) f(s)\overset{?}=p(s) f(s)=?p(s)

证明多项式的根

有些多项式是可以分解多个多项式的乘积的,如假设 p ( x ) = ( x − a ) ( x − b ) ( x − c ) p(x)=(x-a)(x-b)(x-c) p(x)=(xa)(xb)(xc)那么
假设 Prover 有一个多项式 p ( x ) p(x) p(x),现在他想证明他的多项式持有一部分根(部分多项式),也就是证明他的多项式 p ( x ) = t ( x ) h ( x ) p(x)=t(x)h(x) p(x)=t(x)h(x)中包含 t ( x ) t(x) t(x)假设为 ( x − a ) ( x − b ) (x-a)(x-b) (xa)(xb),而此时的 t ( x ) t(x) t(x)称为目标多项式,是公开的,要注意 Prover 是不能透露原多项式的。那么有以下协议

  • Verifier 在大范围内随机取值 s s s,计算 t = t ( s ) t= t(s) t=t(s),然后将 s s s发送给 Prover
  • Proer 计算 h ( x ) = p ( x ) t ( x ) h( x) = \frac {p(x)}{t(x)} h(x)=t(x)p(x), h ( s ) h(s) h(s), p ( s ) p(s) p(s),然后发送后两个给 Verifier
  • Verfier 验证 p ( s ) = ? t ( s ) h ( s ) p(s)\overset{?}=t(s)h(s) p(s)=?t(s)h(s)

显而易见以上变量都局限为整数,如果 p p p确实能够整除 t t t,那么等式一定是成立的,如果不能,那么式子将存在余式,有极大的概率不是整数。
当然此协议仍然有很大漏洞,比如 Prover 可能完全不知道 p ( x ) p(x) p(x),但知道公开的 t ( x ) t(x) t(x),所以可以完全捏造出 h ( x ) h(x) h(x)满足条件。

同态加密

显然我们不能在协议里进行明文的传输,但又需要密文的计算,所以需要一个满足加密和计算两种特性的算法。
同态加密算法 E ( x ) E(x) E(x),如 E ( a x + b y ) = g a x + b y = g a x ⋅ g b y = ( g x ) a ⋅ ( g y ) b = E ( x ) a ⋅ E ( y ) b . E(a x+b y)=g^{a x+b y}=g^{a x} \cdot g^{b y}=\left(g^{x}\right)^{a} \cdot\left(g^{y}\right)^{b}=E(x)^{a} \cdot E(y)^{b} . E(ax+by)=gax+by=gaxgby=(gx)a(gy)b=E(x)aE(y)b. g g g是生成元),这里基于离散对数难题和CDH假设(即给定 g a , g b g^a,g^b ga,gb,得到 g a b g^{ab} gab很困难)。显然这是仅仅满足同态加法的同态加密,不支持密文相乘。
那么该算法不支持乘法,仅有一个 s s s的情况下,该怎么同态计算多项式呢?显然是不行的,于是想办法把同态乘法转变为同态加法,注意到,多项式 P ( x ) P(x) P(x)可以看作是一组系数和未知数的线性结合,也就是计算出 s s s的各个幂次,这需要固定好多项式的阶数 d d d,相当于限制了多项式的阶数,这样提前计算出 s 1 , … , s d s^1,\dots,s^d s1,,sd,然后计算出多项式的每个部分相加即可。
具体使用如下,

  1. Verifier 在大范围里随机选择一个 s s s,先计算好 s s s的幂次 s 1 , … , s d s^1,\dots,s^d s1,,sd,接着计算 t ( s ) t(s) t(s),最后 E ( 1 ) , E ( s ) , … , E ( s d ) E(1),E(s),\dots,E(s^d) E(1),E(s),,E(sd)并发给 Prover
  2. Prover 收到数据后计算, h ( x ) = p ( x ) t ( x ) h( x) = \frac {p(x)}{t(x)} h(x)=t(x)p(x),然后配合多项式的系数计算 E ( p ( s ) ) E(p(s)) E(p(s)) E ( h ( s ) ) E(h(s)) E(h(s))并发送给Verifier
  3. Verifier 进行验证 E ( p ( s ) ) = ? E ( t ( s ) ) E ( h ( s ) ) E(p(s))\overset{?}=E(t(s))E(h(s)) E(p(s))=?E(t(s))E(h(s)),即 g p ( s ) = ( g h ( s ) ) t ( s ) g^{p(s)} = (g^{h(s)})^{t(s)} gp(s)=(gh(s))t(s)

** KCA(The Knowledge of Coefficient Test and Assumption)**

上面的协议的仍然有很大漏洞,比如 Prover 在计算多项式的时候,没有采用多项式的格式(常数系数和未知数的线性组合),而是使用了另外的方法,算法找到一个满足 z p = ( z h ) t ( s ) z_p = (z_h)^{t(s)} zp=(zh)t(s)的两个值 z p , z h z_p,z_h zp,zh去替代掉 g p ( s ) , g h ( s ) g^{p(s)},g^{h(s)} gp(s),gh(s),也就是根本没用多项式,直接仿造了满足条件的结果。
这里就需要对 Prover 进行限制,让他必须使用满足条件的多项式,限定为常数,也限定了指数,不能随意改变指数。所以KCA也可以叫做KEA(Knowledge of exponent)
思路如下,
定义一对元素 ( a , b = α ⋅ a ) (a,b = \alpha \cdot a) (a,b=αa)(称为一个 α \alpha α-对), α ⋅ a \alpha \cdot a αa表示 α \alpha α a a a相加,也就是 a α a^\alpha aα,那么一个KC流程如下具体如下,

  1. 首先Verifier会随机选择一个非零的 α \alpha α,计算 b = α ⋅ a b = \alpha \cdot a b=αa,显然这是一个 α − s h i f t \alpha -shift αshift
  2. Verifier 发送这个 challenge pair ( a , b ) (a,b) (a,b)给 Prover。
  3. 这时候 Prover 会 respond 一对不一样,但具有相同性质的 pair ( a ′ , b ′ ) (a',b') (a,b),它应当是 α − s h i f t \alpha -shift αshift
  4. 如果收到的是一个 α − s h i f t \alpha -shift αshift,那么Verifier 接受这个response

注意,这是满足DL问题的, Prover 是很难找到一个 α \alpha α,那么她该如何构造新的 α − s h i f t \alpha -shift αshift呢?一个显而易见的方式是,Prover 选择一个常数系数 γ \gamma γ,直接构造 ( a ′ , b ′ ) = γ ( a , b ) (a',b') = \gamma(a,b) (a,b)=γ(a,b)
假设 Verifier 发送的不是一个,而是是 d d d α − s h i f t \alpha -shift αshift,那么 Prover 也将选择一组系数 c 1 , … , c d c_1,\dots,c_d c1,,cd,respond 一个
( a ′ , b ′ ) = ( ∑ i = 1 d c i a i , ∑ i = 1 d c i b i ) (a',b') = (\sum_{i=1}^d c_ia_i,\sum_{i=1}^d c_ib_i) (a,b)=(i=1dciai,i=1dcibi),显然该对也是满足 α − s h i f t \alpha -shift αshift。如果把 Verifier 发的内容优化一下,就构成了KCA。

Blind Evaluation of Polynomials Verifiable Protocol

完整的多项式盲验证协议。
解决整个问题需要满足的两个性质:

  • **Blindness:**也就是 Prover 不能获取到 s s s,同样 Verifier 也不能拿到 p ( x ) p(x) p(x)(同态)。
  • **Verifiability:**也就是得确保 Prover 发的 E ( p ( x ) ) E(p(x)) E(p(x))确实是用某个多项式 p ( x ) p(x) p(x)计算的,而不是完全不相关的数据(KCA)

那么使用KCA对前面协议进行优化如下,

  1. Verifier 随机选择 α \alpha α(非0)和 s s s,然后计算 t ( s ) t(s) t(s),接着构造 α − s h i f t \alpha -shift αshift ( g , g α ) , ( g s , g α ⋅ s ) , … , ( g s d , g α ⋅ s d ) (g,g^{\alpha}),(g^s,g^{\alpha \cdot s} ),\dots,(g^{s^d},g^{\alpha \cdot s^d}) (g,gα),(gs,gαs),,(gsd,gαsd)
  2. Prover 则使用多项式 p ( x ) p(x) p(x)的系数 c 1 , … , c d c_1,\dots,c_d c1,,cd,然后计算 E ( h ( s ) ) E(h(s)) E(h(s))以及 ( E ( p ( s ) ) , E ( α p ( s ) ) ) = ( g ∑ i = 1 d c i s i , g ∑ i = 1 d c i α ⋅ s d ) (E(p(s)),E(\alpha p(s))) = (g^{\sum_{i=1}^d c_is^i},g^{\sum_{i=1}^d c_i\alpha \cdot s^d}) (E(p(s)),E(αp(s)))=(gi=1dcisi,gi=1dciαsd),发送给Verifier
  3. Verifier进行验证 E ( p ( s ) ) = ? E ( α p ( s ) ) E(p(s))\overset ?=E(\alpha p(s)) E(p(s))=?E(αp(s)) E ( p ( s ) ) = ? E ( t ( s ) ) E ( h ( s ) ) E(p(s))\overset{?}=E(t(s))E(h(s)) E(p(s))=?E(t(s))E(h(s))即可

该方案也可以解决前面的问题,即Prover 不能随意构造满足类似 z p = ( z h ) t ( s ) z_p = (z_h)^{t(s)} zp=(zh)t(s) h ( s ) h(s) h(s),这样会很容易不满足 α − s h i f t \alpha -shift αshift的限制条件。

Parings and bilinear map

前面的协议基本实现了诚实两方之间的交互方案,相关的 proof 仅仅在两方之间有效,无法重复使用,但在实际运用中,存在这恶意的多方的情况,这显然不符合实际。所以,需要让一些秘密参数变得可重复使用甚至公开,而且足够可信以防止滥用。
首先考虑将 Verifier 生成的 ( t ( s ) , α ) (t(s),\alpha) (t(s),α)进行加密保护,防止泄露。如果采用前面的同态加密,那么在后面的乘法计算中就会涉及到同态的乘法 ,但是前面用的同态算法不支持同态乘法。那么必须用到类似乘法的时候应该怎么办呢?这时候就引入了椭圆双曲线映射。
Parings 是能够将一个集合里的两个加密输入确定性的映射到另一个集合里的一个输出的一种乘法表示函数。
即: e : G × G → G T e: \mathbb{G} \times \mathbb{G} \rightarrow \mathbb{G}_T e:G×GGT满足以下性质
e ( g 1 a , g 2 b ) = e ( g 1 , g 2 ) a b = e ( g 1 a b , g 2 ) = e ( g 1 , g 2 a b ) \begin{aligned}e(\mathrm{g_1^a,g_2^b})&=\mathrm{e(g_1,g_2)^{ab}=e(g_1^{ab},g_2)=e(g_1,g_2^{ab})}\end{aligned} e(g1a,g2b)=e(g1,g2)ab=e(g1ab,g2)=e(g1,g2ab)
e ( g 1 a , g 2 b ) e ( g 1 c , g 2 d ) = e ( g 1 , g 2 ) a b + c d \begin{aligned} e(\mathrm{g_1^a,g_2^b})e(\mathrm{g_1^c,g_2^d})&=\mathrm{e(g_1,g_2)^{ab+cd}}\end{aligned} e(g1a,g2b)e(g1c,g2d)=e(g1,g2)ab+cd
其意义在于,将某个群中的一对元素映射到一个新的群,当且仅当两个原像对应指数的积相同其像也相同。并且,该函数要求是可计算的(即不需要用暴力搜索等方式),它能够验证一对(加密后的)数据的乘积是否和另一对相同(虽然算不出这个乘积)
接下来将协议的计算放到满足Parings的椭圆曲线群上来。

Multiple Parties Composite Common Reference String

首先引入一个可信的第三方来随机生成 s s s α \alpha α,并且计算出CRS(Common Reference String),共证明和验证两部分,都是公开的( i ∈ { 0 , … , d } i \in \{0,\dots,d\} i{0,,d}),接着需要删除掉 s s s α \alpha α

  • Proving Key: E ( s i ) , E ( α s i ) = g s i , g α s i E(s^i),E(\alpha s^i) = g^{s^i},g^{\alpha s^i} E(si),E(αsi)=gsi,gαsi
  • Verification Key: E ( t ( s ) ) , E ( α ) = g t ( s ) , g α E(t(s)),E(\alpha) = g^{t(s)},g^{\alpha} E(t(s)),E(α)=gt(s),gα

接着基于CRS,让 Prover 和 Verifier 仅仅通过CRS就能完成协议。继续优化协议如下,(下面简化 p = p ( s ) , t , h p=p(s),t,h p=p(s),t,h也类似)

  • 对于 Prover 来说,公开的CRS中已经包含了第一步的内容,接下来是利用 Proving Key 来计算出 E ( h ( s ) ) E(h(s)) E(h(s)) ( E ( p ( s ) ) , E ( α p ( s ) ) ) (E(p(s)),E(\alpha p(s))) (E(p(s)),E(αp(s)))
  • 对于Verifier来说,是利用CRS中的 Verfication来进行验证( p ′ = α p p' = \alpha p p=αp
    • 首先验证 p = t ⋅ h p=t \cdot h p=th,即 e ( g p , g 1 ) = e ( g t , g h ) = e ( g , g ) p = e ( g , g ) t ⋅ h e(g^p,g^1) = e(g^t,g^h) = e(g,g)^p = e(g,g)^{t \cdot h} e(gp,g1)=e(gt,gh)=e(g,g)p=e(g,g)th
    • 然后验证 α − s h i f t \alpha -shift αshift,即 e ( g p , g α ) = e ( g p ′ , g ) e(g^p,g^\alpha) = e(g^{p'},g) e(gp,gα)=e(gp,g)

注意:这里也暴露出两个问题,

  1. Proving Key 中的 E ( α ) E(\alpha) E(α)是公开的,也就是对于 Prover 来说 ,他是可以打破多项式的限制条件的。
  2. 引入了一个可信第三方,但更复杂的现实中不能保证第三方不存在恶意,比如不销毁 trusted setup 的随机秘密,这一旦暴露会导致任何人都可以伪造证明。

于是 ZKSNARK 引入了多方联合的setup,每个人用自己的私钥 ( α , s ) (\alpha,s) (α,s)和前一个人生成的 CRS 作为输入生成一个新的 CRS,只要保证有一个人销毁了私钥,就能保证最终的CRS是安全的。具体实现如下,
假设有三方 Alice,Bob,Carol 参与,仅需要使用同态乘法让每个人的私钥相加即可
image.png
当然这里敌手是可以对多个不同的 ( α , s ) (\alpha,s) (α,s)进行随机采样,提供随机数来加入到CRS中达到破坏有效性的目的。
那么如何验证最终CRS的一致性呢?采用的是前面的Paring,
检验 s s s:将 s 1 s^1 s1作为一个基准,验证方式如下,
image.png
检验 α − s h i f t \alpha -shift αshift
image.png
为了让参与方诚实的使用前面其他参与方的CRS,需要要求每个参与方( 除了第一个)将自己的秘密参数加密并公开,这样每个参与方就可以通过Paring来验证其他参与方是否诚实的进行了验证。如下,假设 Bob 公开
( g s B i , g α B , g α B s B i ) ∣ i ∈ [ d ] \left.\left(g^{s_B^i},g^{\alpha_B},g^{\alpha_Bs_B^i}\right)\right|_{i\in[d]} (gsBi,gαB,gαBsBi) i[d]
那么参与方 Alice 就可以验证
image.png
同理参与方 Carol 公开后也可以进行验证。

完整的简短非交互式的多项式证明方案

这里用 { g s i } i ∈ [ d ] \{g^{s^i}\}_{i\in[d]} {gsi}i[d]代表 s 1 , … , s d s^1,\dots,s^d s1,,sd
首先确定好目标多项式 t ( x ) t(x) t(x)和 prover 的多项式的阶数 d d d,prover 需要证明他持有的多项式里含有 t ( x ) t(x) t(x)
具体如下
image.png

参考

浅谈零知识证明:背景与起源
zcash官方科普
Exploring Elliptic Curve Pairings
Quadratic Arithmetic Programs: from Zero to Hero
Why and how zk-SNARK works
ZKSNARK介绍
李威翰,张宗洋,周子博等.简洁非交互零知识证明综述[J].密码学报,2022,9(03):379-447.DOI:10.13868/j.cnki.jcr.000525.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ExpressLRS开源之RC链路性能测试

ExpressLRS开源之RC链路性能测试 1. 源由2. 分析3. 测试方案4. 测试设计4.1 校准测试4.2 实验室测试4.3 拉距测试4.4 遮挡测试 5. 总结6. 参考资料 1. 源由 基于ExpressLRS开源基本调试验证方法,对RC链路性能进行简单的性能测试。 修改设计总能够满足合理的需求&a…

达梦数据库管理用户和创建用户介绍

概述 本文主要对达梦数据库管理用户和创建用户进行介绍和总结。 1.管理用户介绍 1.1 达梦安全机制 任何数据库设计和使用都需要考虑安全机制,达梦数据库采用“三权分立”或“四权分立”的安全机制,将系统中所有的权限按照类型进行划分,为每…

浅谈 Pytest+HttpRunner 如何展开接口测试!

软件测试有多种多样的方法和技术,可以从不同角度对它们进行分类。其中,根据软件生命周期,针对不同的测试对象与目标,可将测试过程分为 4 个阶段:单元测试、集成测试、系统测试和验收测试。本文着重介绍了如何借用 pyte…

基于机器学习的fNIRS信号质量控制方法

摘要 尽管功能性近红外光谱(fNIRS)在神经系统研究中的应用越来越广泛,但fNIRS信号处理仍未标准化,并且受到经验和手动操作的高度影响。在任何信号处理过程的开始阶段,信号质量控制(SQC)对于防止错误和不可靠结果至关重要。在fNIRS分析中&…

Endnote中查看一个文献的分组的具体方法——以Endnote X8为例

Endnote中查看一个文献的分组的具体方法——以Endnote X8为例 一、问题 当Endnote中使用分类方法对文献进行分组管理后,有时需要重新调整该文献的分组,则需要找到这个文献在哪个分组中。本文阐述怎样寻找一个文献的分组的位置信息。 二、解决方法 1.选…

基于单片机的智能数字电子秤proteus仿真设计

一、系统方案 1、当电子称开机时,单片机会进入一系列初始化,进入1602显示模式设定,如开关显示、光标有无设置、光标闪烁设置,定时器初始化,进入定时器模式,如初始值赋值。之后液晶会显示Welcome To Use Ele…

Rust之自动化测试(一):如何编写测试

开发环境 Windows 10Rust 1.71.1 VS Code 1.81.1 项目工程 这里继续沿用上次工程rust-demo 编写自动化测试 Edsger W. Dijkstra在他1972年的文章《谦逊的程序员》中说,“程序测试可以是一种非常有效的方法来显示错误的存在,但它对于显示它们的不存在…

【业务功能篇90】微服务-springcloud-检索服务-ElasticSearch实战运用-DSL语句

商城检索服务 1.检索页面的搭建 商品检索页面我们放在search服务中处理&#xff0c;首页我们需要在mall-search服务中支持Thymeleaf。添加对应的依赖 <!-- 添加Thymeleaf的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifa…

Solidity 小白教程:4. 函数输出 return

Solidity 小白教程&#xff1a;4. 函数输出 return 这一讲&#xff0c;我们将介绍Solidity函数输出&#xff0c;包括&#xff1a;返回多种变量&#xff0c;命名式返回&#xff0c;以及利用解构式赋值读取全部和部分返回值。 返回值 return 和 returns Solidity有两个关键字与…

java八股文面试[JVM]——类初始化过程

回顾类加载过程&#xff1a; 知识来源&#xff1a; 【2023年面试】Class初始化过程是什么_哔哩哔哩_bilibili

物联网智慧种植农业大棚系统

一、项目背景 智慧农业是是将物联网技术和农业生产箱管理的新型农业&#xff0c;依托部署在农业生产现场的各种传感节点&#xff0c;以物联网网关为通道形成数据传输网络&#xff0c;可以实现控制柜、环境监测传感器、气象监测机器等设备的远程监控&#xff0c;达到及时高校的…

LRU代码实现

LRU&#xff1a;最久未使用置换原则 均以3个内存块举例。 FIFO&#xff1a;先进先出 LRU算法代码实现&#xff1a; /* 双链表&#xff1a;最底端是最久未使用的 哈希表&#xff1a;通过缓存数据的键映射到其在双向链表中位置对hash表做put和get&#xff1a;给LRU的cache用map…

高通开发系列 - 5G网络之QTI守护进程服务介绍

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 代码位置和依赖关系功能介绍代码逻辑讲解外设节点关注的目录socket服务端初始化DPM客户端监听守护关键的数据结构体…

day 30 动态GDP柱状图绘制

列表.sort(key选择排序依据的函数&#xff0c;reverseTrue|False) 参数key:要求传入一个函数&#xff0c;表示将列表的每一个元素传入函数当中&#xff0c;返回排序的依据&#xff0c; 参数reverse,是否反转排序结果&#xff0c;True降序&#xff0c;False升序 my_list [[&…

C语言每日一练------(Day3)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今天练习题的关键字&#xff1a; 尼科彻斯定理 等差数列 &#x1f493;博主csdn个人主页&#xff1a…

速腾RS16的ROS2驱动

文章目录 本机软硬件环境ROS2驱动下载ROS2编译设置固定IP编辑配置文件测试参考 本机软硬件环境 ROS2-foxyubuntu20.04速腾RS16 ROS2驱动下载 mkdir laser_ws && cd laser_ws/ mkdir src && cd src/ git clone https://github.com/RoboSense-LiDAR/rslidar_m…

【OpenCV实战】3.OpenCV颜色空间实战

OpenCV颜色空间实战 〇、Coding实战内容一、imread1.1 函数介绍1.2 Flags1.3 Code 二. 色彩空间2.1 获取单色空间2.2. HSV、YUV、RGB2.3. 不同颜色空间应用场景 〇、Coding实战内容 OpenCV imread()方法不同的flags差异性获取单色通道【R通道、G通道、B通道】HSV、YUV、RGB 一…

el-table表尾添加合计行,自动合计,且特殊列自定义计算展示

效果如图 1.element-ui的table表格有合计功能&#xff0c;但是功能却不完善&#xff0c;会有不显示和计算出现错误的问题&#xff0c;项目中有遇到&#xff0c;所以记录下 show-summary&#xff1a;自动合计 getSummaries&#xff08;&#xff09;&#xff1a;对合计行进行特…

2023阿里云学生服务器免费领取入口_学生认证流程

2023阿里云学生服务器价格可以免费申请&#xff0c;阿腾云分享阿里云学生服务器优惠活动入口&#xff0c;学生服务器完成学生认证领取流程&#xff0c;阿里云学生机配置为云服务器ECS、2核2G、1M带宽、40G系统盘&#xff0c;完成学生身份认证即可免费领取1台ECS&#xff0c;在云…

1.8.7 练习 冒泡排序 Bubble Sort(提取函数)

C自学精简教程 目录(必读) 1 前驱知识点 for循环语句 、 if语句、函数 、动态内存 2 排序 是将元素按照从小到大的顺序存放的方法。 一开始元素可能并不是按照从小到大的顺序存放的。 这时候我们需要找到需要调整的元素对&#xff0c;并交换这两个元素的值&#xff0c;不…