DCIPs/assets/eip-5564/minimal_poc.ipynb

640 lines
14 KiB
Plaintext

{
"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
}