示例#1
0
def get_fee(params):
    fee = None
    for item in params:
        if '--fee=' in item:
            params.remove(item)
            fee = get_asset_amount(item.replace('--fee=', ''), Blockchain.SystemCoin().Hash)
    return params, fee
示例#2
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
示例#3
0
    def Verify(self, mempool):
        """
        Verify the transaction.

        Args:
            mempool:

        Returns:
            bool: True if verified. False otherwise.
        """
        if not super(ClaimTransaction, self).Verify(mempool):
            return False

        # wat does this do
        # get all claim transactinos from mempool list
        # that are not this claim
        # and gather all the claims of those claim transactions
        # and see if they intersect the claims of this transaction
        # and if that number is greater than zero that we do not verify
        # (now, to do that in python)
        # if (mempool.OfType < ClaimTransaction > ().Where(p => p != this).SelectMany(p= > p.Claims).Intersect(Claims).Count() > 0)
        # return false;

        # im sorry about the below
        otherclaimTxs = [
            tx for tx in mempool if tx is ClaimTransaction and tx is not self
        ]
        for other in otherclaimTxs:
            # check to see if the length of the intersection between this objects claim's and the other txs claims is > 0
            if len([
                    list(filter(lambda x: x in self.Claims, otherClaims))
                    for otherClaims in other.Claims
            ]):
                return False

        txResult = None
        for tx in self.GetTransactionResults():
            if tx.AssetId == Blockchain.SystemCoin().Hash:
                txResult = tx
                break

        if txResult is None or txResult.Amount > Fixed8(0):
            return False

        try:
            return Blockchain.CalculateBonusIgnoreClaimed(
                self.Claims, False) == -txResult.Amount

        except Exception as e:
            logger.error('Could not calculate bonus: %s ' % e)

        return False
示例#4
0
def get_fee(params):
    to_remove = []
    fee = None
    for item in params:
        if '--fee=' in item:
            to_remove.append(item)
            try:
                fee = get_asset_amount(item.replace('--fee=', ''),
                                       Blockchain.SystemCoin().Hash)
            except Exception as e:
                pass
    for item in to_remove:
        params.remove(item)

    return params, fee
示例#5
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
示例#6
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
        }
示例#7
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
示例#8
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
        }
示例#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 MakeTransaction(self,
                        tx,
                        change_address=None,
                        fee=Fixed8(0),
                        from_addr=None,
                        use_standard=False,
                        watch_only_val=0,
                        exclude_vin=None,
                        use_vins_for_asset=None):
        """
        This method is used to to calculate the necessary TransactionInputs (CoinReferences) and TransactionOutputs to
        be used when creating a transaction that involves an exchange of system assets, ( NEO, Gas, etc ).

        Args:
            tx (Transaction): The Transaction to be used.
            change_address (UInt160): The address any change for the transaction should be returned to.
            fee (Fixed8): A fee to be attached to the Transaction for network processing purposes.
            from_addr (UInt160): If present, all CoinReferences selected will only come from this address.
            use_standard (bool): If true, only CoinReferences from standard addresses ( not contracts that are smart contracts ) will be used.
            watch_only_val (int): 0 or CoinState.WATCH_ONLY, if present only choose coins that are in a WatchOnly address.
            exclude_vin (list): A list of CoinReferences to NOT use in the making of this tx.
            use_vins_for_asset (list): A list of CoinReferences to use.

        Returns:
            tx: (Transaction) Returns the transaction with oupdated inputs and outputs.
        """

        tx.ResetReferences()
        tx.ResetHashData()

        if not tx.outputs:
            tx.outputs = []
        if not tx.inputs:
            tx.inputs = []

        fee = fee + (tx.SystemFee() * Fixed8.FD())


        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction, 'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}
        self._vin_exclude = exclude_vin
#        import pdb
#        pdb.set_trace()

        for assetId, amount in paytotal.items():

            if use_vins_for_asset is not None and len(use_vins_for_asset) > 0 and use_vins_for_asset[1] == assetId:
                paycoins[assetId] = self.FindCoinsByVins(use_vins_for_asset[0])
            else:
                paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                    assetId, amount, from_addr=from_addr, use_standard=use_standard, watch_only_val=watch_only_val)

        self._vin_exclude = None
        for key, unspents in paycoins.items():
            if unspents is None:
                if not self.IsSynced:
                    logger.warning("Wait for your wallet to be synced before doing "
                                   "transactions. To check enter 'wallet' and look at "
                                   "'percent_synced', it should be 100. Also the blockchain "
                                   "should be up to the latest blocks (see Progress). Issuing "
                                   "'wallet rebuild' restarts the syncing process.")
                    return None

                else:
                    logger.error("insufficient funds for asset id: %s " % key)
                    return None
        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress(from_addr=from_addr)

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId, Value=difference, script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
示例#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 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
示例#13
0
def ClaimGas(wallet, require_password=True):

    unclaimed_coins = wallet.GetUnclaimedCoins()
    unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins]

    if len(unclaimed_coin_refs) == 0:
        print("no claims to process")
        return False

    available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed(
        unclaimed_coin_refs)

    if available_bonus == Fixed8.Zero():

        print("No gas to claim")
        return False

    claim_tx = ClaimTransaction()
    claim_tx.Claims = unclaimed_coin_refs
    claim_tx.Attributes = []
    claim_tx.inputs = []
    claim_tx.outputs = [
        TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                          Value=available_bonus,
                          script_hash=wallet.GetChangeAddress())
    ]

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

    print("\n---------------------------------------------------------------")
    print("Will make claim for %s GAS" % available_bonus.ToString())
    print(
        "------------------------------------------------------------------\n")

    if require_password:
        print("Enter your password to complete this claim")

        passwd = prompt("[Password]> ", is_password=True)

        if not wallet.ValidatePassword(passwd):
            print("incorrect password")
            return

    if context.Completed:

        claim_tx.scripts = context.GetScripts()
        wallet.SaveTransaction(claim_tx)

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

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

            print("Could not relay tx %s " % claim_tx.Hash.ToString())
        return claim_tx, relayed

    else:

        print("could not sign tx")

    return None, False
示例#14
0
def ClaimGas(wallet, require_password=True, args=None):

    unclaimed_coins = wallet.GetUnclaimedCoins()
    unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins]

    if len(unclaimed_coin_refs) == 0:
        print("no claims to process")
        return False

    available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed(
        unclaimed_coin_refs)

    if available_bonus == Fixed8.Zero():
        print("No gas to claim")
        return False

    claim_tx = ClaimTransaction()
    claim_tx.Claims = unclaimed_coin_refs
    claim_tx.Attributes = []
    claim_tx.inputs = []

    script_hash = wallet.GetChangeAddress()

    # the following can be used to claim gas that is in an imported contract_addr
    # example, wallet claim --from-addr={smart contract addr}
    if args:
        params, from_addr_str = get_from_addr(args)
        if from_addr_str:
            script_hash = wallet.ToScriptHash(from_addr_str)
            standard_contract = wallet.GetStandardAddress()
            claim_tx.Attributes = [
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=standard_contract.Data)
            ]

    claim_tx.outputs = [
        TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                          Value=available_bonus,
                          script_hash=script_hash)
    ]

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

    print("\n---------------------------------------------------------------")
    print("Will make claim for %s GAS" % available_bonus.ToString())
    print(
        "------------------------------------------------------------------\n")

    if require_password:
        print("Enter your password to complete this claim")

        passwd = prompt("[Password]> ", is_password=True)

        if not wallet.ValidatePassword(passwd):
            print("incorrect password")
            return

    if context.Completed:

        claim_tx.scripts = context.GetScripts()

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

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

        if relayed:
            print("Relayed Tx: %s " % claim_tx.Hash.ToString())
            wallet.SaveTransaction(claim_tx)
        else:

            print("Could not relay tx %s " % claim_tx.Hash.ToString())
        return claim_tx, relayed

    else:

        print("could not sign tx")

    return None, False
示例#15
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
示例#16
0
def ClaimGas(wallet, require_password=True, args=None):
    """

    Args:
        wallet:
        require_password:
        args:

    Returns:
        (claim transaction, relayed status)
            if successful: (tx, True)
            if unsuccessful: (None, False)
    """
    if args:
        params, from_addr_str = get_from_addr(args)
    else:
        params = None
        from_addr_str = None

    unclaimed_coins = wallet.GetUnclaimedCoins()

    unclaimed_count = len(unclaimed_coins)
    if unclaimed_count == 0:
        print("no claims to process")
        return None, False

    max_coins_per_claim = None
    if params:
        max_coins_per_claim = get_arg(params, 0, convert_to_int=True)
        if not max_coins_per_claim:
            print("max_coins_to_claim must be an integer")
            return None, False
        if max_coins_per_claim <= 0:
            print("max_coins_to_claim must be greater than zero")
            return None, False
    if max_coins_per_claim and unclaimed_count > max_coins_per_claim:
        unclaimed_coins = unclaimed_coins[:max_coins_per_claim]

    unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins]

    available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed(
        unclaimed_coin_refs)

    if available_bonus == Fixed8.Zero():
        print("No gas to claim")
        return None, False

    claim_tx = ClaimTransaction()
    claim_tx.Claims = unclaimed_coin_refs
    claim_tx.Attributes = []
    claim_tx.inputs = []

    script_hash = wallet.GetChangeAddress()

    # the following can be used to claim gas that is in an imported contract_addr
    # example, wallet claim --from-addr={smart contract addr}
    if from_addr_str:
        script_hash = wallet.ToScriptHash(from_addr_str)
        standard_contract = wallet.GetStandardAddress()
        claim_tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=standard_contract.Data)
        ]

    claim_tx.outputs = [
        TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                          Value=available_bonus,
                          script_hash=script_hash)
    ]

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

    print("\n---------------------------------------------------------------")
    print("Will make claim for %s GAS" % available_bonus.ToString())
    if max_coins_per_claim and unclaimed_count > max_coins_per_claim:
        print(
            "NOTE: You are claiming GAS on %s unclaimed coins. %s additional claim transactions will be required to claim all available GAS."
            % (max_coins_per_claim,
               math.floor(unclaimed_count / max_coins_per_claim)))
    print(
        "------------------------------------------------------------------\n")

    if require_password:
        print("Enter your password to complete this claim")

        passwd = prompt("[Password]> ", is_password=True)

        if not wallet.ValidatePassword(passwd):
            print("incorrect password")
            return None, False

    if context.Completed:

        claim_tx.scripts = context.GetScripts()

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

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

        if relayed:
            print("Relayed Tx: %s " % claim_tx.Hash.ToString())
            wallet.SaveTransaction(claim_tx)
        else:

            print("Could not relay tx %s " % claim_tx.Hash.ToString())
        return claim_tx, relayed

    else:

        print("could not sign tx")

    return None, False
示例#17
0
    def MakeTransaction(self,
                        tx,
                        change_address=None,
                        fee=Fixed8(0),
                        from_addr=None,
                        use_standard=False,
                        watch_only_val=0,
                        exclude_vin=None,
                        use_vins_for_asset=None):
        """
        This method is used to to calculate the necessary TransactionInputs (CoinReferences) and TransactionOutputs to
        be used when creating a transaction that involves an exchange of system assets, ( NEO, Gas, etc )

        Args:
            tx: (Transaction) The Transaction to be used
            change_address: (UInt160) The address any change for the transaction should be returned to
            fee: (Fixed8) A fee to be attached to the Transaction for network processing purposes
            from_addr: (UInt160) If present, all CoinReferences selected will only come from this address
            use_standard: (bool) If true, only CoinReferences from standard addresses ( not contracts that are smart contracts ) will be used
            watch_only_val: (int) 0 or CoinState.WATCH_ONLY, if present only choose coins that are in a WatchOnly address
            exclude_vin: (list) A list of CoinReferences to NOT use in the making of this tx
            use_vins_for_asset: (list) A list of CoinReferences to use

        Returns:
            tx: (Transaction) Returns the transaction with oupdated inputs and outputs
        """

        tx.ResetReferences()

        if not tx.outputs:
            tx.outputs = []
        if not tx.inputs:
            tx.inputs = []

        fee = fee + (tx.SystemFee() * Fixed8.FD())

        #        pdb.set_trace()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction,
                                     'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().
                         Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        self._vin_exclude = exclude_vin

        for assetId, amount in paytotal.items():

            if use_vins_for_asset is not None and len(
                    use_vins_for_asset
            ) > 0 and use_vins_for_asset[1] == assetId:
                paycoins[assetId] = self.FindCoinsByVins(use_vins_for_asset[0])
            else:
                paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                    assetId,
                    amount,
                    from_addr=from_addr,
                    use_standard=use_standard,
                    watch_only_val=watch_only_val)

        self._vin_exclude = None

        for key, unspents in paycoins.items():
            if unspents is None:
                print("insufficient funds for asset id: %s " % key)
                return None

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress(from_addr=from_addr)

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId,
                                           Value=difference,
                                           script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
示例#18
0
    def MakeTransaction(self, tx, change_address=None, fee=Fixed8(0)):

        tx.ResetReferences()

        if not tx.outputs: tx.outputs = []
        if not tx.inputs: tx.inputs = []

        fee = fee + tx.SystemFee()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction,
                                     'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().
                         Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        for assetId, amount in paytotal.items():
            paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                assetId, amount)

        for key, unspents in paycoins.items():
            if unspents == None:
                print("insufficient funds for asset id: %s " % key)
                return None

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress()

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId,
                                           Value=difference,
                                           script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
示例#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, 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
示例#20
0
def GetSystemCoin():
    from neo.Core.Blockchain import Blockchain
    return Blockchain.SystemCoin()
示例#21
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
示例#22
0
def ClaimGas(wallet,
             require_password=True,
             from_addr_str=None,
             to_addr_str=None):
    """
    Args:
        wallet:
        require_password:
        from_addr_str:
    Returns:
        (claim transaction, relayed status)
            if successful: (tx, True)
            if unsuccessful: (None, False)
    """
    if not wallet:
        print("Please open a wallet")
        return None, False

    unclaimed_coins = wallet.GetUnclaimedCoins()

    unclaimed_count = len(unclaimed_coins)
    if unclaimed_count == 0:
        print("No claims to process")
        return None, False

    unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins]

    available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed(
        unclaimed_coin_refs)

    if available_bonus == Fixed8.Zero():
        print("No gas to claim")
        return None, False

    claim_tx = ClaimTransaction()
    claim_tx.Claims = unclaimed_coin_refs
    claim_tx.Attributes = []
    claim_tx.inputs = []

    script_hash = wallet.GetChangeAddress()

    # the following can be used to claim gas that is in an imported contract_addr
    # example, wallet claim --from-addr={smart contract addr}
    if from_addr_str:
        script_hash = None
        script_hash = PromptUtils.lookup_addr_str(wallet, from_addr_str)
        if script_hash is None:
            logger.debug("invalid source address")
            return None, False
        standard_contract = wallet.GetStandardAddress()
        claim_tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=standard_contract.Data)
        ]

    if to_addr_str:
        script_hash = None
        script_hash = PromptUtils.lookup_addr_str(wallet, to_addr_str)
        if script_hash is None:
            logger.debug("invalid destination address")
            return None, False

    claim_tx.outputs = [
        TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                          Value=available_bonus,
                          script_hash=script_hash)
    ]

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

    print("\n---------------------------------------------------------------")
    print(f"Will make claim for {available_bonus.ToString()} GAS")
    print(
        "------------------------------------------------------------------\n")

    if require_password:
        print("Enter your password to complete this claim")

        passwd = prompt("[Password]> ", is_password=True)

        if not wallet.ValidatePassword(passwd):
            print("Incorrect password")
            return None, False

    if context.Completed:

        claim_tx.scripts = context.GetScripts()

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

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

        if relayed:
            print("Relayed Tx: %s " % claim_tx.Hash.ToString())
            wallet.SaveTransaction(claim_tx)
        else:
            print("Could not relay tx %s " % claim_tx.Hash.ToString())
        return claim_tx, relayed

    else:
        print("could not sign tx")

    return None, False
示例#23
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()}
示例#24
0
    def MakeTransaction(self,
                        tx,
                        change_address=None,
                        fee=Fixed8(0),
                        from_addr=None,
                        use_standard=False,
                        watch_only_val=0,
                        exclude_vin=None,
                        use_vins_for_asset=None,
                        skip_fee_calc=False):
        """
        This method is used to to calculate the necessary TransactionInputs (CoinReferences) and TransactionOutputs to
        be used when creating a transaction that involves an exchange of system assets, ( NEO, Gas, etc ).

        Args:
            tx (Transaction): The Transaction to be used.
            change_address (UInt160): The address any change for the transaction should be returned to.
            fee (Fixed8): A fee to be attached to the Transaction for network processing purposes.
            from_addr (UInt160): If present, all CoinReferences selected will only come from this address.
            use_standard (bool): If true, only CoinReferences from standard addresses ( not contracts that are smart contracts ) will be used.
            watch_only_val (int): 0 or CoinState.WATCH_ONLY, if present only choose coins that are in a WatchOnly address.
            exclude_vin (list): A list of CoinReferences to NOT use in the making of this tx.
            use_vins_for_asset (list): A list of CoinReferences to use.
            skip_fee_calc (bool): If true, the network fee calculation and verification will be skipped.

        Returns:
            tx: (Transaction) Returns the transaction with oupdated inputs and outputs.
        """

        tx.ResetReferences()
        tx.ResetHashData()

        if not tx.outputs:
            tx.outputs = []
        if not tx.inputs:
            tx.inputs = []

        fee = fee + tx.SystemFee()

        #        pdb.set_trace()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction, 'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                cur_val = paytotal.get(key, Fixed8.Zero())
                paytotal[key] = cur_val + sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        self._vin_exclude = exclude_vin

        for assetId, amount in paytotal.items():

            if use_vins_for_asset is not None and len(use_vins_for_asset) > 0 and use_vins_for_asset[1] == assetId:
                paycoins[assetId] = self.FindCoinsByVins(use_vins_for_asset[0])
            else:
                paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                    assetId, amount, from_addr=from_addr, use_standard=use_standard, watch_only_val=watch_only_val)

        self._vin_exclude = None

        for key, unspents in paycoins.items():
            if unspents is None:
                if not self.IsSynced:
                    logger.warning("Wait for your wallet to be synced before doing "
                                   "transactions. To check enter 'wallet' and look at "
                                   "'percent_synced', it should be 100. Also the blockchain "
                                   "should be up to the latest blocks (see Progress). Issuing "
                                   "'wallet rebuild' restarts the syncing process.")
                    return None

                else:
                    raise ValueError(f"insufficient funds for asset id: {key}")

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress(from_addr=from_addr)

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId, Value=difference, script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        # calculate and verify the required network fee for the tx
        if tx.Size() > settings.MAX_FREE_TX_SIZE and not skip_fee_calc:
            req_fee = Fixed8.FromDecimal(settings.FEE_PER_EXTRA_BYTE * (tx.Size() - settings.MAX_FREE_TX_SIZE))
            if req_fee < settings.LOW_PRIORITY_THRESHOLD:
                req_fee = settings.LOW_PRIORITY_THRESHOLD
            if fee < req_fee:
                raise TXFeeError(f'Transaction cancelled. The tx size ({tx.Size()}) exceeds the max free tx size ({settings.MAX_FREE_TX_SIZE}).\nA network fee of {req_fee.ToString()} GAS is required.')

        return tx