web3开胃菜 - Account

232 阅读6分钟

简介

在以太坊中,账户是一个拥有以太币(ETH)余额的实体,可以在以太坊上发送交易。也可以作为智能合约部署;

账户类型

以太坊中账户分为两种类型:

  • 外部账户(Externally-owned account):通过私钥进行控制

  • 合约账户(Contract account):被部署在区块链上的合约代码控制

共同特点

  • 接收并持有 ETH 和 tokens

  • 可以跟已经部署的智能合约交互

主要区别

外部账户:

  • 创建账户是免费

  • 可以发送交易(transaction)

  • 可以跟所有外部账户交易 ETH 和 tokens

  • 由一对加密密钥组成: 控制帐户活动的公钥和私钥

合约账户:

  • 创建合约需要成本(gas),因为用到了网络存储

  • 只有在接收到交易的时候才能发送交易

  • 从外部账户到合约账户的发送交易的时候能触发代码执行不同的行为,如转账或者创建新的合约

  • 合约账户没有私钥,它们被智能合约代码逻辑控制

账户组成

以太坊账户由四个部分组成

  • noce:表示这个账户发送交易的数量,在合约账户中表示这个账户创建的合约的数量
  • balance:账户拥有的Wei的数量,wei是以太坊的记述单位,与以太坊的换算规则如下所示
  • codeHash:该哈希表示以太坊虚拟机 (EVM) 上的帐户代码。 合约帐户具有编程的代码片段,可以执行不同的操作。 如果帐户收到消息调用,则执行此 EVM 代码。 与其他帐户字段不同,不能更改。 所有代码片段都被保存在状态数据库的相应哈希下,供后续检索。 此哈希值称为 codeHash。 对于外部所有的帐户,codeHash 字段是空字符串的哈希。
  • storageRoot:Merkle Patricia trie根节点的 256 位哈希已编码了帐户的存储内容(256 位整数值映射),并编码为 Trie,作为来自 256 的Keccak 256位哈希的映射位整数键,用于 RLP 编码的 256 位整数值。 此 Trie 对此帐户存储内容的哈希进行编码,默认情况下为空。 accounts.png

单位换算规则单位

单位wei值Wei
wei11 wei
Kwei (babbage)1e3 wei1,000
Mwei (lovelace)1e6 wei1,000,000
Gwei (shannon)1e9 wei1,000,000,000
microether (szabo)1e12 wei1,000,000,000,000
milliether (finney)1e15 wei1,000,000,000,000,000
ether1e18 wei1,000,000,000,000,000,000

外部账户

外部账户由一个密钥对(公钥/私钥)组成;它们用于证明交易是被实际的发送者所签名的。私钥用于签名交易,所以他授予你对于你账户的监督权;你不曾真的持有加密货币,你持有的是私钥,你的资金一直在以太坊账本上;这可以防止恶意行为者广播虚假交易,因为您总是可以验证交易的发送方

创建账户

创建流程:

  1. 创建一个随机数私钥,私钥由64个十六进制字符组成,通过密码进行加密
  2. 通过椭圆曲线加密从私钥生成公钥
  3. 通过获得的公钥进行Keccak-256 hash算法加密,取加密后结果最后20个字节,再添加上0x,就可以作为账户地址使用

接下来,我们通过安装geth(go-ethereum)客户端来创建以太坊账户:

安装geth

1、通过homebrew直接安装

> brew install ethereum

2、通过github自行编译安装,注:geth安装需要安装1.17版本以上的go环境

# git clone 代码
> git clone git@github.com:ethereum/go-ethereum.git

# 编译
> make geth

编译完成之后将安装目录下的/build/bin。配置环境变量

export PATH=${PATH}:/Users/xxx/Blockchain/go-ethereum/build/bin

配置完成后,检查是否生效

> geth version

Geth
Version: 1.11.0-unstable
Git Commit: b9ba6f6e4d86d0ee86c63e8f4552e233fe0450aa
Git Commit Date: 20221020
Architecture: amd64
Go Version: go1.19.2
Operating System: darwin
GOPATH=
GOROOT=

通过命令行

账户可以脱离于以太坊客户端单独创建,因此我们可以在不启动服务的情况下通过命令行直接获取

> geth account new

# 输入密码,并确认
INFO [10-24|18:53:08.542] Maximum peer count ETH=50 LES=0 total=50

Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:

# 完成

Your new key was generated
Public address of the key: 0x0edE7fEc62050e38962AaC5640A1E7A335163A0A
Path of the secret key file: /Users/wansy/Library/Ethereum/keystore/UTC--2022-10-24T10-53-42.399057000Z--0ede7fec62050e38962aac5640a1e7a335163a0a

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!

通过下面命令获取账户地址

> geth account list

Account #0: {3e911d72fb689dce90e67797be1d6cf34a7afde9} keystore:///Users/xxx/Library/Ethereum/keystore/UTC--2022-10-20T09-48-51.342283000Z--3e911d72fb689dce90e67797be1d6cf34a7afde9
Account #1: {0ede7fec62050e38962aac5640a1e7a335163a0a} keystore:///Users/xxx/Library/Ethereum/keystore/UTC--2022-10-24T10-53-42.399057000Z--0ede7fec62050e38962aac5640a1e7a335163a0a

通过console

通过console控制台方式启动geth客户端,直接调用函数来创建账号

# rinkeby 为以太坊测试环境
> geth --rinkeby console

创建账号

# 通过交互方式确定密码
> personal.newAccount()
Passphrase:
Repeat passphrase:

"0xf425a790bb2ef4e3aced59506878c172325bf36d"

# 直接传密码
> personal.newAccount(“123")

0x3d80b31a78c30fc628f20b2c89d7ddbf6e53cedc"

通过JSON-RPC

通过JSON-RPC的方式创建账户为最普遍的方式,也是dapp中创建账户的方式。在已经启动的console界面中,通过调用如下函数启动JSON-RPC服务

> admin.startRPC("127.0.0.1",8546,"*","eth,net,web3,personal")

true

通过crul调用JSON-RPC服务

# 创建账户
> curl -X POST -H'content-type: application/json' --data '{"jsonrpc":"2.0","method": "personal_newAccount","params":["123"],"id":1}' http://127.0.0.1:8546

# 返回
{"jsonrpc":"2.0","id":1,"result":"0x782f71ebc818589959797f3dafa788de9947f775"}

# 获取账户
> curl -X POST -H'content-type: application/json' --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' http://127.0.0.1:8546

# 返回
{"jsonrpc":"2.0","id":1,"result":["0x782f71ebc818589959797f3dafa788de9947f775"]}

不难看出,这种方式调用的方法命与console中直接调用的函数是同一个,只不过一个是本地过程调用(Local Procedure Call),一个是远程过程调用(Remote Procedure Call)

合约账户

合约帐户也有一个 42 个字符组成的十六进制地址。合约地址通常在将合约部署到以太坊区块链时给出。地址产生自创建人的地址和从创建人地址发送的交易数量(nonce)。 该部分内容在以后章节会详细说明。