Ejemplo n.º 1
0
    def AddSignature(self, contract, pubkey, signature):

        if contract.Type == ContractType.MultiSigContract:

            item = self.CreateItem(contract)
            if item is None:
                return False
            for p in item.ContractParameters:
                if p.Value is not None:
                    return False
            if item.Signatures is None:
                item.Signatures = {}
            elif pubkey.encode_point(True) in item.Signatures:
                return False

            points = []
            temp = binascii.unhexlify(contract.Script)
            ms = MemoryStream(binascii.unhexlify(contract.Script))
            reader = BinaryReader(ms)
            numr = reader.ReadUInt8()
            while reader.ReadUInt8() == 33:
                points.append(binascii.hexlify(reader.ReadBytes(33)))
            ms.close()

            if pubkey.encode_point(True) not in points:
                return False

            item.Signatures[pubkey.encode_point(True).decode()] = binascii.hexlify(signature)

            if len(item.Signatures) == len(contract.ParameterList):
                i = 0
                points.sort(reverse=True)
                for k in points:
                    if k.decode() in item.Signatures:
                        if self.Add(contract, i, item.Signatures[k.decode()]) is None:
                            raise Exception("Invalid operation")
                        i += 1
                item.Signatures = None
            return True

        else:
            index = -1
            if contract.ParameterList == '00':
                contract.ParameterList = b'\x00'
            length = len(contract.ParameterList)
            for i in range(0, length):
                if ContractParameterType(contract.ParameterList[i]) == ContractParameterType.Signature:
                    if index >= 0:
                        raise Exception("Signature must be first")
                    else:
                        index = i
            return self.Add(contract, index, signature)
Ejemplo n.º 2
0
    def test_yet_another_tx(self):

        ms = MemoryStream(binascii.unhexlify(self.yatx))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.ToArray(), self.yatx)
        self.assertEqual(tx.Hash.ToBytes(), self.yatx_id)
Ejemplo n.º 3
0
    def test_contract_tx_again(self):
        ms = MemoryStream(binascii.unhexlify(self.cr))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.cr)
        self.assertEqual(tx.Hash.ToBytes(), self.crid)
Ejemplo n.º 4
0
    def ToJson(self):
        jsn = {}
        jsn['type'] = 'Neo.Core.ContractTransaction'  # Verifiable.GetType().FullName
        ms = MemoryStream()
        w = BinaryWriter(ms)
        self.Verifiable.SerializeUnsigned(w)
        ms.flush()
        jsn['hex'] = ms.ToArray().decode()
        jsn['items'] = {}
        for key, value in self.ContextItems.items():
            if type(key) == str:
                shkey = "0x{}".format(key)
            else:
                shkey = "0x{}".format(key.decode())
            jsn['items'][shkey] = value.ToJson()

        return jsn
Ejemplo n.º 5
0
    def test_miner_tx(self):
        ms = MemoryStream(binascii.unhexlify(self.mr))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.Nonce, self.mrn)
        self.assertEqual(tx.ToArray(), self.mr)
        self.assertEqual(tx.Hash.ToBytes(), self.mrh)
Ejemplo n.º 6
0
    def test_invocation_transaction(self):
        ms = MemoryStream(binascii.unhexlify(self.ir))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.ToArray(), self.ir)
        self.assertEqual(tx.Hash.ToBytes(), self.ir_id)
Ejemplo n.º 7
0
    def ToJson(self):
        jsn = {}
        jsn['type'] = 'Neo.Core.ContractTransaction'  # Verifiable.GetType().FullName
        ms = MemoryStream()
        w = BinaryWriter(ms)
        self.Verifiable.SerializeUnsigned(w)
        ms.flush()
        jsn['hex'] = ms.ToArray().decode()
        jsn['items'] = {}
        for key, value in self.ContextItems.items():
            if type(key) == str:
                shkey = "0x{}".format(key)
            else:
                shkey = "0x{}".format(key.decode())
            jsn['items'][shkey] = value.ToJson()

        return jsn
Ejemplo n.º 8
0
class ScriptBuilder(object):
    """docstring for ScriptBuilder"""
    def __init__(self):
        super(ScriptBuilder, self).__init__()
        self.ms = MemoryStream()  # MemoryStream

    def add(self, op):
        if isinstance(op, int):
            self.ms.write(bytes([op]))
        else:
            self.ms.write(op)
        return

    def push(self, data):
        if data == None:
            return
        if isinstance(data,int):
            if data == -1:
                return self.add(PUSHM1)
            elif data == 0:
                return self.add(PUSH0)
            elif data > 0 and data <= 16:
                return self.add(int.from_bytes(PUSH1,'big') -1  + data)
            else:
                return self.push(bytes(data))
        else:
            buf = binascii.unhexlify(data)
        if len(buf) <= int.from_bytes( PUSHBYTES75, 'big'):
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x100:
            self.add(PUSH1)
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x10000:
            self.add(PUSH2)
            self.add(len(buf) & 0xff)
            self.add(len(buf) >> 8)
            self.add(buf)
        elif len(buf) < 0x100000000:
            self.add(PUSH4)
            self.add(len(buf) & 0xff)
            self.add((len(buf) >> 8) & 0xff)
            self.add((len(buf) >> 16) & 0xff)
            self.add(len(buf) >> 24)
            self.add(buf)
        return

    def ToArray(self):
        self.ms.flush()
        retval = self.ms.ToArray()
        self.ms.Cleanup()
        self.ms = None

        return retval
Ejemplo n.º 9
0
    def test_enrollment_tx(self):

        ms = MemoryStream(binascii.unhexlify(self.eraw))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.eraw)
        self.assertEqual(tx.Hash.ToBytes(), self.eid)
Ejemplo n.º 10
0
    def test_pub_two(self):
        ms = MemoryStream(binascii.unhexlify(self.p2))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.p2)
        self.assertEqual(tx.Hash.ToBytes(), self.p2id)
Ejemplo n.º 11
0
    def test_GetScriptHashesForVerifying_neo_gas(self):
        # test a raw tx using neo
        ms = MemoryStream(binascii.unhexlify(self.ntx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx.raw_tx = True

        res = tx.GetScriptHashesForVerifying()

        self.assertTrue(type(res), list)

        # test a raw tx using gas
        ms = MemoryStream(binascii.unhexlify(self.gtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx.raw_tx = True

        res = tx.GetScriptHashesForVerifying()

        self.assertTrue(type(res), list)
Ejemplo n.º 12
0
    def test_enrollment_tx(self):
        ms = MemoryStream(binascii.unhexlify(self.eraw))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.eraw)
        self.assertEqual(tx.Hash.ToBytes(), self.eid)
        self.assertEqual(
            Fixed8.FromDecimal(settings.ALL_FEES['EnrollmentTransaction']),
            tx.SystemFee())
Ejemplo n.º 13
0
    def test_GetScriptHashesForVerifying_invalid_operation(self):
        # test a normal tx with a bad assetId
        ms = MemoryStream(binascii.unhexlify(self.rtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        with self.assertRaises(Exception) as e:
            tx.GetScriptHashesForVerifying()

        self.assertTrue("Invalid operation" in str(e.exception))

        # test a raw tx with a bad assetId
        ms = MemoryStream(binascii.unhexlify(self.rtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx.raw_tx = True

        with self.assertRaises(Exception) as e:
            tx.GetScriptHashesForVerifying()

        self.assertTrue("Invalid operation" in str(e.exception))
Ejemplo n.º 14
0
    def test_pub_two(self):
        ms = MemoryStream(binascii.unhexlify(self.p2))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.p2)
        self.assertEqual(tx.Hash.ToBytes(), self.p2id)

        json = tx.ToJson()
        self.assertEqual(json['size'], 402)
        self.assertEqual(json['type'], 'PublishTransaction')
Ejemplo n.º 15
0
    def test_contract_tx_deserialize(self):
        ms = MemoryStream(binascii.unhexlify(self.ctx_raw))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.ctx_raw)
        self.assertEqual(tx.Hash.ToBytes(), self.ctx_id)

        json = tx.ToJson()
        self.assertEqual(json['size'], 605)
        self.assertEqual(json['type'], 'ContractTransaction')
Ejemplo n.º 16
0
    def FromTrimmedData(bytes, index, transaction_method):
        block = Block()
        ms = MemoryStream()
        reader = BinaryReader(ms)

        block.DeserializeUnsigned(reader)
        reader.ReadByte()
        block.Script = reader.ReadSerializableArray('neo.Core.Witness.Witness')
        block.Transactions = []
        for i in range(0, reader.ReadVarInt()):
            tx = Transaction.DeserializeFrom(reader)
            block.Transactions.append(tx)

        return block
Ejemplo n.º 17
0
    def test_register_tx(self):

        ms = MemoryStream(binascii.unhexlify(self.rr))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(self.rrid, tx.Hash.ToBytes())

        json = tx.ToJson()
        asset = json['asset']

        self.assertEqual(asset['admin'], 'ARFe4mTKRTETerRoMsyzBXoPt2EKBvBXFX')
        self.assertEqual(asset['name'], '[{"lang":"zh-CN","name":"TestCoin"}]')
        self.assertEqual(asset['precision'], 8)
Ejemplo n.º 18
0
    def FromTrimmedData(data, index):

        header = Header()

        ms = MemoryStream(data)

        reader = BinaryReader(ms)

        header.DeserializeUnsigned(reader)
        reader.ReadByte()

        witness = Witness()
        witness.Deserialize(reader)
        header.Script = witness

        return header
Ejemplo n.º 19
0
    def test_verify_claim_tx_high_priority(self):
        ms = MemoryStream(binascii.unhexlify(self.cltx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.cltx)
        self.assertEqual(tx.Hash.ToBytes(), self.cltx_id)
        snapshot = GetBlockchain()._db.createSnapshot()

        with patch("neo.Core.TX.Transaction.Transaction.Size", return_value=(settings.MAX_FREE_TX_SIZE + 1)):
            with patch('neo.SmartContract.Helper.Helper.VerifyWitnesses', return_value=True):  # we are not testing VerifyScripts
                with patch('neo.Core.Blockchain.Blockchain.CalculateBonusIgnoreClaimed', return_value=Fixed8.FromDecimal(0.30551243)):
                    res = tx.Verify(snapshot, [tx])
                    self.assertTrue(res)

                    tx_size = tx.Size()
                    self.assertGreater(tx_size, settings.MAX_FREE_TX_SIZE)
Ejemplo n.º 20
0
    def test_GetScriptHashesForVerifying_DutyFlag(self):
        # test a raw tx
        ms = MemoryStream(binascii.unhexlify(self.rtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx.raw_tx = True

        # create the mocked asset
        mock_asset = AssetState()
        mock_asset.AssetType = 0x80

        snapshot = GetBlockchain()._db.createSnapshot()
        with patch("neo.Core.Helper.Helper.StaticAssetState", return_value=mock_asset):
            res = tx.GetScriptHashesForVerifying(snapshot)

        self.assertTrue(type(res), list)
        self.assertEqual(res[0], Helper.AddrStrToScriptHash("AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3"))
Ejemplo n.º 21
0
    def test_verify_exceeds_max_tx_size(self):
        ms = MemoryStream(binascii.unhexlify(self.vvtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx._network_fee = Fixed8.FromDecimal(0.001)

        self.assertEqual(tx.ToArray(), self.vvtx)
        self.assertEqual(tx.Hash.ToBytes(), self.vvtx_id)

        snapshot = GetBlockchain()._db.createSnapshot()

        with patch("neo.Core.TX.Transaction.Transaction.Size", return_value=(Transaction.MAX_TX_SIZE + 1)):
            res = tx.Verify(snapshot, [tx])
            self.assertFalse(res)

            tx_size = tx.Size()
            self.assertGreater(tx_size, Transaction.MAX_TX_SIZE)
Ejemplo n.º 22
0
    def ImportFromArray(self, raw_tx):
        """
        Import a raw transaction from an array.

        Args:
            raw_tx: (bytes) the raw transaction array
        """
        if not isinstance(raw_tx, bytes):
            raise TypeError('Please input a byte array.')

        try:
            raw_tx = binascii.unhexlify(raw_tx)
            ms = MemoryStream(raw_tx)
            reader = BinaryReader(ms)
            self.DeserializeFrom(reader)
        except Exception as e:
            raise FormatError(
                f'Unable to import raw transaction.\nError output: {e}')
Ejemplo n.º 23
0
    def test_claim_tx(self):
        ms = MemoryStream(binascii.unhexlify(self.cltx))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.ToArray(), self.cltx)
        self.assertEqual(tx.Hash.ToBytes(), self.cltx_id)

        json = tx.ToJson()
        self.assertEqual(json['size'], 577)
        self.assertEqual(json['type'], "ClaimTransaction")
        self.assertEqual(json['version'], 0)
        self.assertEqual(len(json['attributes']), 0)
        self.assertEqual(len(json['vout']), 1)
        self.assertEqual(len(json['vin']), 0)
        self.assertEqual(json['sys_fee'], "0")
        self.assertEqual(json['net_fee'], "0")

        self.assertEqual(len(json['claims']), 12)
Ejemplo n.º 24
0
    def test_publish_tx_deserialize(self):

        ms = MemoryStream(binascii.unhexlify(self.pb_raw))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.ToArray(), self.pb_raw)
        self.assertEqual(tx.Hash.ToBytes(), self.pb_hash)

        json = tx.ToJson()

        contract = json['contract']
        self.assertEqual(contract['author'], 'Erik Zhang')
        self.assertEqual(contract['description'], 'Lock your assets until a timestamp.')

        self.assertEqual(contract['code']['hash'], 'ffbd1a7ad1e2348b6b3822426f364bfb4bcce3b9')
        self.assertEqual(contract['code']['returntype'], 1)
        self.assertEqual(contract['code']['parameters'], '020500')
Ejemplo n.º 25
0
    def DeserializeFromAsyncSocket(socket, cancellation_token):
        buffer = bytearray(24)

        try:
            socket.recv_into(buffer, 24)

            ms = MemoryStream(buffer)
            reader = BinaryReader(ms)

            message = Message()

            message.Magic = reader.ReadUInt32()
            message.Command = reader.ReadFixedString(12).decode('utf-8')

            length = reader.ReadUInt32()

            if length > Message.PayloadMaxSizeInt:
                raise Exception("format too big")

            message.Checksum = reader.ReadUInt32()

            message.Payload = bytearray(length)

            if length > 0:
                message.Payload = Message.FillBufferAsyncStream(
                    socket, length, None)

            checksum = Message.GetChecksum(message.Payload)

            if checksum != message.Checksum:

                print("Message command :%s " % message.Command)
                print("Checksum mismatch: %s " % message.Checksum)
                print("message payload: %s " % message.Payload)

                raise Exception("invalid checksum")

            return message

        except Exception as e:
            print("could not receive buffer from socket: %s " % e)
Ejemplo n.º 26
0
    def test_verify_exceeds_free_tx_size_less_low_priority_threshhold(self):
        ms = MemoryStream(binascii.unhexlify(self.vtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)

        self.assertEqual(tx.ToArray(), self.vtx)
        self.assertEqual(tx.Hash.ToBytes(), self.vtx_id)

        snapshot = GetBlockchain()._db.createSnapshot()
        res = tx.Verify(snapshot, [tx])
        self.assertFalse(res)

        tx_size = tx.Size()
        self.assertGreater(tx_size, settings.MAX_FREE_TX_SIZE)

        req_fee = Fixed8.FromDecimal(settings.FEE_PER_EXTRA_BYTE * (tx_size - settings.MAX_FREE_TX_SIZE))
        self.assertLess(req_fee, settings.LOW_PRIORITY_THRESHOLD)

        n_fee = tx.NetworkFee()
        self.assertEqual(n_fee.ToString(), '0')
        self.assertLess(n_fee, req_fee)
Ejemplo n.º 27
0
    def test_publish_tx_deserialize(self):
        ms = MemoryStream(binascii.unhexlify(self.pb_raw))

        reader = BinaryReader(ms)

        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(tx.ToArray(), self.pb_raw)
        self.assertEqual(tx.Hash.ToBytes(), self.pb_hash)

        json = tx.ToJson()
        self.assertEqual(json['size'], 613)
        self.assertEqual(json['type'], 'PublishTransaction')

        contract = json['contract']
        self.assertEqual(contract['author'], 'Erik Zhang')
        self.assertEqual(contract['description'], 'Lock your assets until a timestamp.')

        self.assertEqual(contract['code']['hash'], '0xffbd1a7ad1e2348b6b3822426f364bfb4bcce3b9')
        self.assertEqual(contract['code']['returntype'], "Boolean")
        self.assertEqual(contract['code']['parameters'], ['Integer', 'ByteArray', 'Signature'])
        self.assertEqual(Fixed8.FromDecimal(settings.ALL_FEES['PublishTransaction']), tx.SystemFee())
Ejemplo n.º 28
0
    def test_issue_tx(self):
        ms = MemoryStream(binascii.unhexlify(self.ii))

        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        self.assertEqual(self.ii_id, tx.Hash.ToBytes())

        json = tx.ToJson()
        self.assertEqual(json['size'], 69)
        self.assertEqual(json['type'], "IssueTransaction")
        self.assertEqual(json['version'], 0)
        self.assertEqual(len(json['attributes']), 0)

        jsn_vout = json['vout'][0]
        self.assertEqual(jsn_vout['asset'], "0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b")
        self.assertEqual(jsn_vout['value'], "100000000")
        self.assertEqual(jsn_vout['address'], "AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i")

        self.assertEqual(len(json['vin']), 0)
        self.assertEqual(json['sys_fee'], "0")
        self.assertEqual(json['net_fee'], "0")
        self.assertEqual(json['scripts'][0]['invocation'], "")
        self.assertEqual(json['scripts'][0]['verification'], "51")
Ejemplo n.º 29
0
    def test_message_serialization(self):

        message = Message('version', payload=self.payload)

        self.assertEqual(message.Command, 'version')

        ms = MemoryStream()
        writer = BinaryWriter(ms)

        message.Serialize(writer)
        ms.flush()
        result = binascii.unhexlify(ms.ToArray())

        ms = MemoryStream(result)
        reader = BinaryReader(ms)

        deserialized_message = Message()
        deserialized_message.Deserialize(reader)

        dm = deserialized_message

        self.assertEqual(dm.Command, 'version')

        self.assertEqual(dm.Magic, Settings.MAGIC)

        checksum = Message.GetChecksum(dm.Payload)

        self.assertEqual(checksum, dm.Checksum)

        deserialized_version = IOHelper.AsSerializableWithType(
            dm.Payload, 'neo.Network.Payloads.VersionPayload.VersionPayload')

        self.assertEqual(deserialized_version.Port, self.port)
        self.assertEqual(deserialized_version.UserAgent, self.ua)

        self.assertEqual(deserialized_version.Timestamp,
                         self.payload.Timestamp)
Ejemplo n.º 30
0
 def DeserializeFromBufer(buffer, offset=0):
     mstream = MemoryStream(buffer, offset)
     reader = BinaryReader(mstream)
     return Transaction.DeserializeFrom(reader)
Ejemplo n.º 31
0
 def __init__(self):
     super(ScriptBuilder, self).__init__()
     self.ms = MemoryStream()  # MemoryStream
Ejemplo n.º 32
0
class ScriptBuilder(object):
    """docstring for ScriptBuilder"""
    def __init__(self):
        super(ScriptBuilder, self).__init__()
        self.ms = MemoryStream()  # MemoryStream

    def WriteUInt16(self, value, endian="<"):
        return self.pack('%sH' % endian, value)

    def WriteUInt32(self, value, endian="<"):
        return self.pack('%sI' % endian, value)

    def WriteUInt64(self, value, endian="<"):
        return self.pack('%sQ' % endian, value)

    def WriteVarInt(self, value, endian="<"):
        if not isinstance(value, int):
            raise TypeError('%s not int type.' % value)

        if value < 0:
            raise Exception('%d too small.' % value)

        elif value < 0xfd:
            return self.WriteByte(value)

        elif value <= 0xffff:
            self.WriteByte(0xfd)
            return self.WriteUInt16(value, endian)

        elif value <= 0xFFFFFFFF:
            self.WriteByte(0xfd)
            return self.WriteUInt32(value, endian)

        else:
            self.WriteByte(0xff)
            return self.WriteUInt64(value, endian)

    def WriteVarBytes(self, value, endian="<", unhexlify=True):
        length = len(value)
        self.WriteVarInt(length, endian)
        return self.WriteBytes(value)

    def WriteByte(self, value):
        if type(value) is bytes:
            self.ms.write(value)
        elif type(value) is str:
            self.ms.write(value.encode('utf-8'))
        elif type(value) is int:
            self.ms.write(bytes([value]))

    def WriteBytes(self, value):
        try:
            value = binascii.unhexlify(value)
        except TypeError:
            pass
        except binascii.Error:
            pass
        self.ms.write(value)

    def WriteBool(self, value, endian="<"):
        if value:
            self.add(PUSHT)
        else:
            self.add(PUSHF)

    def pack(self, fmt, data):
        return self.WriteBytes(struct.pack(fmt, data))

    def add(self, op):
        if isinstance(op, int):
            self.ms.write(bytes([op]))
        else:
            self.ms.write(op)
        return

    def push(self, data):
        if data == None:
            return

        if type(data) is bool:
            return self.add(data)

        if type(data) is int or type(data) is BigInteger:
            if data == -1:
                return self.add(PUSHM1)
            elif data == 0:
                return self.add(PUSH0)
            elif data > 0 and data <= 16:
                return self.add(int.from_bytes(PUSH1, 'little') - 1 + data)
            else:
                return self.push(binascii.hexlify(base256_encode(data)))
        else:
            if not type(data) == bytearray:
                buf = binascii.unhexlify(data)
            else:
                buf = bytes(data)
        if len(buf) <= int.from_bytes(PUSHBYTES75, 'big'):
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x100:
            self.add(PUSH1)
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x10000:
            self.add(PUSH2)
            self.add(len(buf) & 0xff)
            self.add(len(buf) >> 8)
            self.add(buf)
        elif len(buf) < 0x100000000:
            self.add(PUSH4)
            self.add(len(buf) & 0xff)
            self.add((len(buf) >> 8) & 0xff)
            self.add((len(buf) >> 16) & 0xff)
            self.add(len(buf) >> 24)
            self.add(buf)
        return

    def WriteVarData(self, data):
        length = len(data)

        if length <= 75:
            self.WriteByte(length)
        elif length < 0x100:
            self.ms.write(PUSHDATA1)
            self.WriteByte(length)
        elif length < 0x1000:
            self.ms.write(PUSHDATA2)
            self.WriteBytes(length.to_bytes(2, 'little'))
        elif length < 0x10000:
            self.ms.write(PUSHDATA4)
            self.WriteBytes(length.to_bytes(4, 'little'))

        self.WriteBytes(data)

    def Emit(self, op, arg=None):
        self.ms.write(op)
        if arg is not None:
            self.ms.write(arg)

    def EmitPushBigInteger(self, number):
        if number == -1: return self.Emit(PUSHM1)
        if number == 0: return self.Emit(PUSH0)
        if number > 0 and number <= 16:
            return self.Emit(int.from_bytes(PUSH1, 'little') - 1 + number)
        return self.Emit(number)

    def EmitAppCall(self, scriptHash, useTailCall=False):
        if len(scriptHash) != 20:
            raise Exception("Invalid script")
        if useTailCall:
            return self.Emit(TAILCALL, scriptHash)
        return self.Emit(APPCALL, scriptHash)

    def EmitSysCall(self, api):
        if api is None:
            raise Exception("Please specify an api")

        api_bytes = bytearray(api.encode('utf-8'))
        length = len(api_bytes)
        length_bytes = bytearray(length.to_bytes(1, 'little'))
        out = length_bytes + api_bytes
        return self.Emit(SYSCALL, out)

    def EmitSysCallWithArguments(self, api, args):

        args.reverse()
        for argument in args:

            if type(argument) is bool:
                self.WriteBool(argument)
            elif type(argument) is bytes and len(argument) == 1:
                self.WriteByte(argument)
            else:
                self.push(binascii.hexlify(argument))

        self.EmitSysCall(api)

    def ToArray(self, cleanup=True):
        retval = self.ms.ToArray()
        if cleanup:
            self.ms.Cleanup()
            self.ms = None

        return retval
Ejemplo n.º 33
0
class ScriptBuilder:
    """docstring for ScriptBuilder"""

    def __init__(self):
        super(ScriptBuilder, self).__init__()
        self.ms = MemoryStream()  # MemoryStream

    def WriteUInt16(self, value, endian="<"):
        return self.pack('%sH' % endian, value)

    def WriteUInt32(self, value, endian="<"):
        return self.pack('%sI' % endian, value)

    def WriteUInt64(self, value, endian="<"):
        return self.pack('%sQ' % endian, value)

    def WriteVarInt(self, value, endian="<"):
        if not isinstance(value, int):
            raise TypeError('%s not int type.' % value)

        if value < 0:
            raise Exception('%d too small.' % value)

        elif value < 0xfd:
            return self.WriteByte(value)

        elif value <= 0xffff:
            self.WriteByte(0xfd)
            return self.WriteUInt16(value, endian)

        elif value <= 0xFFFFFFFF:
            self.WriteByte(0xfe)
            return self.WriteUInt32(value, endian)

        else:
            self.WriteByte(0xff)
            return self.WriteUInt64(value, endian)

    def WriteVarBytes(self, value, endian="<", unhexlify=True):
        length = len(value)
        self.WriteVarInt(length, endian)
        return self.WriteBytes(value)

    def WriteByte(self, value):
        if type(value) is bytes:
            self.ms.write(value)
        elif type(value) is str:
            self.ms.write(value.encode('utf-8'))
        elif type(value) is int:
            self.ms.write(bytes([value]))

    def WriteBytes(self, value):
        try:
            value = binascii.unhexlify(value)
        except TypeError:
            pass
        except binascii.Error:
            pass
        self.ms.write(value)

    def WriteBool(self, value, endian="<"):
        if value:
            self.add(PUSHT)
        else:
            self.add(PUSHF)

    def pack(self, fmt, data):
        return self.WriteBytes(struct.pack(fmt, data))

    def add(self, op):
        if isinstance(op, int):
            self.ms.write(bytes([op]))
        else:
            self.ms.write(op)
        return

    def push(self, data):
        if data is None:
            return

        if type(data) is bool:
            return self.add(data)

        if type(data) is int or type(data) is BigInteger:
            if data == -1:
                return self.add(PUSHM1)
            elif data == 0:
                return self.add(PUSH0)
            elif data > 0 and data <= 16:
                return self.add(int.from_bytes(PUSH1, 'little') - 1 + data)
            else:
                return self.push(binascii.hexlify(data.ToByteArray()))
        else:
            if not type(data) == bytearray:
                buf = binascii.unhexlify(data)
            else:
                buf = bytes(data)
        if len(buf) <= int.from_bytes(PUSHBYTES75, 'big'):
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x100:
            self.add(PUSHDATA1)
            self.add(len(buf))
            self.add(buf)
        elif len(buf) < 0x10000:
            self.add(PUSHDATA2)
            self.add(len(buf) & 0xff)
            self.add(len(buf) >> 8)
            self.add(buf)
        elif len(buf) < 0x100000000:
            self.add(PUSHDATA4)
            self.add(len(buf) & 0xff)
            self.add((len(buf) >> 8) & 0xff)
            self.add((len(buf) >> 16) & 0xff)
            self.add(len(buf) >> 24)
            self.add(buf)
        return

    def WriteVarData(self, data):
        length = len(data)

        if length <= 75:
            self.WriteByte(length)
        elif length < 0x100:
            self.ms.write(PUSHDATA1)
            self.WriteByte(length)
        elif length < 0x1000:
            self.ms.write(PUSHDATA2)
            self.WriteBytes(length.to_bytes(2, 'little'))
        elif length < 0x10000:
            self.ms.write(PUSHDATA4)
            self.WriteBytes(length.to_bytes(4, 'little'))

        self.WriteBytes(data)

    def Emit(self, op, arg=None):
        self.ms.write(op)
        if arg is not None:
            self.ms.write(arg)

    def EmitPushBigInteger(self, number):
        if number == -1:
            return self.Emit(PUSHM1)
        if number == 0:
            return self.Emit(PUSH0)
        if number > 0 and number <= 16:
            return self.Emit(int.from_bytes(PUSH1, 'little') - 1 + number)
        return self.Emit(number)

    def EmitAppCall(self, scriptHash, useTailCall=False):
        if len(scriptHash) != 20:
            raise Exception("Invalid script")
        if useTailCall:
            return self.Emit(TAILCALL, scriptHash)
        return self.Emit(APPCALL, scriptHash)

    def EmitAppCallWithOperationAndData(self, script_hash, operation, data):
        self.push(data)
        self.push(operation.encode('utf-8').hex())
        self.Emit(APPCALL, script_hash.Data)

    def EmitAppCallWithOperationAndArgs(self, script_hash, operation, args):
        args.reverse()
        for i in args:
            self.push(i)
        self.push(len(args))
        self.Emit(PACK)
        self.push(operation.encode('utf-8').hex())
        self.Emit(APPCALL, script_hash.Data)

    def EmitAppCallWithOperation(self, script_hash, operation):
        self.push(False)
        self.push(operation.encode('utf-8').hex())
        self.Emit(APPCALL, script_hash.Data)

    def EmitAppCallWithJsonArgs(self, script_hash, args):
        args.reverse()
        for a in args:
            if isinstance(a.Value, list):
                a.Value.reverse()
                for item in a.Value:
                    self.push(item.ToVM())
                self.push(len(a.Value))
                self.Emit(PACK)
            else:
                self.push(a.ToVM())
        self.Emit(APPCALL, script_hash.Data)

    def EmitSysCall(self, api):
        if api is None:
            raise Exception("Please specify an api")

        api_bytes = bytearray(api.encode('utf-8'))
        length = len(api_bytes)
        length_bytes = bytearray(length.to_bytes(1, 'little'))
        out = length_bytes + api_bytes
        return self.Emit(SYSCALL, out)

    def EmitSysCallWithArguments(self, api, args):

        args.reverse()
        for argument in args:

            if type(argument) is bool:
                self.WriteBool(argument)
            elif type(argument) is bytes and len(argument) == 1:
                self.WriteByte(argument)
            else:
                self.push(binascii.hexlify(argument))

        self.EmitSysCall(api)

    def ToArray(self, cleanup=True):
        retval = self.ms.ToArray()
        if cleanup:
            self.ms.Cleanup()
            self.ms = None

        return retval
Ejemplo n.º 34
0
 def __init__(self):
     super(ScriptBuilder, self).__init__()
     self.ms = MemoryStream()  # MemoryStream