知世金融网专注于股票行情,期货开户,外汇储备等最新相关资讯信息提供投资者参考学习!

当前位置:网站首页 > 区块链 > 正文

使用Rust实现发送以太坊交易

原创
文章作者
知世-金融领域资深作者
知名金融领域作者,从事金融超过十余年,在行业内有一定影响力。
金融风险管理师认证证书 常识职业资格认证 特许金融分析师 国际金融理财师认证证书
发布时间:2020-02-16 18:39:19 发布来源:区块链研究实验室 文章点击:122

本教程将指导如何使用rust实现发送以太坊交易所需的代码。 先决条件 我们假设您已经拥有Rust IDE,并且具有Rust编程的合理知识。我们还假设一些关于以太坊的基本知识,并且不涉及以...

目录

    本文标题使用Rust实现发送以太坊交易,作者:知世,本文有2962个文字,大小约为11KB,预计阅读时间8分钟,请您欣赏。知世金融网众多优秀文章,如果想要浏览更多相关文章,请使用网站导航的搜索进行搜索。本站虽然不乏优秀之作,但仅作为投资者学习参考。

    本教程将指导如何使用rust实现发送以太坊交易所需的代码。

    先决条件

    我们假设您已经拥有Rust IDE,并且具有Rust编程的合理知识。我们还假设一些关于以太坊的基本知识,并且不涉及以太坊事务的内容等概念。

    · Rust入门
    · 以太坊101

    库的使用

    本教程使用MIT许可的rust-web3库。要在您的应用程序中使用此库,请将其添加到Cargo.toml文件中:

    [dependencies]
    web3 = { git = "https://github.com/tomusdrw/rust-web3" }

    然后,您可以将库添加到您的包中:

    extern crate web3;

    启动以太坊节点

    我们需要访问我们可以发送事务的节点。在本教程中,我们使用ganache-cli,它允许您启动个人以太坊网络,其中有许多未锁定的和已资助的帐户。

    从ganache-cli安装文档中获取,要使用npm进行安装,请使用以下命令:

    npm install -g ganache-cli

    或者如果你喜欢用yarn命令

    yarn global add ganache-cli

    安装后,运行下面的命令以启动专用以太坊测试网络:

    ganache-cli -d

    注意,-d参数指示ganache cli始终以预先填充eth的相同帐户开始。这在本教程的原始事务部分很有用,因为我们将知道这些帐户的私钥。

    从节点管理帐户发送事务

    发送事务的最简单方法是依靠连接的以太坊节点执行事务签名。这通常是一种不太安全的方法,因为它依赖于在节点上“unlock”帐户。

    use声明

    use web3::futures::Future;
    use web3::types::{TransactionRequest, U256};

    节点连接

    let (_eloop, transport) = web3::transports::Http::new(
    "http://localhost:8545").unwrap();

    let web3 = web3::Web3::new(transport);

    首先,我们创建一个用于连接节点的传输对象。在这个例子中,我们通过http连接到端口8545上的localhost,这是Ganache的默认端口,以及大多数(如果不是全部)以太坊客户端。

    注意:还会返回EventLoop,但这超出了本指南的范围。

    接下来,我们构造一个web3对象,传入先前创建的传输变量,就是这样!我们现在已连接到以太坊节点!

    获取帐户详细信息

    GANACHE CLI自动解锁多个账户,并使用100ETH为其提供资金,这对测试很有用。每次重新启动时帐户都不同,因此我们需要一种以编程方式获取帐户信息的方法:

    let accounts = web3.eth().accounts().wait().unwrap();

    通过web3.eth()获得的Eth命名空间包含许多用于与以太坊节点交互的有用函数。通过accounts()获取管理帐户列表就是其中之一。它返回异步的未来,所以我们等待任务完成(wait()),并获得结果(unwrap())。

    发送交易

    我们定义要通过TransactionRequest结构发送的事务的参数:

    let tx = TransactionRequest {
    from: accounts[0],
    to: Some(accounts[1]),
    gas: None,
    gas_price: None,
    value: Some(U256::from(10000)),
    data: None,
    nonce: None,
    condition: None
    };

    此结构中的大多数字段都是可选的,如果不手动指定,则使用合理的默认值。当我们发送简单的ETH转移事务时,数据字段为空,在此示例中,我们使用默认的gas和gas_price值。我们也没有指定nonce,因为rust-web3库默认情况下会向以太坊客户端查询最新的nonce值。该条件是rust-web3特定字段,允许您延迟发送事务直到满足某个条件,例如达到特定的块编号。

    一旦启动TransactionRequest,它就是一个发送交易的单行:

    let tx_hash = web3.eth().send_transaction(tx).wait().unwrap();

    TransactionRequest传递给Eth命名空间中的send_transaction(..)函数,该函数返回一个在广播到网络后完成的Future。完成后,Promise返回事务哈希Result,然后我们可以unwrap。

    全部放在一起......

    extern crate web3;

    use web3::futures::Future;
    use web3::types::{TransactionRequest, U256};

    fn main() {
    let (_eloop, transport) = web3::transports::Http::new("http://localhost:8545").unwrap();

    let web3 = web3::Web3::new(transport);
    let accounts = web3.eth().accounts().wait().unwrap();

    let balance_before = web3.eth().balance(accounts[1], None).wait().unwrap();

    let tx = TransactionRequest {
    from: accounts[0],
    to: Some(accounts[1]),
    gas: None,
    gas_price: None,
    value: Some(U256::from(10000)),
    data: None,
    nonce: None,
    condition: None
    };

    let tx_hash = web3.eth().send_transaction(tx).wait().unwrap();

    let balance_after = web3.eth().balance(accounts[1], None).wait().unwrap();

    println!("TX Hash: {:?}", tx_hash);
    println!("Balance before: {}", balance_before);
    println!("Balance after: {}", balance_after);
    }

    我们使用web3.eth()。balance(..)函数来获取转移前后收件人帐户的余额,以证明转移发生。运行此代码,您应该看到在事务发送后帐户[1]余额超过10000 wei ...成功的以太转移!

    发送原始交易

    发送原始事务意味着在Rust端而不是在节点上使用私钥对事务进行签名。然后,该节点将此事务转发到以太坊网络。

    ethereum-tx-sign库可以帮助我们进行这种脱链签名,但由于缺少共享结构,因此不容易与rust-web3一起使用。在本指南的这一部分中,我将解释如何让这些库很好地协同工作。

    使用的其他库

    在构造RawTransaction时,ethereum-tx-sign库依赖于以太它类型库。我们还使用十六进制库将十六进制私钥转换为字节。

    将这些条目添加到cargo.toml文件中:

    ethereum-tx-sign = "0.0.2"
    ethereum-types = "0.4"
    hex = "0.3.1"

    然后,您可以将它们添加到您的包中:

    extern crate ethereum_tx_sign;
    extern crate ethereum_types;
    extern crate hex;

    签署交易

    ethereum_tx_sign库包含一个RawTransaction结构,我们可以在初始化后用它来签署以太坊事务。初始化是棘手的部分,因为我们需要在rust-web3和ethereum_types结构之间进行转换。

    一些转换函数可以将由rust-web3函数返回的web3 ::类型的H160(对于以太坊帐户地址)和U256(对于nonce值)结构转换为由ethereum-tx-sign预期的theherehere_types:

    fn convert_u256(value: web3::types::U256) -> U256 {
    let web3::types::U256(ref arr) = value;
    let mut ret = [0; 4];
    ret[0] = arr[0];
    ret[1] = arr[1];
    U256(ret)
    }

    fn convert_account(value: web3::types::H160) -> H160 {
    let ret = H160::from(value.0);
    ret
    }

    我们现在可以构造一个RawTransaction对象(替换下面的代码,让balance_before):

    let nonce = web3.eth().transaction_count(accounts[0], None).wait().unwrap();

    let tx = RawTransaction {
    nonce: convert_u256(nonce),
    to: Some(convert_account(accounts[1])),
    value: U256::from(10000),
    gas_price: U256::from(1000000000),
    gas: U256::from(21000),
    data: Vec::new()
    };

    请注意,构造RawTransaction时不会自动计算nonce。我们需要通过调用Eth命名空间中的transaction_count函数来获取发送帐户的nonce。随后需要将此值转换为RawTransaction期望的格式。

    与TransactionRequest结构不同,我们还必须手动提供一些合理的gas和gas_price值。

    获取私钥

    签名之前,我们需要访问用于签名的私钥。在这个例子中,我们硬编码ganache中第一个ETH填充帐户的私钥(记得以-d参数开头)。这可以用于测试,但是您不应该在生产环境中公开私钥!

    fn get_private_key() -> H256 {
    // Remember to change the below
    let private_key = hex::decode(
    "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7

    d21715b23b1d").unwrap();

    return H256(to_array(private_key.as_slice()));
    }

    fn to_array(bytes: &[u8]) -> [u8; 32] {
    let mut array = [0; 32];
    let bytes = &bytes[..array.len()];
    array.copy_from_slice(bytes);
    array
    }

    hex:decode函数将十六进制字符串(确保删除0x前缀)转换为Vec <u8>,但RawTransction的sign函数采用ethereum_types :: H256格式的私钥。不幸的是,h256在构建期间采用的是[u8;32]而不是vec<t>,因此我们需要进行另一个转换!

    私钥作为切片传递给to_array,然后将此切片转换为[u8:32]。

    签名

    既然我们有了一个以正确格式返回私钥的函数,那么我们可以通过调用以下命令来对事务进行签名:

    let signed_tx = tx.sign(&get_private_key());

    发送交易

    签署后,向以太坊网络广播交易也是一条一行程序:

    let tx_hash = web3.eth().send_raw_transaction(Bytes::from(signed_tx)).wait().unwrap()

    注意,我们必须在这里进行另一次转换!send_raw_transaction将Bytes值作为参数,而RawTransaction的sign函数返回Vec <u8>。 幸运的是,这种转换很容易,因为bytes结构有一个现成的from特性,可以从vec<u8>转换。

    与send_transaction等效项一样,此函数返回Future,后者又返回一个Result对象,该对象包含完成时广播事务的事务哈希。

    把它们放在一起

    extern crate web3;
    extern crate ethereum_tx_sign;
    extern crate ethereum_types;
    extern crate hex;

    use web3::futures::Future;
    use web3::types::Bytes;
    use ethereum_tx_sign::RawTransaction;
    use ethereum_types::{H160,H256,U256};

    fn main() {
    let (_eloop, transport) = web3::transports::Http::new("http://localhost:8545").unwrap();

    let web3 = web3::Web3::new(transport);
    let accounts = web3.eth().accounts().wait().unwrap();

    let balance_before = web3.eth().balance(accounts[1], None).wait().unwrap();

    let nonce = web3.eth().transaction_count(accounts[0], None).wait().unwrap();

    let tx = RawTransaction {
    nonce: convert_u256(nonce),
    to: Some(convert_account(accounts[1])),
    value: U256::from(10000),
    gas_price: U256::from(1000000000),
    gas: U256::from(21000),
    data: Vec::new()
    };

    let signed_tx = tx.sign(&get_private_key());

    let tx_hash = web3.eth().send_raw_transaction(Bytes::from(signed_tx)).wait().unwrap();

    let balance_after = web3.eth().balance(accounts[1], None).wait().unwrap();

    println!("TX Hash: {:?}", tx_hash);
    println!("Balance before: {}", balance_before);
    println!("Balance after: {}", balance_after);
    }

    fn get_private_key() -> H256 {
    let private_key = hex::decode(
    "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d").unwrap();

    return H256(to_array(private_key.as_slice()));
    }

    fn convert_u256(value: web3::types::U256) -> U256 {
    let web3::types::U256(ref arr) = value;
    let mut ret = [0; 4];
    ret[0] = arr[0];
    ret[1] = arr[1];
    U256(ret)
    }

    fn convert_account(value: web3::types::H160) -> H160 {
    let ret = H160::from(value.0);
    ret
    }

    fn to_array(bytes: &[u8]) -> [u8; 32] {
    let mut array = [0; 32];
    let bytes = &bytes[..array.len()];
    array.copy_from_slice(bytes);
    array
    }

    总结

    在本教程中,我们学习了如何使用Rust将基本以太网值转移事务从一个帐户发送到另一个帐户。我们解释了两种签名方法:通过解锁帐户在节点上签名,以及在Rust端签署一个事务。

    本文相关推荐: 以太网交换机、IndusCloud工业私有云方案和大网管软件等可用于透明工厂

    以上便是知世金融网给大家分享的关于使用Rust实现发送以太坊交易/qkl/27200.html的相关信息了,希望能帮助到大家,更多金融相关信息,敬请关注知世金融网!

    网站内容均来自互联网,如侵害您的利益联系客服进行删除!

    关键词:以太
    (0)
    (0)

    上一篇:IRIS Hub v0.15平滑升级成功,三大核心功能赋能DeFi

    下一篇:容量证明(Proof of Capacity)里的真相

    本文标题:使用Rust实现发送以太坊交易

    本文地址:/index.php?s=article&c=search&keyword=%E4%BB%A5%E5%A4%AA

    金融知名领域

    南方财富网 | 金融界 | 金融界 |

    更多推荐

    • 茅台吃饱,经销商哭倒
      茅台吃饱,经销商哭倒
    • 汇金的五次增持从短期看具有一定的“稳定器“作用,但从市场表现看效果逐次递减
      汇金的五次增持从短期看具有一定的“稳定器“作用,但从市场表现看效果逐次递减
    • 158亿元!比亚迪收购!
      158亿元!比亚迪收购!
    • 9月价格回落近五成 “冷静期”酒店业备战“十一”市场
      9月价格回落近五成 “冷静期”酒店业备战“十一”市场
    • 2023哈马博览会哈尔滨银行展区精彩纷呈
      2023哈马博览会哈尔滨银行展区精彩纷呈
    • 大额解禁撂倒股价 医疗影像龙头跌出千亿俱乐部 葛兰二季度大幅减仓
      大额解禁撂倒股价 医疗影像龙头跌出千亿俱乐部 葛兰二季度大幅减仓
    • A股,又上了热搜!数字要素概念走高多股涨停,锂电池板块走低恩捷股份大举跌停
      A股,又上了热搜!数字要素概念走高多股涨停,锂电池板块走低恩捷股份大举跌停
    • 最新!巨头出手,加仓宁王51%
      最新!巨头出手,加仓宁王51%
    • 600亿巨头暴雷
      600亿巨头暴雷
    • 一天32家!科创板回购潮涌来
      一天32家!科创板回购潮涌来
    • 提振信心实招来了!30余家上市公司密集出手 最高要买10亿
      提振信心实招来了!30余家上市公司密集出手 最高要买10亿
    • 高盛再发50年后预测:2075年印度股市全球市值占比将升4倍 中国升3成
      高盛再发50年后预测:2075年印度股市全球市值占比将升4倍 中国升3成

    新闻资讯栏目

    站长QQ: 2397470084