def sign(self, private_seed: bytes) -> None: # TODO # self.app_log.error("TODO: Message.sign()") self._sourceNodeIdentifier = KeyUtil.private_to_public( private_seed.hex()) self._sourceNodeSignature = KeyUtil.signBytes( self.get_bytes_for_signing(), private_seed)
def load(dir: str = './'): """ Overload info with config.default.txt and config.txt :return: """ global PRIVATE_KEY global PUBLIC_KEY if path.exists(dir + "config.default.txt"): _overload(dir + "config.default.txt") if path.exists(dir + "config.txt"): _overload(dir + "config.txt") # Load the keys if not path.isfile(NYZO_SEED): print(f"No key file, creating one into {NYZO_SEED}") PRIVATE_KEY = KeyUtil.generateSeed() KeyUtil.save_to_private_seed_file(NYZO_SEED, PRIVATE_KEY) PRIVATE_KEY, PUBLIC_KEY = KeyUtil.get_from_private_seed_file(NYZO_SEED) # We can tweak verbosity later on, do not print here but later on. if DEBUG: print( f"Key Loaded, public id {ByteUtil.bytes_as_string_with_dashes(PUBLIC_KEY.to_bytes())}" ) return {var: globals()[var] for var in _VARS}
def token_burn(ctx, token_name: str, amount: str, key_: str = ""): # ./Nyzocli.py --verbose token burn TEST3 1.12345 if key_ == "": seed = config.PRIVATE_KEY.to_bytes() key_ = NyzoStringEncoder.encode( NyzoStringPrivateSeed.from_hex(seed.hex())) else: seed = NyzoStringEncoder.decode(key_).get_bytes() key, pub = KeyUtil.get_from_private_seed(seed.hex()) address = pub.to_ascii(encoding="hex").decode('utf-8') if float(amount) <= 0: raise ValueError("Amount has to be > 0") if not re.match(r"[0-9A-Z_]{3,32}", token_name): raise ValueError(f"Token name '{token_name}' does not follow rules") if VERBOSE: print(f"token burn {token_name} amount {amount}") data = f"TB:{token_name}:{amount}" fees = 0.000001 # Test via API recipient = CYCLE_ADDRESS_HEX url = f"{ctx.obj['token']}/check_tx/{address}/{recipient}/{fees:0.6f}/{data}" if VERBOSE: print(url) res = get(url).text if VERBOSE: print(res) if "Error:" in res: print(res) else: # Assemble, sign and forward if ok client = NyzoClient(ctx.obj['client']) res = client.send(recipient, fees, data, key_) print(res)
def token_ownership(ctx, token_name: str, recipient: str, key_: str = ""): # ./Nyzocli.py --verbose token ownership TEST3 3f19e603b9577b6f91d4c84531e1e94e946aa172063ea3a88efb26e3fe75bb84 if key_ == "": seed = config.PRIVATE_KEY.to_bytes() key_ = NyzoStringEncoder.encode( NyzoStringPrivateSeed.from_hex(seed.hex())) else: seed = NyzoStringEncoder.decode(key_).get_bytes() key, pub = KeyUtil.get_from_private_seed(seed.hex()) address = pub.to_ascii(encoding="hex").decode('utf-8') id__recipient, recipient = normalize_address(recipient, asHex=True) print(f"token ownership transfer {token_name} to {recipient}") data = f"TO:{token_name}" fees = 0.000001 # Test via API url = f"{ctx.obj['token']}/check_tx/{address}/{recipient}/{fees:0.6f}/{data}" if VERBOSE: print(url) res = get(url).text if VERBOSE: print(res) if "Error:" in res: print("E", res) else: # Assemble, sign and forward if ok client = NyzoClient(ctx.obj['client']) res = client.send(recipient, fees, data, key_) print(res)
def send(self, recipient: str, amount: float = 0, data: str = "", key_: str = "", frozen: dict=None): """ Send Nyzo with data string to a RECIPIENT. """ if key_ == "": raise ValueError("Need a key_") seed = NyzoStringEncoder.decode(key_).get_bytes() # convert key to address address = KeyUtil.private_to_public(seed.hex()) recipient, recipient_raw = self.normalize_address(recipient, as_hex=True) if frozen is None: frozen = self.get_frozen() # print (f"Sending {amount} to {recipient} since balance of {address} is > {above}.") # print(f"Frozen edge is at {frozen['height']}") # Create a tx timestamp = int(time() * 10) * 100 + 10000 # Fixed 10 sec delay for inclusion # print(timestamp, hex(timestamp)) data_bytes = data[:32].encode("utf-8") transaction = Transaction(buffer=None, type=Transaction.type_standard, timestamp=timestamp, sender_identifier=bytes.fromhex(address), amount=int(amount * 1e6), receiver_identifier=bytes.fromhex(recipient_raw), previous_block_hash=bytes.fromhex(frozen["hash"]), previous_hash_height=frozen['height'], signature=b'', sender_data=data_bytes) # print(transaction.to_json()) key, _ = KeyUtil.get_from_private_seed(seed.hex()) to_sign = transaction.get_bytes(for_signing=True) sign = KeyUtil.sign_bytes(to_sign, key) tx = NyzoStringTransaction(Transaction.type_standard, timestamp, int(amount * 1e6), bytes.fromhex(recipient_raw), frozen['height'], bytes.fromhex(frozen["hash"]), bytes.fromhex(address), data_bytes, sign) tx__ = NyzoStringEncoder.encode(tx) # Send the tx url = "{}/forwardTransaction?transaction={}&action=run".format(self.client, tx__) res = get(url) # print(res.text) temp = self.fake_table_to_list(res.text) # print(temp) temp = temp[0] # Add tx to data temp["tx__"] = tx__ return temp
def vote(ctx, cycle_tx_sig: str, vote: int = 1, key_: str = ""): """ Vote for the given cycle tx sig with the provided seed. If no seed is given, use the wallet one. - ex: python3 Nyzocli.py vote sig_gc6VHCY_yfjRc_DyosRLdi084AbY5wP9yVdTTRhajp4JUk7nbRw9c-aufwEwGY~.x0m55u.v.tGzjnA7VYP4V0m-eXyG - ex: python3 Nyzocli.py vote sig_gc6VHCY_yfjRc_DyosRLdi084AbY5wP9yVdTTRhajp4JUk7nbRw9c-aufwEwGY~.x0m55u.v.tGzjnA7VYP4V0m-eXyG 1 - ex: python3 Nyzocli.py vote sig_gc6VHCY_yfjRc_DyosRLdi084AbY5wP9yVdTTRhajp4JUk7nbRw9c-aufwEwGY~.x0m55u.v.tGzjnA7VYP4V0m-eXyG 0 key_... """ if key_ == "": seed = config.PRIVATE_KEY.to_bytes() else: seed = NyzoStringEncoder.decode(key_).get_bytes() key, _ = KeyUtil.get_from_private_seed(seed.hex()) # reconvert key to address address = KeyUtil.private_to_public(seed.hex()) if VERBOSE: app_log.info(f"Voting {vote} for {cycle_tx_sig} with id {address}") cycle_tx_sig_bytes = NyzoStringEncoder.decode(cycle_tx_sig).get_bytes() # Create a tx timestamp = int( time() * 10) * 100 + 10000 # Fixed 10 sec delay for inclusion # print(timestamp, hex(timestamp)) cycle_transaction_signature_hex = cycle_tx_sig_bytes.hex() transaction = Transaction.from_vote_data(timestamp, bytes.fromhex(address), vote, cycle_tx_sig_bytes) print(transaction.to_json()) sign = KeyUtil.sign_bytes( transaction.get_bytes(for_signing=True)[:106], key) tx = NyzoStringTransaction.from_hex_vote(hex(timestamp), address, sign.hex(), vote, cycle_transaction_signature_hex) tx__ = NyzoStringEncoder.encode(tx) # Send the tx url = "{}/forwardTransaction?transaction={}&action=run".format( ctx.obj['client'], tx__) if VERBOSE: app_log.info(f"Calling {url}") res = get(url) if VERBOSE: app_log.info(res) if path.isdir("tmp"): # Store for debug purposes with open("tmp/answer.txt", "w") as fp: fp.write(res.text) print(json.dumps(fake_table_to_list(res.text)))
def safe_send(ctx, recipient, amount: float = 0, data: str = "", key_: str = ""): """ Send Nyzo to a RECIPIENT then makes sure it is embedded in the planned block. If no seed is given, use the wallet one. - ex: python3 Nyzocli.py safe_send abd7fede35a84b10-8a36e6dc361d9b32-ca84d149f6eb85b4-a4e63015278d4c9f 10 - ex: python3 Nyzocli.py safe_send abd7fede35a84b10-8a36e6dc361d9b32-ca84d149f6eb85b4-a4e63015278d4c9f 10 key_... """ if key_ == "": seed = config.PRIVATE_KEY.to_bytes() key_ = NyzoStringEncoder.encode( NyzoStringPrivateSeed.from_hex(seed.hex())) else: seed = NyzoStringEncoder.decode(key_).get_bytes() # convert key to address address = KeyUtil.private_to_public(seed.hex()) my_balance = ctx.invoke(balance, address=address) if amount == -1: if my_balance is None: my_balance = ctx.invoke(balance, address=address) print(my_balance) # my_balance = balance(ctx, address) amount = float(my_balance) if amount <= 0: if VERBOSE: app_log.warning( "Balance too low or unknown {}, dropping.".format( my_balance)) print( json.dumps({ "result": "Error", "reason": "Balance too low, {}".format(my_balance) })) return else: if VERBOSE: app_log.warning("Sending full balance {}.".format(my_balance)) recipient, recipient_raw = normalize_address(recipient, asHex=True) client = NyzoClient(ctx.obj['client']) res = client.safe_send(recipient, amount, data, key_, max_tries=5, verbose=True) print(res) return
def test_keys_1(verbose=False): master = b'9444' # Nyzo port as test seed seed = hashlib.sha256(master).digest() assert seed == b',V@?\xcf\xfb\xd14M\xfbw&\x89\xf6\x0eDoDq\xd2\xca\x17\xf3\xa5\xea\xa6)\xf6\xc52<l' # NEVER USE THAT KEY IN REAL WORLD!!! signing_key = ed25519.SigningKey(seed) hex = signing_key.to_ascii(encoding="hex").decode('utf-8') if verbose: print("private", hex) assert hex == '2c56403fcffbd1344dfb772689f60e446f4471d2ca17f3a5eaa629f6c5323c6c' public = KeyUtil.private_to_public(hex) if verbose: print("public", public) assert public == 'a34abe2176eeb545735b25ff68c41d716db462e55c7c3a5d48db0ae4fc95ae9e'
def token_issue(ctx, token_name: str, decimals: int, supply: str, key_: str = ""): # ./Nyzocli.py --verbose token issue -- TEST3 3 -1 if key_ == "": seed = config.PRIVATE_KEY.to_bytes() key_ = NyzoStringEncoder.encode( NyzoStringPrivateSeed.from_hex(seed.hex())) else: seed = NyzoStringEncoder.decode(key_).get_bytes() key, pub = KeyUtil.get_from_private_seed(seed.hex()) address = pub.to_ascii(encoding="hex").decode('utf-8') if decimals < 0: raise ValueError("Decimals have to be >= 0") if decimals > 18: raise ValueError("Decimals have to be <= 18") dec = str(decimals) while len(dec) < 2: dec = "0" + dec if not re.match(r"[0-9A-Z_]{3,32}", token_name): raise ValueError(f"Token name '{token_name}' does not follow rules") if VERBOSE: print(f"token issue {token_name} decimals {dec} supply {supply}") data = f"TI:{token_name}:d{dec}:{supply}" # get fees url = f"{ctx.obj['token']}/fees" res = get(url) fees = res.json() issue_fees = fees[-1]["issue_fees"] # micro_nyzos amount = issue_fees / 1000000 if VERBOSE: print(f"Issue fees are {issue_fees} micro nyzos.") # Test via API recipient = CYCLE_ADDRESS_HEX url = f"{ctx.obj['token']}/check_tx/{address}/{recipient}/{amount:0.6f}/{data}" if VERBOSE: print(url) res = get(url).text if VERBOSE: print(res) if "Error:" in res: print(res) else: # Assemble, sign and forward if ok client = NyzoClient(ctx.obj['client']) res = client.send(recipient, amount, data, key_) print(res)
def __init__(self, a_type: MessageType, sourceNodePrivateKey, content: MessageObject, app_log: object = None, sourceNodeIdentifier: bytes = None, sourceNodeSignature: bytes=None, source_ip_address: bytes=None, timestamp: int=0): """This is the constructor for a new message originating from this system AND from the outside, depending on the params.""" self.app_log = base_app_log(app_log) self._type = a_type self._content = content self._valid = True # if sourceNodeIdentifier is None: self._timestamp = int(time()*1000) if sourceNodePrivateKey is not None: private_key, pub_key = KeyUtil.get_from_string(sourceNodePrivateKey) self._sourceNodeIdentifier = pub_key.to_bytes() self._sourceNodeSignature = KeyUtil.sign_bytes(self.get_bytes_for_signing(), private_key) else: print(sourceNodePrivateKey) # From our system print('wrong') print(dir()) self._sourceNodeIdentifier = config.PUBLIC_KEY.to_bytes() self._sourceNodeSignature = KeyUtil.sign_bytes(self.get_bytes_for_signing(), config.PRIVATE_KEY) # As a test, we can verify our sig before sending """
def __init__(self, a_type: MessageType, content: MessageObject, app_log: object = None, sourceNodeIdentifier: bytes = None, sourceNodeSignature: bytes = None, source_ip_address: bytes = None, timestamp: int = 0): """This is the constructor for a new message originating from this system AND from the outside, depending on the params.""" self.app_log = base_app_log(app_log) self._type = a_type self._content = content self._valid = True if sourceNodeIdentifier is None: # From our system self._timestamp = int(time() * 1000) self._sourceNodeIdentifier = config.PUBLIC_KEY.to_bytes() self._sourceNodeSignature = KeyUtil.sign_bytes( self.get_bytes_for_signing(), config.PRIVATE_KEY) # As a test, we can verify our sig before sending """ KeyUtil.signature_is_valid(self._sourceNodeSignature, self.get_bytes_for_signing(), config.PUBLIC_KEY.to_bytes()) """ else: # From another system self._timestamp = timestamp self._sourceNodeIdentifier = sourceNodeIdentifier self._sourceNodeSignature = sourceNodeSignature self._sourceIpAddress = source_ip_address # self._valid = KeyUtil.signature_is_valid(sourceNodeSignature, self.get_bytes_for_signing(), # sourceNodeIdentifier) self.valid = True # TODO: needs all the chain of get_bytes to validate; let suppose for now it is valid. if config.VERBOSE: self.app_log.warning( f"TODO: Did NOT validate message from " f"{ByteUtil.bytes_as_string_with_dashes(sourceNodeIdentifier)} " f"of type {self._type.name}") if not self._valid: self.app_log.warning( f"message from {ByteUtil.bytes_as_string_with_dashes(sourceNodeIdentifier)} " f"of type {self._type.name} is not valid") # Temp log
def send(ctx, recipient, amount: float = 0, above: float = 0, data: str = "", key_: str = ""): """ Send Nyzo to a RECIPIENT. ABOVE is optional, if > 0 then the tx will only be sent when balance > ABOVE Using -1 as amount will send the FULL balance of the address If no seed is given, use the wallet one. - ex: python3 Nyzocli.py send abd7fede35a84b10-8a36e6dc361d9b32-ca84d149f6eb85b4-a4e63015278d4c9f 10 - ex: python3 Nyzocli.py send abd7fede35a84b10-8a36e6dc361d9b32-ca84d149f6eb85b4-a4e63015278d4c9f 10 0 key_... """ # TODO: Use newest helper from pynyzo if key_ == "": seed = config.PRIVATE_KEY.to_bytes() else: seed = NyzoStringEncoder.decode(key_).get_bytes() # convert key to address address = KeyUtil.private_to_public(seed.hex()) my_balance = None if above > 0: my_balance = ctx.invoke(balance, address=address) if my_balance <= above: if VERBOSE: app_log.warning( "Balance too low, {} instead of required {}, dropping.". format(my_balance, above)) print( json.dumps({ "result": "Error", "reason": "Balance too low, {} instead of required {}".format( my_balance, above) })) return if amount == -1: if my_balance is None: my_balance = ctx.invoke(balance, address=address) print(my_balance) # my_balance = balance(ctx, address) amount = float(my_balance) if amount <= 0: if VERBOSE: app_log.warning( "Balance too low or unknown {}, dropping.".format( my_balance)) print( json.dumps({ "result": "Error", "reason": "Balance too low, {}".format(my_balance) })) return else: if VERBOSE: app_log.warning("Sending full balance {}.".format(my_balance)) recipient, recipient_raw = normalize_address(recipient, asHex=True) frozen = get_frozen(ctx) if VERBOSE: app_log.info( f"Sending {amount} to {recipient} since balance of {address} is > {above}." ) app_log.info(f"Frozen edge is at {frozen['height']}") # Create a tx timestamp = int( time() * 10) * 100 + 10000 # Fixed 10 sec delay for inclusion # print(timestamp, hex(timestamp)) data_bytes = data[:32].encode("utf-8") transaction = Transaction(buffer=None, type=Transaction.type_standard, timestamp=timestamp, sender_identifier=bytes.fromhex(address), amount=int(amount * 1e6), receiver_identifier=bytes.fromhex(recipient_raw), previous_block_hash=bytes.fromhex( frozen["hash"]), previous_hash_height=frozen['height'], signature=b'', sender_data=data_bytes) # transaction = Transaction.from_vote_data(timestamp, bytes.fromhex(address), vote, cycle_tx_sig_bytes) if VERBOSE: print(transaction.to_json()) key, _ = KeyUtil.get_from_private_seed(seed.hex()) # print("key", key.to_bytes().hex()) to_sign = transaction.get_bytes(for_signing=True) # print("To Sign", to_sign.hex()) sign = KeyUtil.sign_bytes(to_sign, key) # print("Sign", sign.hex()) """" tx_type: int, timestamp: int, amount: int, receiver_identifier: bytes, previous_hash_height: int, previous_block_hash: bytes, sender_identifier: bytes, sender_data: bytes, signature: bytes, vote: int = 0, transaction_signature: bytes = b'' """ tx = NyzoStringTransaction(Transaction.type_standard, timestamp, int(amount * 1e6), bytes.fromhex(recipient_raw), frozen['height'], bytes.fromhex(frozen["hash"]), bytes.fromhex(address), data_bytes, sign) tx__ = NyzoStringEncoder.encode(tx) # Send the tx url = "{}/forwardTransaction?transaction={}&action=run".format( ctx.obj['client'], tx__) if VERBOSE: app_log.info(f"Calling {url}") res = get(url) if VERBOSE: app_log.info(res) if path.isdir("tmp"): # Store for debug purposes with open("tmp/answer.txt", "w") as fp: fp.write(res.text) temp = fake_table_to_list(res.text) if ctx.obj['json']: print(json.dumps(temp)) else: if "error" in temp[-1]: print("Error:", temp[-1]["error"]) else: print("Ok")
if ASK_NYZO_TODAY: hex_sig = NyzoStringEncoder.decode(sig[0]).get_bytes().hex() res = get(f"https://nyzo.today/api/transactionvotes/{hex_sig}") VOTED[sig[0]] = json.loads(res.text) else: VOTED[sig[0]] = {} total_pre = len(sigs) * len(keys) estimate = ((MIN_WAIT_BETWEEN_VOTE + MAX_WAIT_BETWEEN_VOTE) / 2 + 3) * total_pre / 60 print("{} keys and {} sigs, total {} votes.\nEstimated time {} min" .format(len(keys), len(sigs), total_pre, estimate)) total = list() for key in keys: key_hex = NyzoStringEncoder.decode(key).get_bytes().hex() # calc matching id as hex id_hex = KeyUtil.private_to_public(key_hex) for sig in sigs: if id_hex not in VOTED[sig[0]]: total.append((sig, key)) shuffle(total) estimate = ((MIN_WAIT_BETWEEN_VOTE + MAX_WAIT_BETWEEN_VOTE) / 2 + 3) * len(total) / 60 print(f"{len(keys)} keys and {len(sigs)} sigs, total after filter {len(total)} votes " f"instead of {total_pre}.\nEstimated time {estimate} min") bash = ["#!/bin/bash"] for item in total: line = "../Nyzocli.py vote {} {} {}".format(item[0][0], item[0][1], item[1]) bash.append(line) delay = randint(MIN_WAIT_BETWEEN_VOTE, MAX_WAIT_BETWEEN_VOTE) line = "sleep {}".format(delay) bash.append(line) # print("\n".join(bash))