diff --git a/cmd.py b/cmd.py index 5c71ca8..bca3257 100755 --- a/cmd.py +++ b/cmd.py @@ -6,7 +6,7 @@ import json import base64 from trezorlib.client import TrezorClientDebug -from trezorlib.api_blockchain import BlockchainApi +from trezorlib.tx_api import TXAPIBlockchain from trezorlib.protobuf_json import pb2json def parse_args(commands): @@ -324,7 +324,7 @@ def main(): transport = get_transport(args.transport, args.path) client = TrezorClientDebug(transport) - client.set_tx_func(BlockchainApi().get_tx) + client.set_tx_api(TXAPIBlockchain()) cmds = Commands(client) res = args.func(cmds, args) diff --git a/tests/common.py b/tests/common.py index 8e51125..6694268 100644 --- a/tests/common.py +++ b/tests/common.py @@ -2,7 +2,7 @@ import unittest import config from trezorlib.client import TrezorDebugClient -from trezorlib.api_blockchain import BlockchainApi +from trezorlib.tx_api import TXAPIBlockchain class TrezorTest(unittest.TestCase): def setUp(self): @@ -10,7 +10,7 @@ class TrezorTest(unittest.TestCase): self.transport = config.TRANSPORT(*config.TRANSPORT_ARGS, **config.TRANSPORT_KWARGS) self.client = TrezorDebugClient(self.transport) self.client.set_debuglink(self.debug_transport) - self.client.set_tx_func(BlockchainApi().get_tx) + self.client.set_tx_api(TXAPIBlockchain()) # 1 2 3 4 5 6 7 8 9 10 11 12 self.mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' diff --git a/tests/test_msg_simplesigntx.py b/tests/test_msg_simplesigntx.py index 8bc4871..5f90a7e 100644 --- a/tests/test_msg_simplesigntx.py +++ b/tests/test_msg_simplesigntx.py @@ -8,35 +8,7 @@ import binascii import trezorlib.messages_pb2 as proto import trezorlib.types_pb2 as proto_types from trezorlib.client import CallException - -class FakeTestnetBlockchain(object): - def get_tx(self, txhash): - if txhash != '6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54': - raise Exception("Unexpected hash") - - t = proto_types.TransactionType() - - i = t.inputs.add() - i.prev_hash = binascii.unhexlify('ee336e79153d51f4f3e45278f1f77ab29fd5bb135dce467282e2aff22cb9c570') - i.prev_index = 1 - i.script_sig = binascii.unhexlify('483045022066c418874dbe5628296700382d727ce1734928796068c26271472df09dccf1a20221009dec59d19f9d73db381fcd35c0fff757ad73e54ef59157b0d7c57e6739a092f00121033fef08c603943dc7d25f4ce65771762143b1cd8678343d660a1a76b9d1d3ced7') - - i = t.inputs.add() - i.prev_hash = binascii.unhexlify('2fe4d8af2b44faccc10dd5a6578c923491d2d21269a1dfe8c83f492a30fb8f9f') - i.prev_index = 1 - i.script_sig = binascii.unhexlify('47304402206fbb8e14be706b8557a2280d2a2a75c0a65c4f7936d90d510f0971c93f41f74402201b79c8c4e4ac4c944913611633c230193558296e70a36269b7fc3a80efa27d120121030cb5be79bdc36a4ff4443dbac43068cc43d638ea06ff2fa1b8dab389e39aefc7') - - o = t.outputs.add() - o.amount = 403850989 - o.script_pubkey = binascii.unhexlify('76a914f5a05c2664b40d3116b1c5086c9ba38ed15b742e88ac') - - o = t.outputs.add() - o.amount = 1000000000 - o.script_pubkey = binascii.unhexlify('76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac') - - t.version = 1 - t.lock_time = 0 - return t +from trezorlib.tx_api import TXAPITestnetFake class TestMsgSimplesigntx(common.TrezorTest): @@ -89,7 +61,7 @@ class TestMsgSimplesigntx(common.TrezorTest): ) with self.client: - self.client.set_tx_func(FakeTestnetBlockchain().get_tx) + self.client.set_tx_api(TXAPITestnetFake()) msg = self.client._prepare_simple_sign_tx('Testnet', [inp1, ], [out1, out2]) self.client.set_expected_responses([proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), # proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), # don't confirm change @@ -121,7 +93,7 @@ class TestMsgSimplesigntx(common.TrezorTest): ) with self.client: - self.client.set_tx_func(FakeTestnetBlockchain().get_tx) + self.client.set_tx_api(TXAPITestnetFake()) msg = self.client._prepare_simple_sign_tx('Testnet', [inp1, ], [out1, out2]) self.client.set_expected_responses([proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), # proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), # don't confirm change diff --git a/trezorlib/api_blockchain.py b/trezorlib/api_blockchain.py deleted file mode 100644 index 8c65c8c..0000000 --- a/trezorlib/api_blockchain.py +++ /dev/null @@ -1,53 +0,0 @@ -''' - Blockchain API implementing Blockchain.info interface -''' -import binascii -import urllib2 -import json -try: - from filecache import filecache, MONTH -except: - def filecache(x): - def _inner(y): - return y - return _inner - MONTH = None - -import types_pb2 as proto_types - -class BlockchainApi(object): - def _raw_tx(self, txhash): - # Download tx data from blockchain.info - url = 'http://blockchain.info/rawtx/%s?scripts=true' % txhash - print "Downloading", url - f = urllib2.urlopen(url) - return json.load(f) - - def submit(self, tx): - raise Exception("Not implemented yet") - - @filecache(MONTH) - def get_tx(self, txhash): - # Build protobuf transaction structure from blockchain.info - d = self._raw_tx(txhash) - t = proto_types.TransactionType() - - for inp in d['inputs']: - di = self._raw_tx(inp['prev_out']['tx_index']) - i = t.inputs.add() - i.prev_hash = binascii.unhexlify(di['hash']) - i.prev_index = inp['prev_out']['n'] - i.script_sig = binascii.unhexlify(inp['script']) - - for output in d['out']: - o = t.outputs.add() - o.amount = output['value'] - o.script_pubkey = binascii.unhexlify(output['script']) - - t.version = 1 - t.lock_time = 0 - return t - -if __name__ == '__main__': - api = BlockchainApi() - print api.get_tx('b9f382b8dfc34accc05491712a1ad8f7f075a02056dc4821d1f60702fb3fdb2f') diff --git a/trezorlib/client.py b/trezorlib/client.py index 8dccbb3..50a08b9 100644 --- a/trezorlib/client.py +++ b/trezorlib/client.py @@ -286,13 +286,10 @@ class ProtocolMixin(object): def __init__(self, *args, **kwargs): super(ProtocolMixin, self).__init__(*args, **kwargs) self.init_device() - - def get_tx_func_placeholder(txhash): - raise Exception("Please call set_tx_func() first.") - self.get_tx_func = get_tx_func_placeholder + self.tx_api = None - def set_tx_func(self, tx_func): - self.get_tx_func = tx_func + def set_tx_api(self, tx_api): + self.tx_api = tx_api def init_device(self): self.features = expect(proto.Features)(self.call)(proto.Initialize()) @@ -430,7 +427,7 @@ class ProtocolMixin(object): continue tx = msg.transactions.add() - tx.CopyFrom(self.get_tx_func(binascii.hexlify(inp.prev_hash))) + tx.CopyFrom(self.tx_api.get_tx(binascii.hexlify(inp.prev_hash))) known_hashes.append(inp.prev_hash) return msg diff --git a/trezorlib/tx_api.py b/trezorlib/tx_api.py new file mode 100644 index 0000000..f89ff8e --- /dev/null +++ b/trezorlib/tx_api.py @@ -0,0 +1,76 @@ +import binascii +import urllib2 +import json +try: + from filecache import filecache, MONTH +except: + def filecache(x): + def _inner(y): + return y + return _inner + MONTH = None + +import types_pb2 as proto_types + +class TXAPIBlockchain(object): + def _raw_tx(self, txhash): + # Download tx data from blockchain.info + url = 'http://blockchain.info/rawtx/%s?scripts=true' % txhash + print "Downloading", url + f = urllib2.urlopen(url) + return json.load(f) + + @filecache(MONTH) + def get_tx(self, txhash): + # Build protobuf transaction structure from blockchain.info + d = self._raw_tx(txhash) + t = proto_types.TransactionType() + + for inp in d['inputs']: + di = self._raw_tx(inp['prev_out']['tx_index']) + i = t.inputs.add() + i.prev_hash = binascii.unhexlify(di['hash']) + i.prev_index = inp['prev_out']['n'] + i.script_sig = binascii.unhexlify(inp['script']) + + for output in d['out']: + o = t.outputs.add() + o.amount = output['value'] + o.script_pubkey = binascii.unhexlify(output['script']) + + t.version = 1 + t.lock_time = 0 + return t + +class TXAPITestnetFake(object): + def get_tx(self, txhash): + if txhash != '6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54': + raise Exception("Unexpected hash") + + t = proto_types.TransactionType() + + i = t.inputs.add() + i.prev_hash = binascii.unhexlify('ee336e79153d51f4f3e45278f1f77ab29fd5bb135dce467282e2aff22cb9c570') + i.prev_index = 1 + i.script_sig = binascii.unhexlify('483045022066c418874dbe5628296700382d727ce1734928796068c26271472df09dccf1a20221009dec59d19f9d73db381fcd35c0fff757ad73e54ef59157b0d7c57e6739a092f00121033fef08c603943dc7d25f4ce65771762143b1cd8678343d660a1a76b9d1d3ced7') + + i = t.inputs.add() + i.prev_hash = binascii.unhexlify('2fe4d8af2b44faccc10dd5a6578c923491d2d21269a1dfe8c83f492a30fb8f9f') + i.prev_index = 1 + i.script_sig = binascii.unhexlify('47304402206fbb8e14be706b8557a2280d2a2a75c0a65c4f7936d90d510f0971c93f41f74402201b79c8c4e4ac4c944913611633c230193558296e70a36269b7fc3a80efa27d120121030cb5be79bdc36a4ff4443dbac43068cc43d638ea06ff2fa1b8dab389e39aefc7') + + o = t.outputs.add() + o.amount = 403850989 + o.script_pubkey = binascii.unhexlify('76a914f5a05c2664b40d3116b1c5086c9ba38ed15b742e88ac') + + o = t.outputs.add() + o.amount = 1000000000 + o.script_pubkey = binascii.unhexlify('76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac') + + t.version = 1 + t.lock_time = 0 + return t + +if __name__ == '__main__': + api = TXAPIBlockchain() + print api.get_tx('b9f382b8dfc34accc05491712a1ad8f7f075a02056dc4821d1f60702fb3fdb2f')