跳至主要內容

Solana 基礎知識參考指南

更新於
2025年11月26日

閱讀時間 13 分鐘

概覽

Solana 區塊鏈是一項強大的工具,每秒可處理數千筆交易,且交易手續費幾乎為零。無論您是 Web3 的新手,還是曾於基於 EVM 的區塊鏈上進行過開發,本指南都能協助您理解 Solana 的基礎元件,並開啟您的 Solana 開發之旅。若您已經在 Solana 上進行開發,不妨將本指南作為參考,以持續深化對 Solana 基礎原理的理解。

在本指南中,我們將介紹 Solana 的基本組成要素,具體包括:帳戶、程式、指令、交易、RPC 以及訂閱。讓我們開始吧!

簡而言之

  • 帳戶就像傳統作業系統中的檔案——Solana 上的大多數事物都是帳戶:使用者錢包、程式、資料日誌,甚至系統程式
  • 程式(在其他區塊鏈上稱為「智慧合約」)是一種特殊的「可執行」帳戶——它們沒有狀態,僅根據使用者輸入的參數執行程式碼。程式不會自行更新,而是擁有特定權限,可更新其「擁有」的其他帳戶的資料(或狀態)。
  • 使用者透過 RPC 向 Solana 叢集簽署並提交交易(一組特定程式的指令),以指示程式該如何執行。
  • Solana 採用一種名為「歷史證明」(Proof of History,PoH)的獨特共識機制,該機制藉由時間與加密技術,為傳送至網路的交易進行時間戳記並排序。
  • 程式與交易簽署者會授權對鏈上特定資料帳戶進行變更,以更新網路的狀態。

還想看更多嗎?繼續往下讀吧! 👇

什麼是 Solana?

Solana 是一個針對速度與成本進行優化的開源區塊鏈,能夠實現資訊與狀態的全域同步。Solana 採用了一種名為「歷史證明」(Proof of History)的獨特權益證明(Proof of Stake)共識機制,該機制利用可驗證的細粒度延遲函數,有效為發送至網路的交易進行時間戳記並排序。 根據阿納托利·雅科文科(Anatoly Yakovenko)在《Solana 白皮書》中的說明:「該機制採用一種加密安全的函數,其設計確保無法根據輸入預測輸出,且必須完全執行該函數才能產生輸出」(3)。「領導節點(Leader)會對使用者訊息進行排序,並將其安排成可由系統中其他節點高效處理的順序,從而最大化吞吐量」(2)。

*本文對 Solana 執行環境的探討大致到此為止,接下來我們將轉而探討如何與 Solana 互動以及如何基於 Solana 進行開發。若您想更深入了解 Solana 的架構及其部分設計特徵背後的理論,以下提供幾項優質資源:

帳戶

就像作業系統中的檔案一樣,帳戶是用來運作系統、儲存資料或狀態,以及執行程式碼的。

Solana 上有 3 種主要帳戶類型:

  1. 資料帳戶用於儲存資訊並管理網路的狀態。資料帳戶分為兩種類型:
    • 系統擁有帳戶(通常被稱為錢包)[範例:使用者錢包]
    • 程式衍生帳戶(通常簡稱為 PDA)——常見的例子是使用者針對特定代幣的代幣帳戶。此帳戶由 Solana SPL 代幣程式衍生而來。[範例:使用者的代幣帳戶]
  2. 存放可執行程式碼的程式帳戶。我們將在下一節中進一步探討這些帳戶,但這些帳戶是無狀態的(意即資料會通過它們,但不會更新它們)[範例:Candy Machine v2 程式帳戶]
  3. 原生系統帳戶(例如:系統程式、投票、質押、BPF 載入器)[範例:Solana 系統程式]

本文將重點探討第 1 點和第 2 點。若想進一步了解第 3 點「原生系統帳戶」,請參閱docs.solana.com

簡而言之,Solana 上的幾乎所有事物都是一個帳戶。最常見的帳戶類型是用戶的錢包,這是一種用於管理用戶 SOL 餘額狀態的資料帳戶。

每個帳戶都有一個唯一的地址(或稱公鑰,類似於檔案路徑),以及一組相關的元資料:

  • lamports:此帳號擁有的 lamports 數量(64 位元無符號整數)*
  • 擁有者:此帳戶所屬的程式擁有者(擁有者程式的字串位址)。擁有者程式負責控制哪些程式具有帳戶的寫入權限——其他程式可以讀取其他帳戶的資料,但若試圖修改該資料,交易將會失敗。
  • 可執行性:此帳戶是否能處理指令(布林值)。可執行性值為true的帳戶,實際上即為程式(或智慧合約)——我們將在下一節中討論這些內容。
  • data:與該帳戶相關的任何其他資料,以原始資料位元組陣列的形式儲存
  • rent_epoch:此帳戶下一次需繳納租金的時段(64 位元無符號整數)

* lamports 是 SOL(Solana 的原生代幣)中面額最小的單位(相當於 1 SOL 的十億分之一)

只要執行getAccountInfo JSON RPC 查詢,或透過Solana Explorer 搜尋,即可讀取任何帳戶的元資料。Solana Explorer 允許您搜尋任何帳戶,並查看其基本詳細資訊,例如帳戶類型以及所關聯的程式。以下是一個系統擁有的資料帳戶(即使用者的錢包)的範例:

讓我們透過一個範例來具體說明所有帳戶類型:

這裡的運作相當複雜,但您在這張圖中所見的一切皆為「帳戶」。左側有一個名為「System Program」的系統帳戶,負責管理所有使用者錢包。 此外,我們還有一個名為「Solana SPL 代幣程式」的可執行程式帳戶,使用者可透過它來鑄造、銷毀及轉移 SPL 代幣。最後,我們還有「程式衍生帳戶」。在此情況下,這些是由代幣程式所擁有、並與使用者帳戶相關聯的代幣帳戶。請注意,一個使用者錢包可以擁有多個代幣帳戶。

請記住,您可以在 Solana Explorer 中搜尋任何帳戶地址,以取得其元資料,並了解該帳戶的類型以及它所關聯的程式。

Lamports 與租金 時代帳戶及其資料皆儲存於驗證者的記憶體中,若要持續儲存於此,必須以 lamports 支付「租金」(金額標示於帳戶的lamports元資料欄位中)。帳戶中儲存的資料越多,所需支付的租金就越多(註:目前帳戶的最大容量為 10 MB)。 您可以使用 JSON RPC 方法getMinimumBalanceForRentExemption 來計算所需的租金。驗證者負責定期掃描所有帳戶並收取租金——帳戶檢查將在rent_epoch元數據欄位中指定的紀元進行檢查。若帳戶餘額降至零 lamport,網路將清除該帳戶,相關資料亦將遺失。截至本文撰寫時,所有新帳戶均須維持「免租」狀態,此狀態需透過在帳戶中持有相當於 2 年租金的金額來獲得。來源:https://docs.solana.com/developing/programming-model/accounts 「紀元」是 Solana 上的時間單位,目前約代表 2.5 天。

節目

Solana 將這些程式稱為「智慧合約」——它們是處理資訊與請求的引擎:從代幣轉移、Candy Machine 鑄造,到「hello world」日誌,乃至 DeFi 託管治理,無所不包。

  • 請記住,Solana 程式是標記為「可執行」的無狀態帳戶:「由於程式帳戶中儲存的主要資料是編譯後的 BPF 程式碼,因此這些程式被視為無狀態。」
  • 程式可透過「跨程式呼叫」來使用或基於其他 Solana 程式進行開發。這通常被稱為「可組合性」。
  • 與許多其他熱門連鎖店不同,這些方案皆可升級。
  • 大多數程式都是由使用者所開發的,但 Solana Labs 已建置並維護了多項鏈上程式,稱為「Solana 程式庫」。

實際上,使用者必須向程式提供特定於該程式的指令,程式會處理這些指令,隨後該程式可能會呼叫其他程式,並/或更新其擁有的、由程式衍生的帳戶(關於 PDA 的詳細說明請見下文)。

程式衍生位址帳戶

「程式衍生位址」(PDA)是由特定程式建立並控制的帳戶。PDA:

  • 允許程式控制特定地址(稱為「程式地址」),以確保任何外部使用者皆無法針對這些地址產生附有有效簽名的交易。
  • 允許程式針對透過「跨程式呼叫」所調用的指令中出現的程式位址,以程式化方式進行簽名。Solana 會根據程式所定義的種子及程式 ID,以確定性方式推導出 PDA。有關生成的程式位址的更多資訊,請參閱docs.solana

來源: _https://docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses
_

這使程式能夠提供無需信任的服務,例如用於安全管理交易、投注或去中心化金融(DeFi)協議的託管帳戶。若參照上方的示意圖,SPL 代幣程式會根據用戶的錢包以及該特定代幣的鑄造地址,為用戶生成一個 PDA。該 PDA 將儲存用戶所持該代幣數量對應的狀態或資料。

讓我們深入探討,我們是如何透過指令和交易來讓程式運作的。

說明

指令的核心功能,是指示程式執行某項操作。Solana 將指令定義為「程式中執行邏輯的最小連續單位。」(來源:docs.solana.com/terminology)。

一條指令由 3 個部分組成:

  1. 您即將呼叫的程式的公鑰,
  2. 一個將被讀取或修改的 Accounts 陣列,以及
  3. 一個字節陣列,用以存放程式執行所需的任何其他資料(特定於該程式)

最後這一點至關重要——指令是針對特定程式的。若您輸入錯誤的程式 ID,或不清楚應傳入程式的預期資料結構,交易將會失敗。

在 JavaScript 中,一則交易指令的樣貌大致如下:

new TransactionInstruction({
programId: new PublicKey(PROGRAM_ID),
keys: [
{ pubkey: signerKeypair.publicKey, isSigner: true, isWritable: true },
{ pubkey: pda, isSigner: false, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
],
data: Buffer.from(SOME_ENCODED_DATA),
})

在此值得特別提及的是,執行交易指令所需的帳戶資訊。我們必須提供該帳戶的公鑰,並說明該帳戶是否為交易的簽署者,以及該帳戶是否會作為交易的一部分被寫入(這有助於提升 Solana 的執行速度)。 在上方的範例中,使用者對錢包進行簽名,並將資料寫入 PDA。通常也需要包含系統程式帳戶(例如,用於建立新帳戶)。最後,我們傳遞SOME_ENCODED_DATA。所需的資料類型在程式內部定義。程式必須對輸入資料進行反序列化,才能正確處理它。

交易

交易是將指令傳遞給網路中程式的一種方式。交易可以將多條指令打包在一起,以便同時處理多項操作。 舉例來說,假設你有三條不同的指令:一條是指示錢包 A 向錢包 B 轉帳 1 $SOL;一條是指示錢包 B 向錢包 A 轉帳 33 $USDC;以及一條是將備註「錢包 A 於 YYYY-MM-DD 與錢包 B 進行 1 $SOL 兌換 33 $USDC」記錄至該筆交易中。 雖然這些指令可以分別發送至網路,但如果其中一項指令失敗,而其他指令卻成功了,會發生什麼情況呢?這將導致一種情況:一個人收到了代幣,而另一個人卻沒有。透過將指令捆綁成一個包,我們可以確保所有交易要麼全部成功,要麼全部失敗。

目前每筆交易的長度上限為 1,232 位元組。每筆交易必須包含以下內容:

  • 由一個或多個交易指令組成的陣列
  • 一個包含所有該程式將與之互動的帳戶地址的陣列
  • 一組簽名:我們傳入交易中的帳戶子集也必須包含簽名。「這些簽名會向鏈上程式發出訊號,表明帳戶持有者已授權該筆交易。通常,程式會利用此授權來允許從帳戶扣款或修改其資料。」(來源:docs.solana.com)。例如,這對於創作者驗證 NFT 的真偽而言,也可能是一項必要條件。
  • 最近的區塊哈希:區塊哈希基本上就是 PoH 時間戳記。Solana 預設會移除「舊」交易,以防止重複計數,讓驗證者僅需針對最新的一批交易進行核對,並讓使用者能迅速確認其交易是否已處理完成(或失敗,以便重新嘗試)。 在提交交易前取得最近的區塊哈希,可讓網路得知我們交易的年齡,以及其何時會過期(如有需要)。

網路一旦接收到一筆交易,便會回傳一個交易 ID(base-58 編碼字串),該 ID 可用於查詢交易詳情。

讓我們來討論一下,該如何將您的交易發送到網路吧!

RPC

JSON-RPC 是一種以 JSON 編碼的遠端程序呼叫協定,可讓使用者將資訊傳送至 Solana 叢集,並從網路取得回應。Solana 目前維護著三個網路叢集:

  • Devnet:一個用於測試應用程式與方法功能的測試平台
  • 測試網:一種用於對系統所有最新規劃升級進行壓力測試的開發環境
  • 主網 Beta 版:生產環境

客戶端可透過 Solana 節點,使用 JSON-RPC 請求向這三個叢集中的任何一個發出讀取或寫入請求。節點在某種程度上扮演著「空中交通管制」的角色,負責處理發送至網路的請求。客戶端透過 Solana Web3Connection類別連線至 Solana 節點:

const HTTP_ENDPOINT = 'https://example.solana-devnet.quiknode.pro/000/'
const SOLANA_CONNECTION = new Connection(HTTP_ENDPOINT)

在上述範例中,HTTP_ENDPOINT是一個 HTTP URL,它指向一個 Solana 節點,該節點最終會將您的請求路由至這三個叢集中的其中一個。

每次請求都需要一個 API 端點才能連線至網路。這正是 Quicknode 派上用場的地方!您可以自由選擇使用公開節點,或是自行部署並管理基礎架構;不過,如果您希望響應時間提升 8 倍,不妨將繁重的工作交給我們處理。


了解為何超過 50% 的 Solana 專案都選擇 Quicknode,並在此註冊帳號。只需登入,並將應用程式中的HTTP_ENDPOINT更新為您帳號儀表板中提供的值,即可開始使用!


了解為何超過 50% 的 Solana 專案都選擇 Quicknode,並在此註冊帳號。只需登入,並將應用程式中的HTTP_ENDPOINT更新為您帳號儀表板中提供的值,即可開始使用!

一旦與 Solana 叢集建立連線,您即可對網路執行多種讀取或寫入方法。完整的 RPC 方法清單及相關文件可於 Quicknode 文件中查閱。雖然每個方法都有其用途,但其中有幾個與本指南迄今為止的討論內容相關,包括:

HTTP 呼叫讓我們能夠指示網路執行某項操作(例如:處理一筆交易及其相關指令、回傳帳戶的當前狀態資訊等),但如果我們希望網路在帳戶狀態發生變更時主動通知我們,該怎麼辦呢?

訂閱

訂閱是一種特殊的 RPC 請求,我們會透過 WebSocket (WSS) 請求來執行,而非使用 HTTP 端點。Solana Web3 JSON RPC 包含數種訂閱方法(例如accountSubscribe,該方法會監聽帳戶的 lamports 或資料變更)。接著,我們可以透過回呼函式訂閱這些事件,讓網路發生變更時,便能觸發預期的動作。

Connection類別的建構函式允許我們傳入一個可選的commitmentOrConfig。在其內部,我們可以傳入一個wsEndpoint。此選項供您提供全節點 JSON RPC WebSocket 端點的 URL。如果您已建立 Quicknode 端點,應可在端點頁面的右側看到此選項。

const HTTP_ENDPOINT = 'https://example.solana-devnet.quiknode.pro/000/'
const WSS_ENDPOINT = 'wss://example.solana-devnet.quiknode.pro/000/'
const solanaConnection = new Connection(HTTP_ENDPOINT, {
wsEndpoint: WSS_ENDPOINT,
})

如果未傳入wsEndpoint 參數會發生什麼情況?其實,Solana 已透過makeWebsocketUrl 函式來處理此情況,該函式會將您的端點 URL 中的https替換為wss,或將http替換為ws來源)。由於所有 Quicknode HTTP 端點都有一個對應的 WSS 端點,且使用相同的驗證憑證,因此除非您希望為 WebSocket 查詢使用獨立的端點,否則省略此參數是可行的。

若想更深入了解如何建立 WebSocket 訂閱,請參閱我們的指南:《如何建立 Solana WebSocket 訂閱》

將一切整合起來

好!資訊量頗大——你大概已經開始看出這些基本元素之間的關聯性了,但在將所有片段串聯起來之前,讓我們先快速複習一下:

  • 在 Solana 上,幾乎所有事物都是一個帳戶:使用者錢包、程式、系統程式、程式資料等。
  • 程式是無狀態的——它們處理指令,可以呼叫其他程式,並改變其所擁有的資料帳戶的狀態。
  • 指令是針對特定程式的,並告訴程式該執行什麼操作。
  • 交易會將一項或多項指令與簽名打包在一起,以授權程式執行一項或多項任務。
  • RPC 協定允許客戶端透過 Quicknode 等節點,向 Solana 的三個叢集之一發送讀取/寫入請求。
  • 客戶可透過 RPC 提供者,利用 WebSocket 請求訂閱網路變更。

讓我們透過一個示範範例來說明。假設有一個名為「GM」的程式,它會維持一個計數器,每當使用者向該程式傳送「GM」訊息時,便會進行記錄。

在上方的範例中,客戶端建立了一筆包含多個交易指令的交易。這些指令是程式專用的,因此必須符合 GM 程式的預期結構。客戶端會透過 RPC 提供者(例如 Quicknode)並使用Connection類別,對交易進行簽名並將其傳送至 Solana 叢集。 RPC 提供者將請求路由至叢集。程式帳戶會執行並處理收到的輸入指令。程式帳戶是無狀態的且不會改變,但會授權變更 PDA 中的資料,以增加 GM 計數器的值。由客戶建立的訂閱會監聽 PDA 的變更;隨後,網路會通知客戶該帳戶已發生變更。

總結

呼!我們剛才講了超多內容。請不要害怕反覆閱讀幾遍,以確保你確實理解這些概念。

既然您已經對 Solana 有更深入的了解,現在正是動手開發的時候了!不妨試試我們的一些Solana 開發指南,開始您的開發之旅。以下提供幾個範例:

對這些概念有任何疑問,或是單純想聊聊技術話題?歡迎在DiscordTwitter上聯絡我們,並告訴我們你正在開發什麼!

我們 ❤️ 您的回饋!

如果您對這份指南有任何意見或疑問,請告訴我們。我們非常樂意聽取您的意見!

參考資料與來源

分享這份指南