def new_address( self, key_pair: Tuple[bytes, bytes], unique_factor: Union[Tuple[int, int], bytes], ) -> Tuple[Tuple[bytes, bytes], Optional[bytes], bytes, bytes]: """ Constructs a new address with the root key pair and the index. Returns the key pair, payment ID, network byte, and unique factor to watch for. """ if isinstance(unique_factor, bytes): if len(unique_factor) == 0: return ( ( ed.public_from_secret(key_pair[0]), key_pair[1], ), None, self.network_bytes[0], key_pair[1], ) else: return ( ( ed.public_from_secret(key_pair[0]), key_pair[1], ), unique_factor, self.network_bytes[1], unique_factor, ) else: raise Exception("Invalid unique factor.")
def __init__(self, crypto: Crypto, key: bytes) -> None: """Constructor.""" # Set the Crypto class. self.crypto: Crypto = crypto # Set the keys. self.private_spend_key: bytes = ed.encodeint(ed.decodeint(key) % ed.l) self.public_spend_key: bytes = ed.public_from_secret( self.private_spend_key) self.private_view_key: bytes = ed.Hs(self.private_spend_key) self.public_view_key: bytes = ed.public_from_secret( self.private_view_key)
def generate_key_image( self, output: OutputInfo, private_view_key: bytes, private_spend_key: bytes, ) -> bytes: """Calculate the key image for the specified input.""" input_key: bytes = self.generate_input_key(output, private_view_key, private_spend_key) return generate_key_image(input_key, ed.public_from_secret(input_key))
def __init__( self, crypto: Crypto, rpc: RPC, private_view_key: bytes, public_spend_key: bytes, state: Union[int, Dict[str, Any]], ) -> None: """Constructor.""" # Set the Crypto class. self.crypto: Crypto = crypto # Set the RPC class. self.rpc: RPC = rpc # Set the spend key. self.public_spend_key: bytes = public_spend_key # Set the view keys. self.private_view_key: bytes = private_view_key self.public_view_key: bytes = ed.public_from_secret( self.private_view_key) # Blocks whose Transactions have yet to confirm. self.confirmation_queue: Deque[Block] = deque([]) # Inputs. self.inputs: Dict[OutputIndex, OutputInfo] = {} # Unique factors. self.unique_factors: Dict[bytes, Tuple[int, int]] = { self.public_spend_key: (0, 0) } # Reload the state. self.load_state(state)
def multiple_Rs_test(harness: Harness) -> None: # Wallet. wallet: Wallet = Wallet(harness.crypto, urandom(32)) # WatchWallet. watch: WatchWallet = WatchWallet( harness.crypto, harness.rpc, wallet.private_view_key, wallet.public_spend_key, harness.rpc.get_block_count() - 1, ) # Test multiple Rs. indexes: List[Tuple[int, int]] = [(0, 0)] amounts: List[int] = [] txs: List[bytes] = [] for _ in range(5): indexes.append((randint(0, 300), randint(0, 300))) amounts.append(randint(ATOMIC_XMR, 40 * ATOMIC_XMR)) txs.append(harness.send(watch.new_address(indexes[-1]), amounts[-1])) # Get the Transaction. tx: Transaction = watch.rpc.get_transaction(txs[-1]) # Add multiple other Rs to the Transaction. for _ in range(3): tx.Rs.append(public_from_secret(Hs(urandom(32)))) # Check the other Rs had no affect. spendable: Tuple[List[bytes], Dict[OutputIndex, OutputInfo]] = watch.can_spend(tx) assert not spendable[0] assert len(spendable[1]) == 1 assert list(spendable[1].keys())[0].tx_hash == txs[-1] assert spendable[1][list(spendable[1].keys())[0]].amount == amounts[-1] # Test multiple identical Rs. for _ in range(5): # Send to a random index. indexes.append((randint(0, 300), randint(0, 300))) amounts.append(randint(ATOMIC_XMR, 5 * ATOMIC_XMR)) txs.append(harness.send(watch.new_address(indexes[-1]), amounts[-1])) # Manually get the Transaction's JSON. tx_json: Dict[str, Any] = json.loads( watch.rpc.rpc_request( "get_transactions", { "txs_hashes": [txs[-1].hex()], "decode_as_json": True }, )["txs"][0]["as_json"]) # Create a Transaction from it. tx: Transaction = Transaction(txs[-1], tx_json) # Get a duplicate list of Rs. Rs: List[bytes] = tx.Rs * 2 # Use the Rs and tx to craft a new extra in tx_json. extra: bytes = bytes([0x01]) + Rs[0] # Add the other Rs. extra += bytes([0x04]) + to_var_int(len(Rs) - 1) for R in Rs[1:]: extra += R # Store it in tx_json. tx_json["extra"] = [] for b in range(len(extra)): tx_json["extra"].append(extra[b]) # Parse the modified JSON. modified_tx: Transaction = Transaction(txs[-1], tx_json) # Check the duplicate Rs were stripped. assert tx.Rs == modified_tx.Rs spendable: Tuple[List[bytes], Dict[OutputIndex, OutputInfo]] = watch.can_spend(tx) assert not spendable[0] assert len(spendable[1]) == 1 assert list(spendable[1].keys())[0].tx_hash == txs[-1] assert spendable[1][list(spendable[1].keys())[0]].amount == amounts[-1] # Send back to the master wallet. harness.return_funds(wallet, watch, sum(amounts))