---
title: "深入探討區塊鏈資料"
description: "了解區塊鏈資料如何在 web3 基礎設施與應用程式中被建立、儲存、存取與使用。"
---

# 深入探討區塊鏈資料

每個區塊鏈都保存著不可竄改的交易與事件記錄。Web3 應用程式仰賴區塊鏈資料來進行警示通知、儀表板呈現、決策制定，或發想新功能。這對 web3 而言至關重要,因為它驅動了從去中心化應用程式、基礎設施到 NFT 的一切。

本指南將涵蓋區塊鏈資料的所有面向,從鏈上與鏈下資料,到區塊鏈索引與 subgraphs。讀完本指南後,你應該能更深入理解區塊鏈資料是如何被建立、儲存和存取的。

## **什麼是鏈上資料?**

鏈上資料就是儲存在區塊鏈網路上的所有資訊。它是網路上曾發生過的所有交易的不可竄改記錄,並且公開供所有人查看。鏈上資料有許多不同的類型,例如:

- **交易資料:** 涵蓋區塊鏈上每筆交易的相關資訊,例如發送方與接收方、轉帳金額,以及交易手續費。
- 區塊資料:涵蓋區塊鏈上每個區塊的相關資訊,例如前一個區塊的雜湊值、區塊內包含的交易、區塊的時間戳記,以及礦工手續費與獎勵。
- **智能合約資料:** 涵蓋部署在區塊鏈上的所有智能合約的相關資訊,例如合約程式碼本身、合約狀態,以及合約發出的事件。

與鏈下資料不同,鏈上資料無法被更改,這對於全面了解區塊鏈網路的狀況相當重要。這些資料可用於追蹤區塊鏈上資產的移動、驗證交易是否成功完成,以及生成對網路活動的洞察。

鏈上資料的挑戰在於,有效地存取它可能相當繁瑣。儘管鏈上資料容易取得,但它是以機器可讀的格式編碼的;這種做法優先考量安全性,卻犧牲了人類可讀性。人類可讀的格式可以是 JSON 和 XML 之類的類型,這正是 ABI(應用二進位介面,application binary interfaces)發揮作用的地方。

### **資料結構是如何定義的?**

如前所述,鏈上資料的儲存方式與一般資料不同。它通常是以位元組碼(bytecode)之類的機器可讀格式儲存的。

ABI(應用二進位介面)協助開發者監控資料並將其解碼為人類可讀的格式。智能合約中的資料結構是使用 ABI 定義的。ABI 作為一種函式選擇器(function selector),協助定義如何與智能合約互動,以及每個函式所接受和回傳的資料類型。換句話說,它是一種標準方式,用來以人類和機器都易於理解的方式來表示資料結構。

### **區塊鏈資料儲存在哪裡?**

區塊鏈資料通常儲存在分散式帳本中,這代表它並非儲存在單一位置,而是分散在節點網路上。節點是儲存區塊鏈資料並確保其安全性的基本組成部分,因為每個節點都會維護一份資料副本。以下列出幾種不同類型的節點以及它們的高階運作方式:

- 全節點(Full nodes):顧名思義,全節點儲存整個區塊鏈歷史記錄,以及網路的最新狀態(最近的 128 個區塊)。最新狀態是所有客戶端驗證傳入交易時所需的資訊。理論上,所有先前的狀態都可以從全節點推導出來,但這需要消耗大量的運算能力。當開發者需要存取區塊鏈最新的資料和狀態時,應該向全節點查詢。以 Ethereum 為例,產生新區塊的平均時間約為 13 秒,你只能取得最近 28-29 分鐘內的鏈狀態。
- 歸檔節點(Archive nodes):除了完整的區塊鏈歷史記錄之外,[歸檔節點還會維護每個區塊的歷史狀態記錄](https://www.alchemy.com/overviews/archive-nodes)。這使得歸檔節點在處理歷史資料請求時,比全節點更有效率。當開發者需要歷史資料時,應該向歸檔節點查詢,因為它不需要像全節點那樣重新生成狀態。對於建立分析工具及其他需要快速存取歷史記錄的工具的開發者來說,歸檔節點是理想選擇。
- 輕節點(Light nodes):這類節點只儲存區塊標頭(block headers),也就是在網路上進行交易所需的最少資料。開發者在從區塊標頭擷取基本區塊鏈資料時,可以選擇向輕節點查詢。

節點並非儲存資料的唯一方式。資料也可以儲存在資料庫、雲端儲存服務,甚至內部伺服器等鏈下位置。將資料儲存在鏈下可能不如鏈上安全,但對許多應用程式來說仍然很有用,因為它的存取成本更低、速度更快。當資料儲存在鏈下時,通常只有用於定位鏈下資料所需的資訊才會儲存在區塊鏈上。

### 智能合約與區塊鏈儲存

智能合約儲存在節點內的區塊鏈上,不過智能合約本身也有其資料儲存機制。智能合約中的資料是依照所謂的合約儲存佈局(contract storage layout)來儲存的。[合約儲存佈局是指規範合約儲存變數在長期記憶體中如何排列的規則](https://www.alchemy.com/docs/smart-contract-storage-layout)。

以 [Solidity](https://www.alchemy.com/overviews/solidity)(一種用於建構智能合約的高階程式語言)為例,有 3 種不同類型的記憶體可以指示 EVM 將變數儲存在何處:memory、calldata 和 storage。

Memory:用於儲存函式執行期間所需的暫時資料

Calldata:這是一個特殊的資料位置,包含函式引數

Storage:這是資料在區塊鏈上永久儲存的位置

### **資料儲存 vs. 檔案儲存**

最簡單來說,資料儲存是將資料儲存起來以便日後檢索和使用的過程。而檔案儲存則不同於資料儲存,當實際檔案儲存的位置與檔案的中繼資料(metadata)不同時,兩者便有所區隔。這種分離通常是為了提升效能、降低成本,或增強安全性。

一種常見的檔案儲存與資料儲存分離方式,是使用像 IPFS 或 Arweave 這樣的去中心化檔案儲存系統。這些系統允許使用者將檔案儲存在分散式的電腦網路上,並且透過減少需要儲存在區塊鏈本身上的資料量來降低成本。

從高階角度來看,關於檔案的中繼資料儲存在鏈上,而檔案本身則儲存在鏈下。當應用程式需要存取檔案時,可以從中繼資料中取得 IPFS 或 Arweave 的 URL。應用程式接著可以使用此 URL 從 IPFS 或 Arweave 下載檔案。

#### **什麼是 IPFS?**

IPFS 使用一種以內容為定址依據的系統,每個檔案都是根據其 CID(內容識別碼,content identifier)來識別的。CID 是唯一的雜湊值,無論檔案儲存在何處,始終指向同一個檔案。

這意味著,如果檔案發生變更或更新,雜湊值也會隨之改變。這種以內容為定址依據的系統,使得檔案能夠根據其 CID 而非其位置來儲存和檢索。

IPFS 運作的整體流程如下:

1. 為檔案建立 CID
1. 檔案接著被上傳到 IPFS 網路
1. IPFS 會在 DHT(分散式雜湊表,distributed hash table)中儲存網路中哪個節點持有與該 CID 相關聯的檔案的資訊
1. 接著可以使用該雜湊值查詢 DHT,找出儲存該檔案的節點
1. CID 會被儲存在代幣智能合約中

#### **Arweave**

Arweave 是另一種分散式儲存解決方案,同樣使用 CID 來儲存和存取內容,並在中繼資料中引用內容。主要的差異在於,Arweave 對於誘因機制和永久性採取不同的做法,透過激勵節點永久保存資料。

### **資料發布 vs. 資料儲存 vs. 資料可用性**

要更深入理解區塊鏈資料,我們還必須了解資料發布(data publishing)、資料儲存(data storage)和資料可用性(data availability)分別代表什麼意思。簡單定義這些術語:**資料發布**是將資料公開讓區塊鏈上其他人可以取得的過程,**資料儲存**是將資料保存在區塊鏈上的過程,而**資料可用性**則是確保區塊鏈網路上所有參與者都能存取到資料的保證。

資料可用性之所以重要,是因為當驗證者(validators)將區塊加入 Ethereum 區塊鏈時,他們必須將該區塊的所有交易資料廣播給網路上的其他驗證者。驗證者的任務是執行所有交易資料,這意味著區塊鏈能處理的交易量,取決於其驗證者能執行多少交易——這簡而言之就是資料可用性問題。

資料可用性核心問題之一,是在無法取得整個區塊的情況下(資料發布),如何得知某個區塊是否已經被發布。

資料發布的主要挑戰在於,區塊生產者不會在包含未知內容的區塊之上繼續生產區塊。這意味著含有未發布資料的區塊可能會被完全忽略。一旦資料被發布,資料儲存的問題就會浮現,然而,目前尚不清楚全節點會將該資料儲存多久。這可能令人擔憂,因為我們無法強制節點保留資料,這進一步加深了對資料可用性的疑慮。

#### 模組化區塊鏈與替代資料可用性方案

模組化區塊鏈是專門處理特定功能的區塊鏈。舉例來說,一個模組化區塊鏈可能專注於資料可用性,而將其他任務,例如執行或共識,交由其他區塊鏈或系統負責。

模組化區塊鏈透過各種技術,例如鏈下資料儲存、資料壓縮、分片(sharding)等,建立替代的資料可用性層,使得發布 calldata 的成本比發布到 Ethereum 更便宜。

使用替代資料可用性層的模組化區塊鏈範例之一是 EigenDA。EigenDA 是一個建立在 Arweave 之上的去中心化資料可用性層。EigenDA 允許使用者將 calldata 發布到 Arweave,然後向 Ethereum 證明該 calldata 已經被發布。這使得使用者能夠在不需支付將 calldata 儲存在鏈上所需的高昂 gas 費用的情況下,將 calldata 發布到 Ethereum。

### **鏈上資料的類型**

現在我們已經了解什麼是鏈上資料,接下來將更深入探討不同類型的鏈上資料,以及它們是如何被產生、儲存和存取的。

#### **什麼是交易資料?**

交易資料包含與區塊鏈上一筆交易相關的所有資訊,例如:

- 發送方
- 接收方
- 轉帳金額
- 交易手續費
- 交易的時間戳記

當使用者在區塊鏈上進行交易時,就會產生這些資料。接著它會被廣播到網路節點,以驗證該交易並將其加入帳本。

交易資料可以透過一種稱為 Merkle 樹(Merkle trees)的樹狀資料結構來儲存和驗證。Merkle 樹是一種二元樹,能夠快速驗證資料,樹中的每個節點都是其所包含資料的雜湊值。要驗證 Merkle 樹中資料的完整性,只需要該樹的根雜湊值即可。將資料儲存在 Merkle 樹中,有助於將區塊鏈的大小保持在盡可能小的範圍內。由於 Merkle 樹還有更多可深入探討的細節,你可以閱讀[Alchemy 文件中關於 Merkle 樹的更多內容](https://www.alchemy.com/docs/merkle-trees-in-blockchains)。特別是對 Ethereum 而言,資料是使用 [Patricia Merkle Tries](https://www.alchemy.com/docs/patricia-merkle-tries) 來儲存的——這是一種結合了基數樹(radix trie,即 Patricia trie)與 Merkle 樹的資料結構。

若要快速存取交易資料,你可以直接使用區塊鏈瀏覽器,例如針對 Ethereum 交易的 [Etherscan](https://www.alchemy.com/dapps/etherscan)。區塊鏈瀏覽器讓使用者能夠檢視和搜尋所有交易資料,可用於追蹤代幣的移動、識別詐欺交易、開發區塊鏈應用程式等等。若要查詢特定交易的資料,你需要該交易的雜湊值。如果你的應用程式需要經常性地存取區塊鏈資料,Alchemy 可以提供協助。

#### **中繼資料(Metadata)**

中繼資料是提供區塊鏈上交易和資產額外資訊的資料。這可能包括以下額外細節:

- 資產的名稱或代號
- 資產的總供應量
- 資產的擁有權歷史
- 資產的合約地址

與交易資料不同,中繼資料對區塊鏈的運作並非必要,但對開發者建構區塊鏈瀏覽器、錢包和儀表板等應用程式時相當有用,這只是其中幾個例子。中繼資料可以由智能合約或區塊鏈自動產生並定義(例如交易中繼資料),也可以由使用者手動定義(例如資產中繼資料)。

若要存取中繼資料,開發者可以使用 **getMetadata** 查詢。要使用這些查詢,開發者需要使用區塊鏈 API,例如 [Alchemy API](https://www.alchemy.com/docs/reference/nft-api-quickstart)。透過使用 **getMetadata** 查詢,開發者可以建構各種能協助使用者理解並與區塊鏈網路互動的應用程式。

#### **事件資料(Events data)**

事件資料是指智能合約在執行交易時發出的資料。這些資料可能包含以下資訊:

- 所發生的事件類型
- 發出該事件的智能合約地址
- 事件的詳細內容(例如轉移的代幣數量、資產的新所有者等)

這些資訊有助於開發者監控智能合約的活動,可以透過日誌(logs)來存取。日誌是區塊鏈上所有已發生事件的記錄,由智能合約產生。這些日誌可以在交易收據中找到,並可以透過向 [eth_getLogs](https://www.alchemy.com/docs/deep-dive-into-eth_getlogs) 發出請求來檢視。

#### **Calldata**

Calldata 是在呼叫函式時傳遞給智能合約的資料。換句話說,它是一種暫時性的資料儲存形式,外部呼叫者的函式引數在傳入智能合約之前會先儲存於此。Calldata 可以包含任何類型的資料,無論是整數、字串、陣列等等。它之所以重要,是因為它讓智能合約能夠彼此溝通,以及與使用者溝通;例如,在 NFT 智能合約中,calldata 可以用來將 NFT 的所有權轉移給使用者。

區塊鏈上所有操作都需要收取 gas 費用,使用 calldata 也不例外。當 L2 交易被發布到 Ethereum 時,calldata 會包含在該交易中。這是因為 Ethereum 網路需要 calldata 來驗證交易,並執行被呼叫的智能合約函式。calldata 所消耗的 gas 取決於 calldata 的大小,以及 calldata 中所包含的資料類型。以 Ethereum 為例,每個區塊所能包含的 calldata 上限為 [1,048,576 位元組](https://eips.ethereum.org/EIPS/eip-4488)。

#### **Blobs**

Blob(二進位大型物件,binary large objects)的設計目的,是透過讓網路確認附加在區塊上的 blob 攜帶正確資料,來提升交易驗證的效率。Blob 是隨著 [proto-danksharding](https://www.alchemy.com/overviews/danksharding) 的提出而引入的,這是一項旨在降低 calldata 成本並增加每個區塊 calldata 容量的提案。

據稱,proto-danksharding 透過引入一種名為 blob-carrying transaction 的新交易類型,使區塊鏈中的 calldata 變得更便宜。Blob-carrying transaction 與一般交易類似,但可以包含資料 blob。

Blob-carrying transaction 比一般交易便宜,因為它們處理所需的 gas 較少。這是因為資料 blob 儲存在鏈下,不需要被包含在交易本身之中。

資料 blob 與 blob-carrying transaction 的引入,將使得在 Ethereum 區塊鏈上以更低成本儲存和處理大量資料成為可能。

## **什麼是區塊鏈索引?**

一本書的索引包含了關鍵字和概念被提及的頁碼。同樣地,區塊鏈索引(blockchain indexing)是將區塊鏈資料組織並儲存起來,使其易於搜尋和查詢的過程。理解這一點對於掌握區塊鏈資料相當重要,因為它讓使用者能夠以更有效率的方式來存取和分析資料。

由於區塊鏈遵循按時間排序的結構,資料可能會分散在眾多區塊之中,並變得糾結難解。索引旨在透過建立區塊鏈*資料*的索引來解決這個問題。

這個索引是一種資料庫,它以針對搜尋和查詢優化過的方式,儲存區塊鏈資料的子集。要對資料建立索引,有多種不同的索引方法,例如:對交易相關資訊建立索引、對地址建立索引、對智能合約互動建立索引等等。已建立索引的資料,接著就可以透過 GraphQL、Alchemy 及其他 web3 協定所提供的 API 供開發者存取。

### **常見的索引使用案例**

現在我們已經了解區塊鏈索引對開發者更有效率地搜尋和查詢資料有多大的幫助,接下來讓我們看看幾個常見的索引使用案例。

**交易歷史索引** - 這可用於追蹤諸如 [Uniswap](https://www.alchemy.com/dapps/uniswap) 資金池的交易量和流動性,以及識別最大的交易者和大戶(whales)。

**分析與報告索引** - 這可用於針對各種指標(例如交易量、gas 費用和使用者活動)產生報告。這在追蹤和分析特定智能合約、加密貨幣、市場趨勢的表現時特別有幫助,或是用於理解使用者活動(例如活躍錢包數量、已處理的交易數量等)。

**中繼資料索引** - 這可用於追蹤 NFT 的所有權和轉移情況。一個實際的例子可能是 NFT 分析工具,你可以針對特定 NFT 系列的交易索引進行查詢,以了解購買/所有權歷史及其他相關細節。

**智能合約事件索引** - 這可用於追蹤代幣的移動(例如特定 ERC-20 代幣的轉移事件)、借貸活動,或是更深入了解 [NFT 市場](https://www.alchemy.com/dapps/best/nft-marketplaces),這裡僅列舉幾個具體例子。整體而言,對智能合約事件建立索引有助於我們監控智能合約的活動,這有助於識別弱點,甚至發掘新應用程式和服務的機會。

#### **鏈下與鏈上索引**

索引可以儲存在鏈上或鏈下,兩者各有其優點與取捨。舉例來說,Satsuma 就是一個被 Alchemy 收購的鏈上索引協定。Satsuma 使用 [GraphQL](https://www.alchemy.com/dapps/graphql)(一種用於 API 的查詢語言),其運作方式是透過掃描網路區塊和智能合約的 subgraph,在單次 API 呼叫中從各種來源收集資料。鏈下索引協定的運作方式,則是將索引儲存在節點的本機儲存空間中(例如 SubQuery),或是儲存在像 AWS 這樣的傳統雲端伺服器中,這可能比鏈上索引更快。無論是鏈下還是鏈上索引協定,開發者都可以輕鬆使用查詢語言:

- **GraphQL** - 開發者可以使用 GraphQL 查詢 subgraph,取得特定 ERC20 代幣的轉移歷史。
- SQL - 開發者可以使用 SQL 查詢鏈下索引,取得已部署在特定區塊鏈上的所有智能合約清單。
- Elasticsearch - 開發者可以使用 Elasticsearch 查詢鏈下索引,取得特定區塊鏈上最受歡迎的 NFT。

## **區塊鏈資料是如何被存取的?**

現在我們已經對鏈上資料及其儲存方式有了一些了解,接下來可以更深入探討開發者實際上是如何存取區塊鏈資料的。

### **查詢節點**

存取區塊鏈資料最直接的方式之一,就是查詢節點,不過這也可能是最耗費資源的方式。

要查詢節點,你必須使用 JSON-RPC 透過全節點或歸檔節點(如前所述,包含完整區塊鏈副本的節點)來存取資料。要使用 JSON-RPC 查詢節點,開發者必須向該節點發送一個 JSON 物件,其中包含你想呼叫的方法、該方法的參數,以及 JSON-RPC 版本。

透過像 Alchemy 這類提供 JSON-RPC API 供查詢節點使用的解決方案,可以輕鬆完成這項工作。

<ImageBlock
  src="https://media.alchemy.com/1704096018-querying-nodes.png"
  alt="若要向節點查詢帳戶餘額，你會傳送以下 JSON 物件給節點"
  width={1600}
  height={632}
  caption="若要向節點查詢帳戶餘額，你會傳送以下 JSON 物件給節點（來源）"
/>

在查詢節點以取得特定區塊鏈事件時,事件過濾器(event filters)也很有用。要使用事件過濾器,你需要指定想要過濾的事件類型以及該事件的參數。使用事件過濾器最簡便的方式,就是透過 [Alchemy 的 Node API](https://www.alchemy.com/supernode)。Alchemy 的 Node API 是一項完全託管的服務,包含執行節點所需的全部基礎設施,以及讓與節點互動和查詢變得容易的 API 和 SDK。

### **透過 webhook 串流資料**

透過 webhook 串流資料,是一種即時接收區塊鏈資料更新的方式。事件資料可以透過自訂 webhook 和 webhook 變數來串流傳送。做法是選擇像 Alchemy 這樣的區塊鏈索引服務,在你的伺服器上建立一個 webhook 端點,訂閱相關事件,並設定 webhook 變數。特別是 Alchemy,允許使用者建立[自訂 webhook](https://www.alchemy.com/docs/reference/custom-webhook-variables),可由各種區塊鏈事件觸發,例如新交易、新智能合約部署,以及智能合約狀態的變更。Alchemy 最近也[升級了他們的自訂 webhook](https://www.alchemy.com/blog/custom-webhooks-variables-filters-block-freshness),協助開發者縮小資料串流範圍以提升精確度,並可以輕鬆使用變數來更新 webhook 查詢。

### **查詢 Subgraph**

Subgraph 是由社群建立的開源 API,用於從 Indexer、Curator 和 Delegator 檢索區塊鏈資料。由於 subgraph 是使用 GraphQL 建構的,開發者可以使用 GraphQL API 來查詢 subgraph。Subgraph 可以是託管的,也可以是自行架設的。託管的 subgraph 可以透過向 GraphQL API URL 發送 GraphQL 查詢來查詢。自行架設的 subgraph 則可以透過將該 subgraph 部署到 GraphQL 伺服器來查詢。這可以透過像 Satsuma 這樣的解決方案來完成,它允許開發者部署自己的 subgraph。

### **查詢資料倉儲**

資料倉儲(Data warehouses)針對查詢歷史資料進行了最佳化,通常採用結構化格式。另一方面,資料湖(Data lakes)則儲存大量通常屬於非結構化或半結構化的資料。[Dune Analytics](https://www.alchemy.com/dapps/dune-analytics) 是一項可用於查詢、擷取和視覺化資料湖中資料的工具。Dune 透過提供諸如其資料集瀏覽器等工具來達成這一點,讓你能夠探索不同鏈上的資料、資料集、原始區塊鏈資料等等。你也可以透過回填資料庫並透過自訂 webhook 串流資料,來建立自己的資料湖。

## **結論**

總結來說,理解區塊鏈資料對任何想要使用或建構 web3 基礎設施或應用程式的開發者來說都很有用。鏈上資料儲存在區塊鏈上,可以細分為不同的類型,例如交易資料、中繼資料、事件資料、calldata,以及 blob。這些資料接著儲存在節點中,並可以根據不同的使用案例,透過各種方式來存取。
