本系列将重点介绍两种函数式编程语言:Rust&Elixir。本篇分享函数式编程的思想和实践。 在这篇文章中将展示Elixir&Rust读取以太坊智能合约的功能。重要的是,该程序不仅在以太坊上工作,而且还在任何支持EVM的区块链上工作,例如,Polkadot上的Moonbeam ! Ethereumex & ExABI我更喜欢 Elixir 的两个存储库是 Ethereumex:用于以太坊区块链的 Elixir JSON-RPC 客户端。 ExABI:Solidity的应用程序二进制接口(ABI)描述了如何将二进制数据转换为Solidity编程语言能够理解的类型。 ABI 小贴士: ABI(应用程序二进制接口)是计算机科学中两个程序模块之间的接口。 它与API(应用程序接口)非常相似,API是代码接口的可读表示形式。ABI定义了用于与二进制合约交互的方法和结构,就像API那样,只是在更低的层次上。 .abi文件包含了json格式的函数接口和事件的描述。 这是 HelloWorld.sol 的示例 ABI: [{ "constant": true, "inputs": [], "name": "get", "outputs": [{"name": "","type": "string"} ], "payable": false, "stateMutability": "view", "type": "function"}]Ethereumex 的配置首先,让我们将 Ethereumex 添加到 mix.exs 中的 depsand 应用领域! # mix.exs:def application do[mod: {TaiShang.Application, []},extra_applications: [:logger, :runtime_tools, :ethereumex]]end……defp deps do [{:ethereumex, "~> 0.7.0"} ]end然后,在config/config.exs中。将以太坊协议主机参数添加到配置文件中: # config.exsconfig :ethereumex,url: "http://localhost:8545" # node urlTx结构在 Elixir 中显示 通过代码很容易理解Elixir中的Struct。 以太坊的tx在Elixir中显示: Transaction{nonce: nonce, # counter to ensure the sequence of txsgas_price: @gas.price, # gas feegas_limit: @gas.limit, # gas gas limitto: bin_to, # addr in binaryvalue: 0, # the eth u are going to sendinit: <<>>, # bytecodedata: data # the data u are going to send}我们刚刚读取了以太坊中的数据,因此随机数是没有用的。只有在我们把数据写进合约的时候才需要更改随机数。 eth_call 立即执行一个新的消息调用,而不需要在区块链上创建交易。 参数 Object -交易调用对象 from: DATA, 20 Bytes -(可选)交易发送的地址 to: DATA, 20 Bytes -交易被指向到的地址 gas: QUANTITY -(可选)为交易执行提供的gas整数。eth_call消耗零gas,但某些执行可能需要这个参数 gasPrice: QUANTITY -(可选)每一种付费gas使用的gasPrice的整数 value: QUANTITY -(可选)与该交易一起发送的值的整数 data: DATA -(可选)方法签名和编码参数的哈希值 QUANTITY|TAG -整数区块号,或字符串"latest", "earliest"或"pending",参见默认区块参数 返回 DATA -已执行合约的返回值。 例子 // Requestcurl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{see above}],"id":1}'// Result{"id":1,"jsonrpc": "2.0","result": "0x"}gas的机制对新人不友好,所以我们现在可以设置gas_price和gas_limit为一个特定的数字: @gas %{price: 0, limit: 300_000} 在 Rust 中显示 它是 Rust 中的一个类似结构: /// from: https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/sending-ethereum-transactions-with-rust/let tx = TransactionRequest {from: accounts[0],to: Some(accounts[1]),gas: None, // gaslimitgas_price: None,value: Some(U256::from(10000)),data: None,nonce: None,condition: None};现在我们应该处理tx的两个参数: to & data。 地址的字符串到二进制区块链中使用的地址(如0x769699506f972A992fc8950C766F0C7256Df601f)可以在Elixir程序中转换为二进制: @spec addr_to_bin(String.t()) :: Binary.t()def addr_to_bin(addr_str) doaddr_str|> String.replace("0x", "")|> Base.decode16!(case: :mixed)end智能合约功能到数据我们希望通过以太坊函数和参数列表的字符串样式生成数据: @spec get_data(String.t(), List.t()) :: String.t()def get_data(func_str, params) dopayload =func_str|> ABI.encode(params)|> Base.encode16(case: :lower)"0x" <> payload“以太坊函数的字符串样式”示例: @func %{balance_of: "balanceOf(address)",token_of_owner_by_index: "tokenOfOwnerByIndex(address, uint256)",token_uri: "tokenURI(uint256)",get_evidence_by_key: "getEvidenceByKey(string)",new_evidence_by_key: "newEvidenceByKey(string, string)",mint_nft: "mintNft(address, string)",owner_of: "ownerOf(uint256)"}eth函数的字符串样式抽象为"function_name(param_type1, param_type2,…)" 深入了解encode函数的实现是很好的! def encode(function_signature, data, data_type \\ :input)# string type of function to function_selector# then call encode function again with function_selectordef encode(function_signature, data, data_type) when is_binary(function_signature) dofunction_signature|> Parser.parse!()|> encode(data, data_type)enddef encode(%FunctionSelector{} = function_selector, data, data_type) doTypeEncoder.encode(data, function_selector, data_type)endFunctionSelector的结构: iex(5)> ABI.Parser.parse!("baz(uint8)")%ABI.FunctionSelector{function: "baz",input_names: [],inputs_indexed: nil,method_id: nil,returns: [],type: nil,types: [uint: 8]}TypeEncoder.encode 的工作是编译数据,function_selector 和 data_type 转换为数据。 智能合约响应的翻译器在 Elixir 中编写一个 TypeTransalator 将十六进制数据更改为普通数据用于智能合约的响应是好的: defmodule Utils.TypeTranslator do……def data_to_int(raw) doraw|> hex_to_bin()|> ABI.TypeDecoder.decode_raw([{:uint, 256}])|> List.first()enddef data_to_str(raw) doraw|> hex_to_bin()|> ABI.TypeDecoder.decode_raw([:string])|> List.first()enddef data_to_addr(raw) doaddr_bin =raw|> hex_to_bin()|> ABI.TypeDecoder.decode_raw([:address])|> List.first()"0x" <> Base.encode16(addr_bin, case: :lower)end……end我们要选择的函数是基于响应的类型,我们可以在ABI中获取它: {"constant": true,"inputs": [],"name": "get","outputs": [{"name": "","type": "string"# The response is string!}],"payable": false,"stateMutability": "view","type": "function"}Elixir中的调用者这是最后一步!只要把上面的功能混合在一起,智能合约的数据读取就可以工作了! 例如:读取ERC20代币的余额: @spec balance_of(String.t(), String.t()) :: Integer.t()def balance_of(contract_addr, addr_str) do{:ok, addr_bytes} = TypeTranslator.hex_to_bytes(addr_str)data = get_data("balanceOf(address)", [addr_bytes]){:ok, balance_hex} =Ethereumex.HttpClient.eth_call(%{ # the tx is encapsulated by ethereumex.data: data,to: contract_addr}) TypeTranslator.data_to_int(balance_hex)endRust 中的调用者最后一个是调用以太坊的例子 extern crate hex;use hex_literal::hex;use web3::{contract::{Contract, Options},types::{U256, H160, Bytes},};#[tokio::main]async fn main() -> web3::contract::Result<()> {let _ = env_logger::try_init();let http = web3::transports::Http::new("https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161")?;let web3 = web3::Web3::new(http);let addr_u8 = hex::decode("7Ad11de6d4C3DA366BC929377EE2CaFEcC412A10").expect("Decoding failed");let addr_h160 = H160::from_slice(&addr_u8);let contra = Contract::from_json(web3.eth(),addr_h160,include_bytes!("../contracts/hello_world.json"),)?;// let acct:[u8; 20] = hex!("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac").into();let result = contra.query::("get", (), None, Options::default(), None).await?;println!("{}", result);Ok(())}Source:https://hackernoon.com/how-rust-and-elixir-read-ethereum-and-other-evm-smart-contracts-functional-programming-and-blockchain —- 编译者/作者:ChinaDeFi 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
Rust 和 Elixir 如何读取以太坊和其他 EVM 智能合约:函数式编程和区块链
2021-09-14 ChinaDeFi 来源:区块链网络
LOADING...
相关阅读:
- A&T Capital: Gamified Economy 开启通向元宇宙的大门2021-09-14
- 公链战局突变,为什么是Avalanche杀出重围?2021-09-14
- 为什么区块链离不开IPFS而IPFS也离不开区块链?2021-09-14
- 周指南:火锅基金V2第27期近况播报2021-09-14
- Terra 价格分析:Luna 在昨天触及 ATH 后回落至 36 美元的低点2021-09-14