以太坊合约调用裸交易签名教程【Web3.js】

交易签名是你向区块链证明自己身份的唯一途径,这也是使用 以太坊的Web3开发库时需要理清的一个基本概念。在这个教程中, 我们讲学习如何使用Web3.js来完成以太坊智能合约调用交易的 签名与提交,适用于包括ERC20代币合约在内的所有以太坊合约的 调用。

用自己熟悉的语言学习以太坊DApp开发: Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart

1、以太坊交易签名概述

有两种方法可以对交易进行签名:使用解锁账号或使用私钥。

如果你在用testRPC或Ganache开发,那么应该已经了解其创建 的测试账号。这些账号默认都是解锁的,因此你可以直接用它们 来签名交易。你也可以使用特殊的Web3提供器例如truffle-hdwallet-provider 来生成解锁账号。

更常见的则是以用发起交易的地址对应的私钥来签名交易。考虑到安全性,当 你用到私钥时需要格外小心。

2、创建以太坊智能合约调用交易

首先你需要构建一个调用合约方法的交易对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 12 word mnemonic for HD Wallet Provider
// You can use any provider such as the HttpProvider if you are
// signing with private key
const mnemonic = "opinion destroy betray …";
const provider = new HDWalletProvider(mnemonic,"http://localhost:8545");
const web3 = new Web3(provider);
const myContract = new web3.eth.Contract(contractAbi,contractAddress);

const tx = {
// this could be provider.addresses[0] if it exists
from: fromAddress,
// target address, this could be a smart contract address
to: toAddress,
// optional if you want to specify the gas limit
gas: gasLimit,
// optional if you are invoking say a payable function
value: value,
// this encodes the ABI of the method and the arguements
data: myContract.methods.myMethod(arg, arg2).encodeABI()
};

接下来如何签名就取决于你使用解锁账号还是私钥了。

3、使用解锁账号签名以太坊交易

如果使用已经解锁账号,那么使用如下的代码进行签名:

1
const signPromise = web3.eth.signTransaction(tx, tx.from);

注意,如果你使用解锁账号,那么直接调用myContract.methods.myMethod(arg, arg2) 就可以自动完成签名,上面的代码只是为了演示这一签名过程。

4、使用私钥签名以太坊交易

不过如果这是一个锁定的账号,或者根本就不是节点管理的账号,那么你 可以使用私钥签名交易:

1
const signPromise = web3.eth.accounts.signTransaction(tx, privateKey);

在上述两种情况下,返回的都是一个Promise对象,其解析结果为签名后 的裸交易字符串。

5、广播签名后的裸交易字符串

由于签名后的裸交易字符串中已经编码了有关合约调用的全部信息,包括方法名、 调用参数、gas价格等等,因此可以直接提交给以太坊节点广播:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
signPromise.then((signedTx) => {  

// raw transaction string may be available in .raw or
// .rawTransaction depending on which signTransaction
// function was called
const sentTx = web3.eth.sendSignedTransaction(signedTx.raw || signedTx.rawTransaction);

sentTx.on("receipt", receipt => {
// do something when receipt comes back
});

sentTx.on("error", err => {
// do something on transaction error
});

}).catch((err) => {

// do something when promise fails

});

再次提醒,上述操作中用到了私钥,因此一定要格外小心安全问题。


原文链接:How do I sign transactions with Web3?

汇智网翻译整理,转载请标明出处