Flow 单公钥地址签名交易

安装flow-cli

安装 flow-cli,MacOS 需要下载最新版本的二进制文件,brew 只能安装旧版本。具体安装方法见文档 Install the Flow CLI,该文档使用版本是 v0.25.0。

生成key-pair

1
2
3
4
5
$ flow keys generate --sig-algo=ECDSA_secp256k1

Store private key safely and don't share with anyone!
Private Key 11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d
Public Key cd23c71391d33c23c867319258ad6cd082b0066e564e23d3fda3c4e5b9ec841eaaa07d2189965130445a4edda244720628334f6a879d80220b573d9914edcbe2

创建testnet flow地址

访问页面:Flow Testnet Faucet ,创建地址。填入生成的 public key,选择ECDSA_secp256k1签名算法和SHA3_256(和 ETH 哈希算法相同)哈希算法。

创建成功后得到地址:0x25470ac6e0585a62,也可以跳过该步骤,直接使用生成好的地址。

初始化flow配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ mkdir flow-example; cd flow-example
$ flow init --service-priv-key 11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d --service-sig-algo=ECDSA_secp256k1 --service-hash-algo=SHA3_256

Configuration initialized
Service account: 0xf8d6e0586b0a20c7

Start emulator by running: 'flow emulator'
Reset configuration using: 'flow init --reset'

$ cat flow.json
{
"emulators": {
"default": {
"port": 3569,
"serviceAccount": "emulator-account"
}
},
"contracts": {},
"networks": {
"emulator": "127.0.0.1:3569",
"mainnet": "access.mainnet.nodes.onflow.org:9000",
"testnet": "access.devnet.nodes.onflow.org:9000"
},
"accounts": {
"emulator-account": {
"address": "f8d6e0586b0a20c7",
"key": {
"type": "hex",
"index": 0,
"signatureAlgorithm": "ECDSA_secp256k1",
"hashAlgorithm": "SHA3_256",
"privateKey": "11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d"
}
}
},
"deployments": {}
}

我们将配置里的地址 f8d6e0586b0a20c7 修改为 25470ac6e0585a62。

创建交易并签名广播

在构造 flow 的交易时,我们需要先使用 Cadence 语言编写执行脚本,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ cat > tx.cdc <<EOF
import FungibleToken from 0x9a0766d93b6608b7
import FlowToken from 0x7e60df042a9c0868

transaction(amount: UFix64, to: Address) {

// The Vault resource that holds the tokens that are being transferred
let sentVault: @FungibleToken.Vault

prepare(signer: AuthAccount) {

// Get a reference to the signer's stored vault
let vaultRef = signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)
?? panic("Could not borrow reference to the owner's Vault!")

// Withdraw tokens from the signer's stored vault
self.sentVault <- vaultRef.withdraw(amount: amount)
}

execute {

// Get a reference to the recipient's Receiver
let receiverRef = getAccount(to)
.getCapability(/public/flowTokenReceiver)
.borrow<&{FungibleToken.Receiver}>()
?? panic("Could not borrow receiver reference to the recipient's Vault")

// Deposit the withdrawn tokens in the recipient's receiver
receiverRef.deposit(from: <-self.sentVault)
}
}
EOF

在 testnet 网络上,FlowToken 的合约地址是 0x7e60df042a9c0868。如果使用主网或者是 emulator,需要替换成对应的合约地址,具体查询:Flow Core Contracts

我们 cdc 代码中定义了 transaction 方法,并且包含两个参数 amount 和 to,我们构造交易时,也要传入对应参数。

我们使用 flow-cli 来构造交易,可以将 flow 发送到 0x72aeca95731d54e5(必须是一个真实创建的地址)。

1
2
3
4
5
6
7
8
9
10
$ flow transactions build ./tx.cdc \
--authorizer emulator-account \
--proposer emulator-account \
--payer emulator-account \
--args-json '[{"type": "UFix64", "value": "1.0"}, {"type": "Address", "value": "0x72aeca95731d54e5"}]' \
--network testnet \
--filter payload \
--save built.rlp

result saved to: built.rlp

我们只保存 payload,我们的接下来对 payload 进行签名,生成签名后的哈希。

1
2
3
4
$ flow transactions sign ./built.rlp --signer emulator-account \
--filter payload --save signed.rlp

result saved to: signed.rlp

广播签名后的交易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
$ flow transactions send-signed --network testnet ./signed.rlp

Sending transaction with ID: 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7

Status ✅ SEALED
ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Payer 25470ac6e0585a62
Authorizers [25470ac6e0585a62]

Proposal Key:
Address 25470ac6e0585a62
Index 0
Sequence 0

No Payload Signatures

Envelope Signature 0: 25470ac6e0585a62
Signatures (minimized, use --include signatures)

Events:
Index 0
Type A.7e60df042a9c0868.FlowToken.TokensWithdrawn
Tx ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Values
- amount (UFix64): 1.00000000
- from (Address?): 0x25470ac6e0585a62

Index 1
Type A.7e60df042a9c0868.FlowToken.TokensDeposited
Tx ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Values
- amount (UFix64): 1.00000000
- to (Address?): 0x72aeca95731d54e5

Index 2
Type A.7e60df042a9c0868.FlowToken.TokensWithdrawn
Tx ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Values
- amount (UFix64): 0.00010000
- from (Address?): 0x25470ac6e0585a62

Index 3
Type A.7e60df042a9c0868.FlowToken.TokensDeposited
Tx ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Values
- amount (UFix64): 0.00010000
- to (Address?): 0x912d5440f7e3769e

Index 4
Type A.912d5440f7e3769e.FlowFees.TokensDeposited
Tx ID 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7
Values
- amount (UFix64): 0.00010000


Code (hidden, use --include code)

Payload (hidden, use --include payload)

广播后如果 Status 为 SEALED 则发送成功。