diff --git a/script.py b/script.py new file mode 100644 index 0000000..681423d --- /dev/null +++ b/script.py @@ -0,0 +1,58 @@ +from usefulfunctions import int_to_little_endian , encode_varint , read_varint , little_endian_to_int + +class Script: + + def __init__(self, cmds=None): + if cmds is None: + self.cmds = [] + else: + self.cmds = cmds + + def parse(cls, s): + length = read_varint(s) + cmds = [] + count = 0 + while count < length: + current = s.read(1) + count += 1 + currbyte = current[0] + if currbyte >= 1 and currbyte <= 75: + n = currbyte + cmds.append(s.read(n)) + count += n + elif currbyte == 76: + l = little_endian_to_int(s.read(1)) + cmds.append(s.read(l)) + count += l + 1 + elif currbyte == 77: + l = little_endian_to_int(s.read(2)) + cmds.append(s.read(l)) + count += l + 2 + else: + op_code = currbyte + cmds.append(op_code) + if count != length: + raise SyntaxError('parsing script failed') + return cls(cmds) + + + def serialize(self): + r = b'' + for cmd in self.cmds: + if type(cmd) == int: + r += int_to_little_endian(cmd, 1) + else: + length = len(cmd) + if length < 75: + r += int_to_little_endian(length, 1) + elif length > 75 and length < 0x100: + r += int_to_little_endian(76, 1) + r += int_to_little_endian(length, 1) + elif length >= 0x100 and length <= 520: + r += int_to_little_endian(77, 1) + r += int_to_little_endian(length, 2) + else: + raise ValueError('cmd is not correct file script.py serialization of script ') + r += cmd + r = encode_varint(len(r)) + r + return r \ No newline at end of file diff --git a/tx.py b/tx.py index 6b4e336..95074b2 100644 --- a/tx.py +++ b/tx.py @@ -3,7 +3,7 @@ # TxIn # TxOut from usefulfunctions import int_to_little_endian , encode_varint - +from script import Script class TxOut: #this is the basic frame of the def __init__(self, amount, script_pubkey): diff --git a/usefulfunctions.py b/usefulfunctions.py index f3cd613..823c359 100644 --- a/usefulfunctions.py +++ b/usefulfunctions.py @@ -1,3 +1,17 @@ +def little_endian_to_int(b): + return int.from_bytes(b, 'little') + +def read_varint(s): + i = s.read(1)[0] + if i == 0xfd: + return little_endian_to_int(s.read(2)) + elif i == 0xfe: + return little_endian_to_int(s.read(4)) + elif i == 0xff: + return little_endian_to_int(s.read(8)) + else: + # anything else is just the integer + return i def int_to_little_endian(n, length): # converting the int into the little edian format return n.to_bytes(length, 'little') @@ -12,3 +26,4 @@ def encode_varint(i): return b'\xfe' + int_to_little_endian(i, 4) elif i < 0x10000000000000000: return b'\xff' + int_to_little_endian(i, 8) +