0%

构建复杂交易

本文在之前的基础上构建复杂交易。

先对”复杂”进行定义

复杂指的是 我们使用两个交易输入,输出到两个地址上。且设定两个输入交易是输入不同的人的(输入属于不同的私钥)。

按照惯例列出主干过程

  1. 构建多输入,多输出的裸交易
  2. 依次进行签名
  3. 广播

因为之前的文章演示已经非常详细,故本文不在做额外展示,另外许多测试过程也不再列出,具体过程如下

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// 复杂交易 所谓的复杂 定义为 2个输入 到两个输出符合官方例子中的情况

//1. 启动私链
bitcoind -printtoconsole -regtest

//2. 查询链信息
bitcoin-cli -regtest -getinfo

//3. 为了符合复杂交易状况 生成第一个输入地址 2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe
bitcoin-cli -regtest getnewaddress

//4. 导出搞地址私钥 备用 cQ9CcvcJziXzpZkwN5JRAptqPJobyaX63JByrEYPN5noBiW4kwn1
bitcoin-cli -regtest dumpprivkey 2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe

//5. 给这个地址挖矿 nblocks = 101
bitcoin-cli -regtest generatetoaddress 101 2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe

//6. 获取当前账户下的信息 确认101个块 得到50个比特币
bitcoin-cli -regtest getbalance

//7. 准备第二个地址 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c
bitcoin-cli -regtest getnewaddress

//8. 导出私钥 cS6U3fHjJLb63WTVVRNEFw5DT2DPWefMGaUFwmBsRVm69vvub9iD
bitcoin-cli -regtest dumpprivkey 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c

//9. 挖矿 nblocks = 1
bitcoin-cli -regtest generatetoaddress 1 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c

//10. 再次查询账户信息
bitcoin-cli -regtest getbalance

//11. 生成两个地址作为输出 2N4EGkdkHKqhChzTG2bgM28xWcykZNkaUap
bitcoin-cli -regtest getnewaddress

//12. 继续 2MvgpC6bYH1GocTNTFwzNJtXX8t3FuN6gXF
bitcoin-cli -regtest getnewaddress

//13. 查询UTXO
bitcoin-cli -regtest listunspent

//14. 确认数目不太够 多挖几次
bitcoin-cli -regtest generatetoaddress 9 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c

bitcoin-cli -regtest generatetoaddress 3 2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe

bitcoin-cli -regtest generatetoaddress 100 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c

//15 挖了足够多的矿之后 (之所以挖这么多次,挖矿得100块个确认以后才可以用) 查询UTXO
bitcoin-cli -regtest listunspent

注意以下的结果不是全部 随机截取了一部分

{
"txid": "63e68a9f7a9d30022a402fe5594c5ab2adf4f6497ed10a248b58c39de0acbce6",
"vout": 0,
"address": "2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe",
"label": "",
"redeemScript": "00148812514082f6599305a1b5c23b9657f852d88099",
"scriptPubKey": "a9144d514986fc491a05730271047dfa5526aff5d29687",
"amount": 50.00000000,
"confirmations": 217,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/13']03f606bed5b7003c34c5098725d3654be8df600a78e0940cf3d833d112066663dd))#lwl54ngn",
"safe": true
},

{
"txid": "b1de08a9e8d803c5b34010773afb0cf607831dc36a7569192e5828f6959719eb",
"vout": 0,
"address": "2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c",
"label": "",
"redeemScript": "0014e1183a028e4141aae89a68bcd1482fb9c692bf60",
"scriptPubKey": "a914fba8b2c876c9e477be38d3f3c9fa81a8cca35bed87",
"amount": 50.00000000,
"confirmations": 116,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/14']02754e91c7f819cf0ffc1842ab00ec19cc5468229ad3a21c36906fa26836f0dfdc))#edq6mslq",
"safe": true
},
{
"txid": "7024e9a21a2b55a93de2fa0d6828ac64243212140ea37055026b8cfeb3133deb",
"vout": 0,
"address": "2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c",
"label": "",
"redeemScript": "0014e1183a028e4141aae89a68bcd1482fb9c692bf60",
"scriptPubKey": "a914fba8b2c876c9e477be38d3f3c9fa81a8cca35bed87",
"amount": 50.00000000,
"confirmations": 118,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/14']02754e91c7f819cf0ffc1842ab00ec19cc5468229ad3a21c36906fa26836f0dfdc))#edq6mslq",
"safe": true
},

{
"txid": "e7a5e1ea37512ec2609d18a9a4040e900e35656cbbf143bb352b42421d50c5f5",
"vout": 0,
"address": "2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe",
"label": "",
"redeemScript": "00148812514082f6599305a1b5c23b9657f852d88099",
"scriptPubKey": "a9144d514986fc491a05730271047dfa5526aff5d29687",
"amount": 50.00000000,
"confirmations": 201,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/13']03f606bed5b7003c34c5098725d3654be8df600a78e0940cf3d833d112066663dd))#lwl54ngn",
"safe": true
},
{
"txid": "d9be71cd09f9e9a47ef54b5b06db8c8c12aad28f0ef76f08b5a838d8a90a85fc",
"vout": 0,
"address": "2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c",
"label": "",
"redeemScript": "0014e1183a028e4141aae89a68bcd1482fb9c692bf60",
"scriptPubKey": "a914fba8b2c876c9e477be38d3f3c9fa81a8cca35bed87",
"amount": 50.00000000,
"confirmations": 120,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/14']02754e91c7f819cf0ffc1842ab00ec19cc5468229ad3a21c36906fa26836f0dfdc))#edq6mslq",
"safe": true
},
{
"txid": "2dd092c66f124e326cc41de4c2c63aa8a4cc3f2b09d68d5eb4f15eae195834fd",
"vout": 0,
"address": "2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe",
"label": "",
"redeemScript": "00148812514082f6599305a1b5c23b9657f852d88099",
"scriptPubKey": "a9144d514986fc491a05730271047dfa5526aff5d29687",
"amount": 50.00000000,
"confirmations": 224,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([bec83093/0'/0'/13']03f606bed5b7003c34c5098725d3654be8df600a78e0940cf3d833d112066663dd))#lwl54ngn",
"safe": true
}

从中间提取两组分属于不同地址的交易作为复杂交易的输入

第一组:
txid: 63e68a9f7a9d30022a402fe5594c5ab2adf4f6497ed10a248b58c39de0acbce6
vout: 0
address: 2MzJ3PzMX6Q2b1yXLpJsQuBP5MmUbsmpQWe
privkey: cQ9CcvcJziXzpZkwN5JRAptqPJobyaX63JByrEYPN5noBiW4kwn1


第二组:
txid: b1de08a9e8d803c5b34010773afb0cf607831dc36a7569192e5828f6959719eb
vout: 0
address: 2NGBsgoTEPFHF5qu83o91ZXu8JE9zT2HL9c
privkey: cS6U3fHjJLb63WTVVRNEFw5DT2DPWefMGaUFwmBsRVm69vvub9iD

目标地址
2N4EGkdkHKqhChzTG2bgM28xWcykZNkaUap

2MvgpC6bYH1GocTNTFwzNJtXX8t3FuN6gXF

16. 在这个基础上创建裸交易 给两个地址分别发送49.9个比特币

bitcoin-cli -regtest createrawtransaction '''
[
{
"txid": "63e68a9f7a9d30022a402fe5594c5ab2adf4f6497ed10a248b58c39de0acbce6",
"vout": 0
},
{
"txid": "b1de08a9e8d803c5b34010773afb0cf607831dc36a7569192e5828f6959719eb",
"vout": 0
}
]
''' '''
{
"2N4EGkdkHKqhChzTG2bgM28xWcykZNkaUap": 49.9,
"2MvgpC6bYH1GocTNTFwzNJtXX8t3FuN6gXF": 49.9
}'''

结果
0200000002e6bcace09dc3588b240ad17e49f6f4adb25a4c59e52f402a02309d7a9f8ae6630000000000ffffffffeb199795f628582e1969756ac31d8307f60cfb3a771040b3c503d8e8a908deb10000000000ffffffff02805b6d290100000017a914787b46861a008ef11cf4168db5e2c787afa0b25e87805b6d290100000017a91425bf54042e8fdc3f50d00ada9fdae02fe4313c918700000000

17. 现在一次进行签名 这里使用私钥进行签名
bitcoin-cli -regtest signrawtransactionwithkey "0200000002e6bcace09dc3588b240ad17e49f6f4adb25a4c59e52f402a02309d7a9f8ae6630000000000ffffffffeb199795f628582e1969756ac31d8307f60cfb3a771040b3c503d8e8a908deb10000000000ffffffff02805b6d290100000017a914787b46861a008ef11cf4168db5e2c787afa0b25e87805b6d290100000017a91425bf54042e8fdc3f50d00ada9fdae02fe4313c918700000000" "[\"cQ9CcvcJziXzpZkwN5JRAptqPJobyaX63JByrEYPN5noBiW4kwn1\"]"

{
"hex": "02000000000102e6bcace09dc3588b240ad17e49f6f4adb25a4c59e52f402a02309d7a9f8ae66300000000171600148812514082f6599305a1b5c23b9657f852d88099ffffffffeb199795f628582e1969756ac31d8307f60cfb3a771040b3c503d8e8a908deb10000000000ffffffff02805b6d290100000017a914787b46861a008ef11cf4168db5e2c787afa0b25e87805b6d290100000017a91425bf54042e8fdc3f50d00ada9fdae02fe4313c91870247304402200323249f760bfe0683673b1af15c893bb695ae154f961c1eb133eacaed89c604022006ec0658177cf101264cd50b23f34a945ecd5359c0f15039962d8ec859a5c497012103f606bed5b7003c34c5098725d3654be8df600a78e0940cf3d833d112066663dd0000000000",
"complete": false,
"errors": [
{
"txid": "b1de08a9e8d803c5b34010773afb0cf607831dc36a7569192e5828f6959719eb",
"vout": 0,
"witness": [
],
"scriptSig": "",
"sequence": 4294967295,
"error": "Unable to sign input, invalid stack size (possibly missing key)"
}
]
}

18. 进行第二次签名 注意这次需要上次签名之后的hex 也就是说需要签名之后再签 签名是逐渐变长的

{
"hex": "02000000000102e6bcace09dc3588b240ad17e49f6f4adb25a4c59e52f402a02309d7a9f8ae66300000000171600148812514082f6599305a1b5c23b9657f852d88099ffffffffeb199795f628582e1969756ac31d8307f60cfb3a771040b3c503d8e8a908deb10000000017160014e1183a028e4141aae89a68bcd1482fb9c692bf60ffffffff02805b6d290100000017a914787b46861a008ef11cf4168db5e2c787afa0b25e87805b6d290100000017a91425bf54042e8fdc3f50d00ada9fdae02fe4313c91870247304402200323249f760bfe0683673b1af15c893bb695ae154f961c1eb133eacaed89c604022006ec0658177cf101264cd50b23f34a945ecd5359c0f15039962d8ec859a5c497012103f606bed5b7003c34c5098725d3654be8df600a78e0940cf3d833d112066663dd02473044022070bf83bb965f10cdd949f696b4268bdaac9a4349250ec9acba28d8e113e5152702204eef794121db0701aeafbe13e0f6cc0db270ed6840b8155071af46b8f644f886012102754e91c7f819cf0ffc1842ab00ec19cc5468229ad3a21c36906fa26836f0dfdc00000000",
"complete": true
}

19. 广播即可 不再展示

按照以上过程即可完成。

这个过程的重点是依次签名,第一次签名之后,在第一次签名的基础上再次签名。签上加签。以此类推,如果需要 n 个输入就连续进行 n 次签名。

还有需要注意的点

  1. 因为是两个输入分别属于不同的人(不同的秘钥),所以我们使用 signrawtransactionwithkey 方法,而不是之前例子中使用钱包的签名方法。
  2. 这个过程中也使用了 createrawtransaction ,未设定找零地址,所以输入和输出的差值还是会作为交易费用贡献给矿工,请谨慎操作
  3. 如果要使用带有找零的交易,参考上一篇文章需要使用 fundrawtrastion 指定找零地址和计算交易费,如在本文的流程中,可以在步骤16之后使用 fundrawtrastion 指定找零地址。然后再签名。
  4. 直接操作私钥是一种非常危险的行为,请参考者清楚自己在做什么,以免造成不必要的损失

最后再留一个引子,假如第19步不进行广播,我们可以在第19步的基础上进行离线签名。换句话说,这个交易不进行广播,那他就不存在交易节点上或者内存池中,是一个不可信交易(unconfirmed transactions)。关于离线签名( Offline Signing)是什么,有什么作用,如何使用会在后续的文章中列出。