| 49 | |
| 50 | |
| 51 | class Script: |
| 52 | |
| 53 | def __init__(self, cmds=None): |
| 54 | if cmds is None: |
| 55 | self.cmds = [] |
| 56 | else: |
| 57 | self.cmds = cmds |
| 58 | |
| 59 | def __repr__(self): |
| 60 | result = [] |
| 61 | for cmd in self.cmds: |
| 62 | if type(cmd) == int: |
| 63 | if OP_CODE_NAMES.get(cmd): |
| 64 | name = OP_CODE_NAMES.get(cmd) |
| 65 | else: |
| 66 | name = 'OP_[{}]'.format(cmd) |
| 67 | result.append(name) |
| 68 | else: |
| 69 | result.append(cmd.hex()) |
| 70 | return ' '.join(result) |
| 71 | |
| 72 | def __add__(self, other): |
| 73 | return Script(self.cmds + other.cmds) |
| 74 | |
| 75 | @classmethod |
| 76 | def parse(cls, s): |
| 77 | # get the length of the entire field |
| 78 | length = read_varint(s) |
| 79 | # initialize the cmds array |
| 80 | cmds = [] |
| 81 | # initialize the number of bytes we've read to 0 |
| 82 | count = 0 |
| 83 | # loop until we've read length bytes |
| 84 | while count < length: |
| 85 | # get the current byte |
| 86 | current = s.read(1) |
| 87 | # increment the bytes we've read |
| 88 | count += 1 |
| 89 | # convert the current byte to an integer |
| 90 | current_byte = current[0] |
| 91 | # if the current byte is between 1 and 75 inclusive |
| 92 | if current_byte >= 1 and current_byte <= 75: |
| 93 | # we have an cmd set n to be the current byte |
| 94 | n = current_byte |
| 95 | # add the next n bytes as an cmd |
| 96 | cmds.append(s.read(n)) |
| 97 | # increase the count by n |
| 98 | count += n |
| 99 | elif current_byte == 76: |
| 100 | # op_pushdata1 |
| 101 | data_length = little_endian_to_int(s.read(1)) |
| 102 | cmds.append(s.read(data_length)) |
| 103 | count += data_length + 1 |
| 104 | elif current_byte == 77: |
| 105 | # op_pushdata2 |
| 106 | data_length = little_endian_to_int(s.read(2)) |
| 107 | cmds.append(s.read(data_length)) |
| 108 | count += data_length + 2 |
no outgoing calls
no test coverage detected