Skip to content

Instantly share code, notes, and snippets.

@richardkiss
Forked from darklow/pycoin_custom_sign.py
Last active March 4, 2020 19:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save richardkiss/0c7d3da47c94d1d662a3cebe0ce32bb8 to your computer and use it in GitHub Desktop.
Save richardkiss/0c7d3da47c94d1d662a3cebe0ce32bb8 to your computer and use it in GitHub Desktop.
pycoin_custom_sign.py
from pycoin.encoding.hexbytes import b2h
from pycoin.intbytes import int2byte
from pycoin.key import Key
from pycoin.networks.registry import network_for_netcode
from pycoin.satoshi.der import sigencode_der
network = network_for_netcode('XTN')
Tx = network.tx
TxIn = network.tx.TxIn
TxOut = network.tx.TxOut
def print_debug(key, s):
print(f'{key: <22} {s}')
key = network.keys.private(1)
hash160_c = key.hash160(is_compressed=True)
# address = network.address.for_p2pkh(hash160_c)
# p2sh_script = network.contract.for_p2pkh_wit(hash160_c)
p2sh_script = network.contract.for_p2pkh(hash160_c)
p2s_address = network.address.for_p2s(p2sh_script)
p2sh_script_hex = b2h(p2sh_script)
print_debug('p2s_address', p2s_address)
print_debug('p2sh_script_hex', b2h(p2sh_script))
# prepare tx
# this was created with `tx -n XTN --coinbase 2NByiBUaEXrhmqAsg7BbLpcQSAQs1EDwt5w`
SOURCE_TX_HEX = (
"01000000010000000000000000000000000000000000000000000000000000000000000000"
"ffffffff1466616b652d7079636f696e2d636f696e62617365ffffffff0100f2052a010000"
"0017a914cd7b44d0b03f2d026d1e586d7ae18903b0d385f68700000000"
)
source_tx = Tx.from_hex(SOURCE_TX_HEX)
tx_out_script = p2sh_script
tx_out = TxOut(100, tx_out_script)
tx_in = TxIn(source_tx.hash(), 0)
tx = Tx(1, [tx_in], [TxOut(100, tx_out_script)])
tx.set_unspents([source_tx.tx_outs_as_spendable()[0]])
print_debug('bad_solutions', tx.bad_solution_count())
# prepare sig hash
flags = network.validator.flags
sig_type = flags.SIGHASH_ALL
solution_checker = network.tx.SolutionChecker(tx)
unsigned_txs_out_idx = 0
sig_hash = solution_checker._signature_hash(tx_out_script, unsigned_txs_out_idx, sig_type)
print_debug('sig_hash', sig_hash)
print_debug('sig_hash hex', '{:x}'.format(sig_hash))
# sign elsewhere (extracted by debug based on network.keys.private(1))
# you can view the r and s values with `tx SIGNED-TX-HEX -s`
r = 0xc9794be4c51d2b5ca82510e456e321c1f403d7c10109c3944d76e4b574246a1b
s = 0x5f920a39a8f32595606071539130da5e5186fdd66575247411886193625eefc9
sig_der = sigencode_der(r, s) + int2byte(sig_type)
sig_der_hex = b2h(sig_der)
print_debug('signature der', sig_der_hex)
p2sh_lookup = network.tx.solve.build_p2sh_lookup([tx_out_script])
# this works now
sec_hints = network.tx.solve.build_sec_lookup([key.sec()])
network.tx_utils.sign_tx(tx, p2sh_lookup=p2sh_lookup, sec_hints=sec_hints, signature_hints=[sig_der])
print_debug('bad_solutions', tx.bad_solution_count())
# also works with WIF signing
# network.tx_utils.sign_tx(tx, [key.wif()])
# print_debug('bad_solutions', tx.bad_solution_count())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment