rework txapi class to use local cache, add txcache fixtures

pull/25/head
Pavol Rusnak 8 years ago
parent 2257117278
commit 046ced3f81
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

@ -2,7 +2,7 @@ from __future__ import print_function
import unittest
from trezorlib.client import TrezorDebugClient
from trezorlib.tx_api import TXAPIBitcoin
from trezorlib.tx_api import TxApiBitcoin
import config
class TrezorTest(unittest.TestCase):
@ -11,7 +11,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_api(TXAPIBitcoin())
self.client.set_tx_api(TxApiBitcoin)
# self.client.set_buttonwait(3)
# 1 2 3 4 5 6 7 8 9 10 11 12

@ -5,7 +5,7 @@ import binascii
import trezorlib.messages_pb2 as proto
import trezorlib.types_pb2 as proto_types
from trezorlib.client import CallException
from trezorlib.tx_api import TXAPITestnet
from trezorlib.tx_api import TxApiTestnet
class TestMsgSigntx(common.TrezorTest):
def test_one_one_fee(self):
@ -68,7 +68,7 @@ class TestMsgSigntx(common.TrezorTest):
)
with self.client:
self.client.set_tx_api(TXAPITestnet())
self.client.set_tx_api(TxApiTestnet)
self.client.set_expected_responses([
proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify(b"6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))),
@ -113,7 +113,7 @@ class TestMsgSigntx(common.TrezorTest):
)
with self.client:
self.client.set_tx_api(TXAPITestnet())
self.client.set_tx_api(TxApiTestnet)
self.client.set_expected_responses([
proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify(b"6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))),
@ -574,7 +574,7 @@ class TestMsgSigntx(common.TrezorTest):
)
with self.client:
self.client.set_tx_api(TXAPITestnet())
self.client.set_tx_api(TxApiTestnet)
self.client.set_expected_responses([
proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify(b"d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236"))),

@ -5,7 +5,7 @@ import binascii
import trezorlib.messages_pb2 as proto
import trezorlib.types_pb2 as proto_types
from trezorlib.client import CallException
from trezorlib.tx_api import TXAPIZcashTestnet
from trezorlib.tx_api import TxApiZcashTestnet
class TestMsgSigntx(common.TrezorTest):
@ -27,7 +27,7 @@ class TestMsgSigntx(common.TrezorTest):
)
with self.client:
self.client.set_tx_api(TXAPIZcashTestnet())
self.client.set_tx_api(TxApiZcashTestnet)
self.client.set_expected_responses([
proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify(b"93373e63cc626c4a7d049ad775d6511bb5eba985f142db660c9b9f955c722f5c"))),

@ -6,7 +6,6 @@ import itertools
import trezorlib.messages_pb2 as proto
import trezorlib.types_pb2 as proto_types
from trezorlib.client import CallException
from trezorlib.tx_api import TXAPITestnet
class TestOpReturn(common.TrezorTest):

@ -0,0 +1 @@
{"valueOut": 3.00986058, "vout": [{"spentIndex": 30, "spentHeight": 288729, "value": "2.98446058", "n": 0, "spentTxId": "6839c71b7d192a698b5388e9ea921805279cbc9f85bae1019d2f4fe7b326979a", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a9149ef561f8f6fe602cba796137f2d56d7e8a0a4c8488ac", "addresses": ["1FVVioK1iE9X6cBZtarVj6e5vjMATc8izW"], "asm": "OP_DUP OP_HASH160 9ef561f8f6fe602cba796137f2d56d7e8a0a4c84 OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": 1, "spentHeight": 284875, "value": "0.02540000", "n": 1, "spentTxId": "4a7b7e0403ae5607e473949cfa03f09f2cd8b0f404bf99ce10b7303d86280bf7", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a914812c13d97f9159e54e326b481b8f88a73df8507a88ac", "addresses": ["1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5"], "asm": "OP_DUP OP_HASH160 812c13d97f9159e54e326b481b8f88a73df8507a OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "00000000000000016732dadfc971c98b308d46283f0340c0ad9479fc65a28550", "valueIn": 3.00996058, "fees": 0.0001, "vin": [{"addr": "1M2Qq4P8bjXrbvEYicwWNeQ3TkikCiMKdz", "vout": 79, "sequence": 4294967295, "doubleSpentTxID": null, "value": 3.00996058, "n": 0, "valueSat": 300996058, "txid": "5794e0110bd0c664ebad6098ea3449a08be6fb2549c65b49554edadb37a15ecb", "scriptSig": {"hex": "48304502205f9dc47d4f4b545c9b565ba9462e47df50d9c62bb1e9e279532d517650eb085e022100eb4ef1ed295c44adbe19a84b4f477dac407d1ba17eeeb54b64c2176101a09b4001410406a078b4ffd2fe15fe516ce0f1ac68668a614a79f3b5f6d493361a16b0ee4138907f04d85f5a53f7dc1d47f26aa990881b725edc89b911481b92f2d31a250360", "asm": "304502205f9dc47d4f4b545c9b565ba9462e47df50d9c62bb1e9e279532d517650eb085e022100eb4ef1ed295c44adbe19a84b4f477dac407d1ba17eeeb54b64c2176101a09b40[ALL] 0406a078b4ffd2fe15fe516ce0f1ac68668a614a79f3b5f6d493361a16b0ee4138907f04d85f5a53f7dc1d47f26aa990881b725edc89b911481b92f2d31a250360"}}], "txid": "39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5", "blocktime": 1391896241, "version": 1, "confirmations": 153064, "time": 1391896241, "blockheight": 284866, "locktime": 0, "size": 258}

@ -0,0 +1 @@
{"valueOut": 1.05472082, "vout": [{"spentIndex": 0, "spentHeight": 293754, "value": "1.05072082", "n": 0, "spentTxId": "b664fca5b225d3fc01d6f562488136adc4d563e52fdc639db8b6f50afaa5d736", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a914486088128a2137cd53b81f3efe4c3d612b7a777f88ac", "addresses": ["17bhHwY6nhomv4RxwkEGRZ6VutKjoGMDSS"], "asm": "OP_DUP OP_HASH160 486088128a2137cd53b81f3efe4c3d612b7a777f OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": 0, "spentHeight": 293786, "value": "0.00400000", "n": 1, "spentTxId": "8cc1f4adf7224ce855cf535a5104594a0004cb3b640d6714fdb00b9128832dd5", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac", "addresses": ["14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"], "asm": "OP_DUP OP_HASH160 24a56db43cf6f2b02e838ea493f95d8d60474231 OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "000000000000000092268fe69290d4150455aee141bfa0271c6948d18e56dfd0", "valueIn": 1.05482082, "fees": 0.0001, "vin": [{"addr": "13vPZWiYyXxX2MWZrzy68juyYLm9hifCbd", "vout": 30, "sequence": 4294967295, "doubleSpentTxID": null, "value": 1.05482082, "n": 0, "valueSat": 105482082, "txid": "86cb076f72e440773b2cd0e52993bb03f68defb9f84ec1c1cbdae0dff2c51ccb", "scriptSig": {"hex": "493046022100e6a32e0a6211c6ce2dbd4e04a2398330757d421988d4db864b3bb634ba1c252b02210082abc8a64a00c0858f211b0a8f155d8dfecbac5af5451c63c32a72ed9942902b0141042b8d0a66cb3c71792b8b9d27ba9a2639261465d75f7aec799250da8174b8e75481b247d5152c578c558530d60dd9ecd6924bab4c1267f8fe4c10401eb67b0d37", "asm": "3046022100e6a32e0a6211c6ce2dbd4e04a2398330757d421988d4db864b3bb634ba1c252b02210082abc8a64a00c0858f211b0a8f155d8dfecbac5af5451c63c32a72ed9942902b[ALL] 042b8d0a66cb3c71792b8b9d27ba9a2639261465d75f7aec799250da8174b8e75481b247d5152c578c558530d60dd9ecd6924bab4c1267f8fe4c10401eb67b0d37"}}], "txid": "54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3", "blocktime": 1396310563, "version": 1, "confirmations": 144448, "time": 1396310563, "blockheight": 293483, "locktime": 0, "size": 259}

@ -0,0 +1 @@
{"valueOut": 0.46995, "vout": [{"spentIndex": 28, "spentHeight": 288729, "value": "0.46885000", "n": 0, "spentTxId": "6839c71b7d192a698b5388e9ea921805279cbc9f85bae1019d2f4fe7b326979a", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a91459581dcaf8ed947343b569f1fa2d855d0fc6d9bf88ac", "addresses": ["199QhWMtYE79AG3547QXmZpa8NtLDgme16"], "asm": "OP_DUP OP_HASH160 59581dcaf8ed947343b569f1fa2d855d0fc6d9bf OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": 1, "spentHeight": 284865, "value": "0.00110000", "n": 1, "spentTxId": "c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a9142db345c36563122e2fd0f5485fb7ea9bbf7cb5a288ac", "addresses": ["15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG"], "asm": "OP_DUP OP_HASH160 2db345c36563122e2fd0f5485fb7ea9bbf7cb5a2 OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "00000000000000009ea3d77854af7c8cc0f28506dc8379c89830e445d951f4bf", "valueIn": 0.47005, "fees": 0.0001, "vin": [{"addr": "19UC6mkNJyqy3iKwQQyNm4TVZMkXyi5TSt", "vout": 0, "sequence": 4294967295, "doubleSpentTxID": null, "value": 0.47005, "n": 0, "valueSat": 47005000, "txid": "8d0650287b230a2708f7cab2099f6062cbfd20f4c298c68f6c6cbc962fb3e044", "scriptSig": {"hex": "4730440220428e0c87d311149c6ea86efcaafbd4830cf2eb14e09ac856ae088bc4b797204902201b9402951a06303336a75d6b77d0c889a53ae7c710642be8b5999583e728d3de014104443b1eb4926c3c90332294eba561962ad28d04eb19514002e20c8ee8d93be576ef9799af500a20864c62a74a0b085b237f71ecb451dd9559cb72ba33d326a912", "asm": "30440220428e0c87d311149c6ea86efcaafbd4830cf2eb14e09ac856ae088bc4b797204902201b9402951a06303336a75d6b77d0c889a53ae7c710642be8b5999583e728d3de[ALL] 04443b1eb4926c3c90332294eba561962ad28d04eb19514002e20c8ee8d93be576ef9799af500a20864c62a74a0b085b237f71ecb451dd9559cb72ba33d326a912"}}], "txid": "58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e", "blocktime": 1391892746, "version": 1, "confirmations": 153072, "time": 1391892746, "blockheight": 284858, "locktime": 0, "size": 257}

@ -0,0 +1 @@
{"valueOut": 0.002, "vout": [{"spentIndex": 29, "spentHeight": 288729, "value": "0.00100000", "n": 0, "spentTxId": "6839c71b7d192a698b5388e9ea921805279cbc9f85bae1019d2f4fe7b326979a", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a9142f4490d5263906e4887ca2996b9e207af3e7824088ac", "addresses": ["15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B"], "asm": "OP_DUP OP_HASH160 2f4490d5263906e4887ca2996b9e207af3e78240 OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": 0, "spentHeight": 284875, "value": "0.00100000", "n": 1, "spentTxId": "4a7b7e0403ae5607e473949cfa03f09f2cd8b0f404bf99ce10b7303d86280bf7", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a914812c13d97f9159e54e326b481b8f88a73df8507a88ac", "addresses": ["1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5"], "asm": "OP_DUP OP_HASH160 812c13d97f9159e54e326b481b8f88a73df8507a OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "0000000000000000ad1b23698d40235f4bc71eb1ab6fa5891ade1fd89b0beb7e", "valueIn": 0.0021, "fees": 0.0001, "vin": [{"addr": "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 0.001, "n": 0, "valueSat": 100000, "txid": "c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c", "scriptSig": {"hex": "493046022100f773c403b2f85a5c1d6c9c4ad69c43de66930fff4b1bc818eb257af98305546a022100bbc421b41bc60d89593186c99b4b9ca6ac8dce1fe62342d38a8e14e0cbf279dc01210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6", "asm": "3046022100f773c403b2f85a5c1d6c9c4ad69c43de66930fff4b1bc818eb257af98305546a022100bbc421b41bc60d89593186c99b4b9ca6ac8dce1fe62342d38a8e14e0cbf279dc[ALL] 0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6"}}, {"addr": "15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 0.0011, "n": 1, "valueSat": 110000, "txid": "58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e", "scriptSig": {"hex": "49304602210090cff1c1911e771605358a8cddd5ae94c7b60cc96e50275908d9bf9d6367c79f022100d4058d1efd9f5eb9542a62fad91ecca30db32a326f311f51dc2b1a71cbb578670121038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3", "asm": "304602210090cff1c1911e771605358a8cddd5ae94c7b60cc96e50275908d9bf9d6367c79f022100d4058d1efd9f5eb9542a62fad91ecca30db32a326f311f51dc2b1a71cbb57867[ALL] 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3"}}], "txid": "c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb", "blocktime": 1391895477, "version": 1, "confirmations": 153065, "time": 1391895477, "blockheight": 284865, "locktime": 0, "size": 376}

@ -0,0 +1 @@
{"valueOut": 3.33165406, "vout": [{"spentIndex": 27, "spentHeight": 288729, "value": "3.33065406", "n": 0, "spentTxId": "6839c71b7d192a698b5388e9ea921805279cbc9f85bae1019d2f4fe7b326979a", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a91459581dcaf8ed947343b569f1fa2d855d0fc6d9bf88ac", "addresses": ["199QhWMtYE79AG3547QXmZpa8NtLDgme16"], "asm": "OP_DUP OP_HASH160 59581dcaf8ed947343b569f1fa2d855d0fc6d9bf OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": 0, "spentHeight": 284865, "value": "0.00100000", "n": 1, "spentTxId": "c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac", "addresses": ["1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb"], "asm": "OP_DUP OP_HASH160 0223b1a09138753c9cb0baf95a0a62c82711567a OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "0000000000000000371eecb3a4a9e2347cd8971b9a50a63ef2a7276c3a5e2ca7", "valueIn": 3.33175406, "fees": 0.0001, "vin": [{"addr": "1FSAF2vZ47XnyiF7CuvTErEvtKaGNvwW7w", "vout": 42, "sequence": 4294967295, "doubleSpentTxID": null, "value": 3.33175406, "n": 0, "valueSat": 333175406, "txid": "c810877b6e207671bd28c48cc2b5b4f1d23214c050279a24a760730acc27818d", "scriptSig": {"hex": "473044022046004772823a664287a9496982d232bae3336f558528ae9ca9fe6c904f61751a0220371e084a83fddbf82023d7017f15128cb4c9874e3f27faaa73ee6df1e303d1b7014104a1e881adf937bfe915e9ce6badd3a46e1d7719e23c71291fbdcce15399148e41f16b76a291414b05bffc8705d90034ca6a080cc75c42e4450dc8ffbcaf0a4c9d", "asm": "3044022046004772823a664287a9496982d232bae3336f558528ae9ca9fe6c904f61751a0220371e084a83fddbf82023d7017f15128cb4c9874e3f27faaa73ee6df1e303d1b7[ALL] 04a1e881adf937bfe915e9ce6badd3a46e1d7719e23c71291fbdcce15399148e41f16b76a291414b05bffc8705d90034ca6a080cc75c42e4450dc8ffbcaf0a4c9d"}}], "txid": "c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c", "blocktime": 1391892541, "version": 1, "confirmations": 153073, "time": 1391892541, "blockheight": 284857, "locktime": 0, "size": 257}

@ -0,0 +1 @@
{"valueOut": 0.0039, "vout": [{"spentIndex": 0, "spentHeight": 280227, "value": "0.00390000", "n": 0, "spentTxId": "fd79435246dee76b2f159d2db08032d666c95adc544de64c8c49f474df4a7fee", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac", "addresses": ["14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"], "asm": "OP_DUP OP_HASH160 24a56db43cf6f2b02e838ea493f95d8d60474231 OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "00000000000000011dec345ceae0765c98c72bdcb7cdd83e749ad37bbc3104cc", "valueIn": 0.004, "fees": 0.0001, "vin": [{"addr": "19qyPUSAXJ8cHw6TxZ6FYQFZdLMdJA7A2t", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 0.002, "n": 0, "valueSat": 200000, "txid": "c16a03f1cf8f99f6b5297ab614586cacec784c2d259af245909dedb0e39eddcf", "scriptSig": {"hex": "483045022072ba61305fe7cb542d142b8f3299a7b10f9ea61f6ffaab5dca8142601869d53c0221009a8027ed79eb3b9bc13577ac2853269323434558528c6b6a7e542be46e7e9a820141047a2d177c0f3626fc68c53610b0270fa6156181f46586c679ba6a88b34c6f4874686390b4d92e5769fbb89c8050b984f4ec0b257a0e5c4ff8bd3b035a51709503", "asm": "3045022072ba61305fe7cb542d142b8f3299a7b10f9ea61f6ffaab5dca8142601869d53c0221009a8027ed79eb3b9bc13577ac2853269323434558528c6b6a7e542be46e7e9a82[ALL] 047a2d177c0f3626fc68c53610b0270fa6156181f46586c679ba6a88b34c6f4874686390b4d92e5769fbb89c8050b984f4ec0b257a0e5c4ff8bd3b035a51709503"}}, {"addr": "1B4scQC2N8NZ5cYVbVwDrao1aSnwNAAvbb", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 0.002, "n": 1, "valueSat": 200000, "txid": "1ae39a2f8d59670c8fc61179148a8e61e039d0d9e8ab08610cb69b4a19453eaf", "scriptSig": {"hex": "48304502200fd63adc8f6cb34359dc6cca9e5458d7ea50376cbd0a74514880735e6d1b8a4c0221008b6ead7fe5fbdab7319d6dfede3a0bc8e2a7c5b5a9301636d1de4aa31a3ee9b101410486ad608470d796236b003635718dfc07c0cac0cfc3bfc3079e4f491b0426f0676e6643a39198e8e7bdaffb94f4b49ea21baa107ec2e237368872836073668214", "asm": "304502200fd63adc8f6cb34359dc6cca9e5458d7ea50376cbd0a74514880735e6d1b8a4c0221008b6ead7fe5fbdab7319d6dfede3a0bc8e2a7c5b5a9301636d1de4aa31a3ee9b1[ALL] 0486ad608470d796236b003635718dfc07c0cac0cfc3bfc3079e4f491b0426f0676e6643a39198e8e7bdaffb94f4b49ea21baa107ec2e237368872836073668214"}}], "txid": "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882", "blocktime": 1389542996, "version": 1, "confirmations": 157821, "time": 1389542996, "blockheight": 280109, "locktime": 0, "size": 404}

@ -0,0 +1 @@
{"valueOut": 14.03850989, "vout": [{"spentIndex": 0, "spentHeight": 203911, "value": "4.03850989", "n": 0, "spentTxId": "5170fe1f25a05e1c9e125c27cd09e11f7c79c41409bc5b68f0e6f056af2d56b0", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a914f5a05c2664b40d3116b1c5086c9ba38ed15b742e88ac", "addresses": ["n3uhx4JymCrWKX3e9i59YdJivMghF1bKZ4"], "asm": "OP_DUP OP_HASH160 f5a05c2664b40d3116b1c5086c9ba38ed15b742e OP_EQUALVERIFY OP_CHECKSIG"}}, {"spentIndex": null, "spentHeight": null, "value": "10.00000000", "n": 1, "spentTxId": null, "scriptPubKey": {"type": "pubkeyhash", "hex": "76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac", "addresses": ["mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL"], "asm": "OP_DUP OP_HASH160 24a56db43cf6f2b02e838ea493f95d8d60474231 OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "000000006656e1d72a211b7f469dd85209ba85c54127957a95591712a63d3848", "valueIn": 14.03850989, "fees": 0, "vin": [{"addr": "mnsfHtywp6AVUzgqu9P4tay6iQYY3WhCpz", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 5.508651, "n": 0, "valueSat": 550865100, "txid": "ee336e79153d51f4f3e45278f1f77ab29fd5bb135dce467282e2aff22cb9c570", "scriptSig": {"hex": "483045022066c418874dbe5628296700382d727ce1734928796068c26271472df09dccf1a20221009dec59d19f9d73db381fcd35c0fff757ad73e54ef59157b0d7c57e6739a092f00121033fef08c603943dc7d25f4ce65771762143b1cd8678343d660a1a76b9d1d3ced7", "asm": "3045022066c418874dbe5628296700382d727ce1734928796068c26271472df09dccf1a20221009dec59d19f9d73db381fcd35c0fff757ad73e54ef59157b0d7c57e6739a092f0[ALL] 033fef08c603943dc7d25f4ce65771762143b1cd8678343d660a1a76b9d1d3ced7"}}, {"addr": "mrDBnbEumaEiHm8pc9pj1rfUCsR4H7N5xh", "vout": 1, "sequence": 4294967295, "doubleSpentTxID": null, "value": 8.52985889, "n": 1, "valueSat": 852985889, "txid": "2fe4d8af2b44faccc10dd5a6578c923491d2d21269a1dfe8c83f492a30fb8f9f", "scriptSig": {"hex": "47304402206fbb8e14be706b8557a2280d2a2a75c0a65c4f7936d90d510f0971c93f41f74402201b79c8c4e4ac4c944913611633c230193558296e70a36269b7fc3a80efa27d120121030cb5be79bdc36a4ff4443dbac43068cc43d638ea06ff2fa1b8dab389e39aefc7", "asm": "304402206fbb8e14be706b8557a2280d2a2a75c0a65c4f7936d90d510f0971c93f41f74402201b79c8c4e4ac4c944913611633c230193558296e70a36269b7fc3a80efa27d12[ALL] 030cb5be79bdc36a4ff4443dbac43068cc43d638ea06ff2fa1b8dab389e39aefc7"}}], "txid": "6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54", "blocktime": 1391901762, "version": 1, "confirmations": 851751, "time": 1391901762, "blockheight": 180573, "locktime": 0, "size": 373}

@ -0,0 +1 @@
{"valueOut": 25.0027823, "isCoinBase": true, "vout": [{"spentIndex": 0, "spentHeight": 245746, "value": "25.00278230", "n": 0, "spentTxId": "871884776fe6aa078a16b66d82157ab4159257aa2889da9229f4e024ba40d6ee", "scriptPubKey": {"type": "pubkeyhash", "hex": "76a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac", "addresses": ["mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV"], "asm": "OP_DUP OP_HASH160 0223b1a09138753c9cb0baf95a0a62c82711567a OP_EQUALVERIFY OP_CHECKSIG"}}], "blockhash": "000000000001994ec2997c267bc843d5b24032db26e5e1c56bffaf43c786a339", "vin": [{"coinbase": "0352bf03062f503253482f04f919855308f8000001c7000000092f7374726174756d2f", "n": 0, "sequence": 0}], "txid": "d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236", "blocktime": 1401231865, "version": 1, "confirmations": 786738, "time": 1401231865, "blockheight": 245586, "locktime": 0, "size": 120}

@ -1,187 +0,0 @@
'''
filecache
filecache is a decorator which saves the return value of functions even
after the interpreter dies. For example this is useful on functions that download
and parse webpages. All you need to do is specify how long
the return values should be cached (use seconds, like time.sleep).
USAGE:
from filecache import filecache
@filecache(24 * 60 * 60)
def time_consuming_function(args):
# etc
@filecache(filecache.YEAR)
def another_function(args):
# etc
NOTE: All arguments of the decorated function and the return value need to be
picklable for this to work.
NOTE: The cache isn't automatically cleaned, it is only overwritten. If your
function can receive many different arguments that rarely repeat, your
cache may forever grow. One day I might add a feature that once in every
100 calls scans the db for outdated stuff and erases.
NOTE: This is less useful on methods of a class because the instance (self)
is cached, and if the instance isn't the same, the cache isn't used. This
makes sense because class methods are affected by changes in whatever
is attached to self.
Tested on python 2.7 and 3.1
License: BSD, do what you wish with this. Could be awesome to hear if you found
it useful and/or you have suggestions. ubershmekel at gmail
A trick to invalidate a single value:
@filecache.filecache
def somefunc(x, y, z):
return x * y * z
del somefunc._db[filecache._args_key(somefunc, (1,2,3), {})]
# or just iterate of somefunc._db (it's a shelve, like a dict) to find the right key.
'''
import collections as _collections
import datetime as _datetime
import functools as _functools
import inspect as _inspect
import os as _os
import pickle as _pickle
import shelve as _shelve
import sys as _sys
import time as _time
import traceback as _traceback
import types
import atexit
_retval = _collections.namedtuple('_retval', 'timesig data')
_SRC_DIR = _os.path.dirname(_os.path.abspath(__file__))
SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
DAY = 24 * HOUR
WEEK = 7 * DAY
MONTH = 30 * DAY
YEAR = 365 * DAY
FOREVER = None
OPEN_DBS = dict()
def _get_cache_name(function):
"""
returns a name for the module's cache db.
"""
module_name = _inspect.getfile(function)
module_name = _os.path.abspath(module_name)
cache_name = module_name
# fix for '<string>' or '<stdin>' in exec or interpreter usage.
cache_name = cache_name.replace('<', '_lt_')
cache_name = cache_name.replace('>', '_gt_')
tmpdir = _os.getenv('TMPDIR') or _os.getenv('TEMP') or _os.getenv('TMP')
if tmpdir:
cache_name = tmpdir + '/filecache_' + cache_name.replace(_os.sep, '@')
cache_name += '.cache'
return cache_name
def _log_error(error_str):
try:
error_log_fname = _os.path.join(_SRC_DIR, 'filecache.err.log')
if _os.path.isfile(error_log_fname):
fhand = open(error_log_fname, 'a')
else:
fhand = open(error_log_fname, 'w')
fhand.write('[%s] %s\r\n' % (_datetime.datetime.now().isoformat(), error_str))
fhand.close()
except Exception:
pass
def _args_key(function, args, kwargs):
arguments = (args, kwargs)
# Check if you have a valid, cached answer, and return it.
# Sadly this is python version dependant
if _sys.version_info[0] == 2:
arguments_pickle = _pickle.dumps(arguments)
else:
# NOTE: protocol=0 so it's ascii, this is crucial for py3k
# because shelve only works with proper strings.
# Otherwise, we'd get an exception because
# function.__name__ is str but dumps returns bytes.
arguments_pickle = _pickle.dumps(arguments, protocol=0).decode('ascii')
key = function.__name__ + arguments_pickle
return key
def filecache(seconds_of_validity=None, fail_silently=False):
'''
filecache is called and the decorator should be returned.
'''
def filecache_decorator(function):
@_functools.wraps(function)
def function_with_cache(*args, **kwargs):
try:
key = _args_key(function, args, kwargs)
if key in function._db:
rv = function._db[key]
if seconds_of_validity is None or _time.time() - rv.timesig < seconds_of_validity:
return rv.data
except Exception:
# in any case of failure, don't let filecache break the program
error_str = _traceback.format_exc()
_log_error(error_str)
if not fail_silently:
raise
retval = function(*args, **kwargs)
# store in cache
# NOTE: no need to _db.sync() because there was no mutation
# NOTE: it's importatnt to do _db.sync() because otherwise the cache doesn't survive Ctrl-Break!
try:
function._db[key] = _retval(_time.time(), retval)
function._db.sync()
except Exception:
# in any case of failure, don't let filecache break the program
error_str = _traceback.format_exc()
_log_error(error_str)
if not fail_silently:
raise
return retval
# make sure cache is loaded
if not hasattr(function, '_db'):
cache_name = _get_cache_name(function)
if cache_name in OPEN_DBS:
function._db = OPEN_DBS[cache_name]
else:
function._db = _shelve.open(cache_name)
OPEN_DBS[cache_name] = function._db
atexit.register(function._db.close)
function_with_cache._db = function._db
return function_with_cache
if type(seconds_of_validity) == types.FunctionType:
# support for when people use '@filecache.filecache' instead of '@filecache.filecache()'
func = seconds_of_validity
seconds_of_validity = None
return filecache_decorator(func)
return filecache_decorator

@ -1,116 +1,120 @@
import binascii
from decimal import Decimal
# from filecache import filecache, DAY
import requests
import json
from . import types_pb2 as proto_types
def fetch_json(url):
try:
r = requests.get(url, headers={'User-agent': 'Mozilla/5.0'})
return r.json()
except:
raise Exception('URL error: %s' % url)
def insight_tx(url, rawdata=False, zcash=False):
if not rawdata:
data = fetch_json(url)
else:
data = url
t = proto_types.TransactionType()
t.version = data['version']
t.lock_time = data['locktime']
for vin in data['vin']:
i = t.inputs.add()
if 'coinbase' in vin.keys():
i.prev_hash = b"\0"*32
i.prev_index = 0xffffffff # signed int -1
i.script_sig = binascii.unhexlify(vin['coinbase'])
i.sequence = vin['sequence']
else:
i.prev_hash = binascii.unhexlify(vin['txid'])
i.prev_index = vin['vout']
i.script_sig = binascii.unhexlify(vin['scriptSig']['hex'])
i.sequence = vin['sequence']
for vout in data['vout']:
o = t.bin_outputs.add()
o.amount = int(Decimal(str(vout['value'])) * 100000000)
o.script_pubkey = binascii.unhexlify(vout['scriptPubKey']['hex'])
if zcash:
if t.version == 2:
joinsplit_cnt = len(data['vjoinsplit'])
if joinsplit_cnt == 0:
t.extra_data =b'\x00'
else:
extra_data_len = 1 + joinsplit_cnt * 1802 + 32 + 64 # we assume cnt < 253, so we can treat varIntLen(cnt) as 1
raw = fetch_json(url.replace('/tx/', '/rawtx/'))
raw = binascii.unhexlify(raw['rawtx'])
t.extra_data = raw[-extra_data_len:]
return t
class TxApi(object):
def __init__(self, network, url):
self.network = network
self.url = url
def fetch_json(self, url, resource, resourceid):
cachefile = '%s_%s_%s' % (self.network, resource, resourceid)
try: # looking into cache first
j = json.load(open('txcache/' + cachefile))
return j
except:
pass
try:
r = requests.get('%s/%s/%s' % (self.url, resource, resourceid), headers={'User-agent': 'Mozilla/5.0'})
j = r.json()
except:
raise Exception('URL error: %s' % url)
try: # saving into cache
json.dump(j, open('txcache/' + cachefile, 'w'))
except:
pass
return j
def smartbit_tx(url, rawdata=False):
if not rawdata:
data = fetch_json(url)
else:
data = url
def get_tx(self, txhash):
raise NotImplementedError
data = data['transaction']
t = proto_types.TransactionType()
t.version = int(data['version'])
t.lock_time = data['locktime']
class TxApiInsight(TxApi):
for vin in data['inputs']:
i = t.inputs.add()
if 'coinbase' in vin.keys():
i.prev_hash = b"\0"*32
i.prev_index = 0xffffffff # signed int -1
i.script_sig = binascii.unhexlify(vin['coinbase'])
i.sequence = vin['sequence']
def __init__(self, network, url, zcash=None):
super(TxApiInsight, self).__init__(network, url)
self.zcash = zcash
else:
i.prev_hash = binascii.unhexlify(vin['txid'])
i.prev_index = vin['vout']
i.script_sig = binascii.unhexlify(vin['script_sig']['hex'])
i.sequence = vin['sequence']
def get_tx(self, txhash):
for vout in data['outputs']:
o = t.bin_outputs.add()
o.amount = int(Decimal(vout['value']) * 100000000)
o.script_pubkey = binascii.unhexlify(vout['script_pub_key']['hex'])
data = self.fetch_json(self.url, 'tx', txhash)
return t
t = proto_types.TransactionType()
t.version = data['version']
t.lock_time = data['locktime']
class TXAPIBitcoin(object):
for vin in data['vin']:
i = t.inputs.add()
if 'coinbase' in vin.keys():
i.prev_hash = b"\0"*32
i.prev_index = 0xffffffff # signed int -1
i.script_sig = binascii.unhexlify(vin['coinbase'])
i.sequence = vin['sequence']
# @filecache(DAY)
def get_tx(self, txhash):
url = 'https://insight.bitpay.com/api/tx/%s' % txhash.decode('ascii')
return insight_tx(url)
else:
i.prev_hash = binascii.unhexlify(vin['txid'])
i.prev_index = vin['vout']
i.script_sig = binascii.unhexlify(vin['scriptSig']['hex'])
i.sequence = vin['sequence']
for vout in data['vout']:
o = t.bin_outputs.add()
o.amount = int(Decimal(str(vout['value'])) * 100000000)
o.script_pubkey = binascii.unhexlify(vout['scriptPubKey']['hex'])
class TXAPITestnet(object):
if self.zcash:
if t.version == 2:
joinsplit_cnt = len(data['vjoinsplit'])
if joinsplit_cnt == 0:
t.extra_data =b'\x00'
else:
extra_data_len = 1 + joinsplit_cnt * 1802 + 32 + 64 # we assume cnt < 253, so we can treat varIntLen(cnt) as 1
raw = fetch_json(self.url, 'rawtx', txhash)
raw = binascii.unhexlify(raw['rawtx'])
t.extra_data = raw[-extra_data_len:]
# @filecache(DAY)
def get_tx(self, txhash):
url = 'https://test-insight.bitpay.com/api/tx/%s' % txhash.decode('ascii')
return insight_tx(url)
return t
class TXAPISegnet(object):
# @filecache(DAY)
class TxApiSmartbit(TxApi):
def get_tx(self, txhash):
url = 'https://segnet-api.smartbit.com.au/v1/blockchain/tx/%s' % txhash.decode('ascii')
return smartbit_tx(url)
class TXAPIZcashTestnet(object):
data = self.fetch_json(self.url, 'tx', txhash)
# @filecache(DAY)
def get_tx(self, txhash):
url = 'https://explorer.testnet.z.cash/api/tx/%s' % txhash.decode('ascii')
return insight_tx(url, zcash=True)
data = data['transaction']
t = proto_types.TransactionType()
t.version = int(data['version'])
t.lock_time = data['locktime']
for vin in data['inputs']:
i = t.inputs.add()
if 'coinbase' in vin.keys():
i.prev_hash = b"\0"*32
i.prev_index = 0xffffffff # signed int -1
i.script_sig = binascii.unhexlify(vin['coinbase'])
i.sequence = vin['sequence']
else:
i.prev_hash = binascii.unhexlify(vin['txid'])
i.prev_index = vin['vout']
i.script_sig = binascii.unhexlify(vin['script_sig']['hex'])
i.sequence = vin['sequence']
for vout in data['outputs']:
o = t.bin_outputs.add()
o.amount = int(Decimal(vout['value']) * 100000000)
o.script_pubkey = binascii.unhexlify(vout['script_pub_key']['hex'])
return t
TxApiBitcoin = TxApiInsight(network='insight_bitcoin', url='https://insight.bitpay.com/api/')
TxApiTestnet = TxApiInsight(network='insight_testnet', url='https://test-insight.bitpay.com/api/')
TxApiSegnet = TxApiSmartbit(network='smartbit_segnet', url='https://segnet-api.smartbit.com.au/v1/blockchain/')
TxApiZcashTestnet = TxApiInsight(network='insight_zcashtestnet', url='https://explorer.testnet.z.cash/api/', zcash=True)

Loading…
Cancel
Save