Skip to content
Permalink
Browse files

finish unittests

  • Loading branch information
justinmoon committed Jul 25, 2019
1 parent f6dd84e commit b614f1c44cbf2b732b4ea591036c5c345fc75fcd
Showing with 65 additions and 63 deletions.
  1. +23 −45 bitboy/sign.py
  2. +3 −6 cli.py
  3. +39 −12 tests/test_signing.py
@@ -1,37 +1,31 @@
import json

from io import BytesIO

from binascii import hexlify, unhexlify

from m5stack import LCD, fonts
from m5stack.pins import BUTTON_A_PIN, BUTTON_B_PIN, BUTTON_C_PIN # FIXME

from bitcoin.helper import encode_varint
from bitcoin.helper import encode_varstr
from bitcoin.tx import Tx
from bitcoin.script import Script
from bitcoin.ecc import PrivateKey

from m5stack import LCD, fonts

lcd = LCD()
lcd.set_font(fonts.tt24)
lcd.erase()


def script_from_hex(script_hex):
script_bytes = unhexlify(script_hex)
script_encoded = encode_varint(len(script_bytes)) + script_bytes
script = Script.parse(BytesIO(script_encoded))
return script

if script_hex is not None:
return Script.parse(BytesIO(unhexlify(script_hex)))

def handle_msg(msg):
if msg["command"] == "sign":
# parse transaction
tx = Tx.parse(BytesIO(unhexlify(msg['payload']['tx'])), testnet=True)
script_pubkeys = [script_from_hex(hx) for hx in msg['payload']['script_pubkeys']]
redeem_scripts = [script_from_hex(hx) for hx in msg['payload']['redeem_scripts']]
witness_scripts = [script_from_hex(hx) for hx in msg['payload']['witness_scripts']]
input_values = msg['payload']['input_values']
signed = sign(tx, script_pubkeys, input_values)
signed = sign(tx, script_pubkeys, redeem_scripts, witness_scripts, input_values)
res = {
"signed": signed,
}
@@ -40,7 +34,6 @@ def handle_msg(msg):
else:
print("not signing")


def reader():
while True:
data = input()
@@ -53,40 +46,25 @@ def reader():
continue
handle_msg(msg)


def sign(tx, script_pubkeys, input_values):
def sign(tx, script_pubkeys, redeem_scripts, witness_scripts, input_values):
"""only supports 1 input from hard-coded private key for now"""
print("signing")
# hard-coded secret
# old
# secret = 58800187338825965989061197411175755305019286370732616970021105328088303800804
# jimmy's
# secret = 8675309
secret = 58800187338825965989061197411175755305019286370732616970021105328088303800803
key = PrivateKey(secret)

# tx.segwit = True

for i, tx_in in enumerate(tx.tx_ins):
script_pubkey = script_pubkeys[i]
print("signing {} w/ pubkey {}".format(tx_in, script_pubkey))
if script_pubkeys[i].is_p2sh_script_pubkey():
sec = key.public_key.sec(compressed=True)
redeem_script = Script(cmds=[sec, 172])
input_value = None
elif script_pubkeys[i].is_p2wpkh_script_pubkey():
redeem_script = None
input_value = input_values[i]
private_key = PrivateKey(secret)
items = zip(range(len(tx.tx_ins)), tx.tx_ins, script_pubkeys, redeem_scripts, witness_scripts, input_values)
for input_index, tx_in, script_pubkey, redeem_script, witness_script, input_value in items:
if script_pubkey.is_p2pkh_script_pubkey():
tx.sign_input_p2pkh(input_index, private_key, script_pubkey)
elif script_pubkey.is_p2sh_script_pubkey():
tx.sign_input_p2sh(input_index, private_key, redeem_script)
elif script_pubkey.is_p2wpkh_script_pubkey():
assert input_value is not None, "input value needed for segwit signature"
tx.sign_input_p2wpkh(input_index, input_value, private_key, script_pubkey)
elif script_pubkey.is_p2wsh_script_pubkey():
assert input_value is not None, "input value needed for segwit signature"
assert witness_script is not None, "witness script required to sign p2wsh input"
tx.sign_input_p2wsh(input_index, input_value, private_key, witness_script)
else:
redeem_script = None
input_value = None
tx.sign_input(i, key, script_pubkey=script_pubkey, redeem_script=redeem_script,
input_value=input_value)
print("script_sig", tx_in.script_sig)
print("witness", tx_in.witness)

# return signed transaction in hexidecimal
raise ValueError('unknown input type')
return hexlify(tx.serialize())


reader()
9 cli.py
@@ -16,14 +16,16 @@
ser = Serial(find_port(), baudrate=115200)


def sign(tx, script_pubkeys, input_values):
def sign(tx, script_pubkeys, redeem_scripts, witness_scripts, input_values):
# request signature over serial port
command = "sign"
msg = {
"command": command,
"payload": {
"tx": tx,
"script_pubkeys": script_pubkeys,
"redeem_scripts": redeem_scripts,
"witness_scripts": witness_scripts,
"input_values": input_values,
}
}
@@ -62,9 +64,7 @@ def handle_send(args):
})
value = tx['vout'][tx_index]['value']
input_sum += value
print(value)
input_values.append(int(value * 100_000_000))
print(input_values)
script_pubkeys.append(tx['vout'][tx_index]['scriptPubKey']['hex'])
if input_sum > args.amount:
break
@@ -89,7 +89,6 @@ def handle_send(args):
# broadcast
sent = testnet.sendrawtransaction(signed)


def parse():
parser = argparse.ArgumentParser(description='BitBoy Bitcoin Wallet')
subparsers = parser.add_subparsers(help='sub-command help')
@@ -102,8 +101,6 @@ def parse():

return parser.parse_args()


if __name__ == '__main__':
args = parse()
args.func(args)

@@ -1,42 +1,50 @@
import logging
import pytest

from decimal import Decimal
from io import BytesIO

from bedrock.tx import Tx, TxIn, TxOut
from bedrock.ecc import PrivateKey
from bedrock.helper import decode_base58, little_endian_to_int, hash256, decode_bech32
from bedrock.script import p2pkh_script, p2sh_script, p2wpkh_script, Script
from bedrock.helper import decode_base58, little_endian_to_int, hash256, decode_bech32, sha256
from bedrock.script import Script, p2pkh_script, p2sh_script, p2wpkh_script, p2wsh_script

from cli import sign

# change log level to logging.DEBUG for more information
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)

secret = 58800187338825965989061197411175755305019286370732616970021105328088303800803
key = PrivateKey(secret)

def p2pk_script():
sec = key.point.sec(compressed=True)
return Script(cmds=[sec, 172])

def test_sign_p2pkh():
raw_tx = '0100000001aab6e859ca31f1e6a954323c5ca0d0ec02244016e1d45df502989ff3eadb92690000000000ffffffff014c400f00000000001976a914f34a4401e484bfb7862d0e3ecfbed4c484f5480a88ac00000000'
script_pubkey = p2pkh_script(key.point.hash160())
print(script_pubkey.is_p2pkh_script_pubkey())
raw_script_pubkey = script_pubkey.raw_serialize().hex()
raw_script_pubkey = script_pubkey.serialize().hex()
script_pubkeys = [raw_script_pubkey]
input_values = []
result = sign(raw_tx, script_pubkeys, input_values)
redeem_scripts = [None]
input_values = [None]
witness_scripts = [None]
result = sign(raw_tx, script_pubkeys, redeem_scripts, witness_scripts, input_values)
signed_tx = Tx.parse(BytesIO(bytes.fromhex(result)), testnet=True)
print(f"Received Signed TX: {result}")
assert signed_tx.verify()


def test_spend_p2sh():
raw_tx = "01000000014b1ed28bb000739dee2c58b5e3b18e0dfdf929c6917c212da20ab3d7231960f20000000000ffffffff01b8820100000000001976a914507b27411ccf7f16f10297de6cef3f291623eddf88ac00000000"
input_values = [] # FIXME: don't need this for p2sh or p2pkh ...
input_values = [None] # FIXME: don't need this for p2sh or p2pkh ...
script_pubkey = p2sh_script(key.point.hash160())
raw_script_pubkey = script_pubkey.raw_serialize().hex()
raw_script_pubkey = script_pubkey.serialize().hex() # FIXME: merge with line below
script_pubkeys = [raw_script_pubkey]
result = sign(raw_tx, script_pubkeys, input_values)
redeem_scripts = [p2pk_script().serialize().hex()]
witness_scripts = [None]
result = sign(raw_tx, script_pubkeys, redeem_scripts, witness_scripts, input_values)
signed_tx = Tx.parse(BytesIO(bytes.fromhex(result)), testnet=True)
print(f"Received Signed TX: {result}")
assert signed_tx.verify()
@@ -45,9 +53,11 @@ def test_spend_p2wpkh():
raw_tx = '01000000000101ebd12d3bd14fb3d7488b2deb74949b8180bb3138130b22274550e47c691e23630100000000ffffffff01ac8401000000000017a914d2d78617c37107637e76c1b20ffdbc8b58df4e84870000000000'
input_values = [100000]
script_pubkey = p2wpkh_script(key.point.hash160())
raw_script_pubkey = script_pubkey.raw_serialize().hex()
raw_script_pubkey = script_pubkey.serialize().hex()
script_pubkeys = [raw_script_pubkey]
result = sign(raw_tx, script_pubkeys, input_values)
redeem_scripts = [None]
witness_scripts = [None]
result = sign(raw_tx, script_pubkeys, redeem_scripts, witness_scripts, input_values)
signed_tx = Tx.parse(BytesIO(bytes.fromhex(result)), testnet=True)
print(f"Received Signed TX: {result}")
assert signed_tx.verify()
@@ -60,4 +70,21 @@ def test_spent_p2sh_p2wsh():
pass

def test_spend_p2wsh():
pass
raw_tx = '01000000000101be6eb198e588d33a1d25a396c057c48c7828d010f6c8633930660ecde447d7ab0000000000ffffffff01ac8401000000000017a914096e78e80cef3d484e123051011e4362b326fe71870000000000'

input_values = [100000]

witness_script = p2pk_script()
witness_scripts = [witness_script.serialize().hex()]

script_pubkey = p2wsh_script(sha256(witness_script.raw_serialize()))
assert not script_pubkey.is_p2wpkh_script_pubkey()
script_pubkeys = [script_pubkey.serialize().hex()]

redeem_scripts = [None]

result = sign(raw_tx, script_pubkeys, redeem_scripts, witness_scripts, input_values)
signed_tx = Tx.parse(BytesIO(bytes.fromhex(result)), testnet=True)
print(f"Received Signed TX: {result}")
assert signed_tx.verify()

0 comments on commit b614f1c

Please sign in to comment.
You can’t perform that action at this time.