欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

當前位置:主頁 > 區(qū)塊鏈 > 區(qū)塊鏈技術(shù) > solana開發(fā)教程

Solana開發(fā)學習筆記(一)——從Hello World出發(fā)

2024-04-30 14:42:33 | 來源: | 作者:佚名
本章對Solana區(qū)塊鏈的基本概念進行了簡要介紹,并介紹了開發(fā)Solana鏈上程序必須安裝和配置的編程環(huán)境,通過對Hello World這個官方演示項目源碼的解讀,了解如何使用Rust開發(fā)鏈上程序,并使用Solana CLI來構(gòu)建與部署,以及使用Solana JavaScript SDK與鏈上程序進行交互

筆者注:因近期筆者工作需要,開始接觸 Solana 鏈上程序開發(fā)。本系列文章是筆者的學習筆記,既是為了備忘,也是希望得到 Solana 開發(fā)者的指點與交流。本系列文章將默認讀者已經(jīng)掌握 Rust 的基礎(chǔ)語法,故不涉及對 Rust 語法細節(jié)的解釋。如果讀者對 Rust 基礎(chǔ)語法還不熟練的話,本文下方推薦的 Rust 入門書籍《Rust 編程入門、實戰(zhàn)與進階》學習。

1.1 Solana 簡介

Solana 是一個高性能、無許可的底層公鏈,專注于在不犧牲去中心化或安全性的前提下提供可擴展性。Solana 主網(wǎng)于 2020 年一季度上線,目前主網(wǎng)的全球節(jié)點超過 800 個,TPS 最高可達 6.5 萬,出塊時間約 400 毫秒。

Solana 的共識算法采用 PoH(歷史證明),其核心是一個去中心化時鐘,該時鐘旨在解決缺乏單個可信賴時間源在分布式網(wǎng)絡中的時間問題。PoH 免除了在節(jié)點網(wǎng)絡中廣播時間戳的需求,從而提高整個網(wǎng)絡的效率。

1.1.1 鏈上程序

Solana 的智能合約叫做鏈上程序(On-chain Program),Solana 官方提供了 Rust 和 C 的 SDK 來支持開發(fā)鏈上程序。鏈上程序的開發(fā)工作流如圖 1-1 所示,開發(fā)者可以使用工具將程序編譯成 Berkley Packet Filter (BPF) 字節(jié)碼(文件以 .so 為擴展名),再部署到 Solana 鏈上,通過 Sealevel 并行智能合約運行時去執(zhí)行智能合約的邏輯。此外,基于 Solana JSON RPC API,官方提供了諸多 SDK 用于客戶端與 Solana 鏈上數(shù)據(jù)交互。

圖 1-1 鏈上程序開發(fā)工作流

1.1.2 賬戶模型

與以太坊類似,Solana 也是基于賬戶模型的區(qū)塊鏈。通過將任意狀態(tài)存儲于鏈上賬戶并同步復制給集群中的所有節(jié)點,可以創(chuàng)建復雜而強大的去中心化應用程序。

Solana 提供了一套不同于以太坊的賬戶模型,賬戶定義的字段如表 1-1 所示。Solana 的賬戶可以分為可執(zhí)行賬戶和不可執(zhí)行賬戶。

  • 可執(zhí)行賬戶:存儲不可變的數(shù)據(jù),主要用于存儲程序的 BPF 字節(jié)碼。
  • 不可執(zhí)行賬戶:存儲可變的數(shù)據(jù),主要用于存儲程序的狀態(tài)。

表 1-1 賬戶定義字段

字段描述
lamports賬戶余額
owner賬戶所有者
executable是否為可執(zhí)行賬戶
data賬戶存儲的數(shù)據(jù)
rent_epochSolana鏈上程序的部署是按其賬戶大小進行定期收費的,如果賬戶無法支付租金,系統(tǒng)將清除該賬號

我們知道以太坊上每個智能合約的代碼和狀態(tài)都存儲在同一個賬戶中,而 Solana 鏈上程序是只讀或無狀態(tài)的,即程序的賬戶(可執(zhí)行賬戶)只存儲 BPF 字節(jié)碼,不存儲任何狀態(tài),程序會把狀態(tài)存儲在其他獨立的賬戶(不可執(zhí)行賬戶)中。為了區(qū)分某個賬戶是用作哪個程序的狀態(tài)存儲,每個賬戶都指定了一個程序作為其所有者。程序可以讀取其不作為所有者的賬戶中的狀態(tài),但只有作為所有者的程序才能修改賬戶中的狀態(tài),任何其他程序所做的修改都會被還原并導致交易失敗。

更多關(guān)于賬戶模型的資料可以參見官方文檔:https://solana.wiki/zh-cn/docs/account-model/

1.2 搭建編程環(huán)境

在開始 Solana 鏈上程序開發(fā)之前,需要先安裝和配置相關(guān)的編程環(huán)境。首先請正確安裝 Node、NPM 和 Rust 的最新穩(wěn)定版本,下面來安裝 Solana CLI 并配置相關(guān)環(huán)境。

1.2.1 安裝 Solana CLI

Solana CLI 是與 Solana 集群進行交互的命令行管理工具,包含節(jié)點程序 solana-validator、密鑰對生成工具 solana-keygen,以及合約開發(fā)工具 cargo-build-bpf、cargo-test-bpf 等。

在終端運行以下命令,可完成 Solana CLI 最新穩(wěn)定版的下載與安裝。

sh -c "$(curl -sSfL https://release.solana.com/stable/install)"

如果安裝成功,會出現(xiàn)以下內(nèi)容。

downloading stable installer
  ? stable commit e9bef425 initialized
Adding export PATH="~/.local/share/solana/install/active_release/bin:$PATH" to ~/.profile
Adding export PATH="~/.local/share/solana/install/active_release/bin:$PATH" to ~/.bash_profile
Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:
  export PATH="~/.local/share/solana/install/active_release/bin:$PATH"

Solana CLI 的所有命令行工具都安裝在 ~/.local/share/solana/install/active_release/bin 中,并會自動將該路徑加入 ~/.profile 和 ~/.bash_profile 文件的 PATH 環(huán)境變量。

運行以下命令,檢查 PATH 環(huán)境變量是否已正確設置。

solana --version
// solana-cli 1.7.18 (src:e9bef425; feat:140464022)

如果能顯示 solana-cli 的版本號、版本哈希等信息,代表環(huán)境變量設置成功。如果未看到這些信息,請檢查相關(guān)文件中 PATH 環(huán)境變量設置的路徑是否正確。

如果已安裝過 Solana CLI,想升級到最新版本,可在終端運行以下命令。

solana-install update

1.2.2 配置 Solana CLI

1. 連接到集群

Solana 的集群有本地集群(localhost)和公開集群。根據(jù)不同的用途,公開集群又分為開發(fā)者網(wǎng)絡(devnet)、測試網(wǎng)(testnet)和主網(wǎng)(mainnet-beta)。

  • devnet 是適用于開發(fā)者的集群,開發(fā)者可獲得 SOL token 的空投,但這個 SOL token 不具有真實價值,僅限測試使用。devnet 的 RPC 鏈接是 https://api.devnet.solana.com 。
  • testnet 是用于測試最新功能的集群,如網(wǎng)絡性能、穩(wěn)定性和驗證程序行為等。同樣可獲得 SOL token 的空投,但也僅限測試使用。testnet 的 RPC 鏈接是 https://api.testnet.solana.com 。
  • mainnet-beta 是主網(wǎng)集群,在 Mainnet Beta 上發(fā)行的 SOL token 具有真實價值。mainnet-beta 的 RPC 鏈接是 https://api.mainnet-beta.solana.com 。

運行以下命令,根據(jù)實際需要來選擇集群。

// 選擇localhost集群
solana config set --url localhost
// 選擇devnet集群
solana config set --url devnet

2. 創(chuàng)建賬戶

如果是第一次使用 Solana CLI,需要先創(chuàng)建一個賬戶。運行以下命令,根據(jù)操作提示可以設置一個 BIP39 規(guī)范的密碼,此密碼用來增強助記詞的安全性,當然也可以為空。生成新的賬戶后,密鑰對會被自動寫入 ~/.config/solana/id.json 文件中。需要注意的是,這種存儲密鑰對的方式是不安全的,僅限開發(fā)測試使用。

solana-keygen new

要查看當前這個賬戶的公鑰,運行以下命令。

solana-keygen pubkey

當前如果是在 devnet 集群,該賬戶的余額為 0 SOL,可以運行以下命令查詢余額。

solana balance

在 devnet 上申請 SOL 空投,運行以下命令后再次查詢當前賬戶的余額,會發(fā)現(xiàn)余額為 2 SOL。

solana airdrop 2

1.3 第一個 Solana 項目——Hello World

Hello World 是一個官方演示項目,展示了如何使用 Rust 和 C 開發(fā)鏈上程序,并使用 Solana CLI 來構(gòu)建與部署,以及使用 Solana JavaScript SDK 與鏈上程序進行交互。

1.3.1 Hello World 源碼解讀

example-helloworld 項目的目錄結(jié)構(gòu)如下所示,其中 program-rust 目錄下是 Rust 開發(fā)的程序源代碼,client 目錄下是客戶端的源代碼。

example-helloworld
|
+-- src
|  |
|  +-- client
|  |  |
|  |  +-- hello_world.ts
|  |  |
|  |  +-- main.ts
|  |  |
|  |  +-- utils.ts
|  |
|  +-- program-rust
|  |  |
|  |  +-- src
|  |  |  |
|  |  |  +-- lib.rs
|  |  |
|  |  +-- tests
|  |  |  |
|  |  |  +-- lib.rs
|  |  |
|  |  +-- Cargo.toml
|  |  |
|  |  +-- Xargo.toml
|
+-- .gitignore
|
+-- package.json
|
+-- tsconfig.json

1. 鏈上程序源碼解讀

program-rust/src/lib.rs 是鏈上程序的核心代碼,如代碼清單 1-1 所示,實現(xiàn)了將程序被調(diào)用次數(shù)存儲在鏈上賬戶中。

第 1 行代碼將 borsh::BorshDeserialize 和 borsh::BorshSerialize 引入本地作用域,用于序列化和反序列化數(shù)據(jù)。第 2~9 行代碼將 Solana Rust SDK 的模塊引入本地作用域,使用 Rust 編寫程序都需要這個 SDK。

第 13~16 行代碼定義了 GreetingAccount 結(jié)構(gòu)體作為存儲在賬戶中的狀態(tài)類型,里面有一個 u32 類型的字段 counter,用于記錄程序被有效調(diào)用的次數(shù)。

第 19 行代碼 entrypoint 聲明了 process_instruction 函數(shù)是程序入口,每個程序都有一個唯一的入口。第 22~26 行代碼是 process_instruction 函數(shù)簽名,它要接收 3 個參數(shù):

  • program_id:鏈上程序的部署地址,在這里也就是 helloworld 程序賬戶的公鑰。
  • accounts:與程序交互的賬戶列表,當前程序會使用賬戶列表中的賬戶來存儲狀態(tài)或修改賬戶中的數(shù)據(jù)。如果當前程序不是某個賬戶的所有者,那就無法使用該賬戶存儲狀態(tài)或修改數(shù)據(jù),當前交易會執(zhí)行失敗。
  • instruction_data:指令數(shù)據(jù),比如要轉(zhuǎn)賬的代幣數(shù)量、轉(zhuǎn)賬地址等。

process_instruction 函數(shù)的返回值類型是 ProgramResult,ProgramResult 類型的定義如下所示。

pub type ProgramResult = Result<(), ProgramError>;

當程序的邏輯執(zhí)行成功時返回 Ok(()),否則將 ProgramError 錯誤返回。ProgramError 是自定義錯誤的枚舉類型,其中包含程序可能失敗的各種原因。

第 27 行代碼使用 msg! 宏將字符串輸出到日志中,方便觀察業(yè)務的執(zhí)行邏輯和調(diào)試信息。第 30 行代碼通過 iter 方法將賬戶列表轉(zhuǎn)換為迭代器,以安全的方式獲取賬戶地址。第 33 行代碼使用了 ? 操作符,如果迭代器中有賬戶地址,會將賬戶地址與變量 account 綁定。如果迭代器中沒有賬戶地址,? 操作符會讓程序執(zhí)行失敗。

第 36~39 行代碼判斷存儲狀態(tài)的賬戶所有者是否是當前程序。只有賬戶所有者才能修改數(shù)據(jù),否則輸出日志并返回。

第 42~44 行代碼先對賬戶中的數(shù)據(jù)進行反序列化操作,再將 counter 加一,最后將其序列化后存儲到賬戶中。

代碼清單 1-1 helloworld 鏈上程序

use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
    account_info::{next_account_info, AccountInfo},
    entrypoint,
    entrypoint::ProgramResult,
    msg,
    program_error::ProgramError,
    pubkey::Pubkey,
};

/// Define the type of state stored in accounts
#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct GreetingAccount {
    /// number of greetings
    pub counter: u32,
}

// Declare and export the program's entrypoint
entrypoint!(process_instruction);

// Program entrypoint's implementation
pub fn process_instruction(
    program_id: &Pubkey, // Public key of the account the hello world program was loaded into
    accounts: &[AccountInfo], // The account to say hello to
    _instruction_data: &[u8], // Ignored, all helloworld instructions are hellos
) -> ProgramResult {
    msg!("Hello World Rust program entrypoint");

    // Iterating accounts is safer then indexing
    let accounts_iter = &mut accounts.iter();

    // Get the account to say hello to
    let account = next_account_info(accounts_iter)?;

    // The account must be owned by the program in order to modify its data
    if account.owner != program_id {
        msg!("Greeted account does not have the correct program id");
        return Err(ProgramError::IncorrectProgramId);
    }

    // Increment and store the number of times the account has been greeted
    let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?;
    greeting_account.counter += 1;
    greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;

    msg!("Greeted {} time(s)!", greeting_account.counter);

    Ok(())
}

2. 客戶端程序源碼解讀

要想測試鏈上程序,我們必須通過 Solana JSON RPC API 去和鏈上程序進行交互。example-helloworld 項目提供的客戶端用 Typescript 編寫,使用了 web3.js 庫這個 Solana JavaScript SDK。

在 client 目錄下,客戶端執(zhí)行的入口是 main.ts 文件,它按特定的順序執(zhí)行任務,每個任務的業(yè)務邏輯代碼在 hello_world.ts 文件。

首先,客戶端調(diào)用 establishConnection 函數(shù)與集群建立連接。

export async function establishConnection(): Promise<void> {
  const rpcUrl = await getRpcUrl();
  connection = new Connection(rpcUrl, 'confirmed');
  const version = await connection.getVersion();
  console.log('Connection to cluster established:', rpcUrl, version);
}

接著,客戶端調(diào)用 establishPayer 函數(shù)來確保有一個有支付能力的賬戶。

export async function establishPayer(): Promise<void> {
  let fees = 0;
  if (!payer) {
    const {feeCalculator} = await connection.getRecentBlockhash();

    // Calculate the cost to fund the greeter account
    fees += await connection.getMinimumBalanceForRentExemption(GREETING_SIZE);

    // Calculate the cost of sending transactions
    fees += feeCalculator.lamportsPerSignature * 100; // wag

    try {
      // Get payer from cli config
      payer = await getPayer();
    } catch (err) {
      // Fund a new payer via airdrop
      payer = await newAccountWithLamports(connection, fees);
    }
  }

  const lamports = await connection.getBalance(payer.publicKey);
  if (lamports < fees) {
    // This should only happen when using cli config keypair
    const sig = await connection.requestAirdrop(
      payer.publicKey,
      fees - lamports,
    );
    await connection.confirmTransaction(sig);
  }

  console.log(
    'Using account',
    payer.publicKey.toBase58(),
    'containing',
    lamports / LAMPORTS_PER_SOL,
    'SOL to pay for fees',
  );
}

然后,客戶端調(diào)用 checkProgram 函數(shù)從 src/program-rust/target/deploy/helloworld-keypair.json 中加載已部署程序的密鑰對(此操作前需先構(gòu)建鏈上程序,詳見 1.3.2 節(jié)),并使用密鑰對的公鑰來獲取程序賬戶。如果程序不存在,客戶端會報錯并停止執(zhí)行。如果程序存在,將創(chuàng)建一個新賬戶來存儲狀態(tài),并以該程序作為新賬戶所有者。這里新賬戶存儲的狀態(tài),就是程序被調(diào)用的次數(shù)。

export async function checkProgram(): Promise<void> {
  // Read program id from keypair file
  try {
    const programKeypair = await createKeypairFromFile(PROGRAM_KEYPAIR_PATH);
    programId = programKeypair.publicKey;
  } catch (err) {
    const errMsg = (err as Error).message;
    throw new Error(
      `Failed to read program keypair at '${PROGRAM_KEYPAIR_PATH}' due to error: ${errMsg}.`,
    );
  }

  // Check if the program has been deployed
  const programInfo = await connection.getAccountInfo(programId);
  if (programInfo === null) {
    if (fs.existsSync(PROGRAM_SO_PATH)) {
      throw new Error(
        'Program needs to be deployed with `solana program deploy dist/program/helloworld.so`',
      );
    } else {
      throw new Error('Program needs to be built and deployed');
    }
  } else if (!programInfo.executable) {
    throw new Error(`Program is not executable`);
  }
  console.log(`Using program ${programId.toBase58()}`);

  // Derive the address (public key) of a greeting account from the program so that it's easy to find later.
  const GREETING_SEED = 'hello';
  greetedPubkey = await PublicKey.createWithSeed(
    payer.publicKey,
    GREETING_SEED,
    programId,
  );

  // Check if the greeting account has already been created
  const greetedAccount = await connection.getAccountInfo(greetedPubkey);
  if (greetedAccount === null) {
    console.log(
      'Creating account',
      greetedPubkey.toBase58(),
      'to say hello to',
    );
    const lamports = await connection.getMinimumBalanceForRentExemption(
      GREETING_SIZE,
    );

    const transaction = new Transaction().add(
      SystemProgram.createAccountWithSeed({
        fromPubkey: payer.publicKey,
        basePubkey: payer.publicKey,
        seed: GREETING_SEED,
        newAccountPubkey: greetedPubkey,
        lamports,
        space: GREETING_SIZE,
        programId,
      }),
    );
    await sendAndConfirmTransaction(connection, transaction, [payer]);
  }
}

客戶端再調(diào)用 sayHello 函數(shù)向鏈上程序發(fā)送交易。一個交易可以包含一個或多個不同的指令,當前該交易包含了一個指令,指令中帶有要調(diào)用鏈上程序的 Program Id 以及客戶端要交互的賬戶地址。需要注意的是,如果交易中包含多個不同的指令,其中有一個指令執(zhí)行失敗,那么所有指令所做的操作都會被還原。

export async function sayHello(): Promise<void> {
  console.log('Saying hello to', greetedPubkey.toBase58());
  const instruction = new TransactionInstruction({
    keys: [{pubkey: greetedPubkey, isSigner: false, isWritable: true}],
    programId,
    data: Buffer.alloc(0), // All instructions are hellos
  });
  await sendAndConfirmTransaction(
    connection,
    new Transaction().add(instruction),
    [payer],
  );
}

最后,客戶端調(diào)用 reportGreetings 函數(shù)訪問賬戶數(shù)據(jù),查詢鏈上程序被有效調(diào)用的次數(shù)。

export async function reportGreetings(): Promise<void> {
  const accountInfo = await connection.getAccountInfo(greetedPubkey);
  if (accountInfo === null) {
    throw 'Error: cannot find the greeted account';
  }
  const greeting = borsh.deserialize(
    GreetingSchema,
    GreetingAccount,
    accountInfo.data,
  );
  console.log(
    greetedPubkey.toBase58(),
    'has been greeted',
    greeting.counter,
    'time(s)',
  );
}

1.3.2 Hello World 構(gòu)建與部署

1. 創(chuàng)建項目

使用 git clone 命令下載 example-helloworld 項目。

git clone https://github.com/solana-labs/example-helloworld.git
cd example-helloworld

2. 構(gòu)建鏈上程序

運行以下命令,在 program-rust 目錄下構(gòu)建鏈上程序。

cd src/program-rust/
cargo build-bpf

構(gòu)建完成后,src/program-rust/target/deploy 目錄下的 helloworld.so 就是可在 Solana 集群部署的鏈上程序的 BPF 字節(jié)碼文件。

3. 啟動本地集群

當前項目在本地集群部署運行,因此首先選擇 localhost 集群,運行以下命令。

solana config set --url localhost

本地集群設置成功,會出現(xiàn)以下內(nèi)容。

Config File: ~/.config/solana/cli/config.yml
RPC URL: http://localhost:8899
WebSocket URL: ws://localhost:8900/ (computed)
Keypair Path: ~/.config/solana/id.json
Commitment: confirmed

再運行以下命令,啟動 localhost 集群。

solana-test-validator

看到以下內(nèi)容,代表本地集群已成功啟動。

Ledger location: test-ledger
Log: test-ledger/validator.log
Identity: A4HuRgmABNCe94epY2mU7q6WqEHCo2B9iBFE5Yphiw5u
Genesis Hash: 96TF9n1uuyFv4rAKECffA61jLrgYjMjNRZ3hJpP6HSr7
Version: 1.7.18
Shred Version: 13390
Gossip Address: 127.0.0.1:1024
TPU Address: 127.0.0.1:1027
JSON RPC URL: http://127.0.0.1:8899
? 00:00:42 | Processed Slot: 45430 | Confirmed Slot: 45430 | Finalized Slot: 45398 | Snapshot Slot: 45300 | Transactions: 45452 | ◎499.772930000

4. 部署鏈上程序

運行以下命令,在 localhost 集群部署鏈上程序。

solana program deploy target/deploy/helloworld.so

// Program Id: 6AArMEBpFhhtU2mBnEMEPeEH7xkhfUwPseUeG4fhLYto

鏈上程序部署成功會返回 Program Id,它類似于以太坊智能合約的地址。

5. 調(diào)用鏈上程序

helloworld 已成功部署,可以與它進行交互了!example-helloworld 項目提供了一個簡單的客戶端,在運行客戶端之前先安裝依賴軟件包。

npm install

由于我們調(diào)整了鏈上程序的構(gòu)建方式,沒有使用該項目默認的 npm run build:program-rust 命令,因此需要修改 client 目錄下的 hello_world.ts 文件,將第 48 行代碼定義的變量 PROGRAM_PATH 的路徑由“../../dist/program”改為“../program-rust/target/deploy”。 再運行以下命令,啟動客戶端去調(diào)用鏈上程序。

npm run start

客戶端成功調(diào)用鏈上程序,輸出內(nèi)容如下所示。如果再次運行客戶端,第 10 行所顯示的次數(shù)會加一。至此,我們已經(jīng)成功在 Solana 集群部署鏈上程序并與之交互了。

> helloworld@0.0.1 start
> ts-node src/client/main.ts

Let's say hello to a Solana account...
Connection to cluster established: http://localhost:8899 { 'feature-set': 3179062686, 'solana-core': '1.6.23' }
Using account 4xRm2FYmRB8WdxJk6nXicVMgsPnsxChEnpQwFDGwdcSS containing 499999999.93435186 SOL to pay for fees
Using program 6AArMEBpFhhtU2mBnEMEPeEH7xkhfUwPseUeG4fhLYto
Creating account Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy to say hello to
Saying hello to Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy
Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy has been greeted 1 time(s)
Success

如果沒有輸出期望值,請首先確認是否已正確啟動了本地集群,構(gòu)建并部署好了鏈上程序。此外,可以運行以下命令查看程序日志,日志包括程序日志消息以及程序失敗信息。

solana logs

包含程序失敗信息的日志如下所示,檢查日志找出程序失敗的原因。

<img src="https://learnblockchain.cn/css/default/copy.svg" /><code>Transaction executed in slot 5621:
Signature: 4pya5iyvNfAZj9sVWHzByrxdKB84uA5sCxLceBwr9UyuETX2QwnKg56MgBKWSM4breVRzHmpb1EZQXFPPmJnEtsJ
Status: Error processing Instruction 0: Program failed to complete
Log Messages:
  Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA invoke [1]
  Program log: Hello World Rust program entrypoint
  Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA consumed 200000 of 200000 compute units
  Program failed to complete: exceeded maximum number of instructions allowed (200000) at instruction #334
  Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA failed: Program failed to complete

1.4 本章小節(jié)

本章對 Solana 區(qū)塊鏈的基本概念進行了簡要介紹,Solana 的智能合約叫做鏈上程序。在開始 Solana 鏈上程序開發(fā)之前,需要先安裝和配置相關(guān)的編程環(huán)境,我們著重介紹了 Solana CLI 的安裝和配置。

Hello World 是一個官方演示項目,通過對這個項目源碼的解讀,我們了解了如何使用 Rust 開發(fā)鏈上程序,并使用 Solana CLI 來構(gòu)建與部署,以及使用 Solana JavaScript SDK 與鏈上程序進行交互。

聲明:文章內(nèi)容不代表本站觀點及立場,不構(gòu)成本平臺任何投資建議。本文內(nèi)容僅供參考,風險自擔!
Tag:Solana  

你可能感興趣的文章

熱門幣種

  • 幣名
    最新價格
    24H漲幅
  • bitcoin BTC 比特幣

    BTC

    比特幣

    $ 119498.69¥ 856566.6
    +0.96%
  • ethereum ETH 以太坊

    ETH

    以太坊

    $ 3832.35¥ 27470.28
    +2.75%
  • ripple XRP 瑞波幣

    XRP

    瑞波幣

    $ 3.2191¥ 23.0745
    +0.16%
  • tether USDT 泰達幣

    USDT

    泰達幣

    $ 1.0002¥ 7.1694
    +0.01%
  • binance-coin BNB 幣安幣

    BNB

    幣安幣

    $ 820.37¥ 5880.41
    +5.09%
  • solana SOL Solana

    SOL

    Solana

    $ 188.2¥ 1349.01
    +0.59%
  • usdc USDC USD Coin

    USDC

    USD Coin

    $ 0.9994¥ 7.1636
    -0.01%
  • dogecoin DOGE 狗狗幣

    DOGE

    狗狗幣

    $ 0.2401¥ 1.721
    +0.84%
  • tron TRX 波場

    TRX

    波場

    $ 0.3208¥ 2.2994
    +0.44%
  • cardano ADA 艾達幣

    ADA

    艾達幣

    $ 0.8304¥ 5.9523
    -0.41%

幣圈快訊

  • 數(shù)據(jù):過去24小時全網(wǎng)爆倉1.37億美元,多單爆倉5538.91萬美元,空單爆倉8116.75萬美元

    2025-07-28 00:00
    ChainCatcher消息,據(jù)Coinglass數(shù)據(jù),過去24小時全網(wǎng)爆倉1.37億美元,多單爆倉5538.91萬美元,空單爆倉8116.75萬美元。其中比特幣多單爆倉118.62萬美元,比特幣空單爆倉540.81萬美元,以太坊多單爆倉1264.47萬美元,以太坊空單爆倉2863.9萬美元。此外,最近24小時,全球共有69675人被爆倉,最大單筆爆倉單發(fā)生在Binance-BTCUSDT價值110.15萬美元。
  • ENA突破0.64美元,24小時漲幅達13.2%

    2025-07-27 23:57
    金色財經(jīng)報道,行情顯示,ENA突破0.64美元,現(xiàn)報價0.6317美元,24小時漲幅達13.2%,行情波動叫,請做好風險控制。
  • 外媒:中美在瑞典會談中同意將關(guān)稅暫停期限再延長90天

    2025-07-27 23:55
    ChainCatcher消息,據(jù)Cointelegraph報道,中美在瑞典會談中同意將關(guān)稅暫停期限再延長90天。
  • ZORA于各主流CEX內(nèi)資金費率高度偏空

    2025-07-27 23:21
    7月27日消息,據(jù)Coinglass數(shù)據(jù),ZORA當前合約持倉量達1.7億美元,24小時增157.22%,其于各主流CEX內(nèi)資金費率高度偏空。ZORA24小時合約成交額最大的平臺是Binance,當前資金費率為-1.9406%。此外,其于Bitget、Gate、Bybit分別報-2%、-1.8131%、-2%。
  • 數(shù)據(jù):某巨鯨將171萬枚Fartcoin換倉為7.9億枚PUMP

    2025-07-27 23:17
    ChainCatcher消息,據(jù)Lookonchain監(jiān)測,大約20小時前,某巨鯨將持有的全部171萬枚Fartcoin(價值228萬美元)換倉為7.9041億枚PUMP。
  • 查看更多