예제 #1
0
    def Storage_Delete(self, engine):

        context = engine.EvaluationStack.Pop().GetInterface()

        if not self.CheckStorageContext(context):
            return False

        key = engine.EvaluationStack.Pop().GetByteArray()

        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)

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

            self.events_to_dispatch.append(
                SmartContractEvent(SmartContractEvent.STORAGE_DELETE, [keystr],
                                   context.ScriptHash,
                                   Blockchain.Default().Height + 1,
                                   engine.ScriptContainer.Hash
                                   if engine.ScriptContainer else None,
                                   test_mode=engine.testMode))

        self._storages.Remove(storage_key.ToArray())

        return True
예제 #2
0
    def Contract_Destroy(self, engine):
        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        contract = self._contracts.TryGet(hash.ToBytes())

        if contract is not None:

            self._contracts.Remove(hash.ToBytes())

            if contract.HasStorage:

                for pair in self._storages.Find(hash.ToBytes()):
                    self._storages.Remove(pair.Key)

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_DESTROY,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))
        return True
예제 #3
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:
                pass

        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
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))

        return True
예제 #4
0
    def Storage_Put(self, engine: ExecutionEngine):

        context = None
        try:

            context = engine.CurrentContext.EvaluationStack.Pop().GetInterface(
            )
        except Exception as e:
            logger.error("Storage Context Not found on stack")
            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()

        new_item = StorageItem(value=value)
        storage_key = StorageKey(script_hash=context.ScriptHash, key=key)
        item = self._storages.ReplaceOrAdd(storage_key.ToArray(), new_item)

        keystr = key
        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:
                pass

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

        return True
예제 #5
0
    def Contract_Migrate(self, engine):

        script = engine.EvaluationStack.Pop().GetByteArray()

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.EvaluationStack.Pop().GetByteArray()

        if len(param_list) > 252:
            return False

        return_type = int(engine.EvaluationStack.Pop().GetBigInteger())

        contract_properties = engine.EvaluationStack.Pop().GetBigInteger()

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False

        name = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8')

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        version = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8')

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        author = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8')

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        email = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8')

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 65536:
            return False
        description = engine.EvaluationStack.Pop().GetByteArray().decode(
            'utf-8')

        hash = Crypto.ToScriptHash(script, unhex=False)

        contract = self._contracts.TryGet(hash.ToBytes())

        if contract is None:

            code = FunctionCode(script=script,
                                param_list=param_list,
                                return_type=return_type)

            contract = ContractState(code=code,
                                     contract_properties=contract_properties,
                                     name=name,
                                     version=version,
                                     author=author,
                                     email=email,
                                     description=description)

            self._contracts.Add(hash.ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

            if contract.HasStorage:

                for pair in self._storages.Find(
                        engine.CurrentContext.ScriptHash()):
                    key = StorageKey(script_hash=hash, key=pair.Key.Key)
                    item = StorageItem(pair.Value.Value)
                    self._storages.Add(key, item)

        engine.EvaluationStack.PushT(StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_MIGRATED,
                               [contract],
                               hash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))

        return self.Contract_Destroy(engine)
예제 #6
0
    def Contract_Create(self, engine):

        script = engine.EvaluationStack.Pop().GetByteArray()

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.EvaluationStack.Pop().GetByteArray()
        if len(param_list) > 252:
            return False

        return_type = int(engine.EvaluationStack.Pop().GetBigInteger())

        contract_properties = int(engine.EvaluationStack.Pop().GetBigInteger())

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False

        name = engine.EvaluationStack.Pop().GetByteArray()

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        code_version = engine.EvaluationStack.Pop().GetByteArray()

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        author = engine.EvaluationStack.Pop().GetByteArray()

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 252:
            return False
        email = engine.EvaluationStack.Pop().GetByteArray()

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 65536:
            return False

        description = engine.EvaluationStack.Pop().GetByteArray()

        hash = Crypto.ToScriptHash(script, unhex=False)

        contract = self._contracts.TryGet(hash.ToBytes())

        if contract is None:
            code = FunctionCode(script=script,
                                param_list=param_list,
                                return_type=return_type,
                                contract_properties=contract_properties)

            contract = ContractState(code, contract_properties, name,
                                     code_version, author, email, description)

            self._contracts.GetAndChange(code.ScriptHash().ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

        engine.EvaluationStack.PushT(StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_CREATED, [contract],
                               hash,
                               Blockchain.Default().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))
        return True
예제 #7
0
    def Contract_Migrate(self, engine: ExecutionEngine):

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

        if len(script) > 1024 * 1024:
            return False

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

        if len(param_list) > 252:
            return False

        return_type = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())

        contract_properties = engine.CurrentContext.EvaluationStack.Pop(
        ).GetBigInteger()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False

        name = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        version = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        author = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        email = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 65536:
            return False
        description = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(
        ).decode('utf-8')

        hash = Crypto.ToScriptHash(script, unhex=False)

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

        if contract is None:

            code = FunctionCode(script=script,
                                param_list=param_list,
                                return_type=return_type)

            contract = ContractState(code=code,
                                     contract_properties=contract_properties,
                                     name=name,
                                     version=version,
                                     author=author,
                                     email=email,
                                     description=description)

            self.Snapshot.Contracts.Add(hash.ToBytes(), contract)

            cur_hash = UInt160(data=engine.CurrentContext.ScriptHash())
            self._contracts_created[hash.ToBytes()] = cur_hash

            if contract.HasStorage:
                to_add = []
                for key, item in self.Snapshot.Storages.Find(
                        cur_hash.ToArray()):
                    key = StorageKey(script_hash=hash, key=key[20:])
                    to_add.append((key.ToArray(), item))

                for k, v in to_add:
                    self.Snapshot.Storages.Add(k, v)

        engine.CurrentContext.EvaluationStack.PushT(
            StackItem.FromInterface(contract))

        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.CONTRACT_MIGRATED,
                               ContractParameter(
                                   ContractParameterType.InteropInterface,
                                   contract),
                               hash,
                               GetBlockchain().Height + 1,
                               engine.ScriptContainer.Hash
                               if engine.ScriptContainer else None,
                               test_mode=engine.testMode))

        return self.Contract_Destroy(engine)
예제 #8
0
    def Contract_Create(self, engine: ExecutionEngine):

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

        if len(script) > 1024 * 1024:
            return False

        param_list = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        if len(param_list) > 252:
            return False
        return_type = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())
        if return_type < 0 or return_type > 0xff:
            raise ValueError("Invalid return type data popped from stack")

        contract_properties = int(
            engine.CurrentContext.EvaluationStack.Pop().GetBigInteger())

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        name = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        code_version = engine.CurrentContext.EvaluationStack.Pop(
        ).GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        author = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 252:
            return False
        email = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        if len(engine.CurrentContext.EvaluationStack.Peek().GetByteArray()
               ) > 65536:
            return False

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

        hash = Crypto.ToScriptHash(script, unhex=False)

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

        if contract is None:
            try:
                code = FunctionCode(script=script,
                                    param_list=param_list,
                                    return_type=return_type,
                                    contract_properties=contract_properties)
            except ValueError:
                # exception is caused by an invalid `return_type`. neo-cli accepts this , but we throw an exception
                # this is a dirty hack to work around the VM state difference that it causes until neo-cli hopefully fixes it
                # see https://github.com/neo-project/neo/issues/827
                code = FunctionCode(script=script,
                                    param_list=param_list,
                                    contract_properties=contract_properties)
                code.ReturnType = return_type

            contract = ContractState(code, contract_properties, name,
                                     code_version, author, email, description)

            self.Snapshot.Contracts.Add(code.ScriptHash().ToBytes(), contract)

            self._contracts_created[hash.ToBytes()] = UInt160(
                data=engine.CurrentContext.ScriptHash())

        engine.CurrentContext.EvaluationStack.PushT(
            StackItem.FromInterface(contract))

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