示例#1
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface()

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            logger.error("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            return False

        acct = self._accounts.GetAndChange(account.AddressBytes)
        voteset = []
        for v in vote_list:
            if v not in voteset:
                voteset.append(v.GetByteArray())
        acct.Votes = voteset

        # print("*****************************************************")
        # print("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        # print("*****************************************************")
        return True
示例#2
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface(
                'neo.Core.State.AccountState.AccountState')

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            self.__log.debug("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            print("no balance, return false!")
            return False

        print("Setting votes!!!")

        acct = self._accounts.GetAndChange(account.AddressBytes)
        voteset = set()
        for v in vote_list:
            voteset.add(v.GetByteArray())
        acct.Votes = list(voteset)
        print("*****************************************************")
        print("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        print("*****************************************************")
        return True
示例#3
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface(
                'neo.Core.State.AccountState.AccountState')

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            self.__log.debug("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            return False

#       disable setting votes for now until further testing to make sure we're not duplicating votes
#
#        acct = self._accounts.GetAndChange(account.AddressBytes)
#        voteset = set()
#        for v in vote_list:
#            voteset.add(v.GetByteArray())
#        acct.Votes = list(voteset)
#        self.__log.debug("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        return True
示例#4
0
    def test_issue_tx(self):

        miner_tx = MinerTransaction()
        miner_tx.Nonce = 2083236893

        share_tx = GetSystemShare()
        coin_tx = GetSystemCoin()

        script = Contract.CreateMultiSigRedeemScript(int(len(Blockchain.StandbyValidators()) / 2) + 1, Blockchain.StandbyValidators())

        if Settings.MAGIC == 1953787457:
            self.assertEqual(script, self.contractraw)
            out = Crypto.ToScriptHash(script)

            output = TransactionOutput(
                share_tx.Hash,
                Blockchain.SystemShare().Amount,
                out
            )

            script = Witness( bytearray(0), bytearray(PUSHT))

            issue_tx = IssueTransaction([],[output],[], [script])
            self.assertEqual(issue_tx.GetHashData(), self.issuetx_rraw)
            self.assertEqual(issue_tx.Hash.ToBytes(), self.gen_issue_tx_id)
示例#5
0
def TestInvokeContract(wallet, args, withdrawal_tx=None, from_addr=None,
                       min_fee=DEFAULT_MIN_FEE, invoke_attrs=None, owners=None):
    BC = GetBlockchain()

    contract = BC.GetContract(args[0])

    if contract:
        #
        params = args[1:] if len(args) > 1 else []

        params, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(params)
        params, parse_addresses = PromptUtils.get_parse_addresses(params)
        params.reverse()

        if '--i' in params:
            params = []
            for index, iarg in enumerate(contract.Code.ParameterList):
                param, abort = PromptUtils.gather_param(index, iarg)
                if abort:
                    return None, None, None, None, False
                params.append(param)
            params.reverse()

        sb = ScriptBuilder()

        for p in params:
            process_params(sb, p, wallet, parse_addresses)

        sb.EmitAppCall(contract.Code.ScriptHash().Data)

        out = 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)

        return test_invoke(out, wallet, outputs, withdrawal_tx, from_addr, min_fee, invoke_attrs=invoke_attrs, owners=owners)

    else:

        print("Contract %s not found" % args[0])

    return None, None, None, None, False
示例#6
0
    def _generate_tx(self):
        wallet = self.GetWallet1()

        output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash, Value=Fixed8.One(),
                                   script_hash=LeaderTestCase.wallet_1_script_hash)
        contract_tx = ContractTransaction(outputs=[output])
        wallet.MakeTransaction(contract_tx)
        ctx = ContractParametersContext(contract_tx)
        wallet.Sign(ctx)
        contract_tx.scripts = ctx.GetScripts()
        return contract_tx
示例#7
0
 def GetUnavailableBonus(self):
     """
     Gets the total claimable amount of Gas in the wallet that is not available to claim
     because it has not yet been spent
     Returns:
         Fixed8: the amount of Gas unavailable to claim
     """
     height = Blockchain.Default().Height + 1
     unspents = self.FindUnspentCoinsByAsset(Blockchain.SystemShare().Hash)
     refs = [coin.Reference for coin in unspents]
     unavailable_bonus = Blockchain.CalculateBonus(refs, height_end=height)
     return unavailable_bonus
示例#8
0
    def test_9_send_neo_tx(self):

        wallet = self.GetWallet1()

        tx = ContractTransaction()
        tx.outputs = [TransactionOutput(Blockchain.SystemShare().Hash, Fixed8.FromDecimal(10.0), self.import_watch_addr)]

        tx = wallet.MakeTransaction(tx)

        cpc = ContractParametersContext(tx)
        wallet.Sign(cpc)
        tx.scripts = cpc.GetScripts()

        result = NodeLeader.Instance().Relay(tx)
        self.assertEqual(result, True)
示例#9
0
    def _generate_tx(self, amount):
        wallet = self.GetWallet1()

        output = TransactionOutput(
            AssetId=Blockchain.SystemShare().Hash,
            Value=amount,
            script_hash=LeaderTestCase.wallet_1_script_hash)
        contract_tx = ContractTransaction(outputs=[output])
        try:
            wallet.MakeTransaction(contract_tx)
        except ValueError:
            pass
        ctx = ContractParametersContext(contract_tx)
        wallet.Sign(ctx)
        contract_tx.scripts = ctx.GetScripts()
        return contract_tx
示例#10
0
    def _make_tx(self, addr_to):
        """
        process transaction
        """
        output1 = TransactionOutput(
            AssetId = Blockchain.SystemCoin().Hash, # hash of the Gas transaction
            Value = Fixed8.FromDecimal(2000), # this is how much gas each request will provide
            script_hash = addr_to # address to send the Gas to
        )
        output2 = TransactionOutput(
            AssetId = Blockchain.SystemShare().Hash, # hash of the NEO token transaction
            Value = Fixed8.FromDecimal(100), # this is how much NEO each request will provide
            script_hash = addr_to # address to send the NEO tokens too
        )

        contract_tx = ContractTransaction() # creates an instance of the transaction
        contract_tx.outputs = [output1, output2] # outputs the data from the transaction
        contract_tx = self.wallet.MakeTransaction(contract_tx) # processes transaction 

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

        context = ContractParametersContext(contract_tx, isMultiSig=False) # getting the contract context (listed above)
        self.wallet.Sign(context) # signs the contract

        if context.Completed:

            contract_tx.scripts = context.GetScripts() # gets the script hashes from the context 

            self.wallet.SaveTransaction(contract_tx) # update the state of the coins in the wallet

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

            relayed = NodeLeader.Instance().Relay(contract_tx)  # relay the transaction to this instance of the node leader 

            if relayed: # if tx relay was successful, inform the user and return the contract transaction
                print("Relayed Tx: %s " % contract_tx.Hash.ToString())
                return contract_tx
            else:

                print("Could not relay tx %s " % contract_tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

        return False
示例#11
0
    def _get_context(self):

        neo_balance = Fixed8.Zero()
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemShare().Hash):
            neo_balance += coin.Output.Value

        gas_balance = Fixed8.Zero()
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemCoin().Hash):
            gas_balance += coin.Output.Value

        return {
            'message':'Hello',
            'height':Blockchain.Default().Height,
            'neo': neo_balance.ToInt(),
            'gas': gas_balance.ToInt(),
            'wallet_height': self.wallet.WalletHeight
        }
示例#12
0
    def _make_tx(self, addr_to):

        output1 = TransactionOutput(
            AssetId = Blockchain.SystemCoin().Hash,
            Value = Fixed8.FromDecimal(2000),
            script_hash = addr_to
        )
        output2 = TransactionOutput(
            AssetId = Blockchain.SystemShare().Hash,
            Value = Fixed8.FromDecimal(100),
            script_hash = addr_to
        )

        contract_tx = ContractTransaction()
        contract_tx.outputs = [output1, output2]
        contract_tx = self.wallet.MakeTransaction(contract_tx)

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

        context = ContractParametersContext(contract_tx, isMultiSig=False)
        self.wallet.Sign(context)

        if context.Completed:

            contract_tx.scripts = context.GetScripts()

            self.wallet.SaveTransaction(contract_tx)

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

            relayed = NodeLeader.Instance().Relay(contract_tx)

            if relayed:
                print("Relayed Tx: %s " % contract_tx.Hash.ToString())
                return contract_tx
            else:

                print("Could not relay tx %s " % contract_tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

        return False
示例#13
0
    def _get_context(self):
        """
        function gets the current amount of neo and gas in the user's wallet
        then returns a json object stating those values
        """
        neo_balance = Fixed8.Zero()  # initializes NEO balance at 0 (to 8 decimal places)
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemShare().Hash):
            neo_balance += coin.Output.Value

        gas_balance = Fixed8.Zero()  # initializes NEOGas balance at 0 (to 8 decimal places)
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemCoin().Hash):
            gas_balance += coin.Output.Value

        return {
            'message': 'Hello',
            'height': Blockchain.Default().Height,  # current number of blocks on this instance of the blockchain
            'neo': neo_balance.ToInt(),
            'gas': gas_balance.ToInt(),
            'wallet_height': self.wallet.WalletHeight # this is just the number of transactions that the wallet has had
        }
示例#14
0
    def test_account_state(self):
        hash = UInt160(data=self.shash)
        account = AccountState(script_hash=hash)

        addr = account.Address

        self.assertEqual(addr, self.saddr)

        input = binascii.unhexlify(self.assset)

        asset = AssetState.DeserializeFromDB(input)

        account.AddToBalance(asset.AssetId, Fixed8(2440000000))

        self.assertEqual(account.BalanceFor(asset.AssetId), Fixed8(2440000000))

        account.SubtractFromBalance(asset.AssetId, Fixed8(1220000000))

        self.assertEqual(account.BalanceFor(asset.AssetId), Fixed8(1220000000))

        self.assertEqual(account.HasBalance(asset.AssetId), True)

        sshare_hash = Blockchain.SystemShare().Hash

        account.SubtractFromBalance(sshare_hash, Fixed8(800000000))

        self.assertFalse(account.AllBalancesZeroOrLess())

        acct_json = account.ToJson()

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

        account.Serialize(writer)
        out = stream.ToArray()
        StreamManager.ReleaseStream(stream)

        input = binascii.unhexlify(out)
        newaccount = AccountState.DeserializeFromDB(input)

        self.assertEqual(acct_json, newaccount.ToJson())
示例#15
0
    def GetUnclaimedCoins(self):
        """
        Gets coins in the wallet that have not been 'claimed', or redeemed for their gas value on the blockchain.

        Returns:
            list: a list of ``neo.Wallet.Coin`` that have 'claimable' value
        """
        unclaimed = []

        neo = Blockchain.SystemShare().Hash

        for coin in self.GetCoins():
            if coin.Output.AssetId == neo and \
                    coin.State & CoinState.Confirmed > 0 and \
                    coin.State & CoinState.Spent > 0 and \
                    coin.State & CoinState.Claimed == 0 and \
                    coin.State & CoinState.Frozen == 0 and \
                    coin.State & CoinState.WatchOnly == 0:
                unclaimed.append(coin)

        return unclaimed
示例#16
0
    def test_9_send_neo_tx(self):
        with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)):
            wallet = self.GetWallet1()

            tx = ContractTransaction()
            tx.outputs = [TransactionOutput(Blockchain.SystemShare().Hash, Fixed8.FromDecimal(10.0), self.import_watch_addr)]

            try:
                tx = wallet.MakeTransaction(tx)
            except (ValueError):
                pass

            cpc = ContractParametersContext(tx)
            wallet.Sign(cpc)
            tx.scripts = cpc.GetScripts()

            nodemgr = NodeManager()
            # we need at least 1 node for relay to be mocked
            nodemgr.nodes = [NeoNode(object, object)]
            result = nodemgr.relay(tx)
            self.assertEqual(result, True)
示例#17
0
    def ProcessNewBlock(self, block):

        added = set()
        changed = set()
        deleted = set()

        try:

            for tx in block.FullTransactions:

                for index, output in enumerate(tx.outputs):

                    state = self.CheckAddressState(output.ScriptHash)

                    if state & AddressState.InWallet > 0:

                        key = CoinReference(tx.Hash, index)

                        if key in self._coins.keys():
                            coin = self._coins[key]
                            coin.State |= CoinState.Confirmed
                            changed.add(coin)

                        else:
                            newcoin = Coin.CoinFromRef(
                                coin_ref=key,
                                tx_output=output,
                                state=CoinState.Confirmed)
                            self._coins[key] = newcoin
                            added.add(newcoin)

                        if state & AddressState.WatchOnly > 0:

                            self._coins[key].State |= CoinState.WatchOnly
                            changed.add(self._coins[key])

            for tx in block.FullTransactions:

                for input in tx.inputs:

                    if input in self._coins.keys():

                        if self._coins[input].Output.AssetId.ToBytes(
                        ) == Blockchain.SystemShare().Hash.ToBytes():
                            self._coins[
                                input].State |= CoinState.Spent | CoinState.Confirmed
                            changed.add(self._coins[input])

                        else:
                            deleted.add(self._coins[input])
                            del self._coins[input]

            for claimTx in [
                    tx for tx in block.Transactions
                    if tx.Type == TransactionType.ClaimTransaction
            ]:

                for ref in claimTx.Claims:
                    if ref in self._coins.keys():
                        deleted.add(self._coins[ref])
                        del self._coins[ref]

            self._current_height += 1
            self.OnProcessNewBlock(block, added, changed, deleted)

            if len(added) + len(deleted) + len(changed) > 0:
                self.BalanceChanged()

        except Exception as e:
            traceback.print_stack()
            traceback.print_exc()
            print("could not process %s " % e)
示例#18
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)
示例#19
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
示例#20
0
    def ProcessNewBlock(self, block):
        """
        Processes a block on the blockchain.  This should be done in a sequential order, ie block 4 should be
        only processed after block 3.

        Args:
            block: (neo.Core.Block) a block on the blockchain.
        """
        added = set()
        changed = set()
        deleted = set()

        try:
            # go through the list of transactions in the block and enumerate
            # over their outputs
            for tx in block.FullTransactions:

                for index, output in enumerate(tx.outputs):

                    # check to see if the outputs in the tx are in this wallet
                    state = self.CheckAddressState(output.ScriptHash)

                    if state & AddressState.InWallet > 0:

                        # if its in the wallet, check to see if the coin exists yet
                        key = CoinReference(tx.Hash, index)

                        # if it exists, update it, otherwise create a new one
                        if key in self._coins.keys():
                            coin = self._coins[key]
                            coin.State |= CoinState.Confirmed
                            changed.add(coin)
                        else:
                            newcoin = Coin.CoinFromRef(coin_ref=key, tx_output=output, state=CoinState.Confirmed, transaction=tx)
                            self._coins[key] = newcoin
                            added.add(newcoin)

                        if state & AddressState.WatchOnly > 0:
                            self._coins[key].State |= CoinState.WatchOnly
                            changed.add(self._coins[key])

            # now iterate over the inputs of the tx and do the same
            for tx in block.FullTransactions:

                for input in tx.inputs:

                    if input in self._coins.keys():
                        if self._coins[input].Output.AssetId == Blockchain.SystemShare().Hash:
                            coin = self._coins[input]
                            coin.State |= CoinState.Spent | CoinState.Confirmed
                            changed.add(coin)

                        else:
                            deleted.add(self._coins[input])
                            del self._coins[input]

            for claimTx in [tx for tx in block.Transactions if tx.Type == TransactionType.ClaimTransaction]:

                for ref in claimTx.Claims:
                    if ref in self._coins.keys():
                        deleted.add(self._coins[ref])
                        del self._coins[ref]

            # update the current height of the wallet
            self._current_height += 1

            # in the case that another wallet implementation needs to do something
            # with the coins that have been changed ( ie persist to db ) this
            # method is called
            self.OnProcessNewBlock(block, added, changed, deleted)

            # this is not necessary at the moment, but any outside process
            # that wants to subscribe to the balance changed event could do
            # so from the BalanceChanged method
            if len(added) + len(deleted) + len(changed) > 0:
                self.BalanceChanged()

        except Exception as e:
            traceback.print_stack()
            traceback.print_exc()
            logger.error("could not process %s " % e)
示例#21
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, enable_debugger=False, snapshot=None):

    if settings.USE_DEBUG_STORAGE:
        debug_storage = DebugStorage.instance()
        storages = DBInterface(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):
        pass

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

    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 = []

    if snapshot is None:
        snapshot = GetBlockchain()._db.createSnapshot().Clone()
    engine = ApplicationEngine(
        trigger_type=TriggerType.Application,
        container=dtx,
        snapshot=snapshot,
        gas=dtx.Gas,
        testMode=True
    )

    engine.LoadScript(dtx.Script)

    # first we will execute the test deploy
    # then right after, we execute the test invoke
    if enable_debugger:
        debugger = Debugger(engine)
        d_success = debugger.Execute()
    else:
        d_success = engine.Execute()

    # the old setup provided the same StateMachine object to the ApplicationEngine for deploy and invoke
    # this allowed for a single dispatch of events at the end of the function. Now a new StateMachine is automatically
    # created when creating an ApplicationEngine, thus we have to dispatch events after the deploy to not lose them as
    # testcases expect them
    to_dispatch = to_dispatch + engine._Service.events_to_dispatch
    for event in to_dispatch:
        events.emit(event.event_type, event)
    to_dispatch = []

    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:
            process_params(sb, p, wallet, no_parse_addresses)

        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):
            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.")

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

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

        if enable_debugger:
            debugger = Debugger(engine)
            i_success = debugger.Execute()
        else:
            i_success = engine.Execute()

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

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

        if i_success:
            if len(engine._Service.notifications) > 0:

                for n in engine._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
示例#22
0
def TestInvokeContract(wallet,
                       args,
                       withdrawal_tx=None,
                       parse_params=True,
                       from_addr=None,
                       min_fee=DEFAULT_MIN_FEE):

    BC = GetBlockchain()

    contract = BC.GetContract(args[0])

    if contract:

        verbose = False

        if 'verbose' in args:
            descripe_contract(contract)
            verbose = True
            args.remove('verbose')


#
        params = args[1:] if len(args) > 1 else []

        if len(params) > 0 and params[0] == 'describe':
            return

        params, neo_to_attach, gas_to_attach = get_asset_attachments(params)

        params.reverse()

        sb = ScriptBuilder()

        for p in params:

            if parse_params:
                item = parse_param(p, wallet)
            else:
                item = 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(contract.Code.ScriptHash().Data)

        out = 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)

        return test_invoke(out, wallet, outputs, withdrawal_tx, from_addr,
                           min_fee)

    else:

        print("Contract %s not found" % args[0])

    return None, None, None, None
示例#23
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
示例#24
0
def TestInvokeContract(wallet,
                       args,
                       withdrawal_tx=None,
                       parse_params=True,
                       from_addr=None,
                       min_fee=DEFAULT_MIN_FEE,
                       invoke_attrs=None,
                       owners=None):

    BC = GetBlockchain()

    contract = BC.GetContract(args[0])

    if contract:
        #
        params = args[1:] if len(args) > 1 else []

        params, neo_to_attach, gas_to_attach = get_asset_attachments(params)
        params, parse_addresses = get_parse_addresses(params)
        params.reverse()

        if '--i' in params:
            params = []
            for index, iarg in enumerate(contract.Code.ParameterList):
                param, abort = gather_param(index, iarg)
                if abort:
                    return None, None, None, None
                params.append(param)
            params.reverse()

        sb = ScriptBuilder()

        for p in params:

            if parse_params:
                item = parse_param(p, wallet, parse_addr=parse_addresses)
            else:
                item = p
            if type(item) is list:
                item.reverse()
                listlength = len(item)
                for listitem in item:
                    subitem = parse_param(listitem,
                                          wallet,
                                          parse_addr=parse_addresses)
                    if type(subitem) is list:
                        subitem.reverse()
                        for listitem2 in subitem:
                            subsub = parse_param(listitem2,
                                                 wallet,
                                                 parse_addr=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(contract.Code.ScriptHash().Data)

        out = 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)

        return test_invoke(out,
                           wallet,
                           outputs,
                           withdrawal_tx,
                           from_addr,
                           min_fee,
                           invoke_attrs=invoke_attrs,
                           owners=owners)

    else:

        print("Contract %s not found" % args[0])

    return None, None, None, None
def MonkeyPatchPersist(self, block, snapshot=None):

    if snapshot is None:
        snapshot = self._db.createSnapshot()
        snapshot.PersistingBlock = block

    amount_sysfee = self.GetSysFeeAmount(
        block.PrevHash) + (block.TotalFees().value / Fixed8.D)
    amount_sysfee_bytes = struct.pack("<d", amount_sysfee)

    with self._db.getBatch() as wb:
        for tx in block.Transactions:
            unspentcoinstate = UnspentCoinState.FromTXOutputsConfirmed(
                tx.outputs)
            snapshot.UnspentCoins.Add(tx.Hash.ToBytes(), unspentcoinstate)

            # go through all the accounts in the tx outputs
            for output in tx.outputs:
                account = snapshot.Accounts.GetAndChange(
                    output.AddressBytes,
                    lambda: 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:

                    snapshot.UnspentCoins.GetAndChange(
                        input.PrevHash.ToBytes()).Items[
                            input.PrevIndex] |= CoinState.Spent

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

                    output = prevTx.outputs[input.PrevIndex]
                    acct = snapshot.Accounts.GetAndChange(
                        prevTx.outputs[input.PrevIndex].AddressBytes,
                        lambda: 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)

                snapshot.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 = snapshot.Assets.GetAndChange(
                        result.AssetId.ToBytes())
                    asset.Available = asset.Available - result.Amount

            elif tx.Type == TransactionType.ClaimTransaction:

                for input in tx.Claims:

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

            elif tx.Type == TransactionType.EnrollmentTransaction:

                snapshot.Validators.GetAndChange(
                    tx.PublicKey.ToBytes(),
                    lambda: 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:

                def create_contract_state():
                    return ContractState(tx.Code, tx.NeedStorage, tx.Name,
                                         tx.CodeVersion, tx.Author, tx.Email,
                                         tx.Description)

                snapshot.Contracts.GetAndChange(tx.Code.ScriptHash().ToBytes(),
                                                create_contract_state)

            elif tx.Type == TransactionType.InvocationTransaction:
                return ApplicationEngine.Run(TriggerType.Application, tx,
                                             snapshot.Clone(), tx.Gas, True,
                                             wb)
示例#26
0
文件: Wallet.py 项目: lcux/neo-python
    def ProcessNewBlock(self, block):

        added = set()
        changed = set()
        deleted = set()

        self._lock.acquire()
        try:

            for tx in block.Transactions:

                for index, output in enumerate(tx.outputs):

                    state = self.CheckAddressState(output.ScriptHash)

                    if state > 0:
                        key = CoinReference(tx.Hash, index)

                        found = False
                        for coin in self._coins:
                            if coin.CoinRef.Equals(key):
                                coin.State |= CoinState.Confirmed
                                changed.add(coin.CoinRef)
                                found = True
                        if not found:
                            newcoin = Coin.CoinFromRef(
                                key, output, state=CoinState.Confirmed)
                            self._coins.append(newcoin)
                            added.add(newcoin.CoinRef)

                        if state == AddressState.WatchOnly:
                            for coin in self._coins:
                                if coin.CoinRef.Equals(key):
                                    coin.State |= CoinState.WatchOnly
                                    changed.add(coin.CoinRef)

            for tx in block.Transactions:

                for input in tx.inputs:

                    for coin in self._coins:
                        if coin.CoinRef.Equals(input):

                            if coin.TXOutput.AssetId == Blockchain.SystemShare(
                            ).Hash():
                                coin.State |= CoinState.Spent | CoinState.Confirmed
                                changed.add(coin.CoinRef)
                            else:
                                self._coins.remove(coin)
                                deleted.add(coin.CoinRef)

            for claimTx in [
                    tx for tx in block.Transactions
                    if tx.Type == TransactionType.ClaimTransaction
            ]:
                for ref in claimTx.Claims:
                    if ref in self._coins:
                        self._coins.remove(ref)
                        deleted.add(ref)

            self._current_height += 1
            self.OnProcessNewBlock(block, added, changed, deleted)

            if len(added) + len(deleted) + len(changed) > 0:
                self.BalanceChanged()

        except Exception as e:
            print("could not process: %s " % e)
        finally:
            self._lock.release()
示例#27
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)
示例#28
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()}
示例#29
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
示例#30
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