Skip to content

Commit

Permalink
Merge pull request Fankouzu#25 from hattiepwvi/main
Browse files Browse the repository at this point in the history
校对
  • Loading branch information
Fankouzu authored May 26, 2024
2 parents 053e75a + 7864b91 commit c49d9c8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 102 deletions.
103 changes: 46 additions & 57 deletions docs/SolanaDocumention/lookup-tables.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,98 @@

# **地址查找表**

地址查找表通常称为“查找表”或简称“ALT”,允许开发人员创建相关地址的集合,以便在单个事务中有效地加载更多地址
地址查找表通常称为 “查找表” 或简称 “ALT”,允许开发人员创建相关地址的集合,以便在单个交易中有效地加载更多地址

由于 Solana 区块链上的每笔交易都需要列出作为交易一部分进行交互的每个地址,因此该列表实际上将限制每笔交易的 32 个地址。在地址查找表的帮助下,一笔交易现在可以将该限制提高到每笔交易 256 个地址。
由于 Solana 区块链上的每笔交易都需要列出作为交易一部分进行交互的每个地址,这种列表实际上限制每笔交易 32 个地址。使用地址查找表的话,可以将限制提高到每笔交易 256 个地址。

## 压缩链上地址

将所有所需地址存储在链上地址查找表中后,可以通过表中的 1 字节索引(而不是完整的 32 字节地址)在事务内引用每个地址。这种查找方法有效地将 32 字节地址“压缩”为 1 字节索引值。
将所有地址存储在链上地址查找表后,通过表中的 1 字节索引(而不是完整的 32 字节地址)在交易中引用每个地址。这种查找方法有效地将 32 字节地址 “压缩” 为 1 字节索引值。

## 版本化交易

要在事务中使用地址查找表,开发人员必须使用随新版本事务格式引入的 v0 事务
在交易中使用地址查找表时,开发人员必须使用 `Versioned Transaction format` 引入的 v0 版本交易

## 如何创建地址查找表

使用 @solana/web3.js 库创建新的查找表与旧的遗留事务类似,但有一些差异。
使用 `@solana/web3.js` 库创建新的查找表与`legacy` 交易类似,但有一些差异。

使用 @solana/web3.js 库,您可以使用 createLookupTable 函数来构造创建新查找表所需的指令,并确定其地址:
使用 `@solana/web3.js` 库的 `createLookupTable` 函数来构造创建新查找表所需的指令,并确定其地址:

```js
const web3 = require("@solana/web3.js");
// 连接RPC

// 连接 RPC
const connection = new web3.Connection(web3.clusterApiUrl("devnet"));
// 获取slot
const slot = await connection.getSlot();

// 假设:
// `payer` 是一个有效的有足够的 SOL 来支付执行费用 的`Keypair`
const [lookupTableInst, lookupTableAddress] =
// `payer` 是一个有效的有足够的 SOL 来支付执行费用的 `Keypair`
const [lookupTableInst, lookupTableAddress] =
web3.AddressLookupTableProgram.createLookupTable({
authority: payer.publicKey,
payer: payer.publicKey,
recentSlot: slot,
});

console.log("lookup table address:", lookupTableAddress.toBase58());

// 在链上创建地址查找表:
// 在交易中发送 `lookupTableInst` 指令
```

> 小贴士
>
> 注意:地址查找表可以使用 v0 事务或旧事务创建。但在使用 v0 版本事务时,Solana 运行时只能检索和处理查找表中的其他地址。

> 注意:地址查找表可以使用 v0 或 `legacy` 交易创建。但在使用 v0 版本交易时,Solana 运行时只能检索和处理查找表中的其他地址。
## 将地址添加到查找表

将地址添加到查找表称为“扩展”。使用@solana/web3.js库,您可以使用extendLookupTable方法创建新的扩展指令
将地址添加到查找表称为 “extending”。使用 `@solana/web3.js 库``extendLookupTable` 方法创建新的扩展指令

```js
// 通过“extend”指令将地址添加到“lookupTableAddress”表
// 通过 “extend” 指令将地址添加到 “lookupTableAddress”
const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({
payer: payer.publicKey,
authority: payer.publicKey,
lookupTable: lookupTableAddress,
addresses: [
payer.publicKey,
web3.SystemProgram.programId,
// 添加更多的地址
// 添加更多地址
],
});
// 在事务中将此 `extendInstruction` 发送到 rpc

// 在交易中将此 `extendInstruction` 发送到 rpc
// 将 `addresses` 列表插入到地址为 `lookupTableAddress` 的查找表中
```

> 小贴士
>
> 注意:由于与旧事务相同的内存限制,用于扩展地址查找表的任何事务也受到一次可以添加的地址数量的限制
> 注意:由于与 `legacy` 交易具有相同的内存限制,用于扩展地址查找表的交易也有每次可添加的地址数量的限制
>
> 因此,您将需要使用多个事务来扩展具有更多地址(~20)的任何表,这些地址可以适应单个事务的内存限制。
一旦这些地址被插入表中并存储在链上,您将能够在未来的交易中使用地址查找表。在这些未来的交易中启用最多 256 个地址。

> 因此,需要使用多个交易来扩展具有更多地址(~20)的任何表,这些地址可以适应单个交易的内存限制。
将这些地址插入表中并存储在链上,就能在交易中使用地址查找表。在交易中最多使用 256 个地址。

## 获取地址查找表

与从集群请求另一个帐户(或 PDA)类似,您可以使用 getAddressLookupTable 方法获取完整的地址查找表:
与从集群请求另一个帐户(或 PDA)类似,使用 `getAddressLookupTable` 方法获取完整的地址查找表:

```js
// 定义要获取的查找表的`PublicKey`
// 定义要获取的查找表的 `PublicKey`
const lookupTableAddress = new web3.PublicKey("");
// 从链上中获取表

// 从链上获取表
const lookupTableAccount = (
await connection.getAddressLookupTable(lookupTableAddress)
).value;
// `lookupTableAccount` 现在将是一个 `AddressLookupTableAccount` 对象

// `lookupTableAccount` 是一个 `AddressLookupTableAccount` 对象

console.log("Table address from cluster:", lookupTableAccount.key.toBase58());
```

我们的lookupTableAccount变量现在将是一个AddressLookupTableAccount对象,我们可以解析它以读取查找表中链上存储的所有地址的列表
`lookupTableAccount` 是一个 `AddressLookupTableAccount` 对象,可以解析它以读取查找表中链上存储的所有地址的列表

```js
// 循环解析地址查找表中的地址
Expand All @@ -107,62 +102,57 @@ for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) {
}
```



## 如何在交易中使用地址查找表

创建查找表并将所需地址存储在链上(通过扩展查找表)后,您可以创建 v0 交易以利用链上查找功能。
创建查找表并将地址存储在链上(通过扩展查找表)后,创建 v0 交易以利用链上查找功能。

就像旧的遗留交易一样,您可以创建交易将在链上执行的所有指令。然后,您可以向 `v0 事务中使用的消息提供这些指令的数组
就像 `legacy` 交易一样,创建在链上执行的所有交易指令。然后,将这些指令数组提供给 `v0` 交易中使用的消息

> 小贴士
>
> 注意:v0 事务中使用的指令可以使用过去用于创建指令的相同方法和函数来构造。涉及地址查找表的指令无需更改。

> 注意:`v0` 交易的指令的构造方法就是构造指令的常见方法和函数, 涉及地址查找表的指令无需更改。
```js
// 假设:
// - `arrayOfInstructions` 已被创建为 `TransactionInstruction` 的 `array`
// - 我们正在使用上面获得的 `lookupTableAccount`
// 构造一个v0 兼容事务`消息`
// - 使用上面获得的 `lookupTableAccount`

// 构造一个v0 兼容交易`消息`
const messageV0 = new web3.TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions: arrayOfInstructions, // 注意这是一个指令数组
}).compileToV0Message([lookupTableAccount]);

// 根据 v0 消息创建 v0 交易
const transactionV0 = new web3.VersionedTransaction(messageV0);
// 使用我们创建的名为“payer”的文件系统钱包签署 v0 交易

// 使用名为“payer”的文件系统钱包签署 v0 交易
transactionV0.sign([payer]);

// 发送并确认交易
//(注意:这里没有签名者数组;请参阅下面的注释...)
const txid = await web3.sendAndConfirmTransaction(connection, transactionV0);

console.log(
`Transaction: https://explorer.solana.com/tx/${txid}?cluster=devnet`,
`Transaction: https://explorer.solana.com/tx/${txid}?cluster=devnet`
);
```

> 小贴士
>
> 注意:将 VersionedTransaction 发送到集群时,必须在调用 sendAndConfirmTransaction 方法之前对其进行签名。如果您传递签名者数组(就像旧交易一样),该方法将触发错误
> 注意:将 `VersionedTransaction` 发送到集群时,必须在调用 `sendAndConfirmTransaction` 方法之前对其进行签名。传递签名者数组(和 `legacy` 交易一样)将触发错误
## 更多资源

- 阅读 [提案](https://docs.solanalabs.com/proposals/versioned-transactions) 了解地址查找表和版本化事务
- 阅读 [提案](https://docs.solanalabs.com/proposals/versioned-transactions) 了解地址查找表和版本化交易
- [使用地址查找表的 Rust 程序示例](https://github.com/TeamRaccoons/address-lookup-table-multi-swap)


## 地址查找表的应用

地址查找表可以用于减小一个事务中地址占用空间。例如在SPL token分发中,会存在大量的接受地址,如果写完整的地址,会占用大量空间,而使用地址查找表,会节省很多空间,因为地址查找表将32字节的地址压缩为了1字节的索引
地址查找表可以用于减小一个交易的地址占用空间。例如在 SPL token 分发中,会存在大量的接受地址,如果写完整的地址,会占用大量空间,而使用地址查找表,会节省很多空间,因为地址查找表将 32 字节的地址压缩为了 1 字节的索引

看一下分发token场景下,对地址查找表应用的代码示例:
看一下分发 token 场景下,对地址查找表应用的代码示例:

```rust
use solana_sdk::{
Expand Down Expand Up @@ -223,4 +213,3 @@ fn main() {
client.send_and_confirm_transaction(&mut transaction).unwrap();
}
```

84 changes: 39 additions & 45 deletions docs/SolanaDocumention/versions.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
# 版本化交易

版本化事务是新的事务格式,允许在 Solana 运行时中使用附加功能,包括地址查找表。
版本化交易是新的交易形式,允许在 Solana 运行时中使用附加功能,包括地址查找表。

虽然不需要对链上程序进行更改来支持版本化交易的新功能(或向后兼容),但开发人员将需要更新其客户端代码以防止由于不同交易版本而导致的错误。

## 当前交易版本

Solana 运行时支持两种事务版本
Solana 运行时支持两种交易版本

- legacy - 较旧的交易格式,没有额外的好处
- 0 - 添加了对[地址查找表](./lookup-tables)的支持
- legacy - 旧的交易版本,没有额外的功能
- v0 - 添加了对[地址查找表](./lookup-tables)的支持

## 最大支持交易版本
## 最大交易版本

返回事务的所有 RPC 请求都应使用 maxSupportedTransactionVersion 选项指定它们在应用程序中支持的最高事务版本,包括 getBlock 和 getTransaction。
返回交易的所有 RPC 请求都应使用 `maxSupportedTransactionVersion` 选项指定它们在应用程序中支持的最高交易版本,包括 `getBlock``getTransaction`

如果返回的版本化事务高于设置的 maxSupportedTransactionVersion,则 RPC 请求将失败。 (即,如果选择旧版时返回版本 0 交易,返回版本高于maxSupportedTransactionVersion 的版本,交易失败)
如果返回的版本化交易高于设置的 `maxSupportedTransactionVersion`,则 RPC 请求将失败。 (即,如果选择旧版时返回 v0 版本交易,返回版本高于 `maxSupportedTransactionVersion` 的版本,交易失败)

> 小贴士
>
> 警告:如果未设置 maxSupportedTransactionVersion 值,则 RPC 响应中将仅允许旧事务。因此,如果返回任何版本 0 事务,您的 RPC 请求将失败。
> 警告:如果未设置 `maxSupportedTransactionVersion` 值,则 RPC 响应中将仅允许旧交易。因此,如果返回 v0 版本交易,RPC 请求将失败。
## 如何设置最大交易版本


## 如何设置最大支持版本

您可以使用 @solana/web3.js 库和直接向 RPC 端点发送 JSON 格式的请求来设置 maxSupportedTransactionVersion。

可以使用 `@solana/web3.js` 库和直接向 RPC 端点发送 JSON 格式的请求来设置 `maxSupportedTransactionVersion`

### 使用 web3.js

使用 [`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/) 库, 您可以检索最近的块或获取特定的交易
使用 [`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/) 库, 可以检索最近的块或获取指定的交易

```js
// connect to the `devnet` cluster and get the current `slot`
Expand All @@ -47,11 +44,13 @@ const getTx = await connection.getTransaction(
"3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ",
{
maxSupportedTransactionVersion: 0,
},
}
);
```
### JSON requests to the RPC
使用标准 JSON 格式的 POST 请求,您可以在检索特定块时设置 maxSupportedTransactionVersion:

### 向 RPC 发送 JSON 请求

使用标准 JSON 格式的 POST 请求, 在检索指定块时设置 `maxSupportedTransactionVersion`

```bash
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d \
Expand All @@ -63,43 +62,43 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -
}]}'
```

## 如何创建版本化事务
## 如何创建版本化交易

版本化事务的创建方式与创建事务的旧方法类似。需要注意的是,使用某些库时存在差异。
版本化交易的创建方式与创建交易的方法类似。需要注意的是,使用某些库时存在差异。

下面是如何使用 @solana/web3.js 库创建版本化事务以在两个帐户之间执行 SOL 传输的示例。
下面是如何使用 `@solana/web3.js` 库创建版本化交易, 然后在两个帐户之间执行 SOL 传输的示例。

**说明:**

- ``payer``是有效的密钥对钱包,由 SOL 资助
- ``toAccount`` 一个有效的密钥对
- `payer`是有效的密钥对钱包,由 SOL 资助
- `toAccount` 一个有效的密钥对

**步骤:**

1. 导入 web3.js 库并创建与所需集群的连接。
1. 导入 web3.js 库并创建与所需集群的连接 `connection`

2. 我们定义交易和帐户所需的最近的 blockhash 和 minRent:
2. 定义交易和帐户所需的最近的 `blockhash``minRent`

代码片段
示例代码

```js
// 引入solana web3.js的包
const web3 = require("@solana/web3.js");

// 链接RPC
const connection = new web3.Connection(web3.clusterApiUrl("devnet"));
// 获取租金豁免的最余额;也就是账户中最少存在多少sol,可以免除账户租金
// 获取租金豁免的最小余额;也就是账户中最少存在多少sol,可以免除账户租金
let minRent = await connection.getMinimumBalanceForRentExemption(0);
// 获取最新的区块hash
let blockhash = await connection
.getLatestBlockhash()
.then(res => res.blockhash);
.then((res) => res.blockhash);
```

3. 创建一个包含您希望在交易中发送的所有指令的数组。在下面的示例中,我们将创建一个简单的 SOL 传输指令:
3. 创建一个包含在交易中发送的所有指令 `instructions` 的数组。如下所示,创建一个简单的 SOL 传输指令:

```js
// 创建transfer指令数组
// 创建 transfer 指令数组
const instructions = [
web3.SystemProgram.transfer({
fromPubkey: payer.publicKey,
Expand All @@ -109,48 +108,43 @@ let blockhash = await connection
];
```



4. 使用您所需的指令构建 MessageV0 格式的交易消息
4. 使用所需的指令 `instruction` 构建 `MessageV0` 格式的交易消息

```js
// 以MessageVo编译消息
// 以 MessageVo 编译消息
const messageV0 = new web3.TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();
```



5. 创建一个新的 VersionedTransaction,传入我们的 v0 兼容消息:
5. 创建一个新的 `VersionedTransaction`,传入 v0 兼容消息:

```js
// 构造交易对象
const transaction = new web3.VersionedTransaction(messageV0);

// 使用payer签名交易
transaction.sign([payer]);
```

交易签名有两种方式:

- 将签名数组传递到 VersionedTransaction 方法中
- 调用 transaction.sign() 方法,传递所需签名者的数组
- 将签名 `signatures` 数组传递到 `VersionedTransaction` 方法中
- 调用 `transaction.sign()` 方法,传递所需签名者 `Signers` 的数组

6. 向RPC提交交易
6. 向 RPC 提交交易

```js
// 提交VO版本的交易
// 提交 VO 版本的交易
const txId = await connection.sendTransaction(transaction);
console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`);
```

## 更多资源

- 使用 [地址查找表的版本化事务](./lookup-tables.md)
- 在solana浏览器查看 [ v0 交易的示例](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet)
- 使用 [地址查找表的版本化交易](./lookup-tables.md)
- 在 solana 浏览器查看 [ v0 交易的示例](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet)

- 阅读已接受的版本化交易和地址查找表 [提案](https://docs.solanalabs.com/proposals/versioned-transactions)

0 comments on commit c49d9c8

Please sign in to comment.