{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d2c6b4cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# PoC using scaning and spending keys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6bcea120",
   "metadata": {},
   "outputs": [],
   "source": [
    "import hashlib\n",
    "from py_ecc.secp256k1 import *\n",
    "import sha3\n",
    "from eth_account import Account"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e25cb04",
   "metadata": {},
   "source": [
    "## Sender"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22ca0bf7",
   "metadata": {},
   "source": [
    "$S = G*s$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "bb9355a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(22246744184454969143801186698733154500632648736073949898323976612504587645286,\n",
       " 110772761940586493986212935445517909380300793379795289150161960681985511655321)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# privkey: 0xd952fe0740d9d14011fc8ead3ab7de3c739d3aa93ce9254c10b0134d80d26a30\n",
    "# address: 0x3CB39EA2f14B16B69B451719A7BEd55e0aFEcE8F\n",
    "s = int(0xd952fe0740d9d14011fc8ead3ab7de3c739d3aa93ce9254c10b0134d80d26a30) # private key\n",
    "S = secp256k1.privtopub(s.to_bytes(32, \"big\")) # public key\n",
    "S"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8240f67",
   "metadata": {},
   "source": [
    "## Recipient"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6895e603",
   "metadata": {},
   "source": [
    "$P = G*p$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c8e2d6ad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((89565891926547004231252920425935692360644145829622209833684329913297188986597,\n",
       "  12158399299693830322967808612713398636155367887041628176798871954788371653930),\n",
       " (112711660439710606056748659173929673102114977341539408544630613555209775888121,\n",
       "  25583027980570883691656905877401976406448868254816295069919888960541586679410))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# privkey: 0x0000000000000000000000000000000000000000000000000000000000000001\n",
    "# address: 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf\n",
    "p_scan = int(0x0000000000000000000000000000000000000000000000000000000000000002) # private key\n",
    "p_spend = int(0x0000000000000000000000000000000000000000000000000000000000000003) # private key\n",
    "\n",
    "P_scan = secp256k1.privtopub(p_scan.to_bytes(32, \"big\")) # public key\n",
    "P_spend = secp256k1.privtopub(p_spend.to_bytes(32, \"big\")) # public key\n",
    "P_scan, P_spend"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "174929d7",
   "metadata": {},
   "source": [
    "## Calculate Stealth Address: $P_{spend} + G*hash(Q)$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b39ed39",
   "metadata": {},
   "source": [
    "$Q = S * p_{scan}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "63a022d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(65311808848028536848162101908966111079795231803322390815513763038079235257196,\n",
       " 43767810034999830518515787564234053904327508763526333662117780420755425490082)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Q = secp256k1.multiply(P_scan, s)\n",
    "Q"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d79c69fc",
   "metadata": {},
   "source": [
    "$Q = S * p_{scan} = P_{scan} * s$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5f5fbcf4",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert Q == secp256k1.multiply(S, p_scan)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d5803ff",
   "metadata": {},
   "source": [
    "$h(Q)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f1b38cb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "Q_hex = sha3.keccak_256(Q[0].to_bytes(32, \"big\") \n",
    "                        + Q[1].to_bytes(32, \"big\")\n",
    "                       ).hexdigest()\n",
    "Q_hased = bytearray.fromhex(Q_hex)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0647821",
   "metadata": {},
   "source": [
    "$ stA = h(Q) * G + P_{spend}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "865e7f72",
   "metadata": {},
   "source": [
    "#### Sender sends funds to..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d9dd755f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xfed69df0a27f1dae0d7430ead82aaedfad6332bb'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stP = secp256k1.add(P_spend, secp256k1.privtopub(Q_hased))\n",
    "stA = \"0x\"+ sha3.keccak_256(stP[0].to_bytes(32, \"big\")\n",
    "                            +stP[1].to_bytes(32, \"big\")\n",
    "                           ).hexdigest()[-40:]\n",
    "stA"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38e69080",
   "metadata": {},
   "source": [
    "#### Sender broadcasts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cdf57fef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((22246744184454969143801186698733154500632648736073949898323976612504587645286,\n",
       "  110772761940586493986212935445517909380300793379795289150161960681985511655321),\n",
       " '0xfed69df0a27f1dae0d7430ead82aaedfad6332bb')"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S, stA"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "588ccc7c",
   "metadata": {},
   "source": [
    "## Parse received funds"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "462f8c8d",
   "metadata": {},
   "source": [
    "* Note that $p_{scan}$ and $P_{spend}$ can be shared with a trusted party\n",
    "* There may be many S to be parsed"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ba2a295",
   "metadata": {},
   "source": [
    "$h(p_{scan}*S)*G + P_{spend} => toAddress$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "50b63208",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xfed69df0a27f1dae0d7430ead82aaedfad6332bb'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Q = secp256k1.multiply(S, p_scan)\n",
    "Q_hex = sha3.keccak_256(Q[0].to_bytes(32, \"big\")+Q[1].to_bytes(32, \"big\")).hexdigest()\n",
    "Q_hased = bytearray.fromhex(Q_hex)\n",
    "\n",
    "P_stealth = secp256k1.add(P_spend, secp256k1.privtopub(Q_hased))\n",
    "P_stealthAddress  = \"0x\"+ sha3.keccak_256(stP[0].to_bytes(32, \"big\")\n",
    "                                        + stP[1].to_bytes(32, \"big\")\n",
    "                                        ).hexdigest()[-40:]\n",
    "P_stealthAddress"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8055d075",
   "metadata": {},
   "source": [
    "logged stealth address $stA$ equals the derived stealth address $P_stealthAddress$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26758ea5",
   "metadata": {},
   "source": [
    "$stA==stA_d$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "3faed6a3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "P_stealthAddress == stA"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "050e346c",
   "metadata": {},
   "source": [
    "## Derive private key"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44801516",
   "metadata": {},
   "source": [
    "#### Only the recipient has access to $p_{spend}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7673e439",
   "metadata": {},
   "source": [
    "$p_{stealth}=p_{spend}+hash(Q)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "4013b57e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "39153944482575822531387237249775711740128993925789544779866399859639729033274"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Q = secp256k1.multiply(S, p_scan)\n",
    "Q_hex = sha3.keccak_256(Q[0].to_bytes(32, \"big\")+Q[1].to_bytes(32, \"big\")).hexdigest()\n",
    "p_stealth = p_spend + int(Q_hex, 16)\n",
    "p_stealth"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc31c1aa",
   "metadata": {},
   "source": [
    "$P_{stealth} = p_{stealth}*G$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "09b5ccc2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(67663851387124608323744162645277269585638670865381831245083336172545348387042,\n",
       " 80449904826544093817252981338261706033086352950841917067356875711772573870404)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Recipient has private key to ...\n",
    "P_stealth = secp256k1.privtopub(p_stealth.to_bytes(32, \"big\"))\n",
    "P_stealth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "a3ead30e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xfed69df0a27f1dae0d7430ead82aaedfad6332bb'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "P_stealthAddress_d  = \"0x\"+ sha3.keccak_256(P_stealth[0].to_bytes(32, \"big\")\n",
    "                                        + P_stealth[1].to_bytes(32, \"big\")\n",
    "                                        ).hexdigest()[-40:]\n",
    "P_stealthAddress_d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2712c07b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xfEd69Df0a27F1daE0D7430EAd82aaEdfAD6332bb'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Account.from_key((p_stealth).to_bytes(32, \"big\")).address"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74f0325e",
   "metadata": {},
   "source": [
    "## Additionally add view tags"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac45bb87",
   "metadata": {},
   "source": [
    "In addition to S and stA, the sender also broadcasts the first byte of h(Q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "9645b880",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "86"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Q_hased[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8788f2f5",
   "metadata": {},
   "source": [
    "The recipient can do the the same a before without one EC Multiplication, one EC Addition and on Public Key to Address Conversion in order to check being a potential recipient."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "bb9f5852",
   "metadata": {},
   "outputs": [],
   "source": [
    "Q_derived = secp256k1.multiply(S, p_scan)\n",
    "Q_hex_derived = sha3.keccak_256(Q_derived[0].to_bytes(32, \"big\")\n",
    "                                +Q_derived[1].to_bytes(32, \"big\")\n",
    "                               ).hexdigest()\n",
    "Q_hashed_derived = bytearray.fromhex(Q_hex_derived)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7dc4624",
   "metadata": {},
   "source": [
    "Check view tag"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "953bf07d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run = Q_hased[0] == Q_hashed_derived[0] \n",
    "run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "e11ec134",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0xfed69df0a27f1dae0d7430ead82aaedfad6332bb'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "if run:\n",
    "    P_stealth = secp256k1.add(P_spend, secp256k1.privtopub(Q_hased))\n",
    "    P_stealthAddress  = \"0x\"+ sha3.keccak_256(stP[0].to_bytes(32, \"big\")\n",
    "                                            + stP[1].to_bytes(32, \"big\")\n",
    "                                            ).hexdigest()[-40:]\n",
    "P_stealthAddress"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "bd06ffc5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "P_stealthAddress==stA"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "hackathon",
   "language": "python",
   "name": "hackathon"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
