開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Python 3.7 (プログラミング言語)
Programming Bitcoin: Learn How to Program Bitcoin from Scratch (Jimmy Song(著)、O'Reilly Media)のChapter 5(Transactions)、Inputs、Exercises 2(96)の解答を求めてみる。
コード
Python 3
#!/usr/bin/env python3 from unittest import TestCase, main class TransactionTest(TestCase): def setUp(self): pass def tearDown(self): pass def test_parse(self): import io hex_transaction = '0100000004' b = io.BytesIO(bytes.fromhex(hex_transaction)) parsed = Transaction.parse(b) self.assertEqual(1, parsed.version) self.assertEqual(4, len(parsed.tx_ins)) hex_transaction = '01000000fd0400' b = io.BytesIO(bytes.fromhex(hex_transaction)) parsed = Transaction.parse(b) self.assertEqual(1, parsed.version) self.assertEqual(4, len(parsed.tx_ins)) hex_transaction = '01000000fe10000000' b = io.BytesIO(bytes.fromhex(hex_transaction)) parsed = Transaction.parse(b) self.assertEqual(1, parsed.version) self.assertEqual(16, len(parsed.tx_ins)) hex_transaction = '01000000ff0001000000000000' b = io.BytesIO(bytes.fromhex(hex_transaction)) parsed = Transaction.parse(b) self.assertEqual(1, parsed.version) self.assertEqual(256, len(parsed.tx_ins)) class TransactionInputs(TestCase): def setUp(self): pass def tearDown(self): pass def little_endian_to_int(b: bytes) -> int: return int.from_bytes(b, 'little') def read_varint(s): i = s.read(1)[0] d = {0xfd: 2, 0xfe: 4, 0xff: 8} if i in d: return little_endian_to_int(s.read(d[i])) return i class Transaction: def __init__(self, version, tx_ins, tx_outs, locktime, testnet=False): self.version = version self.tx_ins = tx_ins @classmethod def parse(cls, stream): version = little_endian_to_int(stream.read(4)) inputs = [TransactionInput.parse(stream) for _ in range(read_varint(stream))] return cls(version, inputs, None, None) class TransactionInput: def __init__( self, prev_tx, prev_index, script_sig=None, sequence=0xffffffff): pass def __repr__(self): return f'{self.prev_tx.hex()}:{self.prev_index}' @classmethod def parse(cls, stream): tx_id = stream.read(32) prev_index = stream.read(4) # script_sig = Script.parse(s) sequence = stream.read(4) return cls(tx_id, prev_index, None, sequence) if __name__ == '__main__': main()
入出力結果(cmd(コマンドプロンプト)、Terminal、Jupyter(IPython))
C:\Users\...>py sample2.py E ====================================================================== ERROR: test_parse (__main__.TransactionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "sample2.py", line 18, in test_parse self.assertEqual(4, len(parsed.tx_ins)) TypeError: object of type 'NoneType' has no len() ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) C:\Users\...>py sample2.py E ====================================================================== ERROR: test_parse (__main__.TransactionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "sample2.py", line 16, in test_parse parsed = Transaction.parse(b) File "sample2.py", line 50, in parse for _ in range(read_varint(stream))] File "sample2.py", line 50, in <listcomp> for _ in range(read_varint(stream))] AttributeError: type object 'TransactionInput' has no attribute 'parse' ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) C:\Users\...>py sample2.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.000s OK C:\Users\...>py sample2.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.000s OK C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.000s OK C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... FAIL ====================================================================== FAIL: test_parse (__main__.TransactionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "sample2.py", line 36, in test_parse self.assertEqual(16, len(parsed.tx_ins)) AssertionError: 16 != 4 ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (failures=1) C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... FAIL ====================================================================== FAIL: test_parse (__main__.TransactionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "sample2.py", line 36, in test_parse self.assertEqual(16, len(parsed.tx_ins)) AssertionError: 16 != 256 ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (failures=1) C:\Users\...>py sample2.py -v test_parse (__main__.TransactionTest) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK C:\Users\...>
0 コメント:
コメントを投稿