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
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)
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
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']
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
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))
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))
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
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))
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"))
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.' )
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
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
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
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()
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()
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()
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
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
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)
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
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()
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.' )
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()
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()