diff --git a/po/zh-cn.po b/po/zh-cn.po index ea947ffe..dbaf66df 100644 --- a/po/zh-cn.po +++ b/po/zh-cn.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Starknet by Example\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2023-12-02 17:32+0900\n" +"PO-Revision-Date: 2023-12-03 17:59+0800\n" "Last-Translator: StarknetAstro \n" "Language-Team: Language zh-cn\n" "Language: zh_CN\n" @@ -4298,7 +4298,7 @@ msgstr "" #: src/ch02/write_to_any_slot.md:1 msgid "# Writing to any storage slot" -msgstr "" +msgstr "写入任何存储槽" #: src/ch02/write_to_any_slot.md:3 msgid "" @@ -4309,6 +4309,10 @@ msgid "" "keys)`. Interactions with storage variables are commonly performed using the " "`self.var.read()` and `self.var.write()` functions." msgstr "" +"在Starknet上,一个合约的存储是一个拥有 2^251 个槽的map,每个槽是一个初始化为 " +"0 的 felt。存储变量的地址在编译时通过公式计算得出:`存储变量地址 := " +"pedersen(keccak(变量名), keys)`。与存储变量的交互通常使用 `self.var.read()` " +"和 `self.var.write()` 。" #: src/ch02/write_to_any_slot.md:6 msgid "" @@ -4320,6 +4324,10 @@ msgid "" "computation method of storage variable addresses changes, they remain " "accessible." msgstr "" +"然而,我们可以使用 `storage_write_syscall` 和 `storage_read_syscall` 系统调" +"用,来对任何存储槽进行写入和读取。\n" +"这在写入那些在编译时还未确定的存储变量时非常有用,这也可以确保即使合约升级且" +"存储变量地址的计算方法改变,这些变量仍然可访问。" #: src/ch02/write_to_any_slot.md:9 msgid "" @@ -4329,6 +4337,9 @@ msgid "" "onchain computations. Once the address is computed, we use the storage " "syscalls to interact with it." msgstr "" +"在以下示例中,我们使用 Poseidon 哈希函数来计算存储变量的地址。Poseidon 是一" +"个 ZK 友好的哈希函数,比 Pedersen 更便宜、更快,是链上计算的绝佳选择。一旦地" +"址被计算出来,我们就使用存储的系统调用与之交互。" #: src/ch02/write_to_any_slot.md:11 msgid "" @@ -4382,6 +4393,55 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[starknet::interface]\n" +"trait IWriteToAnySlots {\n" +" fn write_slot(ref self: TContractState, value: u32);\n" +" fn read_slot(self: @TContractState) -> u32;\n" +"}\n" +"\n" +"#[starknet::contract]\n" +"mod WriteToAnySlot {\n" +" use starknet::syscalls::{storage_read_syscall, storage_write_syscall};\n" +" use starknet::SyscallResultTrait;\n" +" use poseidon::poseidon_hash_span;\n" +" use starknet::storage_access::Felt252TryIntoStorageAddress;\n" +" use starknet::StorageAddress;\n" +"\n" +" #[storage]\n" +" struct Storage {}\n" +"\n" +" const SLOT_NAME: felt252 = 'test_slot';\n" +"\n" +" #[abi(embed_v0)]\n" +" impl WriteToAnySlot of super::IWriteToAnySlots {\n" +" fn write_slot(ref self: ContractState, value: u32) {\n" +" storage_write_syscall(0, get_address_from_name(SLOT_NAME), value." +"into());\n" +" }\n" +"\n" +" fn read_slot(self: @ContractState) -> u32 {\n" +" storage_read_syscall(0, get_address_from_name(SLOT_NAME))\n" +" .unwrap_syscall()\n" +" .try_into()\n" +" .unwrap()\n" +" }\n" +" }\n" +" fn get_address_from_name(variable_name: felt252) -> StorageAddress {\n" +" let mut data: Array = ArrayTrait::new();\n" +" data.append(variable_name);\n" +" let hashed_name: felt252 = poseidon_hash_span(data.span());\n" +" let MASK_250: u256 = " +"0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n" +" // By taking the 250 least significant bits of the hash output, we " +"get a valid 250bits storage address.\n" +" let result: felt252 = (hashed_name.into() & MASK_250).try_into()." +"unwrap();\n" +" let result: StorageAddress = result.try_into().unwrap();\n" +" result\n" +" }\n" +"}\n" +"```" #: src/ch02/write_to_any_slot.md:56 msgid "" @@ -4392,10 +4452,16 @@ msgid "" "blob/main/listings/ch02-advanced-concepts/write_to_any_slot/src/contract." "cairo)." msgstr "" +"访问 [Voyager](https://goerli.voyager.online/" +"contract/0x033943CB781A4E63C9dcE0A1A09eAa3b617AA43CC61637C08c043a67f3fe0087) " +"上的合约,或者在 [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/write_to_any_slot/src/contract." +"cairo) 中测试它." #: src/ch02/storing_arrays.md:1 msgid "# Storing Arrays" -msgstr "" +msgstr "# 存储数组" #: src/ch02/storing_arrays.md:3 msgid "" @@ -4408,6 +4474,11 @@ msgid "" "for storing arrays in Cairo, so you will need to write your own " "implementation of the `Store` trait for the type of array you wish to store." msgstr "" +"在Starknet上,复杂值(例如元组或结构体)存储在以该存储变量地址开头的连续段" +"中。复杂存储值的大小有 256 个元素的限制,这意味着要在存储中存储超过 255 个元" +"素的数组,我们需要将其分割为大小 `n <= 255` 的段,并将这些段存储在多个存储地" +"址中。目前 Cairo 没有原生支持存储数组,所以你需要为你希望存储的数组类型实现自" +"己的 `Store` 特性。" #: src/ch02/storing_arrays.md:5 msgid "" @@ -4418,6 +4489,10 @@ msgid "" "need to access a single element of the array at a time, it is recommended to " "use a `LegacyMap` and store the length in another variable instead." msgstr "" +"> 注:虽然在存储中保存数组是可行的,但并不总是推荐这么做,因为读写操作的成本" +"可能非常高。例如,读取一个大小为 n 的数组需要进行 `n` 次存储读取,而向一个大" +"小为 `n` 的数组写入需要进行 `n` 次存储写入。如果你只需要一次访问数组中的一个" +"元素,建议使用 `LegacyMap` 并在另一个变量中存储数组长度。" #: src/ch02/storing_arrays.md:7 msgid "" @@ -4425,6 +4500,8 @@ msgid "" "the `StorageAccess` trait for the `Array` type, allowing us to " "store arrays of up to 255 `felt252` elements." msgstr "" +"以下示例展示了如何为 `Array` 类型实现一个简单的 `StorageAccess` 特" +"性,使我们能够存储多达 255 个 `felt252` 元素的数组。" #: src/ch02/storing_arrays.md:9 msgid "" @@ -4501,12 +4578,84 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"impl StoreFelt252Array of Store> {\n" +" fn read(address_domain: u32, base: StorageBaseAddress) -> " +"SyscallResult> {\n" +" StoreFelt252Array::read_at_offset(address_domain, base, 0)\n" +" }\n" +"\n" +" fn write(\n" +" address_domain: u32, base: StorageBaseAddress, value: " +"Array\n" +" ) -> SyscallResult<()> {\n" +" StoreFelt252Array::write_at_offset(address_domain, base, 0, value)\n" +" }\n" +"\n" +" fn read_at_offset(\n" +" address_domain: u32, base: StorageBaseAddress, mut offset: u8\n" +" ) -> SyscallResult> {\n" +" let mut arr: Array = ArrayTrait::new();\n" +"\n" +" // Read the stored array's length. If the length is superior to 255, " +"the read will fail.\n" +" let len: u8 = Store::::read_at_offset(address_domain, base, " +"offset)\n" +" .expect('Storage Span too large');\n" +" offset += 1;\n" +"\n" +" // Sequentially read all stored elements and append them to the " +"array.\n" +" let exit = len + offset;\n" +" loop {\n" +" if offset >= exit {\n" +" break;\n" +" }\n" +"\n" +" let value = Store::::read_at_offset(address_domain, " +"base, offset).unwrap();\n" +" arr.append(value);\n" +" offset += Store::::size();\n" +" };\n" +"\n" +" // Return the array.\n" +" Result::Ok(arr)\n" +" }\n" +"\n" +" fn write_at_offset(\n" +" address_domain: u32, base: StorageBaseAddress, mut offset: u8, mut " +"value: Array\n" +" ) -> SyscallResult<()> {\n" +" // // Store the length of the array in the first storage slot.\n" +" let len: u8 = value.len().try_into().expect('Storage - Span too " +"large');\n" +" Store::::write_at_offset(address_domain, base, offset, len);\n" +" offset += 1;\n" +"\n" +" // Store the array elements sequentially\n" +" loop {\n" +" match value.pop_front() {\n" +" Option::Some(element) => {\n" +" Store::::write_at_offset(address_domain, base, " +"offset, element);\n" +" offset += Store::::size();\n" +" },\n" +" Option::None(_) => { break Result::Ok(()); }\n" +" };\n" +" }\n" +" }\n" +"\n" +" fn size() -> u8 {\n" +" 255 * Store::::size()\n" +" }\n" +"}\n" +"```" #: src/ch02/storing_arrays.md:73 msgid "" "You can then import this implementation in your contract and use it to store " "arrays in storage:" -msgstr "" +msgstr "您可以在合约中导入上面的实现方式,并使用它来在存储中存储数组:" #: src/ch02/storing_arrays.md:75 msgid "" @@ -4539,6 +4688,34 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[starknet::interface]\n" +"trait IStoreArrayContract {\n" +" fn store_array(ref self: TContractState, arr: Array);\n" +" fn read_array(self: @TContractState) -> Array;\n" +"}\n" +"\n" +"#[starknet::contract]\n" +"mod StoreArrayContract {\n" +" use super::StoreFelt252Array;\n" +"\n" +" #[storage]\n" +" struct Storage {\n" +" arr: Array\n" +" }\n" +"\n" +" #[abi(embed_v0)]\n" +" impl StoreArrayImpl of super::IStoreArrayContract {\n" +" fn store_array(ref self: ContractState, arr: Array) {\n" +" self.arr.write(arr);\n" +" }\n" +"\n" +" fn read_array(self: @ContractState) -> Array {\n" +" self.arr.read()\n" +" }\n" +" }\n" +"}\n" +"```" #: src/ch02/storing_arrays.md:103 msgid "" @@ -4548,10 +4725,16 @@ msgid "" "#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" "blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)." msgstr "" +"访问 [Voyager](https://goerli.voyager.online/" +"contract/0x008F8069a3Fcd7691Db46Dc3b6F9D2C0436f9200E861330957Fd780A3595da86) " +"上的合约,或者在 [Remix](https://remix.ethereum.org/?" +"#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/" +"blob/main/listings/ch02-advanced-concepts/storing_arrays/src/contract.cairo)" +"上测试." #: src/ch02/struct-mapping-key.md:1 msgid "# Structs as mapping keys" -msgstr "" +msgstr "# 结构体作为映射键" #: src/ch02/struct-mapping-key.md:3 msgid "" @@ -4560,6 +4743,8 @@ msgid "" "the struct that can be used to represent the struct as a key in a " "`LegacyMap`." msgstr "" +"为了使用结构体作为映射键,您可以在结构体定义上使用 `#[derive(Hash)]`。这将为" +"结构体自动生成一个哈希函数,可以在 `LegacyMap` 中将该结构体作为键来使用。" #: src/ch02/struct-mapping-key.md:5 msgid "" @@ -4568,6 +4753,9 @@ msgid "" "`name`, `age` and `owner`. We consider that the combination of these three " "fields uniquely identifies a pet." msgstr "" +"考虑以下示例,我们希望使用类型为 `Pet` 的对象作为 `LegacyMap` 中的键。`Pet` " +"结构体有三个字段:`name` 、`age` 和 `owner`。假设这三个字段的组合能唯一地标识" +"一只宠物。" #: src/ch02/struct-mapping-key.md:8 msgid "" @@ -4609,6 +4797,43 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[derive(Copy, Drop, Serde, Hash)]\n" +"struct Pet {\n" +" name: felt252,\n" +" age: u8,\n" +" owner: felt252,\n" +"}\n" +"\n" +"#[starknet::interface]\n" +"trait IPetRegistry {\n" +" fn register_pet(ref self: TContractState, key: Pet, timestamp: u64);\n" +" fn get_registration_date(self: @TContractState, key: Pet) -> u64;\n" +"}\n" +"\n" +"#[starknet::contract]\n" +"mod PetRegistry {\n" +" use hash::{HashStateTrait, Hash};\n" +" use super::Pet;\n" +"\n" +" #[storage]\n" +" struct Storage {\n" +" registration_time: LegacyMap::,\n" +" }\n" +"\n" +" #[abi(embed_v0)]\n" +" impl PetRegistry of super::IPetRegistry {\n" +" fn register_pet(ref self: ContractState, key: Pet, timestamp: u64) " +"{\n" +" self.registration_time.write(key, timestamp);\n" +" }\n" +"\n" +" fn get_registration_date(self: @ContractState, key: Pet) -> u64 {\n" +" self.registration_time.read(key)\n" +" }\n" +" }\n" +"}\n" +"```" #: src/ch02/struct-mapping-key.md:45 msgid "" @@ -4617,10 +4842,13 @@ msgid "" "blob/main/listings/ch02-advanced-concepts/struct_as_mapping_key/src/contract." "cairo)." msgstr "" +"在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." +"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-" +"concepts/struct_as_mapping_key/src/contract.cairo) 上测试这个合约." #: src/ch02/hash-solidity-compatible.md:1 msgid "# Hash Solidity Compatible" -msgstr "" +msgstr "# 兼容Hash Solidity" #: src/ch02/hash-solidity-compatible.md:3 msgid "" @@ -4630,6 +4858,10 @@ msgid "" "in big-endian using `keccak_u256s_be_inputs`, and reversing the bytes of the " "result with `u128_byte_reverse`." msgstr "" +"这个合约展示了在 Cairo 中进行 Keccak 哈希处理以匹配 Solidity 的 keccak256。尽" +"管两者都使用 Keccak,但它们的字节序不同:Cairo 是小端序,Solidity 是大端序。" +"该合约通过使用 `keccak_u256s_be_inputs` 以大端序进行哈希处理,并使用 " +"`u128_byte_reverse` 反转结果的字节来实现兼容。" #: src/ch02/hash-solidity-compatible.md:7 msgid "" @@ -4673,6 +4905,45 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[starknet::interface]\n" +"trait ISolidityHashExample {\n" +" fn hash_data(ref self: TContractState, input_data: Span) -> u256;\n" +"}\n" +"\n" +"\n" +"#[starknet::contract]\n" +"mod SolidityHashExample {\n" +" use keccak::{keccak_u256s_be_inputs};\n" +" use array::Span;\n" +"\n" +" #[storage]\n" +" struct Storage {}\n" +"\n" +" #[abi(embed_v0)]\n" +" impl SolidityHashExample of super::ISolidityHashExample " +"{\n" +" fn hash_data(ref self: ContractState, input_data: Span) -> " +"u256 {\n" +" let hashed = keccak_u256s_be_inputs(input_data);\n" +"\n" +" // Split the hashed value into two 128-bit segments\n" +" let low: u128 = hashed.low;\n" +" let high: u128 = hashed.high;\n" +"\n" +" // Reverse each 128-bit segment\n" +" let reversed_low = integer::u128_byte_reverse(low);\n" +" let reversed_high = integer::u128_byte_reverse(high);\n" +"\n" +" // Reverse merge the reversed segments back into a u256 value\n" +" let compatible_hash = u256 { low: reversed_high, high: " +"reversed_low };\n" +"\n" +" compatible_hash\n" +" }\n" +" }\n" +"}\n" +"```" #: src/ch02/hash-solidity-compatible.md:44 msgid "" @@ -4681,22 +4952,25 @@ msgid "" "blob/main/listings/ch02-advanced-concepts/hash_solidity_compatible/src/" "contract.cairo)." msgstr "" +"在 [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github." +"com/NethermindEth/StarknetByExample/blob/main/listings/ch02-advanced-" +"concepts/hash_solidity_compatible/src/contract.cairo) 上测试这个合约." #: src/ch02/hash-solidity-compatible.md:46 msgid "
Last change: 2023-11-21
" -msgstr "" +msgstr "
上次修改: 2023-11-21
" #: src/ch02/optimisations/optimisations.md:1 msgid "# Optimisations " -msgstr "" +msgstr "# 优化" #: src/ch02/optimisations/optimisations.md:3 msgid "A collection of optimisation patterns to save gas and steps." -msgstr "" +msgstr "一系列优化模式,以节省Gas和计算步骤。" #: src/ch02/optimisations/store_using_packing.md:1 msgid "# Storage optimisation " -msgstr "" +msgstr "# 存储优化" #: src/ch02/optimisations/store_using_packing.md:3 msgid "" @@ -4705,6 +4979,8 @@ msgid "" "Writing to a storage slot has a cost, so we want to use as few storage slots " "as possible." msgstr "" +"智能合约只有有限的**存储槽位**。每个槽位可以存储一个 `felt252` 值。\n" +"写入一个存储槽位会产生成本,因此我们希望尽可能少地使用存储槽位。" #: src/ch02/optimisations/store_using_packing.md:6 msgid "" @@ -4714,6 +4990,9 @@ msgid "" "efficient. For example, if we want to store a `u8` value, we need to use an " "entire slot, even though we only need 8 bits." msgstr "" +"在 Cairo 中,每种类型都源自 `felt252` 类型,它使用 252 位来存储一个值。\n" +"这种设计相当简单,但它有一个缺点:它在存储效率方面并不高。例如,如果要存储一" +"个 `u8` 值,我们需要使用整个槽位,尽管我们只需要 8 位。" #: src/ch02/optimisations/store_using_packing.md:9 msgid "## Packing" @@ -4726,6 +5005,8 @@ msgid "" "felt value. This is done by using the bits of the felt value to store " "multiple values." msgstr "" +"当存储多个值时,我们可以使用一种称为**打包**的技术。打包是一种允许我们在单个 " +"felt 值中存储多个值的技术。这是通过使用 felt 值的位来存储多个值来实现的。" #: src/ch02/optimisations/store_using_packing.md:13 msgid "" @@ -4734,12 +5015,16 @@ msgid "" "store the second `u8` value. This way, we can store two `u8` values in a " "single felt value." msgstr "" +"例如,如果我们想存储两个 `u8` 值,我们可以使用 felt 值的前 8 位来存储第一个 " +"`u8` 值,而使用后 8 位来存储第二个 `u8` 值。这样,我们就可以在单个 felt 值中" +"存储两个 `u8` 值。" #: src/ch02/optimisations/store_using_packing.md:15 msgid "" "Cairo provides a built-in store using packing that you can use with the " "`StorePacking` trait." msgstr "" +"Cairo 提供了一个内置的打包存储功能,您可以通过 `StorePacking` 特性来使用它。" #: src/ch02/optimisations/store_using_packing.md:17 msgid "" @@ -4750,6 +5035,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"trait StorePacking {\n" +" fn pack(value: T) -> PackedT;\n" +" fn unpack(value: PackedT) -> T;\n" +"}\n" +"```" #: src/ch02/optimisations/store_using_packing.md:24 msgid "" @@ -4759,12 +5050,17 @@ msgid "" "the `PackedT` value, and then unpack it into the type `T` using the `unpack` " "function." msgstr "" +"这允许通过首先使用 `pack` 函数将类型 `T` 打包成 `PackedT` 类型,然后使用其 " +"`Store` 实现来存储 `PackedT` 值。在读取值时,我们首先获取 `PackedT` 值,然后" +"使用 `unpack` 函数将其解包为类型 `T`。" #: src/ch02/optimisations/store_using_packing.md:26 msgid "" "Here's an example of storing a `Time` struct with two `u8` values using the " "`StorePacking` trait:" msgstr "" +"以下是一个使用 `StorePacking` 特性存储包含两个 `u8` 值的 `Time` 结构体的示" +"例:" #: src/ch02/optimisations/store_using_packing.md:28 msgid "" @@ -4832,6 +5128,69 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[starknet::interface]\n" +"trait ITime {\n" +" fn set(ref self: TContractState, value: TimeContract::Time);\n" +" fn get(self: @TContractState) -> TimeContract::Time;\n" +"}\n" +"\n" +"#[starknet::contract]\n" +"mod TimeContract {\n" +" use starknet::storage_access::StorePacking;\n" +" use integer::{\n" +" U8IntoFelt252, Felt252TryIntoU16, U16DivRem, u16_as_non_zero, " +"U16IntoFelt252,\n" +" Felt252TryIntoU8\n" +" };\n" +" use traits::{Into, TryInto, DivRem};\n" +" use option::OptionTrait;\n" +" use serde::Serde;\n" +"\n" +" #[storage]\n" +" struct Storage {\n" +" time: Time\n" +" }\n" +"\n" +" #[derive(Copy, Serde, Drop)]\n" +" struct Time {\n" +" hour: u8,\n" +" minute: u8\n" +" }\n" +"\n" +" impl TimePackable of StorePacking {\n" +" fn pack(value: Time) -> felt252 {\n" +" let msb: felt252 = 256 * value.hour.into();\n" +" let lsb: felt252 = value.minute.into();\n" +" return msb + lsb;\n" +" }\n" +" fn unpack(value: felt252) -> Time {\n" +" let value: u16 = value.try_into().unwrap();\n" +" let (q, r) = U16DivRem::div_rem(value, u16_as_non_zero(256));\n" +" let hour: u8 = Into::::into(q).try_into()." +"unwrap();\n" +" let minute: u8 = Into::::into(r).try_into()." +"unwrap();\n" +" return Time { hour, minute };\n" +" }\n" +" }\n" +"\n" +" #[abi(embed_v0)]\n" +" impl TimeContract of super::ITime {\n" +" fn set(ref self: ContractState, value: Time) {\n" +" // This will call the pack method of the TimePackable trait\n" +" // and store the resulting felt252\n" +" self.time.write(value);\n" +" }\n" +" fn get(self: @ContractState) -> Time {\n" +" // This will read the felt252 value from storage\n" +" // and return the result of the unpack method of the " +"TimePackable trait\n" +" return self.time.read();\n" +" }\n" +" }\n" +"}\n" +"```" #: src/ch02/optimisations/store_using_packing.md:88 msgid "" @@ -4840,6 +5199,10 @@ msgid "" "StarknetByExample/blob/main/listings/ch02-advanced-concepts/" "store_using_packing/src/contract.cairo)." msgstr "" +"在 [Remix](https://remix.ethereum.org/?#activate=Starknet-cairo1-" +"compiler&url=https://github.com/NethermindEth/StarknetByExample/blob/main/" +"listings/ch02-advanced-concepts/store_using_packing/src/contract.cairo) 上测" +"试这个合约." #: src/ch02/list.md:1 msgid "# List" @@ -4851,14 +5214,17 @@ msgid "" "Alexandria. You can refer to the [Alexandria documentation](https://github." "com/keep-starknet-strange/alexandria/tree/main/src/storage) for more details." msgstr "" +"默认情况下,Cairo 不支持列表类型,但您可以使用 Alexandria。您可以参考 " +"[Alexandria 文档](https://github.com/keep-starknet-strange/alexandria/tree/" +"main/src/storage) 获取更多详细信息。" #: src/ch02/list.md:5 msgid "## What is `List`?" -msgstr "" +msgstr "## `List`是什么?" #: src/ch02/list.md:7 msgid "An ordered sequence of values that can be used in Starknet storage:" -msgstr "" +msgstr "可以在 Starknet 存储中使用的有序值序列:" #: src/ch02/list.md:9 msgid "" @@ -4869,6 +5235,12 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[storage]\n" +"stuct Storage {\n" +" amounts: List\n" +"}\n" +"```" #: src/ch02/list.md:16 msgid "### Interface" @@ -4888,12 +5260,24 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"trait ListTrait {\n" +" fn len(self: @List) -> u32;\n" +" fn is_empty(self: @List) -> bool;\n" +" fn append(ref self: List, value: T) -> u32;\n" +" fn get(self: @List, index: u32) -> Option;\n" +" fn set(ref self: List, index: u32, value: T);\n" +" fn pop_front(ref self: List) -> Option;\n" +" fn array(self: @List) -> Array;\n" +"}\n" +"```" #: src/ch02/list.md:30 msgid "" "`List` also implements `IndexView` so you can use the familiar bracket " "notation to access its members:" msgstr "" +"`List` 还实现了 `IndexView`,因此您可以使用熟悉的方括号表示法来访问其成员:" #: src/ch02/list.md:32 msgid "" @@ -4901,16 +5285,21 @@ msgid "" "let second = self.amounts.read()[1];\n" "```" msgstr "" +"```rust\n" +"let second = self.amounts.read()[1];\n" +"```" #: src/ch02/list.md:36 msgid "" "Note that unlike `get`, using this bracket notation panics when accessing an " "out of bounds index." msgstr "" +"请注意,与 `get` 不同的是,使用这种方括号表示法在访问越界索引时会引发 " +"panic(崩溃)。" #: src/ch02/list.md:38 msgid "### Support for custom types" -msgstr "" +msgstr "### 支持自定义类型" #: src/ch02/list.md:40 msgid "" @@ -4919,14 +5308,17 @@ msgid "" "trait. You can have the compiler derive it for you using the " "`#[derive(starknet::Store)]` attribute." msgstr "" +"`List` 默认支持大多数 corelib 类型。如果您想在 `List` 中存储自己的自定义类" +"型,该类型必须实现 `Store` 特性。您可以使用 `#[derive(starknet::Store)]` 属性" +"让编译器自动生成。" #: src/ch02/list.md:42 msgid "### Caveats" -msgstr "" +msgstr "### 注意事项" #: src/ch02/list.md:44 msgid "There are two idiosyncacies you should be aware of when using `List`" -msgstr "" +msgstr "在使用 `List` 时,有两个特点应该注意:" #: src/ch02/list.md:46 msgid "" @@ -4936,6 +5328,10 @@ msgid "" "operations with a single inline statement. For example, `self.amounts.read()." "append(42);` will not work. You have to do it in 2 steps:" msgstr "" +"1. `append` 操作消耗 2 次存储写入操作 - 一次是为了值本身,另一次是为了更新列" +"表的长度。\n" +"2. 由于编译器的限制,不能使用单个内联语句进行变更操作。例如,`self.amounts." +"read().append(42);` 是不行的。你必须分两步进行:" #: src/ch02/list.md:49 msgid "" @@ -4944,6 +5340,10 @@ msgid "" "amounts.append(42);\n" "```" msgstr "" +"```rust\n" +"let mut amounts = self.amounts.read();\n" +"amounts.append(42);\n" +"```" #: src/ch02/list.md:54 msgid "### Dependencies" @@ -4951,7 +5351,7 @@ msgstr "### 依赖关系" #: src/ch02/list.md:56 msgid "Update your project dependencies by in the `Scarb.toml` file:" -msgstr "" +msgstr "在 `Scarb.toml` 里更新您项目的依赖:" #: src/ch02/list.md:57 msgid "" @@ -4962,12 +5362,18 @@ msgid "" "alexandria.git\" }\n" "```" msgstr "" +"```rust\n" +"[dependencies]\n" +"(...)\n" +"alexandria_storage = { git = \"https://github.com/keep-starknet-strange/" +"alexandria.git\" }\n" +"```" #: src/ch02/list.md:63 msgid "" "For example, let's use `List` to create a contract that tracks a list of " "amounts and tasks:" -msgstr "" +msgstr "例如,我们用 `List` 来创建一个跟踪`amount`和`tasks`的合约:" #: src/ch02/list.md:65 msgid "" @@ -5050,7 +5456,85 @@ msgid "" "}\n" "```" msgstr "" +"```rust\n" +"#[starknet::interface]\n" +"trait IListExample {\n" +" fn add_in_amount(ref self: TContractState, number: u128);\n" +" fn add_in_task(ref self: TContractState, description: felt252, status: " +"felt252);\n" +" fn is_empty_list(self: @TContractState) -> bool;\n" +" fn list_length(self: @TContractState) -> u32;\n" +" fn get_from_index(self: @TContractState, index: u32) -> u128;\n" +" fn set_from_index(ref self: TContractState, index: u32, number: u128);\n" +" fn pop_front_list(ref self: TContractState);\n" +" fn array_conversion(self: @TContractState) -> Array;\n" +"}\n" +"\n" +"#[starknet::contract]\n" +"mod ListExample {\n" +" use alexandria_storage::list::{List, ListTrait};\n" +"\n" +" #[storage]\n" +" struct Storage {\n" +" amount: List,\n" +" tasks: List\n" +" }\n" +"\n" +" #[derive(Copy, Drop, Serde, starknet::Store)]\n" +" struct Task {\n" +" description: felt252,\n" +" status: felt252\n" +" }\n" +"\n" +"\n" +" #[abi(embed_v0)]\n" +" impl ListExample of super::IListExample {\n" +" fn add_in_amount(ref self: ContractState, number: u128) {\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.append(number);\n" +" }\n" +"\n" +" fn add_in_task(ref self: ContractState, description: felt252, " +"status: felt252) {\n" +" let new_task = Task { description: description, status: " +"status };\n" +" let mut current_tasks_list = self.tasks.read();\n" +" current_tasks_list.append(new_task);\n" +" }\n" +"\n" +" fn is_empty_list(self: @ContractState) -> bool {\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.is_empty()\n" +" }\n" +"\n" +" fn list_length(self: @ContractState) -> u32 {\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.len()\n" +" }\n" +"\n" +" fn get_from_index(self: @ContractState, index: u32) -> u128 {\n" +" self.amount.read()[index]\n" +" }\n" +"\n" +" fn set_from_index(ref self: ContractState, index: u32, number: u128) " +"{\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.set(index, number);\n" +" }\n" +"\n" +" fn pop_front_list(ref self: ContractState) {\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.pop_front();\n" +" }\n" +"\n" +" fn array_conversion(self: @ContractState) -> Array {\n" +" let mut current_amount_list = self.amount.read();\n" +" current_amount_list.array()\n" +" }\n" +" }\n" +"}\n" +"```" #: src/ch02/list.md:139 msgid "
Last change: 2023-11-27
" -msgstr "" +msgstr ""