BCSkill (Block chain skill )
区块链中文技术社区

只讨论区块链底层技术
遵守一切相关法律政策!

Beam-SNARK 的工作原理

零知识简洁非交互式知识论证 (Beam-SNARK) 是一种开创性的方法,它允许人们在不透露任何其他信息的情况下证明陈述的真实性。但这为什么有用呢?

零知识证明有广泛的应用场景,例如:

1. 关于私人数据的证明陈述:

  • 确认某人的银行余额超过某个限额,但不透露具体金额。
  • 核实银行在过去一年内没有与特定实体进行过交易。
  • 匹配 DNA 样本但不透露完整的基因图谱。
  • 显示高于一定值的信用评分但不透露详细信息。

2. 匿名授权

  • 证明用户有权访问网站的限制区域,而无需分享其身份(例如登录凭据)。
  • 确认在授权地区的居住权但不透露具体位置。
  • 在不透露身份的情况下验证有效地铁通票的所有权。

3. 匿名支付:

  • 无需关联身份即可进行付款。
  • 不披露收入而纳税。

4. 外包计算:

  • 委托复杂的计算,同时确保结果正确,无需重复工作。
  • 将区块链模型从通用计算转变为一方计算、其他方验证的模型。

零知识证明的底层数学和密码学简直就是奇迹。自 1985 年开创性的论文“交互式证明系统的知识复杂性”以来,该领域已经活跃了四十多年。非交互式证明的引入在区块链环境中尤为关键。

在任何零知识证明系统中,都有两个关键参与者:

  • 证明者:想要让验证者相信某个陈述的真实性的人。
  • 验证者:无需获取任何额外知识即可检查证明者主张的有效性的人。

该系统必须满足三个核心属性:

  1. 完整性:如果陈述是真实的,则证明者可以说服验证者。
  2. 健全性:作弊的证明者无法让验证者相信错误的陈述。
  3. 零知识:交互仅揭示陈述是否真实,而不揭示其他任何内容。

Beam-SNARK 将这些原理应用于通用计算,为实际应用提供了一个优雅的解决方案。

证明的媒介

为了理解 Beam-SNARK,让我们从一个简单的例子开始,而不深入研究零知识或交互性。

假设我们有一个 10 位的数组,并且我们想要向验证者(例如,程序)证明所有位都设置为 1。

假设我们有一个长度为 10 的位数组,并且我们想要向验证者(例如程序)证明所有这些位都设置为 1。

验证者每次只能检查一位。为了验证该声明,验证者可以按随机顺序检查位:

  • 一次成功检查后,验证者对该声明的信心为 10%。
  • 如果某个位为 0,则该断言立即被推翻。
  • 为了获得更高的置信度(例如 50% 或 95%),验证者必须执行更多检查,与阵列的大小成正比。这种方法对于大型数据集来说不切实际。

相反,我们可以利用具有独特属性的多项式。多项式在图形上显示为曲线,由数学方程定义。

上图曲线对应多项式:f(x) = x³ — 6x² + 11x — 6。多项式的次数由其 x 的最大指数决定,在本例中为 3。

多项式有一个优点,即如果我们有两个次数最多为 d 的不相等多项式,它们最多只能在 d 个点处相交。例如,让我们稍微修改一下原始多项式 x³ — 6x² + 10x — 5,并将其可视化为绿色:

如此微小的变化会产生截然不同的结果。事实上,不可能找到两个不相等的多项式,它们共享一条连续的曲线块(单点块的情况除外)。

此属性源自查找公共点的方法。如果我们想找到两个多项式的交点,我们需要使它们相等。例如,要找到多项式与x轴的交点(即f ( x ) = 0),我们使x ³ — 6 x ² + 11 x — 6 = 0相等,并且该等式的解将是这些公共点:x = 1、x = 2 和x = 3,您也可以清楚地看到,在上图上蓝色曲线与x轴线相交的位置,情况确实如此。

同样,我们可以将原始多项式和修改后的多项式相等来找到它们的交点。

所得到的多项式是 1 阶的,显然有一个解x = 1。因此只有一个交点:

对于任意次数为d 的多项式,任何此类方程的结果始终是次数最多为d的另一个多项式,因为没有乘法可以产生更高的次数。例如:5 x ³ + 7 x ² — x + 2 = 3 x ³ — x ² + 2 x — 5,简化为 2 x ³ + 8 x ² — 3 x + 7 = 0。代数基本定理告诉我们,次数为d 的多项式最多可以有d 个解(更多内容见下文),因此最多有d 个共享点。

因此,我们可以得出结论,在任意点处对任何多项式的求值类似于对其唯一身份的表示。让我们在x = 10 处求值示例多项式。

事实上,在所有要评估的x选择中,只有最多 3 个选择在这些多项式中具有相同的评估,而所有其他选择都会有所不同。

这就是为什么如果证明者声称知道某个多项式(无论其度数有多大),而验证者也知道的话,他们可以遵循一个简单的协议:

  • 验证者为x选择一个随机值,并在本地评估多项式
  • 验证者将x提供给证明者,并要求其计算相关多项式
  • 证明者在x 处评估多项式,并将结果提供给验证者
  • 验证者检查本地结果是否等于证明者的结果,如果是,则该语句具有很高的置信度

例如,如果我们考虑x的整数范围从 1 到 1⁰⁷⁷,则评估不同的点数为 1⁰⁷⁷ — d 。因此, x意外“击中”任何d个共享点的概率等于(这被认为是可以忽略不计的):

注意:与低效的位校验协议相比,新协议仅需要一轮,并且对该声明具有压倒性的信心(假设 d 足够小于范围的上限,则几乎为 100%)。

这就是为什么多项式是 Beam -SNARK的核心,尽管也可能存在其他证明媒介。

原文:https://medium.com/@Moonchain_com/why-and-how-beam-snark-works-94f703cf1413

Solana 禁用原有初始化账户

需求

Solana原版代码会在初始化时,预先会创建一系列账户地址和余额
跟进代码,确定初始化地址用途,是否必须的,是否可禁掉

跟进代码

genesis/src/genesis_accounts.rs

fn add_stakes(
    genesis_config: &mut GenesisConfig,
    staker_infos: &[StakerInfo],
    unlock_info: &UnlockInfo,
) -> u64 {
    staker_infos
        .iter()
        .map(|staker_info| create_and_add_stakes(genesis_config, staker_info, unlock_info, None))
        .sum::<u64>()
}

pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig, mut issued_lamports: u64) {
    // add_stakes() and add_validators() award tokens for rent exemption and
    //  to cover an initial transfer-free period of the network

    issued_lamports += add_stakes(
        genesis_config,
        CREATOR_STAKER_INFOS,
        &UNLOCKS_HALF_AT_9_MONTHS,
    ) + add_stakes(
        genesis_config,
        SERVICE_STAKER_INFOS,
        &UNLOCKS_ALL_AT_9_MONTHS,
    ) + add_stakes(
        genesis_config,
        FOUNDATION_STAKER_INFOS,
        &UNLOCKS_ALL_DAY_ZERO,
    ) + add_stakes(genesis_config, GRANTS_STAKER_INFOS, &UNLOCKS_ALL_DAY_ZERO)
        + add_stakes(
            genesis_config,
            COMMUNITY_STAKER_INFOS,
            &UNLOCKS_ALL_DAY_ZERO,
        );

    // "one thanks" (community pool) gets 500_000_000SOL (total) - above distributions
    create_and_add_stakes(
        genesis_config,
        &StakerInfo {
            name: "one thanks",
            staker: "7vEAL3nS9CWmy1q6njUUyHE7Cf5RmyQpND6CsoHjzPiR",
            lamports: (500_000_000 * LAMPORTS_PER_SOL).saturating_sub(issued_lamports),
            withdrawer: Some("3FFaheyqtyAXZSYxDzsr5CVKvJuvZD1WE1VEsBtDbRqB"),
        },
        &UNLOCKS_ALL_DAY_ZERO,
        None,
    );
}

分析

  1. 创建多个质押锁仓地址,并初始化对应量余额
  2. 创建community pool,余额为 500_000_000 - (issued_lamports - faucet_lamports)

从功能来说不是私链初始化链所必须的

Diff

 genesis/src/main.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/genesis/src/main.rs b/genesis/src/main.rs
index 6b7efd5e66..45154443ab 100644
--- a/genesis/src/main.rs
+++ b/genesis/src/main.rs
@@ -15,7 +15,7 @@ use {
         },
     },
     solana_entry::poh::compute_hashes_per_tick,
-    solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account},
+    solana_genesis::{Base64Account},
     solana_ledger::{blockstore::create_new_ledger, blockstore_options::LedgerColumnOptions},
     solana_sdk::{
         account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
@@ -597,7 +597,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
         .map(|account| account.lamports)
         .sum::<u64>();

-    add_genesis_accounts(&mut genesis_config, issued_lamports - faucet_lamports);
+    // add_genesis_accounts(&mut genesis_config, issued_lamports - faucet_lamports);

     let parse_address = |address: &str, input_type: &str| {
         address.parse::<Pubkey>().unwrap_or_else(|err| {

测试

  1. 重置链网络
  2. 查看初始化地址,是否有非预期地址
  3. 查看bootstrap-validator 出块,手续费接收等是否正常

Solana 区块浏览器定制网络配置

github: https://github.com/solana-labs/explorer

Diff

From 88f5c222a19c983fae1c950cc3612d6bbc53a31c Mon Sep 17 00:00:00 2001
From: Hendrik Hofstadt <hendrik@bool.capital>
Date: Sun, 18 Feb 2024 10:19:46 +0100
Subject: [PATCH] reduce cluster options to SPE

---
 app/providers/cluster.tsx                  |  5 ++++-
 app/providers/stats/SolanaPingProvider.tsx |  2 +-
 app/utils/cluster.ts                       | 11 +++++++++--
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/app/providers/cluster.tsx b/app/providers/cluster.tsx
index deef8a2..04bcc6b 100644
--- a/app/providers/cluster.tsx
+++ b/app/providers/cluster.tsx
@@ -59,9 +59,12 @@ function parseQuery(searchParams: ReadonlyURLSearchParams | null): Cluster {
             return Cluster.Devnet;
         case 'testnet':
             return Cluster.Testnet;
+        case 'localspe':
+            return Cluster.SPE;
         case 'mainnet-beta':
-        default:
             return Cluster.MainnetBeta;
+        default:
+            return Cluster.SPE;
     }
 }

diff --git a/app/providers/stats/SolanaPingProvider.tsx b/app/providers/stats/SolanaPingProvider.tsx
index 76b2682..6d5df04 100644
--- a/app/providers/stats/SolanaPingProvider.tsx
+++ b/app/providers/stats/SolanaPingProvider.tsx
@@ -12,7 +12,7 @@ const FETCH_PING_INTERVAL = 60 * 1000;
 function getPingUrl(cluster: Cluster) {
     const slug = clusterSlug(cluster);

-    if (slug === 'custom') {
+    if (slug === 'custom' || slug === 'localspe') {
         return undefined;
     }

diff --git a/app/utils/cluster.ts b/app/utils/cluster.ts
index f30963f..734f121 100644
--- a/app/utils/cluster.ts
+++ b/app/utils/cluster.ts
@@ -8,10 +8,11 @@ export enum Cluster {
     MainnetBeta,
     Testnet,
     Devnet,
+    SPE,
     Custom,
 }

-export const CLUSTERS = [Cluster.MainnetBeta, Cluster.Testnet, Cluster.Devnet, Cluster.Custom];
+export const CLUSTERS = [Cluster.SPE, Cluster.Custom];

 export function clusterSlug(cluster: Cluster): string {
     switch (cluster) {
@@ -21,6 +22,8 @@ export function clusterSlug(cluster: Cluster): string {
             return 'testnet';
         case Cluster.Devnet:
             return 'devnet';
+        case Cluster.SPE:
+            return 'localspe';
         case Cluster.Custom:
             return 'custom';
     }
@@ -34,6 +37,8 @@ export function clusterName(cluster: Cluster): string {
             return 'Testnet';
         case Cluster.Devnet:
             return 'Devnet';
+        case Cluster.SPE:
+            return 'Local SPE';
         case Cluster.Custom:
             return 'Custom';
     }
@@ -59,9 +64,11 @@ export function clusterUrl(cluster: Cluster, customUrl: string): string {
             return process.env.NEXT_PUBLIC_MAINNET_RPC_URL ?? modifyUrl(MAINNET_BETA_URL);
         case Cluster.Testnet:
             return process.env.NEXT_PUBLIC_TESTNET_RPC_URL ?? modifyUrl(TESTNET_URL);
+        case Cluster.SPE:
+            return "http://localhost:8899";
         case Cluster.Custom:
             return customUrl;
     }
 }

-export const DEFAULT_CLUSTER = Cluster.MainnetBeta;
+export const DEFAULT_CLUSTER = Cluster.SPE;
--
2.42.0

Solana 修改最小质押量

需求

自定义最小的质押量,限制外部的加入门槛

代码分析

sdk/program/src/stake/instruction.rs

#[error("delegation amount is less than the minimum")]
InsufficientDelegation,

programs/stake/src/stake_state.rs

fn validate_delegated_amount(
    account: &BorrowedAccount,
    meta: &Meta,
    feature_set: &FeatureSet,
) -> Result<ValidatedDelegatedInfo, InstructionError> {
    let stake_amount = account
        .get_lamports()
        .saturating_sub(meta.rent_exempt_reserve); // 确保委托的质押金额有效。这将检查帐户是否满足委托质押的最低余额要求。如果不满足,则返回错误。

    // 质押账户可能会以低于最低委托额的质押额进行初始化,因此请在委托前检查是否满足最低要求。
    if stake_amount < crate::get_minimum_delegation(feature_set) {
        return Err(StakeError::InsufficientDelegation.into());
    }
    Ok(ValidatedDelegatedInfo { stake_amount })
}
/// 可以委托的最低股权金额,以 lampors 为单位。
/// 注意:这也用于计算股权账户的最低余额,即租金豁免储备加上最低股权委托。
#[inline(always)]
pub fn get_minimum_delegation(feature_set: &FeatureSet) -> u64 {
    if feature_set.is_active(&feature_set::stake_raise_minimum_delegation_to_1_sol::id()) {
        const MINIMUM_DELEGATION_SOL: u64 = 1;
        MINIMUM_DELEGATION_SOL * LAMPORTS_PER_SOL
    } else {
        #[allow(deprecated)]
        solana_sdk::stake::MINIMUM_STAKE_DELEGATION
    }
}

总结

目前测试验证节点,直接硬编码,设置一个较大值来限制外部加入,修改测试代码如下


/// 可以委托的最低股权金额,以 lampors 为单位。
/// 注意:这也用于计算股权账户的最低余额,即租金豁免储备加上最低股权委托。
#[inline(always)]
pub fn get_minimum_delegation(feature_set: &FeatureSet) -> u64 {
    const MINIMUM_DELEGATION_SOL: u64 = 1000000000000;
    MINIMUM_DELEGATION_SOL * LAMPORTS_PER_SOL
}