-
Notifications
You must be signed in to change notification settings - Fork 116
/
Copy pathmulti_input_sighash_transaction.py
131 lines (111 loc) · 3.74 KB
/
multi_input_sighash_transaction.py
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
# Copyright (C) 2018-2024 The python-bitcoin-utils developers
#
# This file is part of python-bitcoin-utils
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoin-utils, including this file, may be copied,
# modified, propagated, or distributed except according to the terms contained
# in the LICENSE file.
from bitcoinutils.setup import setup
from bitcoinutils.utils import to_satoshis
from bitcoinutils.transactions import Transaction, TxInput, TxOutput
from bitcoinutils.keys import P2pkhAddress, PrivateKey
from bitcoinutils.script import Script
from bitcoinutils.constants import SIGHASH_ALL, SIGHASH_SINGLE, SIGHASH_ANYONECANPAY
def main():
# always remember to setup the network
setup("testnet")
# create transaction input from tx id of UTXO (contained 0.39 tBTC)
# 0.1 tBTC
txin = TxInput(
"76464c2b9e2af4d63ef38a77964b3b77e629dddefc5cb9eb1a3645b1608b790f", 0
)
# 0.29 tBTC
txin2 = TxInput(
"76464c2b9e2af4d63ef38a77964b3b77e629dddefc5cb9eb1a3645b1608b790f", 1
)
# create transaction output using P2PKH scriptPubKey (locking script)
addr = P2pkhAddress("myPAE9HwPeKHh8FjKwBNBaHnemApo3dw6e")
txout = TxOutput(
to_satoshis(0.3),
Script(
["OP_DUP", "OP_HASH160", addr.to_hash160(), "OP_EQUALVERIFY", "OP_CHECKSIG"]
),
)
# create another output to get the change - remaining 0.01 is tx fees
change_addr = P2pkhAddress("mmYNBho9BWQB2dSniP1NJvnPoj5EVWw89w")
change_txout = TxOutput(
to_satoshis(0.08),
Script(
[
"OP_DUP",
"OP_HASH160",
change_addr.to_hash160(),
"OP_EQUALVERIFY",
"OP_CHECKSIG",
]
),
)
# create transaction from inputs/outputs -- default locktime is used
tx = Transaction([txin, txin2], [txout, change_txout])
# print raw transaction
print("\nRaw unsigned transaction:\n" + tx.serialize())
#
# use the private keys corresponding to the addresses that contains the
# UTXOs we are trying to spend to create the signatures
#
sk = PrivateKey("cTALNpTpRbbxTCJ2A5Vq88UxT44w1PE2cYqiB3n4hRvzyCev1Wwo")
sk2 = PrivateKey("cVf3kGh6552jU2rLaKwXTKq5APHPoZqCP4GQzQirWGHFoHQ9rEVt")
# we could have derived the addresses from the secret keys
from_addr = P2pkhAddress("n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR")
from_addr2 = P2pkhAddress("mmYNBho9BWQB2dSniP1NJvnPoj5EVWw89w")
# sign the first input
sig = sk.sign_input(
tx,
0,
Script(
[
"OP_DUP",
"OP_HASH160",
from_addr.to_hash160(),
"OP_EQUALVERIFY",
"OP_CHECKSIG",
]
),
SIGHASH_ALL | SIGHASH_ANYONECANPAY,
)
# print(sig)
# sign the second input
sig2 = sk2.sign_input(
tx,
1,
Script(
[
"OP_DUP",
"OP_HASH160",
from_addr2.to_hash160(),
"OP_EQUALVERIFY",
"OP_CHECKSIG",
]
),
SIGHASH_SINGLE | SIGHASH_ANYONECANPAY,
)
# print(sig2)
# get public key as hex
pk = sk.get_public_key()
pk = pk.to_hex()
# print (pk)
# get public key as hex
pk2 = sk2.get_public_key()
pk2 = pk2.to_hex()
# set the scriptSig (unlocking script)
txin.script_sig = Script([sig, pk])
txin2.script_sig = Script([sig2, pk2])
signed_tx = tx.serialize()
# print raw signed transaction ready to be broadcasted
print("\nRaw signed transaction:\n" + signed_tx)
print("\nTxId:", tx.get_txid())
if __name__ == "__main__":
main()