Exemplo n.º 1
0
    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.")
Exemplo n.º 2
0
    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))
Exemplo n.º 4
0
    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))