def test_2_serialize_notify_no_payload(self):

        sc = SmartContractEvent(SmartContractEvent.RUNTIME_NOTIFY, [],
                                self.contract_hash, 99, self.event_tx, True,
                                False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        self.assertEqual(
            out,
            b'\x1cSmartContract.Runtime.Notify\x11\xc4\xd1\xf4\xfb\xa6\x19\xf2b\x88p\xd3n:\x97s\xe8tp[c\x00\x00\x00\x90\xe4\xf1\xbbb\x8e\xf1\x07\xde\xe9\xf0\xd2\x12\xd1w\xbco\x844\x07=\x1b\xa7\x1f\xa7\x94`\x0b\xb4\x88|K'
        )

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)
Exemple #2
0
    def test_1_serialize_runtime_log(self):

        sc = SmartContractEvent(
            SmartContractEvent.RUNTIME_LOG,
            ContractParameter(ContractParameterType.Array, []),
            self.contract_hash, 99999, self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        self.assertEqual(
            out,
            b'\x19SmartContract.Runtime.Log\x11\xc4\xd1\xf4\xfb\xa6\x19\xf2b\x88p\xd3n:\x97s\xe8tp[\x9f\x86\x01\x00\x90\xe4\xf1\xbbb\x8e\xf1\x07\xde\xe9\xf0\xd2\x12\xd1w\xbco\x844\x07=\x1b\xa7\x1f\xa7\x94`\x0b\xb4\x88|K'
        )

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)
Exemple #3
0
    def ExecutionCompleted(self, engine, success, error=None):

        height = Blockchain.Default().Height
        tx_hash = engine.ScriptContainer.Hash

        entry_script = None
        try:
            # get the first script that was executed
            # this is usually the script that sets up the script to be executed
            entry_script = UInt160(data=engine.ExecutedScriptHashes[0])

            # ExecutedScriptHashes[1] will usually be the first contract executed
            if len(engine.ExecutedScriptHashes) > 1:
                entry_script = UInt160(data=engine.ExecutedScriptHashes[1])
        except Exception as e:
            logger.error("Could not get entry script: %s " % e)

        payload = []
        for item in engine.EvaluationStack.Items:
            payload_item = stack_item_to_py(item)
            payload.append(payload_item)

        if success:

            # dispatch all notify events, along with the success of the contract execution
            for notify_event_args in self.notifications:
                self.events_to_dispatch.append(
                    NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY,
                                notify_event_args.State,
                                notify_event_args.ScriptHash, height, tx_hash,
                                success, engine.testMode))

            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))

        else:
            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_FAIL,
                                       [payload, error, engine._VMState],
                                       entry_script, height, tx_hash, success,
                                       engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_FAIL,
                                       [payload, error, engine._VMState],
                                       entry_script, height, tx_hash, success,
                                       engine.testMode))

        self.notifications = []
Exemple #4
0
    def test_4_serialize_full_transfer_notify_payload(self):

        payload = ContractParameter(ContractParameterType.Array, [
            ContractParameter(ContractParameterType.String, b'transfer'),
            ContractParameter(ContractParameterType.ByteArray, self.addr_to),
            ContractParameter(ContractParameterType.ByteArray, self.addr_from),
            ContractParameter(ContractParameterType.Integer, 123000)
        ])

        sc = NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY, payload, self.contract_hash, 91349, self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)

        self.assertEqual(new_event.notify_type, b'transfer')
        self.assertEqual(new_event.AddressTo, 'ALb8FEhEmtSqv97fuNVuoLmcmrSKckffRf')
        self.assertEqual(new_event.AddressFrom, 'AKZmSGPD7ytJBbxpRPmobYGLNxdWH3Jiqs')
        self.assertEqual(new_event.Amount, 123000)
        self.assertEqual(new_event.is_standard_notify, True)
Exemple #5
0
    def test_2_serialize_single_notify_payload(self):

        sc = NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY, ContractParameter(ContractParameterType.Array, [ContractParameter(ContractParameterType.String, b'hello')]), self.contract_hash, 99, self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        self.assertEqual(out, b'\x1cSmartContract.Runtime.Notify\x11\xc4\xd1\xf4\xfb\xa6\x19\xf2b\x88p\xd3n:\x97s\xe8tp[c\x00\x00\x00\x90\xe4\xf1\xbbb\x8e\xf1\x07\xde\xe9\xf0\xd2\x12\xd1w\xbco\x844\x07=\x1b\xa7\x1f\xa7\x94`\x0b\xb4\x88|K\x05hello')

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)

        self.assertEqual(new_event.notify_type, b'hello')
        self.assertEqual(new_event.AddressFrom, None)
        self.assertEqual(new_event.AddressTo, None)
        self.assertEqual(new_event.Amount, 0)
        self.assertEqual(new_event.is_standard_notify, False)
Exemple #6
0
    def Contract_Destroy(self, engine):
        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        contract = self.Snapshot.Contracts.TryGet(hash.ToBytes())

        if contract is not None:

            self.Snapshot.Contracts.Delete(hash.ToBytes())

            if contract.HasStorage:

                to_del = []
                for k, v in self.Snapshot.Storages.Find(hash.ToArray()):
                    storage_key = StorageKey(script_hash=hash, key=k[20:])
                    # Snapshot.Storages.Delete() modifies the underlying dictionary of the cache we'd be iterating
                    # over using Storages.Find. We therefore need to postpone deletion
                    to_del.append(storage_key)

                for storage_key in to_del:
                    self.Snapshot.Storages.Delete(storage_key.ToArray())

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_DESTROY,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               GetBlockchain().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))
        return True
    def test_3_serialize_single_transfer_notify_payload(self):

        sc = NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY, [b'transfer'],
                         self.contract_hash, 99, self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)

        self.assertEqual(new_event.notify_type, b'transfer')
        self.assertEqual(new_event.AddressFrom, None)
        self.assertEqual(new_event.AddressTo, None)
        self.assertEqual(new_event.Amount, 0)
        self.assertEqual(new_event.is_standard_notify, False)
        self.assertEqual(new_event.ShouldPersist, False)
Exemple #8
0
    def get_by_addr(self, address):
        """
        Lookup a set of notifications by address
        Args:
            address (UInt160 or str): hash of address for notifications

        Returns:
            list: a list of notifications
        """
        addr = address
        if isinstance(address, str) and len(address) == 34:
            addr = Helper.AddrStrToScriptHash(address)

        if not isinstance(addr, UInt160):
            raise Exception("Incorrect address format")

        addrlist_snapshot = self.db.prefixed_db(NotificationPrefix.PREFIX_ADDR).snapshot()
        results = []

        for val in addrlist_snapshot.iterator(prefix=bytes(addr.Data), include_key=False):
            if len(val) > 4:
                try:
                    event = SmartContractEvent.FromByteArray(val)
                    results.append(event)
                except Exception as e:
                    logger.error("could not parse event: %s %s" % (e, val))
        return results
    def test_5_serialize_full_refund_payload(self):

        sc = NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY,
                         [b'refund', self.addr_to,
                          BigInteger(123000)], self.contract_hash, 91349,
                         self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)

        self.assertEqual(new_event.notify_type, b'refund')
        self.assertEqual(new_event.AddressTo,
                         'AKZmSGPD7ytJBbxpRPmobYGLNxdWH3Jiqs')
        self.assertEqual(new_event.addr_from, sc.contract_hash)
        self.assertEqual(new_event.Amount, 123000)
        self.assertEqual(new_event.is_standard_notify, True)
Exemple #10
0
    def Runtime_Log(self, engine: ExecutionEngine):
        item = engine.CurrentContext.EvaluationStack.Pop()
        # will raise an exception for types that don't support it
        item.GetByteArray()

        # if we pass we can call the convenience method to pretty print the data
        message = item.GetString()

        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash
        engine.write_log(str(message))

        # Build and emit smart contract event
        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.RUNTIME_LOG,
                               ContractParameter(ContractParameterType.String,
                                                 value=message),
                               hash,
                               GetBlockchain().Height + 1,
                               tx_hash,
                               test_mode=engine.testMode))

        return True
Exemple #11
0
    def get_by_contract(self, contract_hash):
        """
        Look up a set of notifications by the contract they are associated with
        Args:
            contract_hash (UInt160 or str): hash of contract for notifications to be retreived

        Returns:
            list: a list of notifications
        """
        hash = contract_hash
        if isinstance(contract_hash, str) and len(contract_hash) == 40:
            hash = UInt160.ParseString(contract_hash)

        if not isinstance(hash, UInt160):
            raise Exception("Incorrect address format")

        contractlist_snapshot = self.db.prefixed_db(NotificationPrefix.PREFIX_CONTRACT).snapshot()
        results = []

        for val in contractlist_snapshot.iterator(prefix=bytes(hash.Data), include_key=False):
            if len(val) > 4:
                try:
                    event = SmartContractEvent.FromByteArray(val)
                    results.append(event)
                except Exception as e:
                    logger.error("could not parse event: %s %s" % (e, val))
        return results
    def test_6_serialize_full_approve_payload(self):

        sc = NotifyEvent(
            SmartContractEvent.RUNTIME_NOTIFY,
            [b'approve', self.addr_to, self.addr_from, b'x\xe0\x01'],
            self.contract_hash, 91349, self.event_tx, True, False)

        stream = StreamManager.GetStream()
        writer = BinaryWriter(stream)
        sc.Serialize(writer)

        out = bytes(stream.getvalue())

        StreamManager.ReleaseStream(stream)
        new_event = SmartContractEvent.FromByteArray(out)

        self.assertEqual(new_event.event_type, sc.event_type)
        self.assertEqual(new_event.contract_hash, sc.contract_hash)
        self.assertEqual(new_event.test_mode, sc.test_mode)
        self.assertEqual(new_event.tx_hash, sc.tx_hash)
        self.assertEqual(new_event.block_number, sc.block_number)

        self.assertEqual(new_event.notify_type, b'approve')
        self.assertEqual(new_event.AddressFrom,
                         'AKZmSGPD7ytJBbxpRPmobYGLNxdWH3Jiqs')
        self.assertEqual(new_event.AddressTo,
                         'ALb8FEhEmtSqv97fuNVuoLmcmrSKckffRf')
        self.assertEqual(new_event.Amount, 123000)
        self.assertEqual(new_event.is_standard_notify, True)
        self.assertEqual(new_event.ShouldPersist, True)
Exemple #13
0
    def test_2_persist_isnt_notify_event(self):
        sc = SmartContractEvent(SmartContractEvent.RUNTIME_NOTIFY, ContractParameter(ContractParameterType.Array, []), self.contract_hash, 99, self.event_tx, True, False)

        ndb = NotificationDB.instance()
        ndb.on_smart_contract_event(sc)

        self.assertEqual(ndb.current_events, [])
Exemple #14
0
    def Storage_Delete(self, engine: ExecutionEngine):
        if self.Trigger != TriggerType.Application and self.Trigger != TriggerType.ApplicationR:
            return False

        context = engine.CurrentContext.EvaluationStack.Pop().GetInterface(
            neo.SmartContract.StorageContext.StorageContext)
        if not self.CheckStorageContext(context):
            return False
        if context.IsReadOnly:
            return False

        key = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)

        if type(engine) == ExecutionEngine:
            test_mode = False
        else:
            test_mode = engine.testMode
        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.STORAGE_DELETE,
                               ContractParameter(ContractParameterType.String,
                                                 key),
                               context.ScriptHash,
                               GetBlockchain().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=test_mode))

        item = self.Snapshot.Storages.TryGet(storage_key.ToArray())
        if item and item.IsConstant:
            return False

        self.Snapshot.Storages.Delete(storage_key.ToArray())

        return True
Exemple #15
0
def dispatch_smart_contract_event(event_type,
                                  event_payload,
                                  contract_hash,
                                  block_number,
                                  tx_hash,
                                  execution_success=False,
                                  test_mode=False):
    sc_event = SmartContractEvent(event_type, event_payload, contract_hash, block_number, tx_hash, execution_success, test_mode)
    events.emit(event_type, sc_event)
Exemple #16
0
 def on_smart_contract_created(self, sc_event: SmartContractEvent):
     """
     Listener for SmartContractEvent
     Args:
         sc_event (SmartContractEvent): event to check and see if it contains NEP5Token created
     """
     if isinstance(sc_event.contract, ContractState):
         sc_event.CheckIsNEP5()
         if sc_event.token:
             self._new_contracts_to_write.append(sc_event)
Exemple #17
0
    def Storage_Get(self, engine):

        context = None
        try:
            item = engine.EvaluationStack.Pop()
            context = item.GetInterface()
            shash = context.ScriptHash
        except Exception as e:
            logger.error("could not get storage context %s " % e)
            return False

        contract = Blockchain.Default().GetContract(
            context.ScriptHash.ToBytes())

        if contract is not None:
            if not contract.HasStorage:
                return False
        else:
            return False

        key = engine.EvaluationStack.Pop().GetByteArray()
        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)
        item = Blockchain.Default().GetStorageItem(storage_key)

        keystr = key

        valStr = bytearray(0)

        if item is not None:
            valStr = bytearray(item.Value)

        if len(key) == 20:
            keystr = Crypto.ToAddress(UInt160(data=key))

            try:
                valStr = int.from_bytes(valStr, 'little')
            except Exception as e:
                logger.error("Could not convert %s to number: %s " %
                             (valStr, e))

        if item is not None:
            engine.EvaluationStack.PushT(bytearray(item.Value))

        else:
            engine.EvaluationStack.PushT(bytearray(0))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.STORAGE_GET,
                               ['%s -> %s' % (keystr, valStr)],
                               context.ScriptHash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash,
                               test_mode=engine.testMode))

        return True
Exemple #18
0
    def Storage_Get(self, engine):

        context = None
        try:
            item = engine.EvaluationStack.Pop()
            context = item.GetInterface()
        except Exception as e:
            logger.error("could not get storage context %s " % e)
            return False

        if not self.CheckStorageContext(context):
            return False

        key = engine.EvaluationStack.Pop().GetByteArray()
        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)
        item = self.Storages.TryGet(storage_key.ToArray())

        keystr = key

        valStr = bytearray(0)

        if item is not None:
            valStr = bytearray(item.Value)

        if len(key) == 20:
            keystr = Crypto.ToAddress(UInt160(data=key))

            try:
                valStr = int.from_bytes(valStr, 'little')
            except Exception as e:
                logger.error("Could not convert %s to number: %s " %
                             (valStr, e))

        if item is not None:
            engine.EvaluationStack.PushT(bytearray(item.Value))

        else:
            engine.EvaluationStack.PushT(bytearray(0))

        tx_hash = None
        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.STORAGE_GET,
                               ContractParameter(ContractParameterType.String,
                                                 value='%s -> %s' %
                                                 (keystr, valStr)),
                               context.ScriptHash,
                               Blockchain.Default().Height + 1,
                               tx_hash,
                               test_mode=engine.testMode))

        return True
Exemple #19
0
 def get_tokens(self):
     """
     Looks up all tokens
     Returns:
         list: A list of smart contract events with contracts that are NEP5 Tokens
     """
     tokens_snapshot = self.db.prefixed_db(NotificationPrefix.PREFIX_TOKEN).snapshot()
     results = []
     for val in tokens_snapshot.iterator(include_key=False):
         event = SmartContractEvent.FromByteArray(val)
         results.append(event)
     return results
Exemple #20
0
    def get_by_block(self, block_number):

        blocklist_snapshot = self.db.prefixed_db(
            NotificationPrefix.PREFIX_BLOCK).snapshot()
        block_bytes = block_number.to_bytes(4, 'little')
        results = []
        for val in blocklist_snapshot.iterator(prefix=block_bytes,
                                               include_key=False):
            event = SmartContractEvent.FromByteArray(val)
            results.append(event)

        return results
Exemple #21
0
    def Runtime_Log(self, engine):
        message = engine.EvaluationStack.Pop().GetByteArray()

        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        # Build and emit smart contract event
        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.RUNTIME_LOG, [message],
                               hash,
                               Blockchain.Default().Height,
                               engine.ScriptContainer.Hash,
                               test_mode=engine.testMode))

        return True
Exemple #22
0
    def get_tokens(self):
        """
        Looks up all tokens
        Returns:
            list: A list of smart contract events with contracts that are NEP5 Tokens
        """
        tokens_snapshot = self.db.getPrefixedDB(
            NotificationPrefix.PREFIX_TOKEN).createSnapshot()
        results = []

        with tokens_snapshot.db.openIter(
                DBProperties(include_key=False)) as it:
            for val in it:
                event = SmartContractEvent.FromByteArray(val)
                results.append(event)
        return results
Exemple #23
0
    def get_by_block(self, block_number):
        """
        Look up notifications for a block
        Args:
            block_number (int): height of block to search for notifications

        Returns:
            list: a list of notifications
        """
        blocklist_snapshot = self.db.prefixed_db(NotificationPrefix.PREFIX_BLOCK).snapshot()
        block_bytes = block_number.to_bytes(4, 'little')
        results = []
        for val in blocklist_snapshot.iterator(prefix=block_bytes, include_key=False):
            event = SmartContractEvent.FromByteArray(val)
            results.append(event)

        return results
Exemple #24
0
    def Storage_Get(self, engine: ExecutionEngine):
        context = None
        try:
            item = engine.CurrentContext.EvaluationStack.Pop()
            context = item.GetInterface(
                neo.SmartContract.StorageContext.StorageContext)
        except Exception as e:
            return False

        if not self.CheckStorageContext(context):
            return False

        key = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)
        item = self.Snapshot.Storages.TryGet(storage_key.ToArray())

        keystr = key

        valStr = bytearray(0)

        if item is not None:
            valStr = bytearray(item.Value)

        if item is not None:
            engine.CurrentContext.EvaluationStack.PushT(bytearray(item.Value))

        else:
            engine.CurrentContext.EvaluationStack.PushT(bytearray(0))

        tx_hash = None
        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.STORAGE_GET,
                               ContractParameter(ContractParameterType.String,
                                                 value='%s -> %s' %
                                                 (keystr, valStr)),
                               context.ScriptHash,
                               GetBlockchain().Height + 1,
                               tx_hash,
                               test_mode=engine.testMode))

        return True
Exemple #25
0
    def get_token(self, hash):
        """
        Looks up a token by hash
        Args:
            hash (UInt160): The token to look up

        Returns:
            SmartContractEvent: A smart contract event with a contract that is an NEP5 Token
        """
        tokens_snapshot = self.db.prefixed_db(NotificationPrefix.PREFIX_TOKEN).snapshot()

        try:
            val = tokens_snapshot.get(hash.ToBytes())
            if val:
                event = SmartContractEvent.FromByteArray(val)
                return event
        except Exception as e:
            logger.error("Smart contract event with contract hash %s not found: %s " % (hash.ToString(), e))
        return None
Exemple #26
0
    def Storage_Put(self, engine: ExecutionEngine):

        context = None
        try:
            context = engine.CurrentContext.EvaluationStack.Pop().GetInterface(
                neo.SmartContract.StorageContext.StorageContext)
        except Exception as e:
            return False

        if not self.CheckStorageContext(context):
            return False

        key = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        if len(key) > 1024:
            return False

        value = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)
        item = self.Snapshot.Storages.GetAndChange(storage_key.ToArray(),
                                                   lambda: StorageItem())
        item.Value = value

        keystr = key
        valStr = bytearray(item.Value)

        if type(engine) == ExecutionEngine:
            test_mode = False
        else:
            test_mode = engine.testMode

        self.events_to_dispatch.append(
            SmartContractEvent(
                SmartContractEvent.STORAGE_PUT,
                ContractParameter(ContractParameterType.String,
                                  '%s -> %s' % (keystr, valStr)),
                context.ScriptHash,
                GetBlockchain().Height + 1,
                engine.ScriptContainer.Hash
                if engine.ScriptContainer else None,
                test_mode=test_mode))

        return True
Exemple #27
0
    def Runtime_Log(self, engine: ExecutionEngine):
        message = engine.CurrentContext.EvaluationStack.Pop().GetString()

        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash
        engine.write_log(str(message))

        # Build and emit smart contract event
        self.events_to_dispatch.append(SmartContractEvent(SmartContractEvent.RUNTIME_LOG,
                                                          ContractParameter(ContractParameterType.String, value=message),
                                                          hash,
                                                          Blockchain.Default().Height + 1,
                                                          tx_hash,
                                                          test_mode=engine.testMode))

        return True
Exemple #28
0
    def get_by_block(self, block_number):
        """
        Look up notifications for a block
        Args:
            block_number (int): height of block to search for notifications

        Returns:
            list: a list of notifications
        """
        blocklist_snapshot = self.db.getPrefixedDB(
            NotificationPrefix.PREFIX_BLOCK).createSnapshot()

        block_bytes = block_number.to_bytes(4, 'little')
        results = []
        with blocklist_snapshot.db.openIter(
                DBProperties(prefix=block_bytes, include_key=False)) as it:
            for val in it:
                event = SmartContractEvent.FromByteArray(val)
                results.append(event)

        return results
Exemple #29
0
    def ExecutionCompleted(self, engine, success, error=None):
        height = Blockchain.Default().Height + 1
        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash

        if not tx_hash:
            tx_hash = UInt256(data=bytearray(32))

        entry_script = None
        try:
            # get the first script that was executed
            # this is usually the script that sets up the script to be executed
            entry_script = UInt160(data=engine.ExecutedScriptHashes[0])

            # ExecutedScriptHashes[1] will usually be the first contract executed
            if len(engine.ExecutedScriptHashes) > 1:
                entry_script = UInt160(data=engine.ExecutedScriptHashes[1])
        except Exception as e:
            logger.error("Could not get entry script: %s " % e)

        payload = ContractParameter(ContractParameterType.Array, value=[])
        for item in engine.ResultStack.Items:
            payload.Value.append(ContractParameter.ToParameter(item))

        if success:

            # dispatch all notify events, along with the success of the contract execution
            for notify_event_args in self.notifications:
                self.events_to_dispatch.append(NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY, notify_event_args.State,
                                                           notify_event_args.ScriptHash, height, tx_hash,
                                                           success, engine.testMode))

            if engine.Trigger == Application:
                self.events_to_dispatch.append(SmartContractEvent(SmartContractEvent.EXECUTION_SUCCESS, payload, entry_script,
                                                                  height, tx_hash, success, engine.testMode))
            else:
                self.events_to_dispatch.append(SmartContractEvent(SmartContractEvent.VERIFICATION_SUCCESS, payload, entry_script,
                                                                  height, tx_hash, success, engine.testMode))

        else:
            # when a contract exits in a faulted state
            # we should display that in the notification
            if not error:
                error = 'Execution exited in a faulted state. Any payload besides this message contained in this event is the contents of the EvaluationStack of the current script context.'

            payload.Value.append(ContractParameter(ContractParameterType.String, error))

            # If we do not add the eval stack, then exceptions that are raised in a contract
            # are not displayed to the event consumer
            [payload.Value.append(ContractParameter.ToParameter(item)) for item in engine.CurrentContext.EvaluationStack.Items]

            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_FAIL, payload,
                                       entry_script, height, tx_hash, success, engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_FAIL, payload,
                                       entry_script, height, tx_hash, success, engine.testMode))

        self.notifications = []
Exemple #30
0
    def ExecutionCompleted(self, engine, success, error=None):
        height = Blockchain.Default().Height + 1
        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash

        if not tx_hash:
            tx_hash = UInt256(data=bytearray(32))

        entry_script = None
        try:
            # get the first script that was executed
            # this is usually the script that sets up the script to be executed
            entry_script = UInt160(data=engine.ExecutedScriptHashes[0])

            # ExecutedScriptHashes[1] will usually be the first contract executed
            if len(engine.ExecutedScriptHashes) > 1:
                entry_script = UInt160(data=engine.ExecutedScriptHashes[1])
        except Exception as e:
            logger.error("Could not get entry script: %s " % e)

        payload = ContractParameter(ContractParameterType.Array, value=[])
        for item in engine.ResultStack.Items:
            payload.Value.append(ContractParameter.ToParameter(item))

        if success:

            # dispatch all notify events, along with the success of the contract execution
            for notify_event_args in self.notifications:
                self.events_to_dispatch.append(
                    NotifyEvent(SmartContractEvent.RUNTIME_NOTIFY,
                                notify_event_args.State,
                                notify_event_args.ScriptHash, height, tx_hash,
                                success, engine.testMode))

            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_SUCCESS,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))

        else:
            payload.Value.append(
                ContractParameter(ContractParameterType.String, error))
            payload.Value.append(
                ContractParameter(ContractParameterType.String,
                                  engine._VMState))
            if engine.Trigger == Application:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.EXECUTION_FAIL,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))
            else:
                self.events_to_dispatch.append(
                    SmartContractEvent(SmartContractEvent.VERIFICATION_FAIL,
                                       payload, entry_script, height, tx_hash,
                                       success, engine.testMode))

        self.notifications = []