以太坊开发者指南 #2

如何使用账号签名、发起交易。

在指南的第一部分中,我们在与模拟的以太坊网络进行交互时,涵盖了很多内容。 此时,你至少应该对如何回答这些问题有一个模糊的概念:

  • 什么是区块链,区块里有什么?
  • 是什么让以太坊去中心化?
  • 什么是以太币,为什么它是网络的必要组成部分?

在这篇文章中,我们将在这些概念的基础上,探讨对开发者的一些影响,如果你跳过或需要复习,请返回第1部分

接下来做什么?

我们将从账户开始,更深入地了解你如何与以太坊网络交互。 以太坊账户和Web 2.0账户之间有一些显著的区别。

注:Web 2.0是用来描述:引入用户生成内容的互联网时代的,例如社交媒体和博客。 而以太坊和其他去中心化技术则称为是下一代互联网(Web3.0 ,缩写Web3)的一部分。 Web3因此被Web3.jsWeb3.py等库以及生态系统的其他地方使用。

Web2与Web3

在如今的网络中,很难集合账号。 你得为每个社交媒体应用程序、新闻网站、配送服务、零售商和航空公司等等 都注册一个账号 。 每一个账户都在其公司的服务器上,这使得你必须遵守他们的条款和条件、隐私政策和安全惯例。 你的账户可以被冻结、删除、审查或由所在公司酌情更改。

Web3代表了账户管理的范式转变:只有你自己一个人拥有你的以太坊账户。 当你创建一个账户时,它与任何公司无关,此账号并且可以在多个应用程序中使用。 事实上,创建一个以太坊账户根本不需要与以太坊区块链进行交互。 我们现在就来创造一个。

:这个练习纯属教育目的。 在明白安全影响之前,不要在账户中存储真实价值。 否则有些错误是无法挽回的!

创建一个账户

和上次演练一样,依旧在IPython shell中演示这些概念。 如果你不是Python开发者,没问题。 只要在概念上跟着走就可以了。

环境设置

三步到位:

  1. 安装Web3.py、eth-tester和IPython(如果你在第一部分还没有安装的话)。 $ pip install web3 web3[tester] ipython
  2. 启动一个新的沙盒环境。 $ ipython
  3. 导入Web3模块。 在[1]:从web3导入Web3

账户生成

让我们创建一个账户:

In [2]: w3 = Web3() # 现在不需要 provider 

In [3]: acct = w3.eth.account.create()

# public address:
In [4]: acct.address
Out[4]: '0x33736Bf0Ac7A046eAC36648ca852B91EAe5f567A'

# private key:
In [5]: acct.key
Out[5]: HexBytes('0x7aca78f5e54...')

这就是创建账户所有要做的! 没有注册过程,也没有和区块链或任何服务器交互。 事实上,你可以完全断开与互联网的连接,仍然可以创建一个有效的以太坊账户。

在上面的代码中,你会发现一个账户的两个组成部分:一个公开地址和一个私钥。 简单来说,私钥就是一个账户的密码。 公开地址是由私钥衍生出来的可共享账号。 从代码示例中可以看出,两者通常用十六进制数字表示。

:以太坊用户和应用开发者不必了解账户生成过程的具体运作方式,但如果你有兴趣非常深入地了解,可阅读 :理解助记词与HD 钱包

使用账户

在区块链上影响变化的唯一方式是通过交易,每笔交易必须由账户签署。 这是需要了解,且很重要的一点。

账户可以发起转账以太币的交易,部署智能合约,或与合约交互(诸如铸造新的代币)。 我们来简单探讨一下每个方式。

以太币转账

回顾一下,EthereumTesterProvider启用了一个以账户和充值了测试以太币种子的测试环境。 我们先来查看一些测试账户和账户余额。

In [1]: w3 = Web3(Web3.EthereumTesterProvider())

In [2]: w3.eth.accounts
Out[2]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]

In [3]: acct_one = w3.eth.accounts[0]

In [4]: w3.eth.get_balance(acct_one)
Out[4]: 1000000000000000000000000

接下来,我们将介绍一个新的账户。

In [5]: acct_two = w3.eth.accounts.create()

In [6]: acct_two.address
Out[6]: '0x2FF32Bcc040e98EBa3c0ae2d8ad9C451a78d3E24'

In [7]: acct_two.key
Out[7]: HexBytes('0x02af55504048265...f70e9965a3505ea')

然后把一些测试以太币送到新的账户上。

In [8]: tx_hash = w3.eth.send_transaction({
      'from': acct_one,
      'to': acct_two.address,
      'value': 10000000000
    })

这笔交易将立即执行,但一些重要的细节被隐藏起来。 Web3.py很聪明,知道EthereumTesterProvider正在管理acct_one,而且我们正在使用测试环境。 为方便起见,acct_one是 "unlocked(解锁)"的,也就是说,该默认使用该账户来签署交易。

那么,如果从非解锁账户发起交易是什么样的呢? 让我们从acct_two,一个不由EthereumTesterProvider管理的账户发送一些以太币。 这个需要三个步骤。 1)指定交易细节,2)签署交易,3)向网络广播交易。

# 1) 手动构造交易
In [9]: tx = {
          'to': acct_one,
          'value': 10000000,
          'gas': 21000,
          'gasPrice': 1,  # price only possible in eth-tester
          'nonce': 0
        }

# 2) 用私钥签名交易
In[10]: signed = w3.eth.account.sign_transaction(tx, acct_two.key)

# 3) 发送”raw“ 原始交易
In[11]: tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)

让我们来分析一下。 步骤1定义了一个Python字典,其中包含所需的交易字段。 我们在第一部分学习了 gasgasPrice,但 nonce可能是新关键字。 在以太坊中,nonce只是账户的交易次数。 以太坊协议会跟踪这个值,以防止双花

由于这是 acct_two进行的第一笔交易,所以它的nonce为0。 如果你提供了错误的值,结果是无效的交易,并被Web3.py拒绝。

ValidationError: Invalid transaction nonce: Expected 0, but got 4

请注意,当从acct_one发送交易时,仍然需要一个nonce,但EthereumTesterProvider会跟踪管理账户的交易计数,并为新的交易添加适当的nonce。

另一个细节你可能已经注意到了,从 tx中缺少一个 from值。 这是因为,sign_transaction方法可以从发件人的私钥推断出发件人的地址。 上面提到过,公开地址可以从私钥中推导出来,但私钥不能从公开地址反向推导出来。

最后,raw原始交易是以字节表示的交易数据和签名。 在底层,sign_transactionsendRawTransaction采用相同的编码。

部署智能合约

与智能合约的交互看起来与标准交易非常相似。

简单来说,智能合约是”活跃“在以太坊区块链上的程序,任何人都可以使用。 当你准备好部署一个智能合约时,需要将代码编译成字节码,并将其作为一个data值包含在一个交易中。

bytecode = "6080604052348015610...36f6c63430006010033"

tx = {
   'data': bytecode,
   'value': 0,
   'gas': 1500000,
   'gasPrice': 1,
   'nonce': 0
}

除了需要更多的Gas外,合约部署交易中唯一的区别是没有 to值。 其余过程与标准的以太币转账相同。

与智能合约交互

使用部署合约的交易格式类似。 在这种情况下,to值指向合约地址,data值将根据正在执行的合约方法的输入而变化。

需要注意的是,像Web3.py这样的工具为合约的部署和交互提供了更直观的界面。

# 与合约交互
myContract = web3.eth.contract(address=address, abi=abi)
twentyone = myContract.functions.multiply7(3).call()

# 部署新合约
Example = w3.eth.contract(abi=abi, bytecode=bytecode)
tx_hash = Example.constructor().transact()

签名

交易是影响区块链状态的唯一方式,但并不是账户的唯一的使用方式。 仅仅是证明某个账户的所有权,其本身就很有用。

举个例子,OpenSea是一个以太坊市场,你可以用你的账户签名留言来竞拍待售物品。 只有当拍卖到期或卖家接受你的报价时,才是真正的交易。 同样,在向你展示一些账户细节之前,该应用程序使用签名信息作为一种认证形式。

与交易不同的是,签名信息不需要任何费用。 他们没有向网络广播,也没有列入一个区块。 签名信息只是用私钥签署后的一串数据。 和期望的一样,发送者的私钥仍然是隐藏的,但接收者可以用数学方法证明发送者的公共地址。 换句话说,无法冒充信息的发送者。

注:术语 链上链下是表示数据是否活跃在以太坊区块链上的缩写。 例如,账户余额和智能合约状态是链上管理的,但消息签名却发生在链下

我们将在以后的文章中深入探讨消息签名,但这里有一些伪代码可以让你了解工作流程。

# 1. 一串信息
msg = "amanaplanacanalpanama"

# 2. 用私钥签名
pk = b"..."
signed_message = sign_message(message=msg, private_key=pk)

# 3. 用任何方式发送签名信息 `signed_message` 

# 4. 信息接收者解析出 发送者的公共地址
sender = decode_message_sender(msg, signed_message.signature)
print(sender)
# '0x5ce9454...b9aB12E'

Web3账户所涉问题

我们可以轻松创建以太坊账户:离线并与任何应用程序独立。 这些账户可以用来签署信息或发送各种类型的交易。 这对应用开发者意味着什么?

永久密码

这个世界一个残酷的现实是,没有密码恢复服务。 如果你丢失了你的私钥(或助记词短语),你就可以和这个账户吻别了。 这就是真正的所有权的双刃剑。 应用开发者有道德和义务帮助以太坊新人上岗,并教育他们认识到这一现实。 (注:社交恢复型钱包可改善此类用户体验)。

新挑战

将新用户引入以太坊是有门槛的。 正如你一直在学习的那样,有一些范式的转变并不是很明显。 你可能要引导还没有以太坊账户的访客或没有以太币的用户支付交易费用。 教育用户的成本取决于你的受众,但如果你能够优雅地引入新用户,整个生态系统将受益。

较少的账户管理功能

鉴于用户在你的应用之外创建账户,你可能会发现你的使用场景几乎不需要或根本不需要账户管理功能。

新的商业模式

数据挖掘不会消失,但这种新的账户所有权模式是Web 2.0模式的一个健康的替代方案,在Web 2.0模式下,公司拥有用户的每一点数据,并将其出售给出价最高的人。 以太坊的智能合约平台提供了一个新的激励模型。

新的软件架构

在你的商业模式定义中,一个有趣的权衡将是如何处理链上与链下。 正如我们讨论过的,消息签名不需要链上交互。 也没有什么可以阻止你使用私人数据库来处理部分数据,而使用以太坊区块链来处理其他位数据或功能。 需要考虑的权衡因素很多:可用性、成本、透明度、去中心化、隐私等等。

小结

这些都掌握了吗? 检验一下:

  • 以太坊账户与Web2.0中的账户有何不同?
  • 以太坊账户可以在哪些方面使用?
  • 以太坊账户对应用开发者有什么影响?

你可以生成的账户数量没有限制,你可以自由地将同一个账户用于多个应用程序,或者为每个应用程序创建一个新的账户。 当一个公共区块链被描述为无需许可的(permissionless),意思是:你和网络之间没有守卫人。 因此,不要等着别人允许你建造。


本翻译由 Cell Network 赞助支持。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
翻译小组
翻译小组
0x9e64...7c84
大家看到好的文章可以在 GitHub 提 Issue: https://github.com/lbc-team/Pioneer/issues 欢迎关注我的 Twitter: https://twitter.com/UpchainDAO