讨论 Solana 及其架构的特殊性,并介绍在其上开发智能合约的基础知识。
由于其支持自定义智能合约开发的特殊功能,Solana 正迅速成为构建去中心化应用程序的最受欢迎的区块链平台之一。该网络以其令人印象深刻的速度、效率和扩展能力而脱颖而出,使其成为很吸引力的商业选择。 在这篇博文中,我们将讨论 Solana 及其架构的特殊性,并介绍在其上开发智能合约的基础知识。
Solana 是一个高性能的区块链平台,专为去中心化应用程序和加密项目而设计。它以交易速度快和费用低而闻名。它的应用很广泛,包括去中心化金融(DeFi)、不可替代代币(NFT)、去中心化交易所(DEX)等。
可扩展性是区块链面临的重大挑战,特别是随着网络的发展产生的交易速度和确认时间的限制。 Solana 通过创新的验证方法解决了这些问题。它使用了一种称为历史证明(Proof-of-History)的机制以可验证地记录交易的时间。该机制建立了一个无需信任的系统,从而减少了网络开销并提高了交易处理的速度。
Solana 有自己的原生货币,称为 SOL。这种货币用于支付交易费用,在网络中发挥着至关重要的作用。 SOL 对于平台的安全基础设施也至关重要。网络验证者以 SOL 为承诺,这意味着这些验证者可以获得新的 SOL 代币作为对成功验证区块奖励。另一方面,如果验证者行为不当,他们质押的 SOL 可能会被削减(即从流通中部分移除);截至撰写本文时,自动削减尚未实施,也没有近期的计划。然而,削减的可能性仍然让不良行为者望而却步。
Solana 的核心创新在于其独特的Proof of History(PoH)机制,该机制使验证者能够快速就交易的时间和顺序达成共识,从而显着提高网络的可扩展性和吞吐量。这并不是推动 Solana 性能的唯一创新。该网络采用了其他跨时代的技术与PoH相结合,以实现高吞吐量、低延迟并确保平台的可扩展性。
历史证明(PoH)是区块链技术中的一个开创性概念,它源于权益证明(PoS)。与传统的时间戳方法不同,PoH能够验证某一事件相对于其他事件是否按特定的顺序发生。
PoH使用基于SHA256的可验证延迟函数(verifiable delay function, VDF)。VDF的目的是使用前一个哈希值作为下一个哈希计算的输入,从而以尽可能高的速度依次处理哈希计算。因此,“可核实的延迟(verifiable delay)”一词是指计算需要花费一定的最短时间。尽管初始计算需要一些时间,但验证过程可以有效地并行化,使验证速度显著加快。
在计算VDF的任何步骤,都可以将各种事件(如交易)合并到哈希计算的输入中,从而建立一个清晰、可验证的事件序列。由于哈希计算过程需要的时间是一致的,验证者可以准确地确定事件之间经过了多少时间。此外,通过在这个哈希链中安排事务,验证者为每个区块处理和传输的数据会更少。
然而,PoH 也有其局限性。他们包括:
复杂的设置:PoH 的实施比传统方法更复杂。
新的且基本上未经测试:由于 PoH 相对较新,它没有像既定方法那样经过长时间的测试,这引起了人们对未来可能出现的未知问题的担忧。
PoH 本身仅提供可验证的事件序列,Solana 利用一组其他技术来促进快速交易处理。其中包括 Tower BFT、Turbine、Gulf Stream、Sealevel、Cloudbreak。
Tower BFT 是一种旨在提高网络效率的共识机制。本质上,Tower BFT 是委托权益证明 (Delegated Proof of Stake, DPoS) 区块链中实用拜占庭容错 (Practical Byzantine Fault Tolerance, PBFT) 模型的修改迭代。 Tower BFT的主要特点是:
以PoH为可靠的网络时钟。由于 PoH 账本的所有网络事件都附加了可靠的时间戳,因此任何节点都可以计算任何其他节点的确切状态,而无需任何额外的点对点通信,这可以显着减少网络开销。相比之下,传统的 BFT 系统依赖验证者之间的点对点通信来建立事件序列。
验证者每个时隙只能投票一次。一个时隙(slot)是表示固定时间量的多个 PoH 步骤,目标是 400 毫秒左右。这有助于确保网络持续运行并且不会无限期地停滞。
Tower BFT 采用权益加权超时(stake-weighted timeout)机制来激励验证者对最重(heaviest)的分叉进行投票,这有助于避免链分叉。微分叉仍然会发生,但很快就会被丢弃。
Turbine 是一种区块传播协议,使网络能够在不增加数据传输时间的情况下增加节点数量。它的工作方式有点类似于点对点数据传输协议,例如 BitTorrent。它将消息分解为更小的数据包并通过验证者之间的中继系统进行分发。Turbine 显着提高了 Solana 网络上处理交易的吞吐量和整体能力。
Gulf Stream 通过消除传统的内存池(一个等候区,用于放置等待被区块处理的交易)来增强交易处理。事务的缓存和转发被委托给网络边缘。任何时隙中,新区块均由称为领导者(leader)的单个验证者节点生成。领导者按计划轮换,以避免赋予一个验证者过多的权力。每个验证者都知道即将到来的领导者的顺序,从而可以提前将交易转发给预期的领导者。这让验证者能提前执行交易并减少确认时间。
Cloudbreak是针对Solana区块链状态的水平可扩展存储解决方案。它使用的自定义数据结构可优化并行读写,并提高水平扩展性。它的实现对于Solana的可扩展性至关重要。
从本质上讲,Cloudbreak是一个将地址映射到帐户的高性能数据库。
Sealevel是Solana的智能合约运行时(runtime),它旨在允许智能合约的并行执行。与其他领先的智能合约网络相比,这使该平台具有显著的性能优势。得益于这一功能,Solana可以在不影响网络性能的情况下同时处理数千个智能合约。
Sealevel的一个关键方面是帐户模型。在编写Solana智能合约甚至简单地使用区块链时,我们都需要理解它。所以我们将对此进行更详细的讨论。
Solana 账户模型是其生态系统的基本,使其有别于其他区块链平台。
Solana 的帐户充当数据的存储位置。以太坊将智能合约代码及其数据在概念上共存于一个位置,Solana与它不同,Solana 明确讲程序代码和正在处理的数据区分开,并将它们分配给不同的账户。
当调用程序时,调用者必须提供程序将使用的所有帐户,明确标记该帐户是否应为只读、可写,或者是否正在签署操作。这种独特的方法是 Sealevel 实现高度并行的关键因素之一:事实上,在不同帐户上运行的同一程序可以使用 SIMD 处理并行运行。
这种方法还使程序具有高度的可重用性和可组合性。例如,您无需开发和部署单独的智能合约即可在 Solana 上发布memecoin;相反,您只需重复使用 Solana Labs 部署的代币程序即可。
Solana 帐户存储着其 SOL 余额、其所属程序的地址以及程序特定的任意二进制数据。这些是与帐户所有权相关的基本规则:
程序无法更改不属于它们的帐户的数据。
程序只能从其拥有的账户中借记 SOL。
任何程序都可以从任何帐户读取数据或存入SOL。
默认情况下,新帐户归系统程序所有。系统程序促成了各种核心的区块链操作,如在不同账户之间转移SOL。它还可以为帐户分配零初始化的数据,和将帐户所有权转移到其他程序。
Solana 区块链有两种类型的帐户:可执行帐户和不可执行帐户。
可执行帐户是一种特殊类型的帐户,它是不可变的,并且包含可由运行时(runtime)执行的字节码(byte-code)。曾经,Solanaa程序的可执行代码存储在这些可执行帐户中。然而,由于其不可变的性质,升级合同的必要性导致现在使用更复杂的方法。如今,可执行帐户只存储一个小的加载填充程序(loader shim),而实际代码存储在一个没有被标记为可执行的单独帐户中。可执行帐户由BPF加载程序版本1或2,或由可升级的BPF加载程序所有。所有的新账户都归后者所有。
不可执行帐户用于程序特定的数据存储,其数据是可变的。
维护这些账户中的数据会产生称为租金的成本,租金可通过 lamport 支付。lamports代表着Solana 原生代币 SOL 的一小部分,用于网络上的小额支付。租金费用取决于帐户所需的存储大小,数据存储越多,费用越高。目前,所有账户都免租(而是采用保证金模式,译者注),意思是它们必须一直保持一个最低的 SOL 余额。这个最低余额根据帐户存储的数据量而定。在撰写本文时,对于有 128 字节最小存储空间的帐户,所需的最低余额为 0.00089088 SOL,等效为 890,880 lamport。您可以通过运行 solana rent <size>
轻松计算所需的余额,其中 <size>
是帐户大小(以字节为单位)。请记住,solana rent
的参数中了预留了一个 128 字节的最小存储,因为这些字节不可用存储特定的程序。因此,solanarent 5
实际的余额是 133 字节(即 128 + 5)。
SPL 代币是在 Solana 区块链生态系统中运行的数字资产。管理 SPL 代币的代码由 Solana Labs 部署,它是 Solana 程序库的一部分。举个例子,与以太坊形成鲜明对比的是,以太坊上的每个代币都必须有自己的合约,而 Solana 上的代币则重复使用现有的合约。
涉及 SPL 代币的交易费用可以使用该平台的原生代币 SOL 支付。
SPL代币与其他区块链生态系统中的代币标准不同,例如以太坊的ERC标准、波场(TRON)的TRC-20和币安智能链的BEP-20。 SPL 代币的主要特征包括:
NFT 和可替代代币的适用性:SPL 代币涵盖同一标准下的可替代(可互换)和不可替代(唯一)代币。 (而以太坊对每种代币类型都有单独的标准。)
可组合性:代币代码可以重复使用,从而用最小的更改即可创建新的 SPL 代币。这种可组合性意味着开发人员可以通过仅更改某些参数来快速地生成新代币。
效率:SPL 代币直接受益于 Solana 区块链的高性能。该网络的高处理速度提高了 SPL 代币的交易效率,使这些代币比其他区块链上的操作更快、更具成本效益。
Solana 的 Token-2022 计划(也称为Token Extensions)是一种新的实现方式。它在一定程度上向下兼容原来的 SPL 代币。然而,它是一个不同的程序,具有单独的源代码并部署在不同的地址。
Token Extensions扩大了 SPL 代币的铸造和使用范围,使用户能够在更广泛的应用中使用 SPL 代币,例如机密交易、创新合规机制、引入代币转让费用等。Token Extensions同时兼容可替代和不可替代代币。
尽管该计划于 2022 年推出,但 Beta 测试在最近才完成,这为智能合约开发提供了机会。然而,在撰写本文时,程序仍然在更新并有进一步的更改,并暂定计划在 2024 年晚些时候冻结更新。
Token-2022 扩展分为两类:铸造拓展和 账户扩展。
铸造扩展增强了代币铸造者的能力。代币铸造者指的是SPL代币计划(2022)拥有的一个账户,它存储了有关代币的必要元数据,例如谁可以铸造新代币,代币是否可分割,以及可分割到何种程度等。铸造扩展允许为代币指定额外的规则或属性,例如添加面向用户的元数据,如令牌名称和图片。
当代币需要标准发行之外的额外逻辑或信息时,例如为NFT定义唯一标识符或嵌入监管合规检查时,它们非常有用。
目前的铸造拓展包括:
私密转账:允许用户之间进行私人交易,并隐藏转账金额。请注意,在撰写本文时,机密传输仍然需要在网络上激活功能,因此还不起作用。
转账费用:此功能允许每次代币转账收取费用,然后将这些费用分配到指定的帐户。它在用于例如NFT销售的铸币税上会起到作用。
关闭铸造权限:这一扩展授予所有者关闭铸币账户的权力,使他们能够收回这些账户中的lamports。
计息代币:这是一个界面功能,允许指定如何在显示前调整代币金额。具体来说,它允许指定可见代币金额增长(或减少)的利率。实际上没有铸造新的代币。
不可转让代币:此功能限制用户之间的代币转让,将代币锁定到其初始持有者。
永久代理:此功能为铸币指定一名永久代理,授予该代理对与该铸币相关的任何代币账户的无限访问权和控制权。这包括随意转移或焚烧代币的能力。这方面的使用案例可能包括没收受制裁实体的资产或收回未缴纳Harberger税的代币。
转移挂钩(hook):启用后,每个代币的转移都将通过CPI(跨程序调用)触发指定的程序,从而可以在代币转移时运行自定义的链上代码,例如,使用程序定义的逻辑阻止某些转移。
元数据指针:使代币创建者能够指定一个地址,该地址保存代币的官方元数据。有趣的是,这也可以指向铸币本身。
元数据:此扩展通过自定义字段将额外的元数据直接集成到铸币帐户中。需要注意的是,在撰写本文时,DEX和钱包对原生代币2022元数据的支持相当缺乏,因此Metaplex代币元数据暂时仍应是首选。
组指针:代币创建者可以指向提供铸币详细信息的组帐户。这类似于元数据指针,但它描述了代币是如何分组的。例如,这对于集合NFT非常有用。
组:与元数据一样,铸币本身可能被设置为自己的组帐户。附加说明也同样适用:在撰写本文时由于缺乏生态系统的支持,应首选前面提到的Metaplex元数据。
成员指针:此扩展类似于元数据和组指针,但此处指向的帐户描述的是组成员身份。
成员:类似于组和数据,铸币本身可以是自己的成员描述。与“组”和“元数据”相同的注意事项也适用。
账户扩展用于向代币账户添加功能或数据,代币账户是包含特定数量代币的个人持有/账户。这些扩展可以为帐户提供附加功能,例如启用特定于帐户的设置、限制或功能。
帐户扩展对于创建更复杂的代币持有结构特别有用,例如具有条件释放的托管帐户、具有多级访问控制的帐户,或使用自定义元数据增强用户体验。
目前的账户拓展有:
转账时的备忘录要求:此扩展要求在每次代币转账时都包含一份备忘录(即明文说明),以确保法规遵从性、记录和更彻底的审计跟踪。
永久所有权:确保代币账户的所有权不能转移,从而使所有者不可变。这排除了关联代币帐户可能存在的某些攻击。
默认帐户状态:所有新的代币帐户都是在“冻结”状态下创建的,需要与相关项目进行某种形式的交互才能“解冻”并启用帐户或代币。
跨程序调用保护:此设置可以将有问题的代币帐户的某些CPI(跨程序调用)排除掉。这可能会更安全,因为它可以防止程序以用户不可见的方式使用用户权限运行操作。
重新分配功能:此功能允许所有者在创建代币帐户后调整其代币帐户的分配,以允许额外的扩展。
观看Solana官方关于代币扩展的用例视频:https://youtu.be/CEuKahqOYbs
您也可以在Solana官方网站上找到代币扩展的开发者指南。
为Solana智能合约开发选择合适的编程语言极其重要。尽管Solana支持数种语言(例如,C和C++),但首选项是Rust,它以强调内存安全而闻名。
Rust有助于早期识别与内存相关的错误,如缓冲区溢出和空指针取消引用。这一功能显著增强了智能合约的安全性和鲁棒性,使其更能抵御攻击。
Rust还受益于强大的工具和支持Solana开发的社区。Rust的Solana程序开发要成熟得多,有许多专门针对Rust的第一方工具和库。
Solana的智能合约是使用平台生态系统提供的工具开发的。在本节中,我们将对流程进行细分。
设置开发环境涉及以下操作:
安装CLI:Solana命令行界面(CLI)工具套件对于部署智能合约以及在Solana网络上管理和交互智能合约至关重要。您可以在Solana文档网站上找到关于您操作系统的安装指南。
下载并安装Rust:从其官方网站下载Rust,然后按照特定您操作系统的安装说明进行操作。Rustup是一个多功能工具,利用它可以简化Rust、包管理器Cargo以及Solana开发所需的其他基本依赖项的安装。
创建Solana钱包:该工具对于与Solana网络交互至关重要,从签署交易到部署智能合约。您可以通过Solana CLI或基于web的解决方案(如Phantom、Solflare或Backpack)创建钱包。请记住保护您钱包的种子短语,因为丢失它将导致无法访问您的钱包。重要提示:您需要将钱包密钥导出到CLI中才能部署程序,除非您使用的是硬件钱包。因此,如果你有一个包含资产的Solana钱包,由于安全风险,最好避免将其用于部署程序。相反,创建一个专门用于部署程序的单独帐户,并在必要时使用SOL为其提供资金。
配置开发设置:准备好所有必要的工具并设置好钱包后,最后一步是为Solana网络定制开发环境。这包括将Solana CLI连接到相应的Solana集群并链接钱包地址。Solana文档提供了此配置过程的详细说明。
设置好开发环境后,在Solana创建智能合约的下一步是编写代码。
有几种方法可以做到这一点:
所谓的原生Solana程序是用Rust编写的crate,使用solana_program
来调用Solana的API。
Anchor框架是专门为Solana智能合约开发而构建的。Anchor主要用于Rust,但它也支持使用solang编译器的Solidity。
Seahorse框架允许使用Python语法编写Solana程序。Seahorse是在Anchor之上构建的,通过将Python代码翻译成等效的Rust代码来工作,因此它具有与Anchor基本相同的功能。
每一种方法都有其长处和短处。
原生程序使开发人员能够最大限度地控制程序的执行方式,但另一方面,检查和维护非变量以避免安全问题完全是开发人员的责任。原生程序的一个特别的优点是可以使用Rust工具进行单元和集成测试。
Anchor通过处理大量模板(包括检查公共的非变量)简化了开发流程,因此程序员可以专注于业务逻辑。另一方面,它能做的控制更少,并且使用Anchor生成的二进制工作文件往往更大(因此部署它们的租金更高)。Anchor的测试程序主要使用JavaScript,基本上是在本地机器上运行区块链的独立实例,然后部署程序,并针对它进行交易。虽然这种方法能简化一些重要的环节,但它的集成测试受限,而且可能相对较慢。后一个问题可以通过Bankrun测试框架来解决,但它没有与Anchor集成。
Seahorse更进一步,用更加简单的Python语法隐藏了一些Rust特性。然而,这是以灵活性为代价的。此外,在撰写本文时,Seahorse仍处于测试版,因此在生产中使用它时应格外小心。
开发原生程序
用cargo创建一个crate:原生程序只是一些crate,因此首先使用 cargo init<crate_name>--lib
创建一个新crate
。
将 solana-program
添加到依赖项:在crate的根目录中,运行 cargo add solana-program
。这将把链上程序SDK添加为依赖项。
设置所需的Cargo选项:打开 Cargo.toml
,把 crate-type = ["cdylib", "lib"]
添加到lib
部分。
定义入口函数:Solana需要知道该从哪里开始执行程序,从这里开始的函数称为入口(entrypoint)。
导出入口函数:使用solana_program::entrypoint
宏指令来告诉运行时入口函数是哪个,例如:solana_program::entrypoint!(entrypoint)
编写业务逻辑:原始指令数据将会传递到入口。然后,开发人员需要做的是解码这些数据并采取适当的行为。编码格式不是由网络指定的,所以它是任意的。但是,建议使用Borsh序列化/反序列化程序,可以从solana_program::borsh*
模块导出实用程序来使用它。
编写和运行测试:定义常规的Rust单元测试,和/或使用solana-program-test
进行集成测试。
构建程序:前面提到的CLI工具套件附带了cargo-build-bpf
,它可以构建适合部署的二进制工作文件。直接运行它或调用cargo build-bpf
通过Cargo运行它。如果需要的话它将自动下载工具链,并构建二进制工作文件,将其放入target/deploy/
目录。
用Rust开发Anchor程序
安装Anchor:由于Anchor不是Solana的核心部件,因此需要单独安装。有关说明,请参阅官方文档。
新建Anchor项目:使用anchor init <your-project-name>
。
定义帐户的数据结构:用#[account]
注释数据结构,让Anchor知道它应该为结构派生与帐户相关的样板。
定义指令的帐户列表:通过使用 #[derive(Accounts)]
注释数据结构并使用 #[account(...)]
注释其各个字段,您可以指定指令所需的帐户,无论它们是否是可变的,是否要检查的其他约束等等。Anchor 将处理实际编组帐户和检查约束。
将程序指令定义为函数:Anchor 会自动处理指令反/序列化。要在 Anchor 中定义指令及其业务逻辑,请定义一个新模块,并用 #[program]
注释。该模块中定义的公共函数需要有相应的指令。每个函数必须有两个参数:一个是 Context <Descriptor>
,其中 Descriptor
是带有 #[derive(Accounts)]
注释的结构(之前定义的);另一个是以及表示指令数据有效负载的任意类型。该指令有效负载类型必须实现 AnchorDeserialize 特征
(可以派生)。在大多数情况下,它还应该实现 AnchorSerialize
特征(也可以派生)。该函数应返回 Result<()>
。
定义错误:Anchor 允许使用面向用户的消息来自定义错误。定义一个枚举,用 #[error_code]
对其进行注释,并用 #[msg("Error description here")]
注释每个变量(其中"Error description here"
描述错误信息)。在程序的业务逻辑中通过用 err!
宏指令来使用这些自定义错误,或者使用 require!
编写断言。
编写测试:Anchor 使用 TypeScript 通过 Solana TypeScript SDK 定义集成测试。
构建程序:使用anchor build
。
运行测试:使用anchor test
。
测试智能合约的功能和效率是 Solana 开发的关键。 Solana 提供了一系列测试工具和环境,旨在确保您的代码正常工作并集成到 Solana 生态系统中。
单元测试:Rust 中集成的单元测试框架是第一道防线,它允许您单独检查各个代码段,并在开发机器上进行本地测试。使用 Anchor 时,编写单元测试明显更具挑战性,因为框架本身仅使用 Solana TypeScript 客户端 SDK 提供的“外部”集成测试。
集成测试:集成测试可以评估您的智能合约与其他 Solana 网络组件的交互。集成测试有两种主要方法:solana-program-test
,它是一个 Rust 的crate,为集成测试提供模拟的 Solana 网络环境;solana-test-validator
,它运行本地 Solana 节点,用于在本地节点测试智能合约。后者明显慢得多,使用起来也更麻烦,但它的行为几乎就像一个真实的网络。 Anchor 使用后者来运行测试,但使用 Bankrun 测试框架可能是测试 Anchor 程序的另一个可行选择。
测试 Solana 智能合约代码后,下一步是部署到 Solana 网络。操作方法如下:
部署程序:您的智能合约在网络上的唯一标识符是程序 ID。要创建程序 ID,请通过在终端中执行以下命令来使用 Solana 命令行界面 (CLI):solana program deploy <path_to_your_compiled_program>
。此操作会编译您的智能合约并将其上传到网络,为其分配一个程序 ID 以供引用和交互。如果您想要程序的虚地址(vanity address),您可以提前生成它(例如使用 solana-keygen
)并用 --keypair
参数将其提供给 solana program deploy
。默认情况下,您将获得一个随机地址。使用Anchor时,可以使用anchor deploy
。您可以通过将其密钥放入 ./target/deploy/<program_name>-keypair.json
来提供虚地址。
验证部署:通过检查网络上的程序 ID 来确认您的智能合约已正确部署。您可以使用 Solana Explorer、Solscan.io、另一个公共索引器或 Solana CLI 命令 solana program show <program_id>
检索有关合约的详细信息,包括其大小和 SOL 余额。此步骤可确保您的智能合约已激活并准备好在网络上使用。
如果您在开发过程中遇到困难,或者需要对 Solana 智能合约进行第三方审核,我们可以随时为您提供帮助。
Solana 智能合约是否可以与其他区块链平台集成?
不能直接这么做,但您可以设置资产桥(asset bridge),这对于任何支持智能合约的区块链对都是如此。
哪些编程语言适合开发 Solana 智能合约?
您可以主要使用 Rust 创建 Solana 智能合约,但其他语言,例如 C、C++、Solidity(通过 Solang 编译器)和 Python(通过 Seahorse 框架)也适用。
如何测试 Solana 智能合约?
对于本地合约,您可以使用 Rust 的测试工具以及 solana-program-test
进行集成测试。 Anchor 框架提供了自己的基于 solana-test-validator
的集成测试设置。最后,任何程序都可以使用 Bankrun 进行测试,Bankrun 是一个在底层使用 solana-program-test
的 NodeJS 测试工具。
Solana 浏览器有什么作用?
Solana Explorer 是一款在线工具,允许用户直观地导航 Solana 区块链、查看交易并详细检查智能合约。
总之,Solana 为以太坊等旧区块链平台提供了一个有吸引力的替代方案。由于其架构,它提供了高速交易、低延迟和可扩展性。其 Token-2022 计划代表了一组用于构建自定义智能合约的扩展,可满足新的业务环境以及当前和未来的需求。 Solana 的市场地位也非常牢固,并将保持和增强其影响力。
如果您的目标是释放区块链项目的全部潜力,并正在寻找技术精湛、经验丰富的 Solana 智能合约开发人员,Serokell 团队随时准备为您提供帮助。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!