10E polkadot substrate : 配置合约托盘

介绍
添加托盘依赖项
实现 Contracts 配置特征
公开合约 API
更新外部节点
启动本地 Substrate 节点
Substrate Tutorials , Substrate 教程
Contact 联系方式

• 介绍

如果您完成了构建本地区块链教程,那么您已经知道 Substrate节点模板提供了一个工作运行时,其中包括一些供您入门的托盘。在将托盘添加到运行时中,您了解了将新托盘添加到运行时的基本常用步骤。但是,每个托盘都需要您配置特定的参数和类型。为了了解这意味着什么,本教程演示了向运行时添加更复杂的托盘。在本教程中,您将添加Contracts 托盘,以便您可以支持区块链的智能合约开发。

• 添加托盘依赖项

任何时候将托盘添加到运行时,都需要导入适当的 crate 并更新运行时的依赖项。对于 Contracts 托盘,您需要导入pallet-contractscrate。

• runtime/Cargo.toml在文本编辑器中打开配置文件。

• 通过将 crate 添加到依赖项列表中,导入pallet-contractscrate 以使其可用于节点模板运行时。

[dependencies.pallet-contracts]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'latest'
version = '4.0.0-dev'

[dependencies.pallet-contracts-primitives]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'latest'
version = '4.0.0-dev'

• 将 Contracts 托盘添加到std功能列表中,以便在将运行时构建为原生 Rust 二进制文件时包含其功能。

[features]
default = ['std']
std = [
	#--snip--
	'pallet-contracts/std',
	'pallet-contracts-primitives/std',
	#--snip--
 ]

• 保存更改并关闭runtime/Cargo.toml文件。

• 实现 Contracts 配置特征

现在您已成功导入 Contracts 托盘箱,您可以将其添加到运行时。如果您浏览过其他教程,您可能已经知道每个托盘都有一个配置特征 - 称为Config- 运行时必须实现。

要Config在运行时实现 Contracts 托盘的特征:

• runtime/src/lib.rs在文本编辑器中打开文件。

• 找到pub use frame_support块并添加Nothing到特征列表中。

pub use frame_support::{
	construct_runtime, parameter_types,
	traits::{KeyOwnerProofSystem, Randomness, StorageInfo, Nothing},
	weights::{
	constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
	IdentityFee, Weight,
},
StorageValue,
};

• 将WeightInfo属性添加到运行时。

/* After this line */
use pallet_transaction_payment::CurrencyAdapter;
/*** Add this line ***/
use pallet_contracts::weights::WeightInfo;

• 将 Contracts 托盘所需的常量添加到运行时。

/* After this block */
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;

/* Add this block */
// Contracts price units.
pub const MILLICENTS: Balance = 1_000_000_000;
pub const CENTS: Balance = 1_000 * MILLICENTS;
pub const DOLLARS: Balance = 100 * CENTS;

const fn deposit(items: u32, bytes: u32) -> Balance {
	items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS
}

/// Assume ~10% of the block weight is consumed by `on_initialize` handlers.
/// This is used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/*** End Added Block ***/

• 将 Config 特征的参数类型和实现添加到运行时。

impl pallet_timestamp::Config for Runtime {
/* --snip-- */
}

/*** Add this block ***/
parameter_types! {
	pub TombstoneDeposit: Balance = deposit(
		1,
		<pallet_contracts::Pallet<Runtime>>::contract_info_size()
	);
	pub DepositPerContract: Balance = TombstoneDeposit::get();
	pub const DepositPerStorageByte: Balance = deposit(0, 1);
	pub const DepositPerStorageItem: Balance = deposit(1, 0);
	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
	pub const SurchargeReward: Balance = 150 * MILLICENTS;
	pub const SignedClaimHandicap: u32 = 2;
	pub const MaxValueSize: u32 = 16 * 1024;
	// The lazy deletion runs inside on_initialize.
	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
	 BlockWeights::get().max_block;
	// The weight needed for decoding the queue should be less or equal than a fifth
	// of the overall weight dedicated to the lazy deletion.
	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
		<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
		<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
	 )) / 5) as u32;

	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
}

impl pallet_contracts::Config for Runtime {
	type Time = Timestamp;
	type Randomness = RandomnessCollectiveFlip;
	type Currency = Balances;
	type Event = Event;
	type RentPayment = ();
	type SignedClaimHandicap = SignedClaimHandicap;
	type TombstoneDeposit = TombstoneDeposit;
	type DepositPerContract = DepositPerContract;
	type DepositPerStorageByte = DepositPerStorageByte;
	type DepositPerStorageItem = DepositPerStorageItem;
	type RentFraction = RentFraction;
	type SurchargeReward = SurchargeReward;
	type WeightPrice = pallet_transaction_payment::Module<Self>;
	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
	type ChainExtension = ();
	type DeletionQueueDepth = DeletionQueueDepth;
	type DeletionWeightLimit = DeletionWeightLimit;
	type Call = Call;
	/// The safest default is to allow no calls at all.
	///
	/// Runtimes should whitelist dispatchables that are allowed to be called from contracts
	/// and make sure they are stable. Dispatchables exposed to contracts are not allowed to
	/// change because that would break already deployed contracts. The `Call` structure itself
	/// is not allowed to change the indices of existing pallets, too.
	type CallFilter = Nothing;
	type Schedule = Schedule;
	type CallStack = [pallet_contracts::Frame<Self>; 31];
}
/*** End added block ***/

• 将合同托盘中公开的类型添加到construct_runtime!宏中。

construct_runtime!(
	pub enum Runtime where
	 Block = Block,
	 NodeBlock = opaque::Block,
	 UncheckedExtrinsic = UncheckedExtrinsic
	{
	 /* --snip-- */
	 /*** Add this ine ***/
	 Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
	}
);

• 保存更改并关闭runtime/src/lib.rs文件。

• 通过运行以下命令检查您的运行时是否正确编译:

cargo check -p node-template-runtime

尽管运行时应该编译,但您还不能编译整个节点。

• 公开合约 API

一些托盘(包括合同托盘)公开了自定义运行时 API 和 RPC 端点。您无需启用 Contracts 托盘上的 RPC 调用即可在链上使用它。但是,公开 Contracts 托盘的 API 和端点很有用,因为这样做可以让您执行以下任务:

从链下读取合约状态。

在不进行事务的情况下调用节点存储。

要公开 Contracts RPC API:

• 在文本编辑器中打开runtime/Cargo.toml文件并添加依赖项部分以导入 Contracts RPC 端点运行时 API。

[dependencies.pallet-contracts-rpc-runtime-api]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'latest'
version = '4.0.0-dev'

• 将 Contracts RPC API 添加到std功能列表中,以便在将运行时构建为原生 Rust 二进制文件时包含其功能。

[features]
default = ['std']
std = [
	#--snip--
	'pallet-contracts-rpc-runtime-api/std',
]

• 保存更改并关闭runtime/Cargo.toml文件。

• 打开文件并在运行时文件末尾附近的宏runtime/src/lib.rs中实现合约运行时 API 。impl_runtime_apis!lib.rs

impl_runtime_apis! {
	/* --snip-- */
	/*** Add this block ***/
	impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>
	for Runtime {
	 fn call(
			origin: AccountId,
			dest: AccountId,
			value: Balance,
			gas_limit: u64,
			input_data: Vec<u8>,
	 ) -> pallet_contracts_primitives::ContractExecResult {
			let debug = true;
			Contracts::bare_call(origin, dest, value, gas_limit, input_data, debug)
	}

		fn instantiate(
			origin: AccountId,
			endowment: Balance,
			gas_limit: u64,
			code: pallet_contracts_primitives::Code<Hash>,
			data: Vec<u8>,
			salt: Vec<u8>,
	 ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber> {
			let compute_rent_projection = true;
			let debug = true;
			Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, compute_rent_projection, debug)
	 }

	 fn get_storage(
			address: AccountId,
			key: [u8; 32],
	 ) -> pallet_contracts_primitives::GetStorageResult {
			Contracts::get_storage(address, key)
	 }

	 fn rent_projection(
			address: AccountId,
	 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {
			Contracts::rent_projection(address)
	 }
	}
	/*** End added block ***/
}

• 保存更改并关闭runtime/src/lib.rs文件。

• 通过运行以下命令检查您的运行时是否正确编译:

cargo check -p node-template-runtime

• 更新外部节点

至此,您已完成将 Contracts 托盘添加到运行时。现在,您需要考虑外部节点是否需要任何相应的更新。要让 Contracts 托盘利用 RPC 端点 API,您需要将自定义 RPC 端点添加到节点配置中。

要将 RPC API 扩展添加到外部节点:

打开node/Cargo.toml文件并添加依赖项部分以导入 Contracts 和 Contracts RPC crates。

[dependencies]
jsonrpc-core = '15.1.0'
structopt = '0.3.8'
#--snip--
# *** Add the following lines ***

[dependencies.pallet-contracts]
git = 'https://github.com/paritytech/substrate.git'
tag = 'latest'
version = '4.0.0-dev'

[dependencies.pallet-contracts-rpc]
git = 'https://github.com/paritytech/substrate.git'
tag = 'latest'
version = '4.0.0-dev'

• node/src/rpc.rs在文本编辑器中打开文件。

Substrate 提供了一个 RPC 来与节点交互。但是,默认情况下它不包含对合同托盘的访问。要与合同托盘交互,您必须扩展现有的 RPC 并添加合同托盘及其 API。

use node_template_runtime::{opaque::Block, AccountId, Balance, Index, BlockNumber, Hash}; // NOTE THIS IS AN ADJUSTMENT TO AN EXISTING LINE
use pallet_contracts_rpc::{Contracts, ContractsApi};
   /* --snip-- */

/// Instantiate all full RPC extensions.
pub fn create_full<C, P>(
   deps: FullDeps<C, P>,
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata> where
   /* --snip-- */
   C: Send + Sync + 'static,
   C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
   /*** Add This Line ***/
   C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
   /* --snip-- */
{
   /* --snip-- */
   io.extend_with(
		TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))
   );
   /*** Add this block ***/
   // Contracts RPC API extension
   io.extend_with(
		ContractsApi::to_delegate(Contracts::new(client.clone()))
   );
   /*** End added block ***/
   io
}

• 保存更改并关闭node/src/rpc.rs文件。

• 通过运行以下命令检查您的运行时是否正确编译:

cargo check -p node-template-runtime

• 通过运行以下命令以发布模式编译节点:

cargo build --release

• 启动本地 Substrate 节点

在您的节点编译后,您就可以启动已通过Contracts 托盘中的智能合约功能增强的 Substrate 节点,并使用前端模板与其交互。

启动本地节点:

• 如有必要,打开终端外壳。

• 切换到 Substrate 节点模板的根目录。

• 通过运行以下命令以开发模式启动节点:

./target/release/node-template --dev

• 在新终端中,切换到安装前端模板的根目录。

• 通过运行以下命令启动前端模板的 Web 服务器:

yarn start

• 在浏览器中打开http://localhost:8000/以查看前端模板。

• 在 Pallet Interactor 组件中,确认选择了 Extrinsic。

• contracts从可调用的托盘列表中选择。
image

• Substrate Tutorials , Substrate 教程

CN 中文 Github Substrate 教程 : github.com/565ee/Substrate_CN
CN 中文 CSDN Substrate 教程 : blog.csdn.net/wx468116118
EN 英文 Github Substrate Tutorials : github.com/565ee/Substrate_EN
EN 英文 dev.to Substrate Tutorials : dev.to/565ee

• Contact 联系方式

Homepage : 565.ee
微信公众号 : wx468116118
微信 QQ : 468116118
GitHub : github.com/565ee
CSDN : blog.csdn.net/wx468116118
Email : 468116118@qq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wx468116118

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值