區塊鏈重要基礎知識10——比特幣挖礦

1. 比特幣礦工的任務

注意:本節結合比特幣的運行機制食用更佳。

1.1 主要內容

1.1.1 已經瞭解的:

  • 比特幣依賴這些礦工們而運行的——他們查證交易記錄,製造和儲存所有的區塊,並對被寫入區塊鏈的區塊達成共識。我們還知道礦工們會從中得到一些獎勵。

1.1.2 這裏需要進行說明的:

  1. 這些礦工都是誰?
  2. 他們是如何進入這個行業的?
  3. 他們是怎麼運作的?
  4. 他們的商業模式是什麼?
  5. 他們對環境造成什麼影響?

1.1.3 本節內容如下圖所示:

依賴曠工的支付服務
1.這些礦工都是誰?
2.他們是如何進入這個行業的?
3.他們是怎麼運作的?
4.他們的商業模式是什麼?
5.他們對環境造成什麼影響?
1.礦工的任務
2.礦工所需硬件
3.礦池
5.能源消耗和生態環保
4.挖礦的激勵和政策

1.2 礦工的任務

要成爲比特幣礦工,你必須加入比特幣網絡並與其他節點相聯。建立鏈接之後,需完成以下幾個任務:

1.2.1 背景概念理解

其中有個總體的概念交易與區塊之間的關係需要理解:

  • 交易是被打包進區塊中,而各個區塊之間用hash指針進行區塊鏈,形成一個只可以進行增加不可以進行刪減修改的數據庫
  • 示意圖如下:

交易與區塊之間的關係

1.2.2 詳細任務流程

  1. 驗證節點階段
    1. 維護區塊鏈網絡:可以要求其他節點把區塊鏈上的歷史記錄(在你加入區塊鏈網絡之前的)同步過來。然後,監聽那些被廣播到網絡上的新的區塊。然後進行2的操作,驗證區塊交易
    2. 監聽區塊交易廣播。監聽時做兩個驗證a. a.\space然後驗證每一個區塊的交易簽名是正當有效的;b. b.\space區塊的交易輸出沒有被重複支付(每一個區塊有相應的隨機數);
  2. 製作有效的區塊:
    1. 組裝一個備選區塊。擁有最新的全部區塊鏈數據備份之後,可以開始製造你自己的區塊了。保證你建立的新區塊裏的每筆交易都是正當有效的,然後將交易放進相應的區塊中;
    2. 找到一個讓你的區塊有效的隨機數。這一步的工作量最大,也是礦工工作中最難的一個環節。
  3. 和其他礦工競爭,讓大家接受自己創造的區塊
    1. 希望你的區塊被全網接受。進入共識階段讓其他的礦工接受你的區塊,然後從該區塊開始繼續接龍下去,而不是從別人發現的區塊開始。
    2. 利潤。如果所有其他礦工接受了你的區塊,那你就能獲取利潤。
      • 在2015年,一個區塊的獎勵是25個比特幣,大約在10 000美元左右。此外,如果在該區塊裏的任何交易都有交易費,所有交易費也會爲礦工所有。到目前爲止,交易費作爲額外收入,相對來說還比較低,大概是一個區塊默認獎勵的1%。

1.3 對有效區塊的理解以及設定

1.3.1 流程步驟2——尋找有效區塊

1. 等價命題

如何找到一個使區塊有效的隨機數的問題?

2. 區塊以及交易連接的結構

區塊鏈主要有兩層基於哈希函數的結構。

  1. 區塊鏈上,每個區塊的頭部都有一個指針指向其前一個區塊,
  2. 在每一個區塊裏,包括所有交易的梅克爾樹。

3. 尋找有效區塊的步驟:

  1. 從你的交易池中選出一系列有效的交易並且編譯成梅克爾樹;交易數<<上限

  2. 將默克爾樹與其他相關數據組裝成一個新的區塊,新區塊有兩個部分應該注意:

    1. 新的區塊頭部指向區塊鏈上的前一個區塊;
    2. 新區塊的頭部,有一個32位的隨機數區域,做到該隨機數能使整個區塊的哈希值<<目標值。
      1. 出現隨機數始終滿足不了條件的時候:
        • 可以嘗試更改幣基裏面的隨機數,但是不能更改其他交易的隨機數,這是由於幣基是自身節點用來創造比特幣的,所以隨機數在這個階段是能夠進行改動的,但是其他交易就不一樣了,在交易發起的時候就已經進行了設定;

    尋找有效區塊

4. 一個疑惑:每個人都在運算同一個謎題嗎?

  • 首先可能不在同一個區塊;
  • 其次即使在同一個區塊的話,由於默克爾樹底層是hash實現的原因使得只要結構中交易有一點不同或者次序有一點不同就可能導致最後的結構大相徑庭

1.3.2 設定有效區塊的決定難度

1. 歷史難度

其難度:在2015年之前,大約2682^{68}個臨時隨機數裏只有不到一個可以成功

2. 下一個難度公式以及意義

但是這個難度其實是不斷變化波動的,每挖出2 016個區塊,挖礦難度會改變一次,這個週期大約是兩個星期。難度的改變是根據上2016個區塊的挖礦效率來決定的。公式如下:
=×2016×102016 下一個難度=\frac{上一個難度 \times 2016 \times 10分鐘}{產生出2016個區塊所花費的時間}
注:2016×10=2016 \times 10分鐘=兩週

意義:測量全網難度進而維持平均每10分鐘產生一個新的區塊的速度,作爲平衡的一個作用:

  1. 如果這個週期太短,難度會隨着每一個週期找到的區塊的數目的不同而波動(概率問題)。
  2. 如果太長,整個網絡的哈希算力會與難度大大地失去平衡(難度的調整滯後於計算能力的變化),最終產生很多漏洞

3. 難度趨勢變化以及規律總結

挖礦難度會隨着時間不斷地增加。其增加不一定是穩定線性或者是指數型,礦工越多使之效率增加那麼隨之而來挖礦難度自然也會相應變化,有一個不是線性的那麼最終的變化就不會是線性的

找到一個有效區塊所花費的時間2014年

找到一個有效區塊所花費的時間2015年

  • 注:y軸開始於460秒。找到一個有效區塊花費的時間是2 016個區塊樣本花費時間的平均值。由於當時全網挖礦速度的連續快速增長,找到一個有效區塊所花費的時間在兩週的時間內穩步減少。

所以區塊產生時間的增長有一個水平線進行衡量,是根據上一個難度區間2016個區塊的平均效率來定,如果大於平均算力的話就上升,小於的話就下降,這僅僅是針對於一個難度區間時間內的,因爲在一個難度時間區間它的難度是不變的,之後就需要重新進行調整

糟糕的情況就是“死亡螺旋”:不斷下降的比特幣價格導致挖礦無利可圖,礦工們因此而退出挖礦(全網運算能力下降),繼而進一步導致價格下跌

2. 挖礦所需硬件

2.1 挖礦的難度——hashhash函數

挖礦難度主要在於hashhash函數,而區塊鏈主要使用的hashhash函數SHA256SHA-256,之所以選擇這一hashhash函數是因爲在當時的加密算法裏面,SHA256SHA-256的安全性是最高的,其原理如下圖:

SHA-256原理

SHA-256名稱中的“256”代表它有256位的狀態和輸出,屬於SHA-2家族,現在已經有更加安全的SHA-3出現,但是區塊鏈的時候只是SHA-256,所以最終使用的也是SHA-256函數

每一輪運算選擇一定數量的字段——有些會進行一些小的逐位調整

2.2 線性反饋移位寄存器

線性反饋移位寄存器是hash函數的設計靈感:

  • 每一輪運算選擇一定數量的字段——有些會進行一些小的逐位調整——最終進行32位模加法運算(modular addition),然後運算結果被移到狀態最左的第一個字段,這樣使得整個狀態進行向右位移。這種設計的思路來自簡單位的線性反饋移位寄存器(LinearFeedback Shift Registers,簡稱LFSR)。

2.2.1 定義

因爲有相應的反饋函數,並沒有中間的運算都是根據反饋函數計算的,而且變量就存在了每一個寄存器中;

  • 線性反饋移位寄存器(linear feedback shift register, LFSR)是指,給定前一狀態的輸出,將該輸出的線性函數再用作輸入的移位寄存器。異或運算是最常見的單比特線性函數:對寄存器的某些位進行異或操作後作爲輸入,再對寄存器中的各比特進行整體移位。

    輸出到
    前一狀態
    當前

    線性反饋移位寄存器

其中,gng_n爲反饋係數,取值只能爲0011,取爲00時表明不存在該反饋之路,取爲11時表明存在該反饋之路;這裏的反饋係數決定了產生隨機數的算法的不同。用反饋函數表示成y=a0x0+a1x+a2x2.......y=a_0x^0+a_1x+a_2x^2.......反饋函數爲線性的叫線性移位反饋序列,否則叫非線性反饋移位序列。

首先我們看最簡單的反饋函數的線性反饋移位寄存器:y=x0+x1+x2+.......y=x_0+x_1+x_2+.......如下所示:

  • 我們首先得明確輸入以及輸出;\oplus爲異或運算

最簡單的線性反饋移位寄存器

那麼它具有以下幾個特性:

  1. 初始狀態相同,輸出序列相同(也就是說初始狀態決定輸出序列)
  2. 輸出序列看起來是隨機序列,但是達到一定位數後會循環
  3. LFSR可以產生的最長的隨機序列是2n12^n−1的長度,其中nn表示寄存器數目
    • 由於這些特性,LFSR常被用來生成隨機碼,在密碼學中有重要應用。大名鼎鼎的CRC就可以通過LFSR來產生和校驗。在很多文章中,尤其是計算機相關的研究中,人們更多的把LFSR用多項式來表示。

2.2.2 非線性反饋分類

兩種類型的非線性反饋:

  1. 斐波那契LFSR也可以稱爲多到一型LFSR,即抽頭序列對應bit位置的多個觸發器的輸出通過異或邏輯來驅動一個觸發器的輸入。如下圖所示:

    斐波那契LFSR1
    斐波那契LFSR2

  2. 伽羅瓦LFSR和斐波那契剛好相反,它是一到多型的LFSR,即最後一個觸發器的輸出通過與抽頭序列對應位置觸發器前一級觸發器的輸出異或邏輯驅動多個抽頭序列對應位置觸發器的輸入。如下圖所示:

    伽羅瓦LFSR1

    伽羅瓦LFSR2

2.3 三種挖礦方式:CPU和GPU、現場可編程門陣列挖礦

2.3.1 CPU挖礦

CPU挖礦的僞代碼如下:

TARGET(65535 < 208) / DIFFICULTY;
coinbase_nonce;
while (1)
{
    header = makeBlockHeader(transactions, coinbase_nonce);
    for (header - nonce - ; header_nonce < (1 << 32); header_nonce +)
    {
        if (SHA256(SHA256(makeBlock(header, header_nonce))) < TARGET)
            break; //block found!
    }
    coinbase_nonce++;
}

一臺高端的個人桌面電腦,每秒可以計算大約2千萬次哈希函數(20MH/s),按照這個速度,根據2015年早期的難度水平(267),大概需要幾十萬年來找到一個有效區塊。

2.3.2 GPU挖礦

優勢:GPU都有高吞吐量和高並行處理功能

缺點:有大量的內置硬件來進行圖形處理,這些特定硬件對比特幣挖礦沒有任何用處,比如它們大量的浮點運算單元(floating point units),在SHA-256的運算中完全用不到。

一個非常高端的顯卡經過超頻之後可能使得運行速度達到200MH/s,也就是說,每秒可以進行2億次哈希運算,這是用CPU不可能達到的一個數量級

2.3.3 現場可編程門陣列挖礦

FPGA的工作原理是在追求定製硬件的最佳性能的同時,用戶可以現場調試或者修改硬件參數。

計算速度:精心使用FPGA可以使得運算速度上升到1GH/s,也就是每秒10億次哈希運算

但是有兩個很嚴重的缺陷:

  1. 需要一直超頻使用,容易產生很多報錯和故障;
  2. 優化FPGA的32位加法處理上十分困難,而這在SHA-256的運算中非常關鍵。

最關鍵的是即使犧牲了這麼多但是在性能功耗的提升仍然只有這麼多

2.3.4 專用集成電路技術挖礦

當今的挖礦市場主要被ASIC所主導。這些IC芯片(集成電路芯片)被設計、製造、優化,就是爲了比特幣挖礦這個唯一目的,但是ASIC芯片的壽命十分短暫,因爲他的性能不斷被更先進的淘汰

2.3.5 如今:專業挖礦的天下

礦已經從個人領域轉到了大型專業挖礦中心。爲了保持競爭優勢,運作這些挖礦中心的公司不願意公佈其運營細節。據猜測,這些運營者大量採購打過折的更新的功效更高的ASIC礦機而不是採購那些能夠直接出售給個人的ASIC礦機來維持利潤。

挖礦中心

挖礦中心,需要具備三個重要因素:氣候(溫度較低)、電費(便宜)、網絡接入速度(穩定且快),所以格魯吉亞和冰島成爲比特幣挖礦中心的首選之地。

與挖金礦有相似之處:

  • 而歷史上的挖金礦則是從個人拿着盤子在沙裏淘金,到一小羣人用流沙槽來淘金,再到一羣人用水沖刷金山來淘金,直到現代機械化露天挖礦。比特幣與黃金都從個人操作爲主逐步演變爲大公司專業運作。另外一個相似點就是,大多數的利潤都被設備製造商拿走了,不管是黃金採掘設備還是比特幣ASIC礦機生產商,而埋單的都是那些希望一夜致富的人。

    1.人拿着盤子在沙裏淘金
    2.用水沖刷金山
    3.現代機械化露天挖礦
    挖金礦
    淘金
    演變爲大公司運作
    挖比特幣礦
    相同點
    1.大多數的利潤都被設備製造商拿走了
    2.演變爲大公司運作

有個問題值得思考:

  • 用ASIC挖礦是唯一一種可以賺錢的比特幣挖礦手段,但對個體礦工來說週期長以及定價高。那麼未來的發展如何?
    1. 小規模礦工是否永遠不可能再參與到比特幣挖礦中?
    2. 是否有辦法把小規模礦工重新納入挖礦體系中去?
    3. 更重要的是,現在使用的ASIC和專業挖礦中心是否已經違反了比特幣當初設計的初衷:一個完全去中心化的系統,在這個系統上裏每個人都能用自己的電腦去挖礦。

並且及時有其他的幣種,如果依舊與比特幣原理類似,必然導致它也會和比特幣經歷同樣的階段。從CPU到GPU,再到FPGA,或者直接到ASIC的過程並且如果想要經歷這些階段前提還需要這些幣種比較成功。

3. 能源消耗和生態環保

算力單位換算如下圖所示:

算力單位

3.1 藍道爾原理:

任何一個不可逆轉的計算都會消耗一定的能源。而挖礦就是一種不可逆的計算

3.2 能源消耗的幾個方面

每進行一個不可逆的數位運算都會消耗一個最小量的焦耳,能源都是從一種形式轉變成另外一種形式,那麼比特幣挖礦的過程是如何消耗能源的?

  1. 內涵能源:原材料被生產的時候消耗的能源
  2. 電能:當礦機啓動開始挖礦時,它就會消耗電能
  3. 冷卻:在非常寒冷的地方可以降低冷卻成本

內涵能源和電能的消耗(每單位挖礦工作完成)會隨着挖礦運營規模的增加而降低,這是由於批量化的原因,但是冷卻問題的時候卻恰恰相反,這是一個不可控制的因素

3.3 能源消耗估算方法

兩種能源消耗估算方法,但是這些僅僅只是估算,如果有人拿它作爲一個很可靠的東西,那麼本身就不可信。

  1. 自上而下:通過比特幣獎勵從而計算相應的美元,把對應非美元換成電力數目
    • 獎勵→電力
  2. 自下而上:通過難度以及每秒鐘產生多少哈希數來計算最終消耗的電力,有個參照物就是:好的商業化礦機的功效數值差不多是3GH/s/W

3.4 如何有效地利用系統抵消能源消耗?

那麼比特幣這樣一個系統是在浪費電力嗎?這就在於我們是否認爲它是一個有用的系統

如何有效地對能源進行循環使用:現在提出的想法就是把它運算時的熱量當做一個取暖器

將電力轉換爲現金:由於政府對電力的一些補貼,所以這就對挖礦的時候電力提供了一些幫助,也是一種將電力轉換爲現金的方式。

4. 礦池

4.1 礦池的背景——高方差

從礦工第一年能找到有效區塊數的概率分佈上看,這個分佈差異是很大的,期望值(也就是第一年能找到區塊的平均數)是相當的低。

4.2 礦池的運營模式以及分發方式

礦池應運而生——礦池就是一個比特幣礦工互相之間的保險。一組礦工可以形成一個礦池共同進行挖礦,並指定一個幣基接受人。這個接受人就是礦池管理員。

  1. 礦池管理員如何知道礦池裏每個成員實際上到底貢獻了多少工作量呢?

  2. 同時他又是如何去分發收入的呢?

    1. 挖礦工分:通過與有效區塊的接近程度證明他的工作量

      挖礦獎勵

      1. 工分分紅:礦工在發送工分之後,管理員馬上就會對其支付獎勵,而不需要等到整個礦池發現一個有效區塊。
        • 不好的地方:一個惡意的管理員可以作爲礦工參與另外一個礦池,用這個方法攻擊另一個競爭對手,讓他的礦池無法維持下去
    2. 按實際比列分紅:每次找到一個有效區塊纔會按照工分對每個礦工進行分工,這樣的分紅方式實質是對管理員增加了壓力,他要校驗、計算和分配獎勵

4.3 應對頻繁的礦池轉換——礦工在不同礦池的跳轉

礦池轉換是我們需要考慮的問題:由於人們想要獲取高的獎勵,採取以下措施:

  • 在挖礦週期的早期(也就是上一個區塊剛剛被發現),在按實際比例分紅的礦池中挖礦,這個時候的獎勵可能相對比較高,然後只在週期的後期切換(“跳”)到一個工分分紅模式的礦池,因爲這個時候按實際比例分紅的礦池收益可能相對較低。但這樣導致的結果就是按比例分配的礦池可能無法運行。

一些方法可以在一定程度上防止這些事情的產生,比如:根據最近N個工分提交的結果才分配”

4.4 礦池協議API

礦池協議也提供了API,用於礦池管理員與每個礦工交流分派工作礦工們遞交工分給管理員。獲取有效區塊模版(getblocktemplate,簡稱GBT)就作爲一種標準化的礦池協議放進了比特幣改進方案(Bitcoin Improvement Proposal,簡稱BIP)之中。

從事存在多個互不兼容的礦池協議沒有造成太多的不便,最終可以由市場判定誰更好

有些做了一種優化,將協議寫進硬件,那麼只要一插上電就能夠將電能轉換爲收益

4.5 礦池的優缺點

在2014年6月,網絡裏最大的礦池GHash.IO,曾經變得如此巨大,其算力甚至超過了比特幣全網算力的50%。

礦池有可能會掩蓋這樣一個事實:實際上的算力集中在幾個大的挖礦機構手上,這些大的機構可以同時參與多個不同的礦池以掩蓋它們的真實規模。這種做法被稱爲“洗算力”

好處:

  1. 每一個礦池都有一箇中心化的礦池管理員在網絡中組裝區塊,所以網絡更新變得更加容易;

壞處:

  1. 中心化管理。礦池管理員實際掌握了多大的算力
  2. 減少了比特幣網絡上校驗全部交易節點的數量(全節點),慢慢演變成了一個礦池算作一個全節點

5. 挖礦的激勵和策略

在挑選一個區塊開挖之前,做策略上的選擇:

策略選擇
1.包括哪些交易
默認選擇那些交易費比較高的交易
2.對哪一個區塊進行挖礦運算
默認在最長的那條區塊鏈上繼續挖下去
3.在同一高度的多個區塊中做選擇
默認選擇最先被監聽到的那一個區塊
4.什麼時候宣佈新的區塊
默認立刻宣佈

這四種選擇都是根據自己選擇而定德,但是最終網絡只是認可最長的鏈

5.1 區塊獎勵時期存在的一系列攻擊:

  1. 分叉攻擊:

    1. 顯而易見的獲利方式——重複支付

    2. 一個惡意的礦工給一個受害者鮑勃發送了一些比特幣來購買其服務和貨品。鮑勃等到這筆支付交易被放進了最長鏈之後,甚至還等到了6個證實的時候確認支付安全之後,纔開始發貨或者提供服務。現在這個礦工開始跳到前一個區塊上開始重新挖礦——就是在那個包含他給鮑勃的支付交易區塊之前的那一塊。在這個分叉的區塊鏈裏,他插進了另一個替代交易——或者進行一個雙重支付——把那些已經支付給鮑勃的比特幣重新發送回自己的地址裏

      6個證實的時候確認支付安全
      跳到前一個區塊上,已經提交的區塊
      惡意的礦工
      受害者鮑勃
      交易
      上面的交易
      最長鏈
      開始發貨或者提供服務
      重新挖礦
      替代原本的那個交易,轉移比特幣地址
      攻擊能夠成功?
      只要足夠的節點進行確認,原先的就會失效
      • 想要這個攻擊成功,被分叉的區塊鏈必須要覆蓋當前最長的一條鏈,一旦這個情況發生,支付給鮑勃的交易就不再存在於共識的區塊鏈裏。如果這個礦工掌握佔優勢的哈希算力的話,也就是說α > 0.5,這種攻擊就會成功。
        1. 如果α > 0.5的話,發動一個分叉攻擊是很有可能發生的。
        2. 擁有近乎50%算力的攻擊者可能需要花很長時間纔可能成功,因爲有隨機性。
      • 這類攻擊最大的影響並不是它獲得的短期收益,而是摧毀大家對比特幣的信心,比特幣的擁有者們就想要把資產轉移出去,以至於比特幣價格崩潰。
  2. 通過賄賂來進行分叉攻擊:

    1. 系統外的”(out of band)——可能找到一些礦工然後直接用現金來賄賂他們。;
    2. 一個更加聰明的辦法是創建一個新的礦池,然後提供更好的獎勵來吸引其他礦工來加入,雖然不能長期維持但是可以有效地做到一個分叉攻擊
    3. 賄賂可行需要在很多假設的前提下,比如人們想要去圖一個眼前的利益
  3. 臨時保留區塊攻擊:

    • 找到一個區塊之後,不立即宣佈,在這塊上面繼續挖礦,期望你可以在其他礦工找到下一個區塊之前連續找到兩個有效區塊,在整個過程中祕密地保留你所發現的區塊。

    • 這樣導致的事情就是你一下拿出比別人更長的區塊鏈,使得別人多日的努力付諸東流,這樣能夠使得你的獲得比之前正常情況下增加一部分

      臨時保留區塊攻擊2

    • 收益可能比我們想象中的高:假設只有50%的機會可以贏得這個競賽,在α>0.25的情況下,自私挖礦可以比默認策略更有收益。如果α>0.333,即使你輸掉每一個這種競賽,仍然可以獲得更高的收益。

      • 與原本人們所以爲的相悖,以爲的是:如果沒有很大的算力——比如α≤0.5——不會有比默認策略更有利的挖礦策略。
  4. 黑名單與懲罰分叉攻擊

    1. 想把一個來自地址X的交易列入黑名單,換句話說,他想凍結從該地址出來的錢,讓這些錢變得不可用。或許他想用這個辦法來敲詐勒索一筆錢,黑名單可能難以在比特幣的世界中實施,但是另外一種手段卻可以成功實施:懲罰分支
    2. 懲罰分支:
      1. 可以宣佈拒絕在包含來自該地址的交易的區塊鏈上工作。如果你擁有大部分市場運算能力,那應該足以保證這個黑名單上的交易永遠不會被公佈。
  5. 羽量級分叉

    1. 如果沒有很大的算力,上述的幾個分叉攻擊在現實中都不太可能實現。甚至可能導致自己的利益受損,比如:
      1. 如果你宣佈拒絕接受包含某些特定交易的區塊鏈,但這條鏈被網絡上的其他礦工所接受並形成最長鏈的話,你就會發現自己被永遠排除在共識鏈之外(這就是一個硬分叉),所有你做的挖礦工作統統浪費了。更加糟糕的是,黑名單上的交易仍然存在於最長的區塊鏈上。
      2. 與其一看到從地址X裏出來的交易就宣佈你會進行永久分叉,不如宣佈你將會嘗試分叉,這樣是一種心理上的策略,通過宣稱讓別人相信你將會進行這樣一個分支,告訴別人接收來自地址X的交易是有危險,但是這個前提是你的讓人相信,實際上來說概念已經是2\partial^2,比較小,利用的是人們的心理

參考文章:

1.線性反饋移位寄存器

2.線性反饋移位寄存器的分類

3.教你如何看懂比特幣算力“EH/S”、“PH/S”、“TH/S”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章