示例#1
0
    def __init__(self,
                 stamps_enabled=False,
                 timestamps_enabled=False,
                 driver=ContractDBDriver()):
        install_database_loader()

        self.driver = driver

        self.log = logging.getLogger('Engine')
        self.stamps_enabled = stamps_enabled
        self.timestamps_enabled = timestamps_enabled
示例#2
0
    def execute(self,
                sender,
                contract_name,
                function_name,
                kwargs,
                environment={},
                auto_commit=False,
                driver=None,
                stamps=1000000,
                stamp_cost=config.STAMPS_PER_TAU,
                metering=None) -> dict:

        if not self.bypass_privates:
            assert not function_name.startswith(
                config.PRIVATE_METHOD_PREFIX), 'Private method not callable.'

        if metering is None:
            metering = self.metering

        runtime.rt.env.update({'__Driver': self.driver})

        if driver:
            runtime.rt.env.update({'__Driver': driver})
        else:
            driver = runtime.rt.env.get('__Driver')

        install_database_loader(driver=driver)

        balances_key = None
        try:
            if metering:
                balances_key = '{}{}{}{}{}'.format(self.currency_contract,
                                                   config.INDEX_SEPARATOR,
                                                   self.balances_hash,
                                                   config.DELIMITER, sender)

                balance = driver.get(balances_key)
                if balance is None:
                    balance = 0

                assert balance * stamp_cost >= stamps, 'Sender does not have enough stamps for the transaction. \
                                                               Balance at key {} is {}'.format(
                    balances_key, balance)

            runtime.rt.env.update(environment)
            status_code = 0
            runtime.rt.set_up(
                stmps=stamps * 1000, meter=metering
            )  # Multiply stamps by 1000 because we divide by it later

            runtime.rt.context._base_state = {
                'signer': sender,
                'caller': sender,
                'this': contract_name,
                'owner': driver.get_owner(contract_name)
            }

            if runtime.rt.context.owner is not None and runtime.rt.context.owner != runtime.rt.context.caller:
                raise Exception(
                    f'Caller {runtime.rt.context.caller} is not the owner {runtime.rt.context.owner}!'
                )

            decimal.setcontext(CONTEXT)

            module = importlib.import_module(contract_name)
            func = getattr(module, function_name)

            for k, v in kwargs.items():
                if type(v) == float:
                    kwargs[k] = ContractingDecimal(str(v))

            enable_restricted_imports()
            result = func(**kwargs)
            disable_restricted_imports()

            if auto_commit:
                driver.commit()
        except Exception as e:
            result = e
            tb = traceback.format_exc()
            log.error(str(e))
            log.error(tb)
            status_code = 1
            if auto_commit:
                driver.clear_pending_state()

        ### EXECUTION END

        runtime.rt.tracer.stop()

        # Deduct the stamps if that is enabled
        stamps_used = runtime.rt.tracer.get_stamp_used()

        stamps_used = stamps_used // 1000
        stamps_used += 1
        #stamps_used *= 1000

        if stamps_used > stamps:
            stamps_used = stamps

        if metering:
            assert balances_key is not None, 'Balance key was not set properly. Cannot deduct stamps.'

            to_deduct = stamps_used

            to_deduct /= stamp_cost

            to_deduct = ContractingDecimal(to_deduct)

            balance = driver.get(balances_key)
            if balance is None:
                balance = 0

            balance = max(balance - to_deduct, 0)

            driver.set(balances_key, balance)
            #mark=False)  # This makes sure that the key isnt modified every time in the block
            if auto_commit:
                driver.commit()

        runtime.rt.clean_up()
        runtime.rt.env.update({'__Driver': driver})

        output = {
            'status_code': status_code,
            'result': result,
            'stamps_used': stamps_used,
            'writes': deepcopy(driver.pending_writes),
            'reads': driver.reads
        }

        disable_restricted_imports()

        return output
示例#3
0
 def wipe_modules(self):
     uninstall_builtins()
     install_database_loader()