Пример #1
0
    def Run(script,
            container=None,
            exit_on_error=False,
            gas=Fixed8.Zero(),
            test_mode=True):
        """
        Runs a script in a test invoke environment

        Args:
            script (bytes): The script to run
            container (neo.Core.TX.Transaction): [optional] the transaction to use as the script container

        Returns:
            ApplicationEngine
        """

        from neo.Core.Blockchain import Blockchain
        from neo.SmartContract.StateMachine import StateMachine
        from neo.EventHub import events

        bc = Blockchain.Default()
        sn = bc._db.snapshot()

        accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
        assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                                  ValidatorState)
        contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract,
                                 ContractState)
        storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

        script_table = CachedScriptTable(contracts)
        service = StateMachine(accounts, validators, assets, contracts,
                               storages, None)

        engine = ApplicationEngine(trigger_type=TriggerType.Application,
                                   container=container,
                                   table=script_table,
                                   service=service,
                                   gas=gas,
                                   testMode=test_mode,
                                   exit_on_error=exit_on_error)

        script = binascii.unhexlify(script)

        engine.LoadScript(script, False)

        try:
            success = engine.Execute()
            engine.testMode = True
            service.ExecutionCompleted(engine, success)
        except Exception as e:
            engine.testMode = True
            service.ExecutionCompleted(engine, False, e)

        for event in service.events_to_dispatch:
            events.emit(event.event_type, event)

        return engine
Пример #2
0
    def Run(script, container=None):

        from neo.Core.Blockchain import Blockchain
        from neo.SmartContract.StateMachine import StateMachine

        bc = Blockchain.Default()

        sn = bc._db.snapshot()

        accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
        assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator, ValidatorState)
        contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
        storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

        script_table = CachedScriptTable(contracts)
        service = StateMachine(accounts, validators, assets, contracts, storages, None)

        engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=container,
            table=script_table,
            service=service,
            gas=Fixed8.Zero(),
            testMode=True
        )

        engine.LoadScript(script, False)
        engine.Execute()
        return engine
Пример #3
0
def GetStateMachine():
    from neo.SmartContract.StateMachine import StateMachine
    from neo.Storage.Interface.DBInterface import DBInterface
    from neo.Storage.Common.DBPrefix import DBPrefix
    from neo.Core.State.AccountState import AccountState
    from neo.Core.State.AssetState import AssetState
    from neo.Core.State.ValidatorState import ValidatorState
    from neo.Core.State.ContractState import ContractState
    from neo.Core.State.StorageItem import StorageItem

    bc = GetBlockchain()

    accounts = DBInterface(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBInterface(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBInterface(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBInterface(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBInterface(bc._db, DBPrefix.ST_Storage, StorageItem)

    return StateMachine(accounts, validators, assets, contracts, storages,
                        None, bc)
Пример #4
0
    def __init__(self,
                 trigger_type,
                 container,
                 snapshot,
                 gas,
                 testMode=False,
                 exit_on_error=True):

        super(ApplicationEngine,
              self).__init__(container=container,
                             crypto=Crypto.Default(),
                             table=snapshot,
                             service=StateMachine(trigger_type, snapshot),
                             exit_on_error=exit_on_error)

        self.gas_amount = self.gas_free + gas.value
        self.testMode = testMode
        self.snapshot = snapshot
        self._is_stackitem_count_strict = True
        self.debugger = None
        self.gas_consumed = 0
        self.invocation_args = None
Пример #5
0
def construct_invoke_tx(wallet, params):
    params = params[0]
    from_addr = params['from_addr']
    
    BC = GetBlockchain()

    contract = BC.GetContract(params['addr'])

    if not contract:
        raise Exception('no such contract')

    neo_to_attach = params.get('neo_to_attach', 0)
    gas_to_attach = params.get('gas_to_attach', 0)

    sb = ScriptBuilder()
    contract_parameters = [ContractParameter.FromJson(p) for p in params['contract_params']]
    sb.EmitAppCallWithJsonArgs(contract.Code.ScriptHash(), contract_parameters)
    
    invoke_script = sb.ToArray()

    outputs = []

    if neo_to_attach:

        output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract.Code.ScriptHash(),
        )
        outputs.append(output)

    if gas_to_attach:

        output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                Value=gas_to_attach,
                script_hash=contract.Code.ScriptHash(),
        )

        outputs.append(output)

    bc = GetBlockchain()
    sn = bc._db.snapshot()
    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)


    tx = InvocationTransaction()
    tx.outputs = outputs
    tx.inputs = []
    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(invoke_script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages, None)
    contract = wallet.GetDefaultContract()
    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)]
    tx = wallet.MakeTransaction(tx=tx)

    engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=tx,
            table=script_table,
            service=service,
            gas=tx.Gas,
            testMode=True
    )   
    engine.LoadScript(tx.Script, False)
    success = engine.Execute()
    if not success:
        raise Exception('exec failed')
    
    service.ExecutionCompleted(engine, success)

    consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
    consumed = consumed.Ceil()

    net_fee = None
    tx_gas = None

    if consumed <= Fixed8.Zero():
        net_fee = Fixed8.FromDecimal(.0001)
        tx_gas = Fixed8.Zero()
    else:
        tx_gas = consumed
        net_fee = Fixed8.Zero()
    tx.Gas = tx_gas
    tx.outputs = outputs
    tx.Attributes = []



    # InvokeContract
    from_addr = lookup_addr_str(wallet, from_addr)
    tx = wallet.MakeTransaction(tx=tx, fee=net_fee, use_standard=True, from_addr=from_addr)
    if tx is None:
        raise Exception("no gas")


    context = ContractParametersContext(tx)
    ms = StreamManager.GetStream()
    writer = BinaryWriter(ms)
    tx.Serialize(writer)
    ms.flush()
    binary_tx = ms.ToArray()
    return {'context': context.ToJson(), 'tx': binary_tx.decode()}
Пример #6
0
    def Persist(self, block):

        self._persisting_block = block

        sn = self._db.snapshot()
        accounts = DBCollection(self._db, sn, DBPrefix.ST_Account, AccountState)
        unspentcoins = DBCollection(self._db, sn, DBPrefix.ST_Coin, UnspentCoinState)
        spentcoins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState)
        assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(self._db, sn, DBPrefix.ST_Validator, ValidatorState)
        contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState)
        storages = DBCollection(self._db, sn, DBPrefix.ST_Storage, StorageItem)

        amount_sysfee = self.GetSysFeeAmount(block.PrevHash) + block.TotalFees().value
        amount_sysfee_bytes = amount_sysfee.to_bytes(8, 'little')

        to_dispatch = []

        with self._db.write_batch() as wb:

            wb.put(DBPrefix.DATA_Block + block.Hash.ToBytes(), amount_sysfee_bytes + block.Trim())

            for tx in block.Transactions:

                wb.put(DBPrefix.DATA_Transaction + tx.Hash.ToBytes(), block.IndexBytes() + tx.ToArray())

                # go through all outputs and add unspent coins to them

                unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed(tx.outputs)
                unspentcoins.Add(tx.Hash.ToBytes(), unspentcoinstate)

                # go through all the accounts in the tx outputs
                for output in tx.outputs:
                    account = accounts.GetAndChange(output.AddressBytes, AccountState(output.ScriptHash))

                    if account.HasBalance(output.AssetId):
                        account.AddToBalance(output.AssetId, output.Value)
                    else:
                        account.SetBalanceFor(output.AssetId, output.Value)

                # go through all tx inputs
                unique_tx_input_hashes = []
                for input in tx.inputs:
                    if input.PrevHash not in unique_tx_input_hashes:
                        unique_tx_input_hashes.append(input.PrevHash)

                for txhash in unique_tx_input_hashes:
                    prevTx, height = self.GetTransaction(txhash.ToBytes())
                    coin_refs_by_hash = [coinref for coinref in tx.inputs if
                                         coinref.PrevHash.ToBytes() == txhash.ToBytes()]
                    for input in coin_refs_by_hash:

                        uns = unspentcoins.GetAndChange(input.PrevHash.ToBytes())
                        uns.OrEqValueForItemAt(input.PrevIndex, CoinState.Spent)

                        if prevTx.outputs[input.PrevIndex].AssetId.ToBytes() == Blockchain.SystemShare().Hash.ToBytes():
                            sc = spentcoins.GetAndChange(input.PrevHash.ToBytes(),
                                                         SpentCoinState(input.PrevHash, height, []))
                            sc.Items.append(SpentCoinItem(input.PrevIndex, block.Index))

                        output = prevTx.outputs[input.PrevIndex]
                        acct = accounts.GetAndChange(prevTx.outputs[input.PrevIndex].AddressBytes,
                                                     AccountState(output.ScriptHash))
                        assetid = prevTx.outputs[input.PrevIndex].AssetId
                        acct.SubtractFromBalance(assetid, prevTx.outputs[input.PrevIndex].Value)

                # do a whole lotta stuff with tx here...
                if tx.Type == TransactionType.RegisterTransaction:
                    asset = AssetState(tx.Hash, tx.AssetType, tx.Name, tx.Amount,
                                       Fixed8(0), tx.Precision, Fixed8(0), Fixed8(0), UInt160(data=bytearray(20)),
                                       tx.Owner, tx.Admin, tx.Admin, block.Index + 2 * 2000000, False)

                    assets.Add(tx.Hash.ToBytes(), asset)

                elif tx.Type == TransactionType.IssueTransaction:

                    txresults = [result for result in tx.GetTransactionResults() if result.Amount.value < 0]
                    for result in txresults:
                        asset = assets.GetAndChange(result.AssetId.ToBytes())
                        asset.Available = asset.Available - result.Amount

                elif tx.Type == TransactionType.ClaimTransaction:
                    for input in tx.Claims:

                        sc = spentcoins.TryGet(input.PrevHash.ToBytes())
                        if sc and sc.HasIndex(input.PrevIndex):
                            sc.DeleteIndex(input.PrevIndex)
                            spentcoins.GetAndChange(input.PrevHash.ToBytes())

                elif tx.Type == TransactionType.EnrollmentTransaction:
                    newvalidator = ValidatorState(pub_key=tx.PublicKey)
                    validators.GetAndChange(tx.PublicKey.ToBytes(), newvalidator)
                elif tx.Type == TransactionType.StateTransaction:
                    # @TODO Implement persistence for State Descriptors
                    pass

                elif tx.Type == TransactionType.PublishTransaction:
                    contract = ContractState(tx.Code, tx.NeedStorage, tx.Name, tx.CodeVersion,
                                             tx.Author, tx.Email, tx.Description)

                    contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(), contract)
                elif tx.Type == TransactionType.InvocationTransaction:

                    script_table = CachedScriptTable(contracts)
                    service = StateMachine(accounts, validators, assets, contracts, storages, wb)

                    engine = ApplicationEngine(
                        trigger_type=TriggerType.Application,
                        container=tx,
                        table=script_table,
                        service=service,
                        gas=tx.Gas,
                        testMode=False
                    )

                    engine.LoadScript(tx.Script, False)

                    try:
                        success = engine.Execute()
                        service.ExecutionCompleted(engine, success)

                    except Exception as e:
                        service.ExecutionCompleted(engine, False, e)

                    to_dispatch = to_dispatch + service.events_to_dispatch
                else:

                    if tx.Type != b'\x00' and tx.Type != 128:
                        logger.info("TX Not Found %s " % tx.Type)

            # do save all the accounts, unspent, coins, validators, assets, etc
            # now sawe the current sys block

            # filter out accounts to delete then commit
            for key, account in accounts.Current.items():
                if not account.IsFrozen and len(account.Votes) == 0 and account.AllBalancesZeroOrLess():
                    accounts.Remove(key)

            accounts.Commit(wb)

            # filte out unspent coins to delete then commit
            for key, unspent in unspentcoins.Current.items():
                if unspent.IsAllSpent:
                    unspentcoins.Remove(key)
            unspentcoins.Commit(wb)

            # filter out spent coins to delete then commit to db
            for key, spent in spentcoins.Current.items():
                if len(spent.Items) == 0:
                    spentcoins.Remove(key)
            spentcoins.Commit(wb)

            # commit validators
            validators.Commit(wb)

            # commit assets
            assets.Commit(wb)

            # commit contracts
            contracts.Commit(wb)

            sn.close()

            wb.put(DBPrefix.SYS_CurrentBlock, block.Hash.ToBytes() + block.IndexBytes())
            self._current_block_height = block.Index
            self._persisting_block = None

            self.TXProcessed += len(block.Transactions)

        for event in to_dispatch:
            events.emit(event.event_type, event)
Пример #7
0
def construct_deploy_tx(wallet, params):
    params = params[0]
    from_addr = params['from_addr']
    # load_smart_contract
    contract_params = bytearray(binascii.unhexlify(params['contract_params']))
    return_type = bytearray(binascii.unhexlify(params['return_type']))
    
    contract_properties = 0
    if params.get('needs_storage', True):
        contract_properties += ContractPropertyState.HasStorage
    if params.get('needs_dynamic_invoke', False):
        contract_properties += ContractPropertyState.HasDynamicInvoke

    script = binascii.unhexlify(params['bin'])

    function_code = FunctionCode(
            script = script,
            param_list = contract_params,
            return_type = return_type,
            contract_properties = contract_properties,
    )

    if Blockchain.Default().GetContract(function_code.ScriptHash().To0xString()):
        raise Exception('contract already exists')

    # GatherContractDetails
    details = params['details']
    name = details['name']
    version = details['version']
    author = details['author']
    email = details['email']
    description = details['description']

    contract_script = generate_deploy_script(
            function_code.Script,
            name,
            version,
            author,
            email,
            description,
            function_code.ContractProperties,
            function_code.ReturnType,
            function_code.ParameterList,
    )

    # test_invoke    
    bc = GetBlockchain()
    sn = bc._db.snapshot()
    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)


    tx = InvocationTransaction()
    tx.outputs = []
    tx.inputs = []
    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(contract_script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages, None)
    contract = wallet.GetDefaultContract()
    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)]
    tx = wallet.MakeTransaction(tx=tx)

    engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=tx,
            table=script_table,
            service=service,
            gas=tx.Gas,
            testMode=True
    )   
    engine.LoadScript(tx.Script, False)
    success = engine.Execute()
    if not success:
        raise Exception('exec failed')
    
    service.ExecutionCompleted(engine, success)

    consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
    consumed = consumed.Ceil()

    net_fee = None
    tx_gas = None

    if consumed <= Fixed8.Zero():
        net_fee = Fixed8.FromDecimal(.0001)
        tx_gas = Fixed8.Zero()
    else:
        tx_gas = consumed
        net_fee = Fixed8.Zero()
    tx.Gas = tx_gas
    tx.outputs = []
    tx.Attributes = []

    # InvokeContract
    from_addr = lookup_addr_str(wallet, from_addr)
    tx = wallet.MakeTransaction(tx=tx, fee=net_fee, use_standard=True, from_addr=from_addr)
    if tx is None:
        raise Exception("no gas")


    context = ContractParametersContext(tx)
    ms = StreamManager.GetStream()
    writer = BinaryWriter(ms)
    tx.Serialize(writer)
    ms.flush()
    binary_tx = ms.ToArray()
    return {'context': context.ToJson(), 'tx': binary_tx.decode(), 'hash': function_code.ScriptHash().To0xString()}
Пример #8
0
def test_invoke(script,
                wallet,
                outputs,
                withdrawal_tx=None,
                from_addr=None,
                min_fee=DEFAULT_MIN_FEE,
                invoke_attrs=None,
                owners=None):
    # print("invoke script %s " % script)

    if from_addr is not None:
        from_addr = PromptUtils.lookup_addr_str(wallet, from_addr)

    bc = GetBlockchain()

    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)

    # if we are using a withdrawal tx, don't recreate the invocation tx
    # also, we don't want to reset the inputs / outputs
    # since those were already calculated
    if withdrawal_tx is not None:
        tx = withdrawal_tx

    else:
        tx = InvocationTransaction()
        tx.outputs = outputs
        tx.inputs = []

    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)
    tx.Attributes = [] if invoke_attrs is None else deepcopy(invoke_attrs)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes.append(
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=contract.ScriptHash))
        tx.Attributes = make_unique_script_attr(tx.Attributes)

    # same as above. we don't want to re-make the transaction if it is a withdrawal tx
    if withdrawal_tx is not None:
        wallet_tx = tx
    else:
        try:
            wallet_tx = wallet.MakeTransaction(tx=tx,
                                               from_addr=from_addr,
                                               skip_fee_calc=True)
        except ValueError:
            pass

    context = ContractParametersContext(wallet_tx)
    wallet.Sign(context)

    if owners:
        owners = list(owners)
        for owner in owners:
            #            print("contract %s %s" % (wallet.GetDefaultContract().ScriptHash, owner))
            if wallet.GetDefaultContract().ScriptHash != owner:
                wallet_tx.Attributes.append(
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script, data=owner))
                wallet_tx.Attributes = make_unique_script_attr(tx.Attributes)
        context = ContractParametersContext(wallet_tx, isMultiSig=True)

    if context.Completed:
        wallet_tx.scripts = context.GetScripts()
    else:
        logger.warning(
            "Not gathering signatures for test build.  For a non-test invoke that would occur here."
        )
    #        if not gather_signatures(context, wallet_tx, owners):
    #            return None, [], 0, None

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=wallet_tx,
                               table=script_table,
                               service=service,
                               gas=wallet_tx.Gas,
                               testMode=True)

    engine.LoadScript(wallet_tx.Script)

    try:
        success = engine.Execute()

        service.ExecutionCompleted(engine, success)

        for event in service.events_to_dispatch:
            events.emit(event.event_type, event)

        if success:

            # this will be removed in favor of neo.EventHub
            if len(service.notifications) > 0:
                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            # print("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            net_fee = None
            tx_gas = None

            if consumed <= Fixed8.Zero():
                net_fee = min_fee
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            # set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas
            # reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = [] if invoke_attrs is None else deepcopy(
                invoke_attrs)

            # calculate the required network fee for the tx and compare to fee
            if wallet_tx.Size() > settings.MAX_FREE_TX_SIZE:
                req_fee = Fixed8.FromDecimal(
                    settings.FEE_PER_EXTRA_BYTE *
                    (wallet_tx.Size() - settings.MAX_FREE_TX_SIZE))
                if req_fee < settings.LOW_PRIORITY_THRESHOLD:
                    req_fee = settings.LOW_PRIORITY_THRESHOLD
                if net_fee < req_fee:
                    net_fee = req_fee

            return wallet_tx, net_fee, engine.ResultStack.Items, engine.ops_processed, success

        # this allows you to to test invocations that fail
        else:
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = [] if invoke_attrs is None else deepcopy(
                invoke_attrs)
            return wallet_tx, min_fee, [], engine.ops_processed, success

    except Exception as e:
        service.ExecutionCompleted(engine, False, e)

    return None, None, None, None, False
Пример #9
0
def test_deploy_and_invoke(deploy_script,
                           invoke_args,
                           wallet,
                           from_addr=None,
                           min_fee=DEFAULT_MIN_FEE,
                           invocation_test_mode=True,
                           debug_map=None,
                           invoke_attrs=None,
                           owners=None):
    bc = GetBlockchain()

    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)

    if settings.USE_DEBUG_STORAGE:
        debug_storage = DebugStorage.instance()
        storages = DBCollection(debug_storage.db, DBPrefix.ST_Storage,
                                StorageItem)
        storages.DebugStorage = True

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    if from_addr is not None:
        from_addr = PromptUtils.lookup_addr_str(wallet, from_addr)

    try:
        dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr)
    except (ValueError, TXFeeError):
        pass

    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script,
                                                      unhex=False))
    ]
    dtx.Attributes = make_unique_script_attr(dtx.Attributes)

    to_dispatch = []

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=dtx,
                               table=script_table,
                               service=service,
                               gas=dtx.Gas,
                               testMode=True)

    engine.LoadScript(dtx.Script)

    # first we will execute the test deploy
    # then right after, we execute the test invoke

    d_success = engine.Execute()

    if d_success:

        items = engine.ResultStack.Items

        contract_state = None
        for i in items:
            if type(i) is ContractState:
                contract_state = i
                break
            elif type(i) is InteropInterface:
                item = i.GetInterface()
                if type(item) is ContractState:
                    contract_state = item
                    break

        shash = contract_state.Code.ScriptHash()

        invoke_args, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(
            invoke_args)
        invoke_args, no_parse_addresses = PromptUtils.get_parse_addresses(
            invoke_args)

        invoke_args.reverse()

        if '--i' in invoke_args:
            invoke_args = []
            for index, iarg in enumerate(contract_state.Code.ParameterList):
                param, abort = PromptUtils.gather_param(index, iarg)
                if abort:
                    return None, [], 0, None
                else:
                    invoke_args.append(param)
            invoke_args.reverse()

        sb = ScriptBuilder()

        for p in invoke_args:
            item = PromptUtils.parse_param(p,
                                           wallet,
                                           parse_addr=no_parse_addresses)
            if type(item) is list:
                item.reverse()
                listlength = len(item)
                for listitem in item:
                    subitem = PromptUtils.parse_param(
                        listitem, wallet, parse_addr=no_parse_addresses)
                    if type(subitem) is list:
                        subitem.reverse()
                        for listitem2 in subitem:
                            subsub = PromptUtils.parse_param(
                                listitem2,
                                wallet,
                                parse_addr=no_parse_addresses)
                            sb.push(subsub)
                        sb.push(len(subitem))
                        sb.Emit(PACK)
                    else:
                        sb.push(subitem)

                sb.push(listlength)
                sb.Emit(PACK)
            else:
                sb.push(item)

        sb.EmitAppCall(shash.Data)
        out = sb.ToArray()

        outputs = []

        if neo_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract_state.Code.ScriptHash(),
            )
            outputs.append(output)

        if gas_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemCoin().Hash,
                Value=gas_to_attach,
                script_hash=contract_state.Code.ScriptHash())

            outputs.append(output)

        itx = InvocationTransaction()
        itx.Version = 1
        itx.outputs = outputs
        itx.inputs = []
        itx.scripts = []
        itx.Attributes = deepcopy(invoke_attrs) if invoke_attrs else []
        itx.Script = binascii.unhexlify(out)

        if len(outputs) < 1 and not owners:
            contract = wallet.GetDefaultContract()
            itx.Attributes.append(
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=contract.ScriptHash))
            itx.Attributes = make_unique_script_attr(itx.Attributes)

        try:
            itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr)
        except (ValueError, TXFeeError):
            pass

        context = ContractParametersContext(itx)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            for owner in owners:
                itx.Attributes.append(
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script, data=owner))
                itx.Attributes = make_unique_script_attr(itx.Attributes)
            context = ContractParametersContext(itx, isMultiSig=True)

        if context.Completed:
            itx.scripts = context.GetScripts()
        else:
            logger.warn(
                "Not gathering signatures for test build.  For a non-test invoke that would occur here."
            )
        #            if not gather_signatures(context, itx, owners):
        #                return None, [], 0, None

        #        print("gathered signatures %s " % itx.scripts)

        engine = ApplicationEngine(trigger_type=TriggerType.Application,
                                   container=itx,
                                   table=script_table,
                                   service=service,
                                   gas=itx.Gas,
                                   testMode=invocation_test_mode)

        engine.invocation_args = invoke_args
        engine.LoadScript(itx.Script)
        engine.LoadDebugInfoForScriptHash(debug_map, shash.Data)

        i_success = engine.Execute()

        service.ExecutionCompleted(engine, i_success)
        to_dispatch = to_dispatch + service.events_to_dispatch

        for event in to_dispatch:
            events.emit(event.event_type, event)

        if i_success:
            service.TestCommit()
            if len(service.notifications) > 0:

                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            logger.info("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            if consumed <= Fixed8.Zero():
                consumed = min_fee

            total_ops = engine.ops_processed

            # set the amount of gas the tx will need
            itx.Gas = consumed
            itx.Attributes = []
            result = engine.ResultStack.Items
            return itx, result, total_ops, engine
        else:
            print("error executing invoke contract...")

    else:
        print("error executing deploy contract.....")

    service.ExecutionCompleted(engine, False, 'error')

    return None, [], 0, None
Пример #10
0
def test_invoke(script,
                wallet,
                outputs,
                withdrawal_tx=None,
                from_addr=None,
                min_fee=DEFAULT_MIN_FEE):

    # print("invoke script %s " % script)

    if from_addr is not None:
        from_addr = lookup_addr_str(wallet, from_addr)

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    # if we are using a withdrawal tx, don't recreate the invocation tx
    # also, we don't want to reset the inputs / outputs
    # since those were already calculated
    if withdrawal_tx is not None:
        tx = withdrawal_tx

    else:
        tx = InvocationTransaction()
        tx.outputs = outputs
        tx.inputs = []

    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=Crypto.ToScriptHash(contract.Script,
                                                          unhex=False).Data)
        ]

    # same as above. we don't want to re-make the transaction if it is a withdrawal tx
    if withdrawal_tx is not None:
        wallet_tx = tx
    else:
        wallet_tx = wallet.MakeTransaction(tx=tx, from_addr=from_addr)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)
        wallet.Sign(context)
        if context.Completed:
            wallet_tx.scripts = context.GetScripts()

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=wallet_tx,
                               table=script_table,
                               service=service,
                               gas=wallet_tx.Gas,
                               testMode=True)

    engine.LoadScript(wallet_tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        service.ExecutionCompleted(engine, success)

        for event in service.events_to_dispatch:
            events.emit(event.event_type, event)

        if success:

            # this will be removed in favor of neo.EventHub
            if len(service.notifications) > 0:
                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            print("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            net_fee = None
            tx_gas = None

            if consumed <= Fixed8.Zero():
                net_fee = min_fee
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            # set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas
            # reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []

            return wallet_tx, net_fee, engine.EvaluationStack.Items, engine.ops_processed

    except Exception as e:
        service.ExecutionCompleted(engine, False, e)


#        print("COULD NOT EXECUTE %s " % e)

    return None, None, None, None
Пример #11
0
def test_deploy_and_invoke(deploy_script,
                           invoke_args,
                           wallet,
                           from_addr=None,
                           min_fee=DEFAULT_MIN_FEE,
                           invocation_test_mode=True,
                           debug_map=None):

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    if settings.USE_DEBUG_STORAGE:
        debug_storage = DebugStorage.instance()
        debug_sn = debug_storage.db.snapshot()
        storages = DBCollection(debug_storage.db, debug_sn,
                                DBPrefix.ST_Storage, StorageItem)
        storages.DebugStorage = True

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    if from_addr is not None:
        from_addr = lookup_addr_str(wallet, from_addr)

    dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr)
    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script,
                                                      unhex=False))
    ]

    to_dispatch = []

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=dtx,
                               table=script_table,
                               service=service,
                               gas=dtx.Gas,
                               testMode=True)

    engine.LoadScript(dtx.Script, False)

    # first we will execute the test deploy
    # then right after, we execute the test invoke

    d_success = engine.Execute()

    if d_success:

        items = engine.EvaluationStack.Items

        contract_state = None
        for i in items:
            if type(i) is ContractState:
                contract_state = i
                break
            elif type(i) is InteropInterface:
                item = i.GetInterface()
                if type(item) is ContractState:
                    contract_state = item
                    break

        shash = contract_state.Code.ScriptHash()

        invoke_args, neo_to_attach, gas_to_attach = get_asset_attachments(
            invoke_args)

        invoke_args.reverse()

        # print("neo, gas %s %s " % (neo_to_attach,gas_to_attach.ToString()))

        sb = ScriptBuilder()

        for p in invoke_args:

            item = parse_param(p, wallet)

            if type(item) is list:
                item.reverse()
                listlength = len(item)
                for listitem in item:
                    subitem = parse_param(listitem, wallet)
                    sb.push(subitem)
                sb.push(listlength)
                sb.Emit(PACK)
            else:
                sb.push(item)

        sb.EmitAppCall(shash.Data)
        out = sb.ToArray()

        outputs = []

        if neo_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract_state.Code.ScriptHash(),
            )
            outputs.append(output)

        if gas_to_attach:
            output = TransactionOutput(
                AssetId=Blockchain.SystemCoin().Hash,
                Value=gas_to_attach,
                script_hash=contract_state.Code.ScriptHash())

            outputs.append(output)

        itx = InvocationTransaction()
        itx.Version = 1
        itx.outputs = outputs
        itx.inputs = []
        itx.scripts = []
        itx.Attributes = []
        itx.Script = binascii.unhexlify(out)

        if len(outputs) < 1:
            contract = wallet.GetDefaultContract()
            itx.Attributes = [
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=Crypto.ToScriptHash(
                                         contract.Script, unhex=False).Data)
            ]

        itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr)
        context = ContractParametersContext(itx)
        wallet.Sign(context)
        itx.scripts = context.GetScripts()

        #            print("tx: %s " % json.dumps(itx.ToJson(), indent=4))

        engine = ApplicationEngine(trigger_type=TriggerType.Application,
                                   container=itx,
                                   table=script_table,
                                   service=service,
                                   gas=itx.Gas,
                                   testMode=invocation_test_mode)

        engine.LoadScript(itx.Script, False)
        engine.LoadDebugInfo(debug_map)

        # call execute in its own blocking thread

        #        reactor.stop()

        i_success = engine.Execute()

        service.ExecutionCompleted(engine, i_success)
        to_dispatch = to_dispatch + service.events_to_dispatch

        for event in to_dispatch:
            events.emit(event.event_type, event)

        if i_success:
            service.TestCommit()
            if len(service.notifications) > 0:

                for n in service.notifications:
                    #                        print("NOTIFICATION : %s " % n)
                    Blockchain.Default().OnNotify(n)

            logger.info("Used %s Gas " % engine.GasConsumed().ToString())

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed = consumed.Ceil()

            if consumed <= Fixed8.Zero():
                consumed = min_fee

            total_ops = engine.ops_processed

            # set the amount of gas the tx will need
            itx.Gas = consumed
            itx.Attributes = []
            result = engine.EvaluationStack.Items
            return itx, result, total_ops, engine
        else:
            print("error executing invoke contract...")

    else:
        print("error executing deploy contract.....")

    service.ExecutionCompleted(engine, False, 'error')

    return None, [], 0, None
Пример #12
0
def test_invoke(script, wallet, outputs):

    #    print("invoke script %s " % script)

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    tx = InvocationTransaction()
    tx.Version = 1
    tx.outputs = outputs
    tx.inputs = []
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=Crypto.ToScriptHash(
                                     contract.Script).Data)
        ]

    wallet_tx = wallet.MakeTransaction(tx=tx)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)
        wallet.Sign(context)
        if context.Completed:
            wallet_tx.scripts = context.GetScripts()

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=wallet_tx,
                               table=script_table,
                               service=service,
                               gas=wallet_tx.Gas,
                               testMode=True)

    engine.LoadScript(wallet_tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        if success:

            service.TestCommit()

            if len(service.notifications) > 0:
                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed.value = int(consumed.value)

            net_fee = None
            tx_gas = None

            if consumed < Fixed8.One():
                net_fee = Fixed8.FromDecimal(.001)
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            #set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas

            #reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []

            return wallet_tx, net_fee, engine.EvaluationStack.Items, engine.ops_processed
        else:
            print("error executing contract.....")
            #            tx.Gas = Fixed8.One()
            #            tx.Attributes = []
            #            return tx, []
            return None, []

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)

    return None, []
Пример #13
0
    def Persist(self, block):

        accounts = DBCollection(self._db, DBPrefix.ST_Account, AccountState)
        unspentcoins = DBCollection(self._db, DBPrefix.ST_Coin,
                                    UnspentCoinState)
        spentcoins = DBCollection(self._db, DBPrefix.ST_SpentCoin,
                                  SpentCoinState)
        assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(self._db, DBPrefix.ST_Validator,
                                  ValidatorState)
        contracts = DBCollection(self._db, DBPrefix.ST_Contract, ContractState)
        storages = DBCollection(self._db, DBPrefix.ST_Storage, StorageItem)

        amount_sysfee = self.GetSysFeeAmount(
            block.PrevHash) + block.TotalFees().value
        amount_sysfee_bytes = amount_sysfee.to_bytes(8, 'little')

        with self._db.write_batch() as wb:
            for tx in block.Transactions:

                unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed(
                    tx.outputs)
                unspentcoins.Add(tx.Hash.ToBytes(), unspentcoinstate)

                # go through all the accounts in the tx outputs
                for output in tx.outputs:
                    account = accounts.GetAndChange(
                        output.AddressBytes, AccountState(output.ScriptHash))

                    if account.HasBalance(output.AssetId):
                        account.AddToBalance(output.AssetId, output.Value)
                    else:
                        account.SetBalanceFor(output.AssetId, output.Value)

                # go through all tx inputs
                unique_tx_input_hashes = []
                for input in tx.inputs:
                    if input.PrevHash not in unique_tx_input_hashes:
                        unique_tx_input_hashes.append(input.PrevHash)

                for txhash in unique_tx_input_hashes:
                    prevTx, height = self.GetTransaction(txhash.ToBytes())
                    coin_refs_by_hash = [
                        coinref for coinref in tx.inputs
                        if coinref.PrevHash.ToBytes() == txhash.ToBytes()
                    ]
                    for input in coin_refs_by_hash:

                        uns = unspentcoins.GetAndChange(
                            input.PrevHash.ToBytes())
                        uns.OrEqValueForItemAt(input.PrevIndex,
                                               CoinState.Spent)

                        if prevTx.outputs[input.PrevIndex].AssetId.ToBytes(
                        ) == Blockchain.SystemShare().Hash.ToBytes():
                            sc = spentcoins.GetAndChange(
                                input.PrevHash.ToBytes(),
                                SpentCoinState(input.PrevHash, height, []))
                            sc.Items.append(
                                SpentCoinItem(input.PrevIndex, block.Index))

                        output = prevTx.outputs[input.PrevIndex]
                        acct = accounts.GetAndChange(
                            prevTx.outputs[input.PrevIndex].AddressBytes,
                            AccountState(output.ScriptHash))
                        assetid = prevTx.outputs[input.PrevIndex].AssetId
                        acct.SubtractFromBalance(
                            assetid, prevTx.outputs[input.PrevIndex].Value)

                # do a whole lotta stuff with tx here...
                if tx.Type == TransactionType.RegisterTransaction:

                    asset = AssetState(tx.Hash, tx.AssetType, tx.Name,
                                       tx.Amount, Fixed8(0), tx.Precision,
                                       Fixed8(0), Fixed8(0),
                                       UInt160(data=bytearray(20)), tx.Owner,
                                       tx.Admin, tx.Admin,
                                       block.Index + 2 * 2000000, False)

                    assets.Add(tx.Hash.ToBytes(), asset)

                elif tx.Type == TransactionType.IssueTransaction:

                    txresults = [
                        result for result in tx.GetTransactionResults()
                        if result.Amount.value < 0
                    ]
                    for result in txresults:
                        asset = assets.GetAndChange(result.AssetId.ToBytes())
                        asset.Available = asset.Available - result.Amount

                elif tx.Type == TransactionType.ClaimTransaction:

                    for input in tx.Claims:

                        sc = spentcoins.TryGet(input.PrevHash.ToBytes())
                        if sc and sc.HasIndex(input.PrevIndex):
                            sc.DeleteIndex(input.PrevIndex)
                            spentcoins.GetAndChange(input.PrevHash.ToBytes())

                elif tx.Type == TransactionType.EnrollmentTransaction:

                    validator = validators.GetAndChange(
                        tx.PublicKey, ValidatorState(pub_key=tx.PublicKey))
                    #                        logger.info("VALIDATOR %s " % validator.ToJson())

                elif tx.Type == TransactionType.StateTransaction:
                    # @TODO Implement persistence for State Descriptors
                    pass

                elif tx.Type == TransactionType.PublishTransaction:

                    contract = ContractState(tx.Code, tx.NeedStorage, tx.Name,
                                             tx.CodeVersion, tx.Author,
                                             tx.Email, tx.Description)

                    contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(),
                                           contract)

                elif tx.Type == TransactionType.InvocationTransaction:

                    script_table = CachedScriptTable(contracts)
                    service = StateMachine(accounts,
                                           validators,
                                           assets,
                                           contracts,
                                           storages,
                                           wb=wb)

                    engine = ApplicationEngine(
                        trigger_type=TriggerType.Application,
                        container=tx,
                        table=script_table,
                        service=service,
                        gas=tx.Gas,
                        testMode=True)

                    engine.LoadScript(tx.Script)

                    # normally, this function does not return true/false
                    # for testing purposes, we try to execute and if an exception is raised
                    # we will return false, otherwise if success return true

                    # this is different than the 'success' bool returned by engine.Execute()
                    # the 'success' bool returned by engine.Execute() is a value indicating
                    # wether or not the invocation was successful, and if so, we then commit
                    # the changes made by the contract to the database
                    try:
                        success = engine.Execute()
                        # service.ExecutionCompleted(engine, success)
                        return True
                    except Exception as e:
                        # service.ExecutionCompleted(self, False, e)
                        return False
Пример #14
0
    def Persist(self, block):

        start = time.clock()

        sn = self._db.snapshot()
        accounts = DBCollection(self._db, sn, DBPrefix.ST_Account, AccountState)
        unspentcoins = DBCollection(self._db, sn, DBPrefix.ST_Coin, UnspentCoinState)
        spentcoins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState)
        assets = DBCollection(self._db, sn, DBPrefix.ST_Asset, AssetState)
        validators = DBCollection(self._db, sn, DBPrefix.ST_Validator, ValidatorState)
        contracts = DBCollection(self._db, sn, DBPrefix.ST_Contract, ContractState)
        storages = DBCollection(self._db, sn, DBPrefix.ST_Storage, StorageItem)

        amount_sysfee = self.GetSysFeeAmount(block.PrevHash) + block.TotalFees().value
        amount_sysfee_bytes = amount_sysfee.to_bytes(8, 'little')
        self.__log.debug("[BlockFee] : %s %s " % (block.Index, amount_sysfee))

        try:
            with self._db.write_batch() as wb:

                wb.put(DBPrefix.DATA_Block + block.Hash.ToBytes(), amount_sysfee_bytes + block.Trim())

                for tx in block.Transactions:

                    wb.put(DBPrefix.DATA_Transaction + tx.Hash.ToBytes(), block.IndexBytes() + tx.ToArray())

                    # go through all outputs and add unspent coins to them

                    unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed(tx.outputs)
                    unspentcoins.Add(tx.Hash.ToBytes(), unspentcoinstate)

                    # go through all the accounts in the tx outputs
                    for output in tx.outputs:
                        account = accounts.GetAndChange(output.AddressBytes, AccountState(output.ScriptHash))

                        if account.HasBalance(output.AssetId):
                            account.AddToBalance(output.AssetId, output.Value)
                        else:
                            account.SetBalanceFor(output.AssetId, output.Value)

                    # go through all tx inputs
                    unique_tx_input_hashes = []
                    for input in tx.inputs:
                        if input.PrevHash not in unique_tx_input_hashes:
                            unique_tx_input_hashes.append(input.PrevHash)

                    for txhash in unique_tx_input_hashes:
                        prevTx, height = self.GetTransaction(txhash.ToBytes())
                        coin_refs_by_hash = [coinref for coinref in tx.inputs if coinref.PrevHash.ToBytes() == txhash.ToBytes()]
                        for input in coin_refs_by_hash:

                            uns = unspentcoins.GetAndChange(input.PrevHash.ToBytes())
                            uns.OrEqValueForItemAt(input.PrevIndex, CoinState.Spent)

                            if prevTx.outputs[input.PrevIndex].AssetId.ToBytes() == Blockchain.SystemShare().Hash.ToBytes():
                                sc = spentcoins.GetAndChange(input.PrevHash.ToBytes(), SpentCoinState(input.PrevHash, height, []))
                                sc.Items.append(SpentCoinItem(input.PrevIndex, block.Index))

                            output = prevTx.outputs[input.PrevIndex]
                            acct = accounts.GetAndChange(prevTx.outputs[input.PrevIndex].AddressBytes, AccountState(output.ScriptHash))
                            assetid = prevTx.outputs[input.PrevIndex].AssetId
                            acct.SubtractFromBalance(assetid, prevTx.outputs[input.PrevIndex].Value)

                    # do a whole lotta stuff with tx here...
                    if tx.Type == TransactionType.RegisterTransaction:
                        asset = AssetState(tx.Hash, tx.AssetType, tx.Name, tx.Amount,
                                           Fixed8(0), tx.Precision, Fixed8(0), Fixed8(0), UInt160(data=bytearray(20)),
                                           tx.Owner, tx.Admin, tx.Admin, block.Index + 2 * 2000000, False)

                        assets.Add(tx.Hash.ToBytes(), asset)

                    elif tx.Type == TransactionType.IssueTransaction:

                        txresults = [result for result in tx.GetTransactionResults() if result.Amount.value < 0]
                        for result in txresults:
                            asset = assets.GetAndChange(result.AssetId.ToBytes())
                            asset.Available = asset.Available - result.Amount

                    elif tx.Type == TransactionType.ClaimTransaction:
                        for input in tx.Claims:

                            sc = spentcoins.TryGet(input.PrevHash.ToBytes())
                            if sc and sc.HasIndex(input.PrevIndex):
                                sc.DeleteIndex(input.PrevIndex)
                                spentcoins.GetAndChange(input.PrevHash.ToBytes())

                    elif tx.Type == TransactionType.EnrollmentTransaction:
                        newvalidator = ValidatorState(pub_key=tx.PublicKey)
                        validators.GetAndChange(tx.PublicKey.ToBytes(), newvalidator)
                    elif tx.Type == TransactionType.PublishTransaction:
                        contract = ContractState(tx.Code, tx.NeedStorage, tx.Name, tx.CodeVersion,
                                                 tx.Author, tx.Email, tx.Description)

                        contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(), contract)
                    elif tx.Type == TransactionType.InvocationTransaction:

                        #                        print("RUNNING INVOCATION TRASACTION!!!!!! %s %s " % (block.Index, tx.Hash.ToBytes()))
                        print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: Invoke tx] -> index, tx hash %s %s " % (block.Index, tx.Hash.ToBytes()))
                        script_table = CachedScriptTable(contracts)
                        service = StateMachine(accounts, validators, assets, contracts, storages, wb)

                        engine = ApplicationEngine(
                            trigger_type=TriggerType.Application,
                            container=tx,
                            table=script_table,
                            service=service,
                            gas=tx.Gas,
                            testMode=False
                        )

                        engine.LoadScript(tx.Script, False)

                        try:
                            # drum roll?
                            success = engine.Execute()
                            print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute] -> Success")
                            if success:
                                service.Commit()

                                if len(service.notifications) > 0:
                                    for n in service.notifications:
                                        self.OnNotify(n)

                            for item in engine.EvaluationStack.Items:
                                print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute result] -> %s " % item)

                        except Exception as e:
                            print("[neo.Implementations.Blockchains.LevelDBBlockchain.PersistBlock: engine execute result] Could not execute smart contract.  See logs for more details. %s " % e)
                    else:

                        if tx.Type != b'\x00' and tx.Type != 128:
                            self.__log.debug("TX Not Found %s " % tx.Type)

                # do save all the accounts, unspent, coins, validators, assets, etc
                # now sawe the current sys block

                # filter out accounts to delete then commit
                for key, account in accounts.Current.items():
                    if not account.IsFrozen and len(account.Votes) == 0 and account.AllBalancesZeroOrLess():
                        accounts.Remove(key)

                accounts.Commit(wb)

                # filte out unspent coins to delete then commit
                for key, unspent in unspentcoins.Current.items():
                    unspentcoins.Remove(key)
                unspentcoins.Commit(wb)

                # filter out spent coins to delete then commit to db
                for key, spent in spentcoins.Current.items():
                    if len(spent.Items) == 0:
                        spentcoins.Remove(key)
                spentcoins.Commit(wb)

                # commit validators
                validators.Commit(wb)

                # commit assets
                assets.Commit(wb)

                # commit contracts
                contracts.Commit(wb)

                # commit storages ( not implemented )
                storages.Commit(wb)

                sn.close()

                wb.put(DBPrefix.SYS_CurrentBlock, block.Hash.ToBytes() + block.IndexBytes())
                self._current_block_height = block.Index

                end = time.clock()
                self.__log.debug("PERSISTING BLOCK %s (cache) %s %s " % (block.Index, len(self._block_cache), end - start))
        except Exception as e:
            print("couldnt persist block %s " % e)
Пример #15
0
def test_deploy_and_invoke(deploy_script, invoke_args, wallet):

    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    dtx = InvocationTransaction()
    dtx.Version = 1
    dtx.outputs = []
    dtx.inputs = []
    dtx.scripts = []
    dtx.Script = binascii.unhexlify(deploy_script)

    dtx = wallet.MakeTransaction(tx=dtx)
    context = ContractParametersContext(dtx)
    wallet.Sign(context)
    dtx.scripts = context.GetScripts()

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()
    dtx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script))
    ]

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=dtx,
                               table=script_table,
                               service=service,
                               gas=dtx.Gas,
                               testMode=True)

    engine.LoadScript(dtx.Script, False)

    # first we will execute the test deploy
    # then right after, we execute the test invoke

    try:
        d_success = engine.Execute()

        if d_success:

            items = engine.EvaluationStack.Items

            contract_state = None
            for i in items:
                if type(i) is ContractState:
                    contract_state = i
                    break
                elif type(i) is InteropInterface:
                    item = i.GetInterface('neo.whatever')
                    if type(item) is ContractState:
                        contract_state = item
                        break

            shash = contract_state.Code.ScriptHash()

            invoke_args, neo_to_attach, gas_to_attach = get_asset_attachments(
                invoke_args)

            invoke_args.reverse()

            sb = ScriptBuilder()

            # print("neo, gas %s %s " % (neo_to_attach,gas_to_attach.ToString()))

            sb = ScriptBuilder()

            for p in invoke_args:

                item = parse_param(p)

                if type(item) is list:
                    item.reverse()
                    listlength = len(item)
                    for listitem in item:
                        sb.push(listitem)
                    sb.push(listlength)
                    sb.Emit(PACK)
                else:
                    sb.push(item)

            sb.EmitAppCall(shash.Data)
            out = sb.ToArray()

            outputs = []

            if neo_to_attach:
                output = TransactionOutput(
                    AssetId=Blockchain.SystemShare().Hash,
                    Value=neo_to_attach,
                    script_hash=contract_state.Code.ScriptHash(),
                )
                outputs.append(output)

            if gas_to_attach:
                output = TransactionOutput(
                    AssetId=Blockchain.SystemCoin().Hash,
                    Value=gas_to_attach,
                    script_hash=contract_state.Code.ScriptHash())

                outputs.append(output)

            itx = InvocationTransaction()
            itx.Version = 1
            itx.outputs = outputs
            itx.inputs = []
            itx.scripts = []
            itx.Attributes = []
            itx.Script = binascii.unhexlify(out)

            if len(outputs) < 1:
                contract = wallet.GetDefaultContract()
                itx.Attributes = [
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script,
                        data=Crypto.ToScriptHash(contract.Script).Data)
                ]

            itx = wallet.MakeTransaction(tx=itx)
            context = ContractParametersContext(itx)
            wallet.Sign(context)
            itx.scripts = context.GetScripts()

            #            print("tx: %s " % json.dumps(itx.ToJson(), indent=4))

            engine = ApplicationEngine(trigger_type=TriggerType.Application,
                                       container=itx,
                                       table=script_table,
                                       service=service,
                                       gas=itx.Gas,
                                       testMode=True)

            engine.LoadScript(itx.Script, False)

            i_success = engine.Execute()

            if i_success:
                service.TestCommit()

                if len(service.notifications) > 0:
                    for n in service.notifications:
                        Blockchain.Default().OnNotify(n)

                consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
                consumed.value = int(consumed.value)

                if consumed < Fixed8.One():
                    consumed = Fixed8.FromDecimal(.001)

                total_ops = engine.ops_processed

                # set the amount of gas the tx will need
                itx.Gas = consumed
                itx.Attributes = []
                result = engine.ResultsForCode(contract_state.Code)
                return itx, result, total_ops
            else:
                print("error executing invoke contract...")

        else:
            print("error executing deploy contract.....")

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)
        traceback.print_stack()
        traceback.print_exc()

    return None, [], 0
Пример #16
0
def test_invoke(script, wallet):
    bc = GetBlockchain()

    sn = bc._db.snapshot()

    accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator,
                              ValidatorState)
    contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

    tx = InvocationTransaction()
    tx.Version = 0
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    contract = wallet.GetDefaultContract()

    tx.Attributes = [
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=Crypto.ToScriptHash(contract.Script))
    ]

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=tx,
                               table=script_table,
                               service=service,
                               gas=tx.Gas,
                               testMode=True)

    engine.LoadScript(tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        if success:

            service.TestCommit()

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)

            if consumed < Fixed8.One():
                consumed = Fixed8.One()

            #set the amount of gas the tx will need
            tx.Gas = consumed

            #remove the attributes that are used to add a verification script to the tx
            tx.Attributes = []

            return tx, engine.EvaluationStack.Items

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)

    return None, []
Пример #17
0
    def setUp(self):
        self.engine = ExecutionEngine()
        self.econtext = ExecutionContext(Script(self.engine.Crypto, b''), 0)
        self.engine.InvocationStack.PushT(self.econtext)

        self.service = StateMachine(None, None)
Пример #18
0
class InteropSerializeDeserializeTestCase(TestCase):
    def setUp(self):
        self.engine = ExecutionEngine()
        self.econtext = ExecutionContext(Script(self.engine.Crypto, b''), 0)
        self.engine.InvocationStack.PushT(self.econtext)

        self.service = StateMachine(None, None)

    def test_iter_array(self):
        my_array = Array([
            StackItem.New(12),
            StackItem.New(b'Hello World'),
            StackItem.New(True),
            Array([StackItem.New(113442),
                   StackItem.New(2),
                   StackItem.New(3)])
        ])
        self.econtext.EvaluationStack.PushT(my_array)
        self.engine.InvocationStack.PushT(self.econtext)
        self.service.Enumerator_Create(self.engine)

        iterable = self.econtext.EvaluationStack.Peek(0).GetInterface()

        self.assertIsInstance(iterable, ArrayWrapper)

        keys = []
        values = []
        while iterable.Next():
            currentKey = iterable.Key()
            keys.append(currentKey.GetBigInteger())
            values.append(iterable.Value())

        self.assertEqual(keys, [0, 1, 2, 3])
        self.assertEqual(values, my_array.GetArray())

    def test_iter_map(self):
        my_map = Map({
            StackItem.New('a'): StackItem.New(1),
            StackItem.New('b'): StackItem.New(3),
            StackItem.New('d'): StackItem.New(432)
        })

        self.econtext.EvaluationStack.PushT(my_map)
        self.engine.InvocationStack.PushT(self.econtext)

        self.service.Iterator_Create(self.engine)

        iterable = self.econtext.EvaluationStack.Peek(0).GetInterface()

        self.assertIsInstance(iterable, MapWrapper)

        keys = []
        values = []
        while iterable.Next():
            keys.append(iterable.Key())
            values.append(iterable.Value())

        self.assertEqual(
            keys, [StackItem.New('a'),
                   StackItem.New('b'),
                   StackItem.New('d')])
        self.assertEqual(keys, my_map.Keys)

        self.assertEqual(
            values, [StackItem.New(1),
                     StackItem.New(3),
                     StackItem.New(432)])
        self.assertEqual(values, my_map.Values)

    def test_iter_array_keys(self):
        my_array = Array([
            StackItem.New(12),
            StackItem.New(b'Hello World'),
            StackItem.New(True),
            Array([StackItem.New(113442),
                   StackItem.New(2),
                   StackItem.New(3)])
        ])
        self.econtext.EvaluationStack.PushT(my_array)
        self.engine.InvocationStack.PushT(self.econtext)
        self.service.Enumerator_Create(self.engine)

        create_iterkeys = self.service.Iterator_Keys(self.engine)

        self.assertEqual(create_iterkeys, True)

        iterkeys = self.econtext.EvaluationStack.Peek(0).GetInterface()

        self.assertIsInstance(iterkeys, KeysWrapper)

        keys = []
        while iterkeys.Next():
            keys.append(iterkeys.Value().GetBigInteger())

        self.assertEqual(keys, [0, 1, 2, 3])

    def test_iter_array_values(self):
        my_array = Array([
            StackItem.New(12),
            StackItem.New(b'Hello World'),
            StackItem.New(True),
            Array([StackItem.New(113442),
                   StackItem.New(2),
                   StackItem.New(3)])
        ])
        self.econtext.EvaluationStack.PushT(my_array)
        self.engine.InvocationStack.PushT(self.econtext)
        self.service.Enumerator_Create(self.engine)

        create_itervalues = self.service.Iterator_Values(self.engine)

        self.assertEqual(create_itervalues, True)

        itervals = self.econtext.EvaluationStack.Peek(0).GetInterface()

        self.assertIsInstance(itervals, ValuesWrapper)

        values = []
        while itervals.Next():
            values.append(itervals.Value())

        self.assertEqual(values, my_array.GetArray())

    def test_iter_concat(self):
        my_array = Array([
            StackItem.New(12),
            StackItem.New(b'Hello World'),
            StackItem.New(True),
            Array([StackItem.New(113442),
                   StackItem.New(2),
                   StackItem.New(3)])
        ])

        my_array2 = Array([
            StackItem.New(b'a'),
            StackItem.New(b'b'),
            StackItem.New(4),
            StackItem.New(100)
        ])

        self.econtext.EvaluationStack.PushT(my_array2)
        self.engine.InvocationStack.PushT(self.econtext)
        self.service.Enumerator_Create(self.engine)

        self.econtext.EvaluationStack.PushT(my_array)

        self.service.Enumerator_Create(self.engine)

        result = self.service.Enumerator_Concat(self.engine)

        self.assertEqual(result, True)

        concatted_enum = self.econtext.EvaluationStack.Peek().GetInterface()

        self.assertIsInstance(concatted_enum, ConcatenatedEnumerator)

        values = []
        count = 0

        while concatted_enum.Next():
            count += 1
            values.append(concatted_enum.Value())

        self.assertEqual(count, 8)
        self.assertEqual(values, my_array.GetArray() + my_array2.GetArray())

    def test_iter_array_bad(self):
        my_item = StackItem.New(12)
        self.econtext.EvaluationStack.PushT(my_item)
        self.engine.InvocationStack.PushT(self.econtext)

        result = self.service.Enumerator_Create(self.engine)

        self.assertEqual(result, False)
        self.assertEqual(self.econtext.EvaluationStack.Count, 0)

    def test_iter_map_bad(self):
        my_item = StackItem.New(12)
        self.econtext.EvaluationStack.PushT(my_item)
        self.engine.InvocationStack.PushT(self.econtext)
        result = self.service.Iterator_Create(self.engine)

        self.assertEqual(result, False)
        self.assertEqual(self.econtext.EvaluationStack.Count, 0)

    def test_iter_array_key_bad(self):
        my_item = StackItem.New(12)
        self.econtext.EvaluationStack.PushT(my_item)
        self.engine.InvocationStack.PushT(self.econtext)

        result = self.service.Iterator_Key(self.engine)

        self.assertEqual(result, False)
        self.assertEqual(self.econtext.EvaluationStack.Count, 0)

    def test_iter_array_values_bad(self):
        my_item = StackItem.New(12)
        self.econtext.EvaluationStack.PushT(my_item)
        self.engine.InvocationStack.PushT(self.econtext)

        result = self.service.Iterator_Values(self.engine)

        self.assertEqual(result, False)
        self.assertEqual(self.econtext.EvaluationStack.Count, 0)

    def test_iter_array_keys_bad(self):

        my_item = StackItem.New(12)
        self.econtext.EvaluationStack.PushT(my_item)
        self.engine.InvocationStack.PushT(self.econtext)
        result = self.service.Iterator_Keys(self.engine)

        self.assertEqual(result, False)
        self.assertEqual(self.econtext.EvaluationStack.Count, 0)