Exemplo n.º 1
0
def gather_param(index, param_type, do_continue=True):
    ptype = ContractParameterType(param_type)
    prompt_message = '[Param %s] %s input: ' % (index, ptype.name)

    try:
        result = get_input_prompt(prompt_message)
    except KeyboardInterrupt:
        print("Input cancelled")
        return None, True
    except Exception as e:
        print(str(e))
        # no results, abort True
        return None, True

    try:

        if ptype == ContractParameterType.String:
            return str(result), False
        elif ptype == ContractParameterType.Integer:
            return int(result), False
        elif ptype == ContractParameterType.Boolean:
            return bool(result), False
        elif ptype == ContractParameterType.PublicKey:
            try:
                return ECDSA.decode_secp256r1(result).G, False
            except ValueError:
                return None, True
        elif ptype == ContractParameterType.ByteArray:
            if isinstance(result,
                          str) and len(result) == 34 and result[0] == 'A':
                return Helper.AddrStrToScriptHash(result).Data, False
            res = eval(
                result,
                {"__builtins__": {
                    'bytearray': bytearray,
                    'bytes': bytes
                }}, {})
            if isinstance(res, bytes):
                return bytearray(res), False
            return res, False

        elif ptype == ContractParameterType.Array:
            res = eval(result)
            if isinstance(res, list):
                return res, False
            raise Exception("Please provide a list")
        else:
            raise Exception("Unknown param type %s " % ptype.name)

    except KeyboardInterrupt:  # Control-C pressed: exit

        return None, True

    except Exception as e:

        print("Could not parse param as %s : %s " % (ptype, e))
        if do_continue:
            return gather_param(index, param_type, do_continue)

    return None, True
Exemplo n.º 2
0
    def get_accountstate(self, request, key_wallet):
        request.setHeader('Content-Type', 'application/json')
        try:
            print(key_wallet)
            acct = Blockchain.Default().GetAccountState(key_wallet)
            print(acct.ToJson())
            if acct is None:
                try:
                    acct = AccountState(
                        script_hash=Helper.AddrStrToScriptHash(key_wallet))
                except Exception as e:
                    self.format_message(
                        "Could not get contract with hash %s because test" %
                        (key_wallet))

            acctString = json.dumps(acct.ToJson())
            acctString = acctString.replace(
                "0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b",
                "NEO")
            acctString = acctString.replace(
                "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7",
                "GAS")
            return json.dumps({'response': json.loads(acctString)})
        except Exception as e:
            return self.format_message(
                "Could not get contract with hash %s because %s " %
                (acct.ToJson(), e))

        return self.format_message(
            "Could not get contract with hash %s because test" % (key_wallet))
    def test_1_initial_setup(self):

        wallet = self.GetWallet1()

        jsn = wallet.ToJson()

        addr = jsn['addresses'][0]

        self.assertEqual(self.wallet_1_addr, addr['address'])
        self.assertEqual(str(Helper.AddrStrToScriptHash(self.wallet_1_addr)),
                         addr['script_hash'])

        gas_balance_should_be = Fixed8.FromDecimal(13.9998)

        gas_balance = wallet.GetBalance(self.GAS)

        self.assertEqual(gas_balance_should_be, gas_balance)

        neo_balance_should_be = Fixed8.FromDecimal(50)

        neo_balance = wallet.GetBalance(self.NEO)

        self.assertEqual(neo_balance_should_be, neo_balance)

        self.assertEqual(wallet.WalletHeight, 12351)
Exemplo n.º 4
0
 def GetAddress(self, addrStr):
     try:
         script_hash = CoreHelper.AddrStrToScriptHash(addrStr).ToArray()
         addr = Address.get(ScriptHash=bytes(script_hash))
     except Exception as e:
         raise Exception("Address not in wallet")
     return addr
Exemplo n.º 5
0
    def Address(self, from_addr):
        """
        Specify the originating address for the transaction.

        Args:
            from_addr: (str) the source NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
        """
        src_scripthash = Helper.AddrStrToScriptHash(
            from_addr)  # also verifies if the address is valid
        self.SOURCE_SCRIPTHASH = src_scripthash

        url = self._network + self._get_balance + from_addr
        bal = requests.get(url=url)

        if not bal.status_code == 200:
            raise NetworkError(
                'Neoscan request failed. Please check your internet connection.'
            )

        bal = bal.json()
        if not bal['balance']:
            raise RawTXError(
                f"Address {from_addr} has a zero balance. Please ensure the correct network is selected or specify a difference source address."
            )
        self.BALANCE = bal['balance']
Exemplo n.º 6
0
def parse_param(p, wallet=None, ignore_int=False, prefer_hex=True, parse_addr=True):
    # first, we'll try to parse an array
    try:
        items = eval(p, {"__builtins__": {'list': list}}, {})
        if len(items) > 0 and type(items) is list:

            parsed = []
            for item in items:
                parsed.append(parse_param(item, wallet, parse_addr=parse_addr))
            return parsed

    except Exception as e:
        #        print("Could not eval items as array %s " % e)
        pass

    if not ignore_int:
        try:
            val = int(p)
            out = BigInteger(val)
            return out
        except Exception as e:
            pass

    try:
        val = eval(p, {"__builtins__": {'bytearray': bytearray, 'bytes': bytes, 'list': list}}, {})
        if type(val) is bytearray:
            return val
        elif type(val) is bytes:
            # try to unhex
            try:
                val = binascii.unhexlify(val)
            except Exception as e:
                pass
            # now it should be unhexxed no matter what, and we can hex it
            return val.hex().encode('utf-8')
        elif type(val) is bool:
            return val

    except Exception as e:
        pass

    if type(p) is str:

        if wallet is not None:
            for na in wallet.NamedAddr:
                if na.Title == p:
                    return bytearray(na.ScriptHash)

        # check for address strings like 'ANE2ECgA6YAHR5Fh2BrSsiqTyGb5KaS19u' and
        # convert them to a bytearray
        if parse_addr and len(p) == 34 and p[0] == 'A':
            addr = Helper.AddrStrToScriptHash(p).Data
            return addr

        if prefer_hex:
            return binascii.hexlify(p.encode('utf-8'))
        else:
            return p.encode('utf-8')

    return p
    def get_by_addr(self, address):
        """
        Lookup a set of notifications by address
        Args:
            address (UInt160 or str): hash of address for notifications

        Returns:
            list: a list of notifications
        """
        addr = address
        if isinstance(address, str) and len(address) == 34:
            addr = Helper.AddrStrToScriptHash(address)

        if not isinstance(addr, UInt160):
            raise Exception("Incorrect address format")

        addrlist_snapshot = self.db.prefixed_db(
            NotificationPrefix.PREFIX_ADDR).snapshot()
        results = []

        for val in addrlist_snapshot.iterator(prefix=bytes(addr.Data),
                                              include_key=False):
            if len(val) > 4:
                try:
                    event = SmartContractEvent.FromByteArray(val)
                    results.append(event)
                except Exception as e:
                    logger.error("could not parse event: %s %s" % (e, val))
        return results
Exemplo n.º 8
0
    def CalcChange(self, change_addr=None):
        """
        Calculates the change output(s). NOTE: Assumes all other outputs have been added.

        Args:
            change_addr: (str, optional) specify a change address. NOTE: Defaults to the sourceAddress.
        """
        if not change_addr:
            change_addr = self.SOURCE_SCRIPTHASH
        if change_addr != self.SOURCE_SCRIPTHASH:
            change_hash = Helper.AddrStrToScriptHash(
                change_addr)  # also verifies if the address is valid
        else:
            change_hash = change_addr

        if not self.outputs:
            raise RawTXError(
                "Please specify outputs prior to creating change output(s).")

        neo = []
        gas = []
        for output in self.outputs:
            if output.AssetId == UInt256.ParseString(self.neo_asset_id):
                neo.append(output.Value.value)
            elif output.AssetId == UInt256.ParseString(self.gas_asset_id):
                gas.append(output.Value.value)
        if self.SystemFee() > Fixed8.Zero():
            gas.append(self.SystemFee().value)
        if self._network_fee:
            if self._network_fee > Fixed8.Zero():
                gas.append(self._network_fee.value)
        neo_total = 0
        gas_total = 0
        for asset in self.BALANCE:
            if asset['asset_hash'] == self.neo_asset_id:
                neo_total = asset['amount']
            elif asset['asset_hash'] == self.gas_asset_id:
                gas_total = asset['amount']
        neo_diff = Fixed8.FromDecimal(neo_total) - Fixed8(sum(neo))
        gas_diff = Fixed8.FromDecimal(gas_total) - Fixed8(sum(gas))

        if neo_diff < Fixed8.Zero() or gas_diff < Fixed8.Zero():
            raise AssetError('Total outputs exceed the available unspents.')

        if neo_diff > Fixed8.Zero():
            self.outputs.append(
                TransactionOutput(AssetId=UInt256.ParseString(
                    self.neo_asset_id),
                                  Value=neo_diff,
                                  script_hash=change_hash))
        if gas_diff > Fixed8.Zero() and Fixed8(sum(gas)) > Fixed8.Zero():
            self.outputs.append(
                TransactionOutput(AssetId=UInt256.ParseString(
                    self.gas_asset_id),
                                  Value=gas_diff,
                                  script_hash=change_hash))
Exemplo n.º 9
0
    def AddOutput(self, asset, to_addr, amount):
        """
        Specify an output for the transaction.
        NOTE: Can be used multiple times to create multiple outputs.

        Args:
            asset: (str) the asset name or asset hash
            to_addr: (str) the destination NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
            amount: (int/decimal) the amount of the asset to send
        """
        if asset[0:1] == "0x":
            asset == asset[2:]
        if asset.lower() == "neo":
            assetId = self.neo_asset_id
        elif asset == self.neo_asset_id:
            assetId = self.neo_asset_id
        elif asset.lower() == "gas":
            assetId = self.gas_asset_id
        elif asset == self.gas_asset_id:
            assetId = self.gas_asset_id
        else:
            raise AssetError(
                f'Asset {asset} not found. If trying to send tokens use the `buildTokenTransfer` function.'
            )

        dest_scripthash = Helper.AddrStrToScriptHash(
            to_addr)  # also verifies if the address is valid

        if float(amount) == 0:
            raise ValueError('Amount cannot be 0.')
        f8amount = Fixed8.TryParse(amount, require_positive=True)
        if f8amount is None:
            raise ValueError('Invalid amount format.')
        elif assetId == self.neo_asset_id and (f8amount.value /
                                               Fixed8.D) != f8amount.ToInt():
            raise ValueError('Incorrect amount precision.')

        # check if the outputs exceed the available unspents
        subtotal = []
        if self.outputs:
            for output in self.outputs:
                if output.AssetId == assetId:
                    subtotal.append(output.Value.value)
        total = f8amount.value + sum(subtotal)
        total = float(Fixed8(total).ToString())
        for asset in self.BALANCE:
            if assetId == asset['asset_hash']:
                if total > asset['amount']:
                    raise AssetError(
                        'Total outputs exceed the available unspents.')

        self.outputs.append(
            TransactionOutput(AssetId=UInt256.ParseString(assetId),
                              Value=f8amount,
                              script_hash=dest_scripthash))
Exemplo n.º 10
0
def parse_param(p, wallet=None, ignore_int=False, prefer_hex=True):

    # first, we'll try to parse an array

    try:
        items = eval(p)
        if len(items) > 0 and type(items) is list:

            parsed = []
            for item in items:
                parsed.append(parse_param(item, wallet))
            return parsed

    except Exception as e:
        #        print("Could not eval items as array %s " % e)
        pass

    if not ignore_int:
        try:
            val = int(p)
            out = BigInteger(val)
            return out
        except Exception as e:
            pass

    try:
        val = eval(p)

        if type(val) is bytearray:
            return val.hex()

        return val
    except Exception as e:
        pass

    if type(p) is str:

        if wallet is not None:
            for na in wallet.NamedAddr:
                if na.Title == p:
                    return bytearray(na.ScriptHash)

        # check for address strings like 'ANE2ECgA6YAHR5Fh2BrSsiqTyGb5KaS19u' and
        # convert them to a bytearray
        if len(p) == 34 and p[0] == 'A':
            addr = Helper.AddrStrToScriptHash(p).Data
            return addr

        if prefer_hex:
            return binascii.hexlify(p.encode('utf-8'))
        else:
            return p.encode('utf-8')

    return p
Exemplo n.º 11
0
    def AddClaim(self, claim_addr, to_addr=None):
        """
        Builds a claim transaction for the specified address.

        Args:
            claim_addr: (str) the address from which the claim is being constructed (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3'). NOTE: Claimed GAS is sent to the claim_addr by default
            to_addr: (str, optional) specify a different destination NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
        """
        dest_scripthash = Helper.AddrStrToScriptHash(
            claim_addr)  # also verifies if the address is valid
        self.SOURCE_SCRIPTHASH = dest_scripthash

        url = self._network + self._get_claimable + claim_addr
        res = requests.get(url=url)

        if not res.status_code == 200:
            raise NetworkError(
                'Neoscan request failed. Please check your internet connection.'
            )

        res = res.json()
        available = res["unclaimed"]
        if available == 0:
            raise AssetError(
                f"Address {claim_addr} has 0 unclaimed GAS. Please ensure the correct network is selected or specify a difference source address."
            )

        for ref in res['claimable']:
            self.Claims.append(
                CoinReference(prev_hash=UInt256.ParseString(ref['txid']),
                              prev_index=ref['n']))

        if to_addr:
            dest_scripthash = Helper.AddrStrToScriptHash(
                to_addr)  # also verifies if the address is valid

        self.outputs.append(
            TransactionOutput(AssetId=UInt256.ParseString(self.gas_asset_id),
                              Value=Fixed8.FromDecimal(available),
                              script_hash=dest_scripthash))
Exemplo n.º 12
0
    def test_GetScriptHashesForVerifying_DutyFlag(self):
        # test a raw tx
        ms = MemoryStream(binascii.unhexlify(self.rtx))
        reader = BinaryReader(ms)
        tx = Transaction.DeserializeFrom(reader)
        tx.raw_tx = True

        # create the mocked asset
        mock_asset = AssetState()
        mock_asset.AssetType = 0x80

        snapshot = GetBlockchain()._db.createSnapshot()
        with patch("neo.Core.Helper.Helper.StaticAssetState", return_value=mock_asset):
            res = tx.GetScriptHashesForVerifying(snapshot)

        self.assertTrue(type(res), list)
        self.assertEqual(res[0], Helper.AddrStrToScriptHash("AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3"))
Exemplo n.º 13
0
    def AddScript(self, address):
        """
        Specify a script for the transaction

        Args:
            address: (str) an additional address for transaction validation
        """
        address = Helper.AddrStrToScriptHash(
            address)  # also verifies if the address is valid

        if len(self.Attributes) < Transaction.MAX_TX_ATTRIBUTES:
            self.Attributes.append(
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=address))
        else:
            raise TXAttributeError(
                f'Cannot add script attribute. Maximum transaction attributes ({Transaction.MAX_TX_ATTRIBUTES}) already reached.'
            )
Exemplo n.º 14
0
    def get_blog_content(self, height, tag, sender=""):
        data = {}
        list = []
        while height > 1:
            block = Blockchain.Default().GetBlock(height)
            if block:
                block.LoadTransactions()
                jsn = block.ToJson()
                jsn['confirmations'] = Blockchain.Default().Height - block.Index + 1
                hash = Blockchain.Default().GetNextBlockHash(block.Hash)
                if hash:
                    jsn['nextblockhash'] = '0x%s' % hash.decode('utf-8')
                try:
                    if len(jsn['tx']) > 0:
                        for tx in jsn['tx']:
                            if len(tx['attributes']) > 0:
                                blog = {}
                                blog['time'] = jsn['time']
                                for att in tx['attributes']:
                                    if att['usage'] == TransactionAttributeUsage.Remark1:
                                        blog['sender'] = binascii.a2b_hex(att['data']).decode("utf8")
                                    if att['usage'] == TransactionAttributeUsage.Remark:
                                        blog['content'] = binascii.a2b_hex(att['data']).decode("utf8")
                                    if att['usage'] == TransactionAttributeUsage.Script:
                                        blog['sign'] = att['data']
                                if 'sign' in blog and 'sender' in blog:
                                    sign = Helper.AddrStrToScriptHash(blog['sender']).Data
                                    if sign.hex()!= blog['sign']:
                                        blog['sender'] = "匿名"
                                    pass
                                else:
                                    blog['sender'] = "匿名"
                                if tag in blog['content'] and (sender == "" or blog['sender'] == sender):
                                    list.append(blog)

                except:
                    raise
            if len(list) > 10:
                break
            height = height - 1
        data['height'] = height
        data['list'] = list
        return data
Exemplo n.º 15
0
def get_owners_from_params(params):
    to_remove = []
    owners = None

    for item in params:
        if type(item) is str:
            if '--owners=' in item:
                owners = []
                to_remove.append(item)
                try:
                    owner_list = eval(item.replace('--owners=', ''))
                    owners = set()
                    for o in owner_list:
                        shash = Helper.AddrStrToScriptHash(o)
                        owners.add(shash)
                except Exception as e:
                    logger.info("Could not parse owner %s " % e)
                    pass
    for item in to_remove:
        params.remove(item)

    return params, owners
Exemplo n.º 16
0
    def References(self):
        """
        Get all references.

        Returns:
            dict:
                Key (UInt256): input PrevHash
                Value (TransactionOutput): object.
        """
        if self.__references is None:
            refs = {}
            # group by the input prevhash
            for hash, group in groupby(self.inputs, lambda x: x.PrevHash):
                url = self._network + self._get_transaction + hash.ToString()
                tx = requests.get(url=url)

                if not tx.status_code == 200:
                    raise NetworkError(
                        'Neoscan request failed. Please check your internet connection.'
                    )
                tx = tx.json()

                if tx is not None:
                    for input in group:
                        t = tx['vouts'][input.PrevIndex]
                        if t['asset'].lower() == 'neo':
                            asset = UInt256.ParseString(self.neo_asset_id)
                        elif t['asset'].lower() == 'gas':
                            asset = UInt256.ParseString(self.gas_asset_id)
                        refs[input] = TransactionOutput(
                            AssetId=asset,
                            Value=Fixed8.FromDecimal(t['value']),
                            script_hash=Helper.AddrStrToScriptHash(
                                t['address_hash']))

            self.__references = refs

        return self.__references
Exemplo n.º 17
0
    def GetScriptHashesForVerifying(self):
        """
        Get a list of script hashes for verifying transactions.

        Returns:
            list: of UInt160 type script hashes.
        """
        if self.Type == b'\x02':  # ClaimTransaction
            hashes = super(RawTransaction, self).GetScriptHashesForVerifying()

            for hash, group in groupby(self.Claims, lambda x: x.PrevHash):
                url = self._network + self._get_transaction + hash.ToString()
                tx = requests.get(url=url)

                if not tx.status_code == 200:
                    raise NetworkError(
                        'Neoscan request failed. Please check your internet connection.'
                    )
                tx = tx.json()

                if tx is None:
                    raise RawTXError("Invalid Claim Operation")

                for claim in group:
                    if len(tx['vouts']) <= claim.PrevIndex:
                        raise RawTXError("Invalid Claim Operation")

                    script_hash = Helper.AddrStrToScriptHash(
                        tx['vouts'][claim.PrevIndex]['address_hash'])

                    if script_hash not in hashes:
                        hashes.append(script_hash)

            hashes.sort()

            return hashes
        else:
            return super(RawTransaction, self).GetScriptHashesForVerifying()
Exemplo n.º 18
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(
                        script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(
                        -2146233033,
                        "One of the identified items was in an invalid format."
                    )

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode(
                'utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(
                    height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(
                map(lambda hash: "0x%s" % hash.decode('utf-8'),
                    NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [
                ContractParameter.FromJson(p) for p in params[1]
            ]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [
                    ContractParameter.FromJson(p).ToVM() for p in params[2]
                ]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]),
                                               params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        elif method == "getbalance":
            if self.wallet:
                return self.get_balance(params)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getwalletheight":
            if self.wallet:
                return self.wallet.WalletHeight
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "listaddress":
            if self.wallet:
                return self.list_address()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getnewaddress":
            if self.wallet:
                keys = self.wallet.CreateKey()
                account = Account.get(
                    PublicKeyHash=keys.PublicKeyHash.ToBytes())
                return account.contract_set[0].Address.ToString()
            else:
                raise JsonRpcError(-400, "Access denied.")

        raise JsonRpcError.methodNotFound()
Exemplo n.º 19
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int

            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(map(lambda hash: "0x%s" % hash.decode('utf-8'), NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "mw_construct_send_tx":
            return MyWishMethods.construct_send_tx(self.wallet, params)

        elif method == "mw_construct_deploy_tx":
            return MyWishMethods.construct_deploy_tx(self.wallet, params)

        elif method == "mw_construct_invoke_tx":
            return MyWishMethods.construct_invoke_tx(self.wallet, params)

        elif method == "getapplicationlog":
            assert(all([x in '1234567890abcdefABCDEFxX' for x in params[0]])) # prevent traversal
            try:
                with open('/home/neo/neo-python/notis/' + params[0]) as f:
                    res =  [json.loads(x) for x in f.read().split('\n') if x]
                    return [{'name': x['notify_type'], 'contract': x['contract'], 'args': x['payload']} for x in res]
            except FileNotFoundError:
                return ([])

        elif method == "submitblock":
            raise NotImplementedError()

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        raise JsonRpcError.methodNotFound()
Exemplo n.º 20
0
    def ask_for_assets(self, request):
        """
        This function processes the user input; creates and saves the user's IP address and time of their visit and
        their wallet address and time of their visit; if the user's information checks out and they haven't visited
        too many times, then it will send their information to the _make_tx_ function. Upon success, it will redirect
        the user to the success page and display the transaction info

        :param request: klein request object that gets passed into every route function
        :return: upon success, returns a Deferred that already had '.callback(result)' called
        upon failure, returns the index page with some error displayed

        """
        self.sent_tx = None
        ctx = self._get_context()
        ctx['error'] = False
        proceed = True
        step = 0
        iprequest_item = None
        faucetrequest_item = None
        address_to = None
        now = datetime.now()
        past_week = now - timedelta(days=7)
        #next_week = now + timedelta(days=7)  # for testing
        epochTs = time(
        )  # the time() is the time in seconds since the epoch (01/01/1970 for UNIX systems)
        week_in_sec = 60 * 60 * 24 * 7  # 60 seconds * 60 minutes * 24 hours * 7 days
        expire_date = epochTs + week_in_sec

        if ctx[f'{self.token_symbol}'] < 10000:
            request.redirect('/')
            return succeed(None)
        try:
            if b'address_to' in request.args:
                address_to = request.args.get(b'address_to')[0].decode(
                    'utf-8').strip()
                ctx['address_to'] = address_to
                client = None

                if (proceed is True) & (step == 0):  # for IPRequest
                    #client = str(request.getClientAddress().host)  # gets the IPv4 address
                    client = str(
                        request.getHeader(key='x-real-ip')
                    )  # gets the IPv4 address if behind NGINX server
                    iprequest_item = IPRequest(
                        ip_address=client, last_visited=now,
                        ttl=expire_date)  # creates IPRequest item
                    count = 0  # the following gets all requests from this ip address in the past week
                    for item in IPRequest.query(
                            hash_key=client,
                            range_key_condition=IPRequest.last_visited >
                            past_week,
                            limit=10):
                        count += 1

                    logger_request.info(f'IPRequest TOTAL: {count}')
                    if count >= 3:  # if user(s) from this ip has requested >= 3 times in the past week,
                        proceed = False  # stop progress for the program
                        ctx['message'] = 'You have requested too many times for this time period. ' \
                                         'Try again next week.'  # display error message
                        ctx['error'] = True
                    else:  # else go to the next step
                        step += 1
                elif (proceed is True) & (step == 0):
                    ctx['error'] = True
                    ctx['message'] = 'Request failed. Please try again.'

                if (proceed is True) & (step == 1):  # for FaucetRequest
                    faucetrequest_item = FaucetRequest(
                        wallet_address=address_to,
                        last_visited=now,
                        ttl=expire_date)  # creates FaucetRequest item
                    count = 0  # the following gets all requests from this wallet address in the past week
                    for item in FaucetRequest.query(
                            hash_key=address_to,
                            range_key_condition=FaucetRequest.last_visited >
                            past_week,
                            limit=10):
                        count += 1

                    logger_request.info(f'FaucetRequest TOTAL: {count}')
                    if count >= 1:  # if user from this wallet address has requested >= 1 times in the past week,
                        proceed = False  # stop progress for the program
                        ctx['message'] = 'Already requested within the past week'  # display error message
                        ctx['error'] = True
                    else:  # else save the request to the database
                        iprequest_item.save()
                        faucetrequest_item.save()
                        step += 1
                        logger_request.info('\n----------------------------')
                        logger_request.info(f'IP Address: {client}')
                        logger_request.info(f'Wallet Address: {address_to}')
                        logger_request.info(f'Date of Request: {now}')
                        logger_request.info('----------------------------\n')
                elif (proceed is True) & (step == 1):
                    ctx['error'] = True
                    ctx['message'] = 'Request failed. Please try again.'

                if (proceed is True) & (step == 2):  # make transaction
                    tx = self._make_tx(
                        Helper.AddrStrToScriptHash(
                            address=address_to).ToArray())

                    # neo-faucet used ContractTransaction() for this part because they created a smart contract to
                    # transfer the system assets.
                    # Since this is a nep5 token faucet, we use InvocationTransaction() to invoke the token's
                    # 'transfer' function.
                    if type(tx) is InvocationTransaction:
                        logger.info('ALL OK!!!')
                        step = 0
                        self.sent_tx = tx  # sets the objects instance variable sent.tx to the tx info
                        request.redirect(
                            '/success')  # redirects to the success page
                        return succeed(None)
                    else:
                        ctx['message'] = f'Error constructing transaction: {tx}'
                        ctx['error'] = True
                else:
                    if ctx['message'] is None:
                        ctx['message'] = 'You must input a wallet address to proceed'
                        ctx['error'] = True
        except Exception as e:
            logger_request.error(f'exception: {e}')
            ctx['error'] = True
            ctx['message'] = f'Could not process request: {e}'

        output = self.j2_env.get_template('index.html').render(ctx)
        return output
Exemplo n.º 21
0
    def _make_tx(self, address_to):
        """
        Function that creates the parameters for the NEP-5 transfer function and then calls it,
        returning the transaction info

        :param address_to: address to send the tokens to
        :return:
            transaction info
        """
        drip_amount = BigInteger(10000)
        amount = BigInteger(
            drip_amount * 100000000
        )  # must multiply by Fixed8.D and must be BigInteger object
        self.invoke_args.clear()
        self.params.clear(
        )  # make sure that invoke_args and params lists are empty
        scripthash_from = Helper.AddrStrToScriptHash(
            address=self.faucet_wallet_addr).ToArray()
        scripthash_to = address_to

        self.invoke_args.append(scripthash_from)
        self.invoke_args.append(scripthash_to)
        self.invoke_args.append(amount)
        self.params = [
            self.token_script_hash.encode('utf-8'), self.OPERATION,
            self.invoke_args
        ]
        nonce = struct.pack('>i',
                            int(time()))  # convert the int to a big endian int
        # the int(time()) is the time in seconds since the epoch (01/01/1970 for UNIX systems)
        # the nonce was used to append to the TransactionAttribute so that each transaction has slightly
        # different data. Otherwise, each transaction would constantly be given the same transaction hash because
        # all of their parameters are the same
        # TransactionAttributeUsage.Remark is b'\xf0' = 240
        invoke_attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Remark,
                                 data=nonce)
        ]
        # the following test invokes the contract (useful to ensure that noting is wrong)
        tx, fee, results, num_ops = TestInvokeContract(
            wallet=self.wallet,
            args=self.params,
            from_addr=self.faucet_wallet_addr,
            min_fee=Fixed8.Zero(),
            invoke_attrs=invoke_attributes)

        # the following is just used for logging info
        if tx is not None and results is not None:
            logger.info('\n------------------------')
            for item in results:
                logger.info(f'Results: {str(item)}')
                if not len(str(item)) % 2:
                    try:
                        logger.info(
                            f'Hex decode: {binascii.unhexlify(str(item))}')
                    except Exception:
                        logger.warning('Not hex encoded')
            logger.info(f'Invoke TX gas cost: {(tx.Gas.value / Fixed8.D)}')
            logger.info(f'Invoke TX Fee: {(fee.value / Fixed8.D)}')
            logger.info('Relaying invocation tx now')
            logger.info('------------------------\n')

        # invoke the contract
        self.sent_tx = InvokeContract(wallet=self.wallet,
                                      tx=tx,
                                      fee=Fixed8.Zero(),
                                      from_addr=self.faucet_wallet_addr)
        sleep(
            3
        )  # allow a few seconds for the contract to be invoked and return the tx info is actually passed
        return self.sent_tx
Exemplo n.º 22
0
def main():
    parser = argparse.ArgumentParser(
        description=
        'A utility for signing messages.  Example usage: "np-sign mymessage --wallet_file path/to/my/wallet" or use an NEP2 key/passphrase like "np-sign mymessage -n"'
    )
    parser.add_argument('message',
                        type=str,
                        help='The message in string format to be signed')
    parser.add_argument(
        '-w',
        '--wallet_file',
        type=str,
        default=None,
        help='If using a wallet file, the path to the wallet file')
    parser.add_argument(
        '-a',
        '--address',
        type=str,
        default=False,
        help=
        'If using a wallet file with more than 1 address, the address you would like to use.  Otherwise the default address will be used'
    )
    parser.add_argument(
        '-n',
        '--nep2',
        action='store_true',
        help="Whether to use an NEP2 passhrase rather than a wallet")
    parser.add_argument('--wif',
                        type=str,
                        default=None,
                        help='If using a wif pass in the wif')
    args = parser.parse_args()
    try:

        if args.wallet_file:

            passwd = prompt('[Wallet password]> ', is_password=True)
            wallet = UserWallet.Open(args.wallet_file, to_aes_key(passwd))

            contract = wallet.GetDefaultContract()
            if args.address:
                addr = args.address
                script_hash = Helper.AddrStrToScriptHash(addr)
                contract = wallet.GetContract(script_hash)

                if contract is None:
                    raise Exception('Address %s not found in wallet %s ' %
                                    (addr, args.wallet_file))

            print("Signing With Address %s " % contract.Address)
            signature, pubkey = wallet.SignMessage(args.message,
                                                   contract.ScriptHash)

            pubkey = pubkey.encode_point().decode('utf-8')
            signature = signature.hex()
            print("pubkey, sig: %s %s " % (pubkey, signature))

        elif args.nep2:

            nep2_key = prompt('[nep2 key]> ', is_password=True)
            nep2_passwd = prompt("[nep2 key password]> ", is_password=True)

            prikey = KeyPair.PrivateKeyFromNEP2(nep2_key, nep2_passwd)
            keypair = KeyPair(priv_key=prikey)
            contract = Contract.CreateSignatureContract(keypair.PublicKey)
            print("Signing With Address %s " % contract.Address)
            signature = Crypto.Sign(args.message, prikey)

            pubkey = keypair.PublicKey.encode_point().decode('utf-8')
            signature = signature.hex()
            print("pubkey, sig: %s %s " % (pubkey, signature))

        elif args.wif:
            prikey = KeyPair.PrivateKeyFromWIF(args.wif)
            keypair = KeyPair(priv_key=prikey)
            contract = Contract.CreateSignatureContract(keypair.PublicKey)
            print("Signing With Address %s " % contract.Address)
            signature = Crypto.Sign(args.message, prikey)

            pubkey = keypair.PublicKey.encode_point().decode('utf-8')
            signature = signature.hex()
            print("pubkey, sig: %s %s " % (pubkey, signature))

    except Exception as e:
        print("Could not sign: %s " % e)
Exemplo n.º 23
0
def RequestWithdraw(prompter, wallet, args):

    if not wallet:
        print("please open a wallet")
        return

    withdrawal_tx = construct_contract_withdrawal_request(wallet,
                                                          args,
                                                          fee=Fixed8.Zero(),
                                                          check_holds=True)

    if withdrawal_tx:

        # below we are going to mimic a test invoke from the prompt

        invoke_args = []

        contract_addr = args[0]
        contract_hash = Helper.AddrStrToScriptHash(contract_addr).ToString()

        # add contract hash
        invoke_args.append(contract_hash)

        # add 'withdrawRequest' method
        invoke_args.append(parse_param('withdrawalRequest'))

        invoke_args_array = []

        requestor = parse_param(args[2])
        invoke_args_array.append(requestor)

        for input in withdrawal_tx.inputs:
            invoke_args_array.append(bytearray(input.PrevHash.Data))
            invoke_args_array.append(input.PrevIndex)

        invoke_args.append(invoke_args_array)

        print("invoke args array %s " % invoke_args)

        tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args,
                                                       None, False)

        if tx is not None and results is not None:
            print(
                "\n-------------------------------------------------------------------------------------------------------------------------------------"
            )
            print("Request Withdraw successful")
            print("Total operations: %s " % num_ops)
            print("Results %s " % [str(item) for item in results])
            print("Withdraw Request gas cost: %s " % (tx.Gas.value / Fixed8.D))
            print("Withdraw Request Fee: %s " % (fee.value / Fixed8.D))
            print(
                "-------------------------------------------------------------------------------------------------------------------------------------\n"
            )
            print("Enter your password to complete this withdrawal request")

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

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

            result = InvokeContract(wallet, tx, fee)

            return result
        else:
            print("Error testing contract invoke")
            return
Exemplo n.º 24
0
    global Wallet
    Wallet = UserWallet.Open(path="infinitewallet", password="******")
    logger.info("Created the Wallet")
    logger.info(Wallet.AddressVersion)
    walletdb_loop = task.LoopingCall(Wallet.ProcessBlocks)
    walletdb_loop.start(1)
    #Wallet.CreateKey(KeyPair.PrivateKeyFromWIF(wif))

    # Start a thread with custom code
    d = threading.Thread(target=custom_background_code)
    d.setDaemon(
        True
    )  # daemonizing the thread will kill it when the main thread is quit
    d.start()

    # Run all the things (blocking call)
    logger.info("Everything setup and running. Waiting for events...")
    reactor.run()
    logger.info("Shutting down.")


if __name__ == "__main__":
    global wallet_hash
    global wallet_arr
    global smart_contract_hash
    wallet_hash = sys.argv[1]
    smart_contract_hash = sys.argv[2]
    print(wallet_hash)
    wallet_arr = Helper.AddrStrToScriptHash(wallet_hash).ToArray()
    main()
Exemplo n.º 25
0
    def BuildTokenTransfer(self, token, to_addr, amount):
        """
        Build a token transfer for an InvocationTransaction.

        Args:
            token: (str) the asset symbol or asset hash
            to_addr: (str) the destination NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
            amount: (int/decimal) the amount of the asset to send
        """
        if not self.BALANCE:
            raise RawTXError(
                'Please specify a source address before building a token transfer.'
            )

        if not isinstance(token, str):
            raise TypeError('Please enter your token as a string.')

        # check if the token is in the source addr balance
        t_hash = None
        if len(token) == 40:  # check if token is a scripthash
            for asset in self.BALANCE:
                if asset['asset_hash'] == token:
                    t_hash = asset['asset_hash']

                    # also verify not insufficient funds
                    if asset['amount'] < amount:
                        raise AssetError("Insufficient funds.")
                    break
        else:  # assume the symbol was used
            for asset in self.BALANCE:
                if asset['asset_symbol'] == token:
                    t_hash = asset['asset_hash']

                    # also verify not insufficient funds
                    if asset['amount'] < amount:
                        raise AssetError("Insufficient funds.")
                    break
        if not t_hash:
            raise AssetError(
                f'Token {token} not found in the source address balance.')

        dest_scripthash = Helper.AddrStrToScriptHash(
            to_addr)  # also verifies if the address is valid

        sb = ScriptBuilder()
        sb.EmitAppCallWithOperationAndArgs(
            UInt160.ParseString(t_hash), 'transfer', [
                self.SOURCE_SCRIPTHASH.Data, dest_scripthash.Data,
                BigInteger(Fixed8.FromDecimal(amount).value)
            ])
        script = sb.ToArray()

        self.Version = 1
        self.Script = binascii.unhexlify(script)

        # check to see if the source address has been added as a script attribute and add it if not found
        s = 0
        for attr in self.Attributes:
            if attr.Usage == TransactionAttributeUsage.Script:
                s = s + 1
        if s == 0:
            self.Attributes.append(
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=self.SOURCE_SCRIPTHASH))
        if s > 1:
            raise TXAttributeError(
                'The script attribute must be used to verify the source address.'
            )
Exemplo n.º 26
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_str = params[0]
            if asset_str.lower() == 'neo':
                assetId = Blockchain.Default().SystemShare().Hash
            elif asset_str.lower() == 'gas':
                assetId = Blockchain.Default().SystemCoin().Hash
            else:
                assetId = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(assetId.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(self.nodemgr.nodes)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            raise JsonRpcError(-100, "Not supported")
            # return list(map(lambda hash: f"{hash.To0xString()}", self.nodemgr.mempool.pool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": self.nodemgr.id,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettransactionheight":
            try:
                hash = UInt256.ParseString(params[0])
            except Exception:
                # throws exception, not anything more specific
                raise JsonRpcError(-100, "Unknown transaction")

            tx, height = Blockchain.Default().GetTransaction(hash)
            if tx:
                return height
            else:
                raise JsonRpcError(-100, "Unknown transaction")

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            # TODO: relay blocks, change to await in the future
            result = self.nodemgr.relay(transaction)
            return result

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            return self.get_peers()

        elif method == "getbalance":
            if self.wallet:
                return self.get_balance(params)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getwalletheight":
            if self.wallet:
                return self.wallet.WalletHeight
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "listaddress":
            if self.wallet:
                return self.list_address()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getnewaddress":
            if self.wallet:
                keys = self.wallet.CreateKey()
                account = Account.get(
                    PublicKeyHash=keys.PublicKeyHash.ToBytes()
                )
                return account.contract_set[0].Address.ToString()
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendtoaddress":
            if self.wallet:
                contract_tx, fee = self.parse_send_to_address_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendfrom":
            if self.wallet:
                contract_tx, address_from, fee, change_addr = self.parse_send_from_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee, address_from=address_from, change_addr=change_addr)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "sendmany":
            if self.wallet:
                contract_tx, fee, change_addr = self.parse_send_many_params(params)
                return self.process_transaction(contract_tx=contract_tx, fee=fee, change_addr=change_addr)
            else:
                raise JsonRpcError(-400, "Access denied.")

        elif method == "getblockheader":
            # this should work for either str or int
            blockheader = Blockchain.Default().GetHeaderBy(params[0])
            if not blockheader:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_blockheader_output(blockheader, params)

        raise JsonRpcError.methodNotFound()
Exemplo n.º 27
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(map(lambda hash: "0x%s" % hash.decode('utf-8'), NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getLastBlog":

            if len(params) > 0:
                height = params[0]
            else:
                height = Blockchain.Default().Height + 1
            data = self.get_blog_content(height, "")
            return data;
        elif method == "getLastBlogByTag":

            if len(params) > 1:
                height = params[1]
                tag = params[0]
            elif len(params) > 0:
                tag = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, tag)
            return data;
        elif method == "getLastBlogBySender":

            if len(params) > 1:
                height = params[1]
                sender = params[0]
            elif len(params) > 0:
                sender = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, "", sender)
            return data;
        elif method == "getBlogContent":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")

            for attr in tx.Attributes:
                item = attr.ToJson;
                if item['usage'] == 240:
                    item['content'] = binascii.a2b_hex(item['data']).decode("utf8")
                    return item;
            raise JsonRpcError(-100, "no blog content")


        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "createAddress":

            private_key = bytes(Random.get_random_bytes(32))
            key = KeyPair(priv_key=private_key)
            self.wallet._keys[key.PublicKeyHash.ToBytes()] = key
            self.wallet.OnCreateAccount(key)
            contract = WalletContract.CreateSignatureContract(key.PublicKey)
            self.wallet.AddContract(contract)
            if key :
                result = {'privateKey': key.Export(),'address':contract.Address}
                return result;
            else:
                return None
        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())
        # elif method == "sendBlog":
        #     shash = UInt160.ParseString(params[0])
        #     contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
        #     sb = ScriptBuilder()
        #     sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
        #     script = sb.ToArray();
        #     tx = ContractTransaction()
        #     tx.inputs = []
        #     tx.outputs = []
        #     attribute = TransactionAttribute(240, params[2].encode('utf-8'))
        #     standard_contract = self.wallet.GetStandardAddress()
        #     data = standard_contract.Data
        #     tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
        #                                           data=data)]
        #
        #     tx.Attributes.append(attribute)
        #     tx.Version = 1
        #     tx.scripts = []
        #     BC = GetBlockchain()
        #     contract = BC.GetContract(params[0])
        #     output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
        #                                Value=Fixed8.FromDecimal(float(1)),
        #                                script_hash=contract.Code.ScriptHash(),
        #                                )
        #     tx.outputs.append(output)
        #     logger.info("output %s" % output.ToJson(0))
        #     tx.Script = binascii.unhexlify(script)
        #     print("percentage %s %s" % (self.wallet.WalletHeight, Blockchain.Default().Height))
        #     scripthash_from = None
        #     if not self.wallet.IsSynced:
        #         raise JsonRpcError.invalidRequest("wallet not synced")
        #     private_key = None
        #     if len(params) > 3:
        #         from_address = params[3]
        #         if from_address is not None:
        #             scripthash_from = lookup_addr_str(self.wallet, from_address)
        #     if len(params) > 4:
        #         private_key = params[4]
        #     wallet_tx = SendBlog(self.wallet, tx, from_addr=scripthash_from, privatekey=private_key)
        #     if wallet_tx != False:
        #         return wallet_tx.ToJson();
        #     self.wallet.Rebuild()
        #     raise JsonRpcError.invalidRequest("Field 'no enough asset")
        elif method == 'postblog':
            try:

                if len(params) > 3:
                    from_address = params[3]
                assetId =Blockchain.SystemShare().Hash

                if len(params) > 4:
                    private_key = params[4]

                if assetId is None:
                    print("Asset id not found")
                    return False

                contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
                sb = ScriptBuilder()
                sb.EmitAppCallWithJsonArgs(UInt160.ParseString(params[0]), contract_parameters)
                script = sb.ToArray();

                scripthash_from = None

                if from_address is not None:
                    scripthash_from = lookup_addr_str(self.wallet, from_address)

                # f8amount = Fixed8.TryParse(0, require_positive=True)
                # if f8amount is None:
                #     print("invalid amount format")
                #     return False
                #
                # if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(
                #         assetId.ToBytes()).Precision) != 0:
                #     print("incorrect amount precision")
                #     return False
                #
                fee = Fixed8.Zero()
                #
                # output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=contract.Code.ScriptHash())
                tx = InvocationTransaction()

                ttx = self.wallet.MakeTransaction(tx=tx,
                                             change_address=None,
                                             fee=fee,
                                             from_addr=scripthash_from)

                if ttx is None:
                    print("insufficient funds")
                    return False
                standard_contract = self.wallet.GetStandardAddress()
                if scripthash_from is not None:
                    signer_contract = self.wallet.GetContract(scripthash_from)
                else:
                    signer_contract = self.wallet.GetContract(standard_contract)

                if not signer_contract.IsMultiSigContract:
                    data = scripthash_from.Data
                    print(data)
                    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                          data=data),TransactionAttribute(usage=TransactionAttributeUsage.Remark1,
                                                          data=from_address.encode('utf-8'))]

                # insert any additional user specified tx attributes
                tx.Attributes.append(TransactionAttribute(240, params[2].encode('utf-8')))
                tx.Script = binascii.unhexlify(script)

                context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract)
                if private_key is not None:
                    prikey = KeyPair.PrivateKeyFromWIF(private_key)
                    kp = KeyPair(prikey)
                self.wallet.Sign(context,kp)
                attributes = [attr.ToJson() for attr in tx.Attributes]
                print("attributes %s" %attributes)
                if context.Completed:

                    tx.scripts = context.GetScripts()

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

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

                    if relayed:
                        self.wallet.SaveTransaction(tx)

                        print("Relayed Tx: %s " % tx.Hash.ToString())
                        return tx.ToJson()
                    else:

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

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

            except Exception as e:
                print("could not send: %s " % e)

            return False
        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "submitblock":
            raise NotImplementedError()

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            raise NotImplementedError()

        raise JsonRpcError.methodNotFound()