# 浣跨敤Rust杩涜鏅鸿兘鍚堢害寮€鍙� 璇昏€呭璞★細鏈珷鑺備富瑕佹弿杩颁娇鐢≧ust杩涜ChainMaker鍚堢害缂栧啓鐨勬柟娉曪紝涓昏闈㈠悜浜庝娇鐢≧ust杩涜ChainMaker鐨勫悎绾﹀紑鍙戠殑寮€鍙戣€呫€� **姒傝** 1銆佽繍琛屾椂铏氭嫙鏈虹被鍨嬶紙runtime_type锛夛細 WASMER 2銆佷粙缁嶄簡鐜渚濊禆 3銆佷粙缁嶄簡寮€鍙戞柟寮忓強sdk鎺ュ彛 4銆佹彁渚涗簡涓€涓ず渚嬪悎绾� ## 鐜渚濊禆 浣跨敤Rust寮€鍙戠敤浜嶤hainMaker鐨剋asm鍚堢害,闇€瑕佸畨瑁匯ust寮€鍙戠幆澧冿紝骞跺皢 wasm32-unknown-unknown锛堢洰鏍囧钩鍙帮級鍔犲叆鍒癛ust寮€鍙戠幆澧冪殑宸ュ叿閾句腑銆� rust 瀹夎鍙婃暀绋嬭鍙傝€冿細[rust 瀹樼綉](https://www.rust-lang.org/) 瀹夎鎸囦护濡備笅锛� ```sh # 瀹夎 Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # 璁� Rust 鐨勭幆澧冨彉閲忕敓鏁� source "$HOME/.cargo/env" # 鍔犲叆 wasm32-unknown-unknown rustup target add wasm32-unknown-unknown ``` ## 缂栧啓Rust鏅鸿兘鍚堢害 ### 鎼缓寮€鍙戠幆澧� 1锛夋帹鑽愪娇鐢� GoLand闆嗘垚寮€鍙戠幆澧� + Rust鎻掍欢 2锛変笅杞� contracts-rust 绀轰緥宸ョ▼ ```shell git clone git@git.chainmaker.org.cn:contracts/contracts-rust.git -b v2.3.0 ``` 3锛夎繘鍏ヤ笅杞界殑Rust宸ョ▼ ```shell cd contracts-rust/fact ``` ### 浠g爜缂栧啓瑙勫垯 **瀵归摼鏆撮湶鏂规硶鍐欐硶涓猴細** - #[no_mangle] 琛ㄧず鏂规硶鍚嶇紪璇戝悗鏄浐瀹氱殑锛屼笉鍐欎細鐢熸垚 _ZN4rustfn1_34544tert54grt5 绫讳技鐨勬贩娣嗗悕 - pub extern "C" - method_name(): 涓嶅彲甯﹀弬鏁帮紝鏃犺繑鍥炲€� ```rust #[no_mangle]// no_mangle娉ㄨВ锛岃〃鏄庡澶栨毚闇叉柟娉曞悕绉颁笉鍙彉 pub extern "C" fn init_contract() { // pub extern "C" 闆嗘垚C let ctx = &mut sim_context::get_sim_context(); // do something ctx.ok("contract init success.".as_bytes()); } ``` **鍏朵腑init_contract銆乽pgrade鏂规硶蹇呴』鏈変笖瀵瑰鏆撮湶** - init_contract锛氬垱寤哄悎绾︿細鎵ц璇ユ柟娉� - upgrade锛� 鍗囩骇鍚堢害浼氭墽琛岃鏂规硶 ```rust // 瀹夎鍚堢害鏃朵細鎵ц姝ゆ柟娉曘€侰hainMaker涓嶅厑璁哥敤鎴风洿鎺ヨ皟鐢ㄨ鏂规硶銆� #[no_mangle] pub extern "C" fn init_contract() { let ctx = &mut sim_context::get_sim_context(); // do something ctx.ok("contract init success.".as_bytes()); } // 鍗囩骇鍚堢害鏃朵細鎵ц姝ゆ柟娉曘€侰hainMaker涓嶅厑璁哥敤鎴风洿鎺ヨ皟鐢ㄨ鏂规硶銆� #[no_mangle] pub extern "C" fn upgrade() { let ctx = &mut sim_context::get_sim_context(); // do something ctx.ok("contract upgrade success.".as_bytes()); } ``` **鑾峰彇涓庨摼浜や簰鐨勪笂涓嬫枃sim_context** 1銆佸湪`Cargo.toml`涓紩鍏ュ浜� contract-sdk-rust 椤圭洰鐨勪緷璧� ```toml [dependencies] contract_sdk_rust = { git = "https://git.chainmaker.org.cn/chainmaker/contract-sdk-rust", tag = "v2.3.0" } ``` 2銆佸湪浣跨敤鏃跺紩鍏im_context ```rust use contract_sdk_rust::sim_context; use contract_sdk_rust::sim_context::SimContext; use contract_sdk_rust::easycodec::*; fn method_name() { // 鑾峰彇涓婁笅鏂� let ctx = &mut sim_context::get_sim_context(); } ``` ### 瀛樿瘉鍚堢害绀轰緥婧愮爜灞曠ず **瀛樿瘉鍚堢害绀轰緥锛歠act.rs** 瀹炵幇濡備笅涓や釜鍔熻兘 1銆佸瓨鍌ㄦ枃浠跺搱甯屽拰鏂囦欢鍚嶇О鍜屾椂闂淬€� 2銆侀€氳繃鏂囦欢鍝堝笇鏌ヨ璇ユ潯璁板綍 ```rust use contract_sdk_rust::sim_context; use contract_sdk_rust::sim_context::SimContext; use contract_sdk_rust::easycodec::*; // 瀹夎鍚堢害鏃朵細鎵ц姝ゆ柟娉曪紝蹇呴』 #[no_mangle] pub extern "C" fn init_contract() { sim_context::log("init_contract"); let ctx = &mut sim_context::get_sim_context(); // 瀹夎鏃剁殑涓氬姟閫昏緫锛屽唴瀹瑰彲涓虹┖ ctx.ok("contract init success.".as_bytes()); } // 鍗囩骇鍚堢害鏃朵細鎵ц姝ゆ柟娉曪紝蹇呴』 #[no_mangle] pub extern "C" fn upgrade() { sim_context::log("upgrade"); let ctx = &mut sim_context::get_sim_context(); // 鍗囩骇鏃剁殑涓氬姟閫昏緫锛屽唴瀹瑰彲涓虹┖ ctx.ok("contract upgrade success".as_bytes()); } struct Fact { file_hash: String, file_name: String, time: i32, ec: EasyCodec, } impl Fact { fn new_fact(file_hash: String, file_name: String, time: i32) -> Fact { let mut ec = EasyCodec::new(); ec.add_string("file_hash", file_hash.as_str()); ec.add_string("file_name", file_name.as_str()); ec.add_i32("time", time); Fact { file_hash, file_name, time, ec, } } fn get_emit_event_data(&self) -> Vec<String> { let mut arr: Vec<String> = Vec::new(); arr.push(self.file_hash.clone()); arr.push(self.file_name.clone()); arr.push(self.time.to_string()); arr } fn to_json(&self) -> String { self.ec.to_json() } fn marshal(&self) -> Vec<u8> { self.ec.marshal() } fn unmarshal(data: &Vec<u8>) -> Fact { let ec = EasyCodec::new_with_bytes(data); Fact { file_hash: ec.get_string("file_hash").unwrap(), file_name: ec.get_string("file_name").unwrap(), time: ec.get_i32("time").unwrap(), ec, } } } // save 淇濆瓨瀛樿瘉鏁版嵁 #[no_mangle] pub extern "C" fn save() { // 鑾峰彇涓婁笅鏂� let ctx = &mut sim_context::get_sim_context(); // 鑾峰彇浼犲叆鍙傛暟 let file_hash = ctx.arg_as_utf8_str("file_hash"); let file_name = ctx.arg_as_utf8_str("file_name"); let time_str = ctx.arg_as_utf8_str("time"); // 鏋勯€犵粨鏋勪綋 let r_i32 = time_str.parse::<i32>(); if r_i32.is_err() { let msg = format!("time is {:?} not int32 number.", time_str); ctx.log(&msg); ctx.error(&msg); return; } let time: i32 = r_i32.unwrap(); let fact = Fact::new_fact(file_hash, file_name, time); // 浜嬩欢 ctx.emit_event("topic_vx", &fact.get_emit_event_data()); // 搴忓垪鍖栧悗瀛樺偍 ctx.put_state( "fact_ec", fact.file_hash.as_str(), fact.marshal().as_slice(), ); } // find_by_file_hash 鏍规嵁file_hash鏌ヨ瀛樿瘉鏁版嵁 #[no_mangle] pub extern "C" fn find_by_file_hash() { // 鑾峰彇涓婁笅鏂� let ctx = &mut sim_context::get_sim_context(); // 鑾峰彇浼犲叆鍙傛暟 let file_hash = ctx.arg_as_utf8_str("file_hash"); // 鏍¢獙鍙傛暟 if file_hash.len() == 0 { ctx.log("file_hash is null"); ctx.ok("".as_bytes()); return; } // 鏌ヨ let r = ctx.get_state("fact_ec", &file_hash); // 鏍¢獙杩斿洖缁撴灉 if r.is_err() { ctx.log("get_state fail"); ctx.error("get_state fail"); return; } let fact_vec = r.unwrap(); if fact_vec.len() == 0 { ctx.log("None"); ctx.ok("".as_bytes()); return; } // 鏌ヨ let r = ctx.get_state("fact_ec", &file_hash).unwrap(); let fact = Fact::unmarshal(&r); let json_str = fact.to_json(); // 杩斿洖鏌ヨ缁撴灉 ctx.ok(json_str.as_bytes()); ctx.log(&json_str); } ``` ### 鍚堢害SDK鎺ュ彛鎻忚堪 闀垮畨閾炬彁渚汻ust鍚堢害涓庨摼浜や簰鐨勭浉鍏虫帴鍙o紝浠g爜瀛樺湪鍗曠嫭鐨勯」鐩紙https://git.chainmaker.org.cn/chainmaker/contract-sdk-rust锛変腑銆傚啓鍚堢害鏃跺彲鐩存帴鎸囧畾渚濊禆锛屽苟杩涜寮曠敤锛屽叿浣撲俊鎭彲鍙傝€冩枃绔犳湯灏�"鎺ュ彛鎻忚堪绔犺妭"銆� ### 缂栬瘧绀轰緥鍚堢害 ```shell cd contracts_rust/fact/ cargo build --release --target=wasm32-unknown-unknown ``` 鐢熸垚鍚堢害鐨勫瓧鑺傜爜鏂囦欢鍦� ```shell contracts_rust/fact/target/wasm32-unknown-unknown/release/fact.wasm ``` #### 绀轰緥鍚堢害妗嗘灦鎻忚堪 ```shell contract-sdk-rust$ tree -I target 鈹溾攢鈹€ Cargo.lock # 渚濊禆鐗堟湰淇℃伅 鈹溾攢鈹€ Cargo.toml # 椤圭洰閰嶇疆鍙婁緷璧栵紝鍙傝€冿細https://rustwasm.github.io/wasm-pack/book/cargo-toml-configuration.html 鈹溾攢鈹€ README.md # 缂栬瘧鐜璇存槑 鈹溾攢鈹€ src 鈹� 鈹溾攢鈹€ fact.rs # 瀛樿瘉绀轰緥浠g爜 鈹� 鈹斺攢鈹€ lib.rs # 绋嬪簭鍏ュ彛 ``` ### 閮ㄧ讲璋冪敤鍚堢害 缂栬瘧瀹屾垚鍚庯紝灏嗗緱鍒颁竴涓猔.wasm`鏍煎紡鐨勫悎绾︽枃浠讹紝鍙皢涔嬮儴缃插埌鎸囧畾鍒伴暱瀹夐摼涓婏紝瀹屾垚鍚堢害閮ㄧ讲銆� 閮ㄧ讲鍚堢害鐨勪娇鐢ㄦ暀绋嬪彲璇﹁锛歔閮ㄧ讲绀轰緥鍚堢害](./閮ㄧ讲绀轰緥鍚堢害.md)銆� ## 杩唬鍣ㄤ娇鐢ㄧず渚� [鐐瑰嚮姝ゅ鏌ョ湅鎺ュ彛璇存槑](#new_iterator_interface) 浣跨敤绀轰緥濡備笅锛� ```rust #[no_mangle] pub extern "C" fn how_to_use_iterator() { let ctx = &mut sim_context::get_sim_context(); // 鏋勯€犳暟鎹� ctx.put_state("key1", "field1", "val".as_bytes()); ctx.put_state("key1", "field2", "val".as_bytes()); ctx.put_state("key1", "field23", "val".as_bytes()); ctx.put_state("key1", "field3", "val".as_bytes()); // 浣跨敤杩唬鍣紝鑳芥煡鍑烘潵 field1锛宖ield2锛宖ield23 涓夋潯鏁版嵁 let r = ctx.new_iterator_with_field("key1", "field1", "field3"); if r.is_ok() { let rs = r.unwrap(); // 閬嶅巻 while rs.has_next() { // 鑾峰彇涓嬩竴琛屽€� let row = rs.next_row().unwrap(); let key = row.get_string("key").unwrap(); let field = row.get_bytes("field"); let val = row.get_bytes("value"); // do something } // 鍏抽棴娓告爣 rs.close(); } ctx.put_state("key2", "field1", "val".as_bytes()); ctx.put_state("key3", "field2", "val".as_bytes()); ctx.put_state("key33", "field2", "val".as_bytes()); ctx.put_state("key4", "field3", "val".as_bytes()); // 鑳芥煡鍑烘潵 key2锛宬ey3锛宬ey33 涓夋潯鏁版嵁 ctx.new_iterator("key2", "key4"); // 鑳芥煡鍑烘潵 key3锛宬ey33 涓ゆ潯鏁版嵁 ctx.new_iterator_prefix_with_key("key3"); // 鑳芥煡鍑烘潵 field2锛宖ield23 涓夋潯鏁版嵁 ctx.new_iterator_prefix_with_key_field("key1", "field2"); ctx.put_state_from_key("key5","val".as_bytes()); ctx.put_state_from_key("key56","val".as_bytes()); ctx.put_state_from_key("key6","val".as_bytes()); // 鑳芥煡鍑烘潵 key5锛宬ey56 涓ゆ潯鏁版嵁 ctx.new_iterator("key5", "key6"); } ``` ## Rust SDK API鎻忚堪 <span id="api"></span> ### 涓嬭浇 contract-sdk-rust 椤圭洰浠g爜 ```shell git clone --depth=1 https://git.chainmaker.org.cn/chainmaker/contract-sdk-rust -b v2.3.0 ``` ### 椤圭洰鏂囦欢璇存槑 ```shell tree -I target 鈹溾攢鈹€ Cargo.lock # 渚濊禆鐗堟湰淇℃伅 鈹溾攢鈹€ Cargo.toml # 椤圭洰閰嶇疆鍙婁緷璧栵紝鍙傝€冿細https://rustwasm.github.io/wasm-pack/book/cargo-toml-configuration.html 鈹溾攢鈹€ Makefile # build涓€涓獁asm鏂囦欢 鈹溾攢鈹€ README.md # 缂栬瘧鐜璇存槑 鈹溾攢鈹€ src 鈹� 鈹溾攢鈹€ easycodec.rs # 搴忓垪鍖栧伐鍏风被 鈹� 鈹溾攢鈹€ lib.rs # 绋嬪簭鍏ュ彛 鈹� 鈹溾攢鈹€ sim_context.rs # 鍚堢害SDK涓昏鎺ュ彛鍙婂疄鐜� 鈹� 鈹溾攢鈹€ sim_context_bulletproofs.rs # 鍚堢害SDK鍩轰簬bulletproofs鐨勮寖鍥磋瘉鏄庢帴鍙e疄鐜� 鈹� 鈹溾攢鈹€ sim_context_paillier.rs # 鍚堢害SDK鍩轰簬paillier鐨勫崐鍚屾€佽繍绠楁帴鍙e疄鐜� 鈹� 鈹溾攢鈹€ sim_context_rs.rs # 鍚堢害SDK sql鎺ュ彛瀹炵幇 鈹� 鈹斺攢鈹€ vec_box.rs # 鍐呭瓨绠$悊绫� ``` ### 鍐呯疆閾句氦浜掓帴鍙� 鐢ㄤ簬閾句笌SDK鏁版嵁浜や簰銆� ```rust // 鐢宠size澶у皬鍐呭瓨锛岃繑鍥炶鍐呭瓨鐨勯鍦板潃 pub extern "C" fn allocate(size: usize) -> i32 {} // 閲婃斁鏌愬湴鍧€ pub extern "C" fn deallocate(pointer: *mut c_void) {} // 鑾峰彇SDK杩愯鏃剁幆澧� pub extern "C" fn runtime_type() -> i32 { 0 } ``` ### 鐢ㄦ埛涓庨摼浜や簰鎺ュ彛 ```rust /// SimContext is a interface with chainmaker interaction pub trait SimContext { // common method fn call_contract( &self, contract_name: &str, method: &str, param: EasyCodec, ) -> Result<Vec<u8>, result_code>; fn ok(&self, value: &[u8]) -> result_code; fn error(&self, body: &str) -> result_code; fn log(&self, msg: &str); fn arg(&self, key: &str) -> Result<Vec<u8>, String>; fn arg_as_utf8_str(&self, key: &str) -> String; fn args(&self) -> &EasyCodec; fn get_creator_org_id(&self) -> String; fn get_creator_pub_key(&self) -> String; fn get_creator_role(&self) -> String; fn get_sender_org_id(&self) -> String; fn get_sender_pub_key(&self) -> String; fn get_sender_role(&self) -> String; fn get_block_height(&self) -> u64; fn get_tx_id(&self) -> String; fn emit_event(&mut self, topic: &str, data: &Vec<String>) -> result_code; // paillier fn get_paillier_sim_context(&self) -> Box<dyn PaillierSimContext>; // bulletproofs fn get_bulletproofs_sim_context(&self) -> Box<dyn BulletproofsSimContext>; // sql fn get_sql_sim_context(&self) -> Box<dyn SqlSimContext>; // KV method fn get_state(&self, key: &str, field: &str) -> Result<Vec<u8>, result_code>; fn get_state_from_key(&self, key: &str) -> Result<Vec<u8>, result_code>; fn put_state(&self, key: &str, field: &str, value: &[u8]) -> result_code; fn put_state_from_key(&self, key: &str, value: &[u8]) -> result_code; fn delete_state(&self, key: &str, field: &str) -> result_code; fn delete_state_from_key(&self, key: &str) -> result_code; /// new_iterator range of [startKey, limitKey), front closed back open fn new_iterator( &self, start_key: &str, limit_key: &str, ) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_with_field range of [key+"#"+startField, key+"#"+limitField), front closed back open fn new_iterator_with_field( &self, key: &str, start_field: &str, limit_field: &str, ) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_prefix_with_key_field range of [key+"#"+field, key+"#"+field], front closed back closed fn new_iterator_prefix_with_key_field( &self, key: &str, field: &str, ) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_prefix_with_key range of [key, key], front closed back closed fn new_iterator_prefix_with_key(&self, key: &str) -> Result<Box<dyn ResultSet>, result_code>; } pub trait SqlSimContext { fn execute_query_one(&self, sql: &str) -> Result<EasyCodec, result_code>; fn execute_query(&self, sql: &str) -> Result<Box<dyn ResultSet>, result_code>; /// #### ExecuteUpdateSql execute update/insert/delete sql /// ##### It is best to update with primary key /// /// as: /// /// - update table set name = 'Tom' where uniqueKey='xxx' /// - delete from table where uniqueKey='xxx' /// - insert into table(id, xxx,xxx) values(xxx,xxx,xxx) /// /// ### not allow: /// - random methods: NOW() RAND() and so on fn execute_update(&self, sql: &str) -> Result<i32, result_code>; /// ExecuteDDLSql execute DDL sql, for init_contract or upgrade method. allow table create/alter/drop/truncate /// /// ## You must have a primary key to create a table /// ### allow: /// - CREATE TABLE tableName /// - ALTER TABLE tableName /// - DROP TABLE tableName /// - TRUNCATE TABLE tableName /// /// ### not allow: /// - CREATE DATABASE dbName /// - CREATE TABLE dbName.tableName /// - ALTER TABLE dbName.tableName /// - DROP DATABASE dbName /// - DROP TABLE dbName.tableName /// - TRUNCATE TABLE dbName.tableName /// not allow: /// - random methods: NOW() RAND() and so on /// fn execute_ddl(&self, sql: &str) -> Result<i32, result_code>; } pub trait PaillierSimContext { // Paillier method fn add_ciphertext( &self, pubkey: Vec<u8>, ciphertext1: Vec<u8>, ciphertext2: Vec<u8>, ) -> Result<Vec<u8>, result_code>; fn add_plaintext( &self, pubkey: Vec<u8>, ciphertext: Vec<u8>, plaintext: &str, ) -> Result<Vec<u8>, result_code>; fn sub_ciphertext( &self, pubkey: Vec<u8>, ciphertext1: Vec<u8>, ciphertext2: Vec<u8>, ) -> Result<Vec<u8>, result_code>; fn sub_plaintext( &self, pubkey: Vec<u8>, ciphertext: Vec<u8>, plaintext: &str, ) -> Result<Vec<u8>, result_code>; fn num_mul( &self, pubkey: Vec<u8>, ciphertext: Vec<u8>, plaintext: &str, ) -> Result<Vec<u8>, result_code>; } /// BulletproofsSimContext is the trait that wrap the bulletproofs method pub trait BulletproofsSimContext { /// Compute a commitment to x + y from a commitment to x without revealing the value x, where y is a scalar /// /// # Arguments /// /// * `commitment` - C = xB + rB' /// * `num` - the value y /// /// # return /// /// * `return1` - the new commitment to x + y: C' = (x + y)B + rB' /// fn pedersen_add_num(&self, commitment: Vec<u8>, num: &str) -> Result<Vec<u8>, result_code>; /// Compute a commitment to x + y from commitments to x and y, without revealing the value x and y /// /// # Arguments /// /// * `commitment1` - commitment to x: Cx = xB + rB' /// * `commitment2` - commitment to y: Cy = yB + sB' /// /// # return /// /// * `return1` - commitment to x + y: C = (x + y)B + (r + s)B' /// fn pedersen_add_commitment( &self, commitment1: Vec<u8>, commitment2: Vec<u8>, ) -> Result<Vec<u8>, result_code>; /// Compute a commitment to x - y from a commitment to x without revealing the value x, where y is a scalar /// /// # Arguments /// /// * `commitment1` - C = xB + rB' /// * `num` - the value y /// /// # return /// /// * `return1` - the new commitment to x - y: C' = (x - y)B + rB' fn pedersen_sub_num(&self, commitment: Vec<u8>, num: &str) -> Result<Vec<u8>, result_code>; /// Compute a commitment to x - y from commitments to x and y, without revealing the value x and y /// /// # Arguments /// /// * `commitment1` - commitment to x: Cx = xB + rB' /// * `commitment2` - commitment to y: Cy = yB + sB' /// /// # return /// /// * `return1` - commitment to x - y: C = (x - y)B + (r - s)B' fn pedersen_sub_commitment( &self, commitment1: Vec<u8>, commitment2: Vec<u8>, ) -> Result<Vec<u8>, result_code>; /// Compute a commitment to x * y from a commitment to x and an integer y, without revealing the value x and y /// /// # Arguments /// /// * `commitment1` - commitment to x: Cx = xB + rB' /// * `num` - integer value y /// /// # return /// /// * `return1` - commitment to x * y: C = (x * y)B + (r * y)B' fn pedersen_mul_num(&self, commitment: Vec<u8>, num: &str) -> Result<Vec<u8>, result_code>; /// Verify the validity of a proof /// /// # Arguments /// /// * `proof` - the zero-knowledge proof proving the number committed in commitment is in the range [0, 2^64) /// * `commitment` - commitment bindingly hiding the number x /// /// # return /// /// * `return1` - true on valid proof, false otherwise fn verify(&self, proof: Vec<u8>, commitment: Vec<u8>) -> Result<Vec<u8>, result_code>; } ``` get_state ```rust // 鑾峰彇鍚堢害璐︽埛淇℃伅銆傝鎺ュ彛鍙粠閾句笂鑾峰彇绫诲埆 鈥渒ey鈥� 涓嬪睘鎬у悕涓� 鈥渇ield鈥� 鐨勭姸鎬佷俊鎭€� // @param key: 闇€瑕佹煡璇㈢殑key鍊� // @param field: 闇€瑕佹煡璇㈢殑key鍊间笅灞炴€у悕涓篺ield // @return: 鏌ヨ鍒扮殑value鍊硷紝鍙婇敊璇唬鐮� 0: success, 1: failed fn get_state(&self, key: &str, field: &str) -> Result<Vec<u8>, result_code>; ``` get_state_from_key ```rust // 鑾峰彇鍚堢害璐︽埛淇℃伅銆傝鎺ュ彛鍙互浠庨摼涓婅幏鍙栫被鍒负key鐨勭姸鎬佷俊鎭� // @param key: 闇€瑕佹煡璇㈢殑key鍊� // @return1: 鏌ヨ鍒扮殑鍊� // @return2: 0: success, 1: failed fn get_state_from_key(&self, key: &str) -> Result<Vec<u8>, result_code>; ``` put_state ```rust // 鍐欏叆鍚堢害璐︽埛淇℃伅銆傝鎺ュ彛鍙妸绫诲埆 鈥渒ey鈥� 涓嬪睘鎬у悕涓� 鈥渇iled鈥� 鐨勭姸鎬佹洿鏂板埌閾句笂銆傛洿鏂版垚鍔熻繑鍥�0锛屽け璐ュ垯杩斿洖1銆� // @param key: 闇€瑕佸瓨鍌ㄧ殑key鍊� // @param field: 闇€瑕佸瓨鍌ㄧ殑key鍊间笅灞炴€у悕涓篺ield // @param value: 闇€瑕佸瓨鍌ㄧ殑value鍊� // @return: 0: success, 1: failed fn put_state(&self, key: &str, field: &str, value: &[u8]) -> result_code; ``` put_state_from_key ```rust // 鍐欏叆鍚堢害璐︽埛淇℃伅銆� // @param key: 闇€瑕佸瓨鍌ㄧ殑key鍊� // @param value: 闇€瑕佸瓨鍌ㄧ殑value鍊� // @return: 0: success, 1: failed fn put_state_from_key(&self, key: &str, value: &[u8]) -> result_code; ``` delete_state ```rust // 鍒犻櫎鍚堢害璐︽埛淇℃伅銆傝鎺ュ彛鍙妸绫诲埆 鈥渒ey鈥� 涓嬪睘鎬у悕涓� 鈥渘ame鈥� 鐨勭姸鎬佷粠閾句笂鍒犻櫎銆� // @param key: 闇€瑕佸垹闄ょ殑key鍊� // @param field: 闇€瑕佸垹闄ょ殑key鍊间笅灞炴€у悕涓篺ield // @return: 0: success, 1: failed fn delete_state(&self, key: &str, field: &str) -> result_code; ``` delete_state_from_key ```rust // 鍒犻櫎鍚堢害璐︽埛淇℃伅銆傝鎺ュ彛鍙妸绫诲埆 鈥渒ey鈥� 涓嬪睘鎬у悕涓� 鈥渘ame鈥� 鐨勭姸鎬佷粠閾句笂鍒犻櫎銆� // @param key: 闇€瑕佸垹闄ょ殑key鍊� // @return: 0: success, 1: failed fn delete_state_from_key(&self, key: &str) -> result_code; ``` call_contract ```rust // 璺ㄥ悎绾﹁皟鐢� // @param contract_name: 鍚堢害鍚嶇О // @param method: 鍚堢害鏂规硶 // @param EasyCodec: 鍚堢害鍙傛暟 fn call_contract(&self, contract_name: &str, method: &str, param: EasyCodec) -> Result<Vec<u8>, result_code>; ``` args ```rust // @return: EasyCodec fn args(&self) -> &EasyCodec; ``` arg ```rust // 璇ユ帴鍙e彲杩斿洖灞炴€у悕涓� 鈥渒ey鈥� 鐨勫弬鏁扮殑灞炴€у€笺€� // @param key: 鑾峰彇鐨勫弬鏁板悕 // @return: 鑾峰彇鐨勫弬鏁板€� 鎴� 閿欒淇℃伅銆傚綋鏈紶璇ey鐨勫€兼椂锛屾姤閿檖aram not found fn arg(&self, key: &str) -> Result<Vec<u8>, String>; ``` ok ```rust // 璇ユ帴鍙e彲璁板綍鐢ㄦ埛鎿嶄綔鎴愬姛鐨勪俊鎭紝骞跺皢鎿嶄綔缁撴灉璁板綍鍒伴摼涓娿€� // @param body: 鎴愬姛杩斿洖鐨勪俊鎭� fn ok(&self, value: &[u8]) -> result_code; ``` error ```rust // 璇ユ帴鍙e彲璁板綍鐢ㄦ埛鎿嶄綔澶辫触鐨勪俊鎭紝骞跺皢鎿嶄綔缁撴灉璁板綍鍒伴摼涓娿€� // @param body: 澶辫触淇℃伅 fn error(&self, body: &str) -> result_code; ``` log ```rust // 璇ユ帴鍙e彲璁板綍浜嬩欢鏃ュ織銆傛煡鐪嬫柟寮忎负鍦ㄩ摼閰嶇疆鐨刲og.yml涓紝寮€鍚痸m:debug鍗冲彲鐪嬪埌绫讳技锛歸asmer log>> + msg // @param msg: 浜嬩欢淇℃伅 fn log(&self, msg: &str); ``` get_creator_org_id ```rust // 鑾峰彇鍚堢害鍒涘缓鑰呮墍灞炵粍缁嘔D // @return: 鍚堢害鍒涘缓鑰呯殑缁勭粐ID fn get_creator_org_id(&self) -> String; ``` get_creator_role ```rust // 鑾峰彇鍚堢害鍒涘缓鑰呰鑹� // @return: 鍚堢害鍒涘缓鑰呯殑瑙掕壊 fn get_creator_role(&self) -> String; ``` get_creator_pub_key ```rust // 鑾峰彇鍚堢害鍒涘缓鑰呭叕閽� // @return: 鍚堢害鍒涘缓鑰呯殑鍏挜鐨凷KI fn get_creator_pub_key(&self) -> String; ``` get_sender_org_id ```rust // 鑾峰彇浜ゆ槗鍙戣捣鑰呮墍灞炵粍缁嘔D // @return: 浜ゆ槗鍙戣捣鑰呯殑缁勭粐ID fn get_sender_org_id(&self) -> String; ``` get_sender_role ```rust // 鑾峰彇浜ゆ槗鍙戣捣鑰呰鑹� // @return: 浜ゆ槗鍙戣捣鑰呰鑹� fn get_sender_role(&self) -> String; ``` get_sender_pub_key() ```rust // 鑾峰彇浜ゆ槗鍙戣捣鑰呭叕閽� // @return 浜ゆ槗鍙戣捣鑰呯殑鍏挜鐨凷KI fn get_sender_pub_key(&self) -> String; ``` get_block_height ```rust // 鑾峰彇褰撳墠鍖哄潡楂樺害 // @return: 褰撳墠鍧楅珮搴� fn get_block_height(&self) -> i32; ``` get_tx_id ```rust // 鑾峰彇浜ゆ槗ID // @return 浜ゆ槗ID fn get_tx_id(&self) -> String; ``` emit_event ```rust // 鍙戦€佸悎绾︿簨浠� // @param topic: 鍚堢害浜嬩欢涓婚 // @data: 鍚堢害浜嬩欢鏁版嵁锛寁ertor涓簨浠舵暟鎹釜鏁颁笉鍙ぇ浜�16锛屼笉鍙皬浜�1 fn emit_event(&mut self, topic: &str, data: &Vec<String>) -> result_code; ``` <span id="new_iterator_interface">new_iterator</span> ```rust /// new_iterator range of [startKey, limitKey), front closed back open // 鏂板缓key鑼冨洿杩唬鍣紝key鍓嶉棴鍚庡紑锛屽嵆锛歴tart_key <= dbkey < limit_key // @param start_key: 寮€濮嬬殑key // @param limit_key: 缁撴潫鐨刱ey // @return: 缁撴灉闆嗘父鏍� fn new_iterator(&self,start_key: &str,limit_key: &str) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_with_field range of [key+"#"+startField, key+"#"+limitField), front closed back open // 鏂板缓field鑼冨洿杩唬鍣紝key闇€鐩稿悓锛宖ield鍓嶉棴鍚庡紑锛屽嵆锛歬ey = dbdbkey and start_field <= dbfield < limit_field // @param key: 鍥哄畾key // @param start_field: 寮€濮嬬殑field // @param limit_field: 缁撴潫鐨刦ield // @return: 缁撴灉闆嗘父鏍� fn new_iterator_with_field(&self, key: &str, start_field: &str, limit_field: &str) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_prefix_with_key range of [key, key], front closed back closed // 鏂板缓鎸囧畾key鍓嶇紑鍖归厤杩唬鍣紝key闇€鍓嶇紑涓€鑷达紝鍗砫bkey.startWith(key) // @param key: key鍓嶇紑 // @return: 缁撴灉闆嗘父鏍� fn new_iterator_prefix_with_key(&self, key: &str) -> Result<Box<dyn ResultSet>, result_code>; /// new_iterator_prefix_with_key_field range of [key+"#"+field, key+"#"+field], front closed back closed // 鏂板缓鎸囧畾field鍓嶇紑鍖归厤杩唬鍣紝key闇€鐩稿悓锛宖ield鍓嶇紑涓€鑷达紝鍗砫bkey = key and dbfield.startWith(field) // @param key: key鍓嶇紑 // @return: 缁撴灉闆嗘父鏍� fn new_iterator_prefix_with_key_field(&self, key: &str, field: &str) -> Result<Box<dyn ResultSet>, result_code>; ```