Skip to content

Instantly share code, notes, and snippets.

@bbjubjub2494
Last active May 7, 2022 21:25
Show Gist options
  • Save bbjubjub2494/e8aa99f84ac42305ff18855dae083e2f to your computer and use it in GitHub Desktop.
Save bbjubjub2494/e8aa99f84ac42305ff18855dae083e2f to your computer and use it in GitHub Desktop.
Transaction_louis.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Transaction_louis.ipynb",
"provenance": [],
"toc_visible": true,
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/lourkeur/e8aa99f84ac42305ff18855dae083e2f/transaction_louis.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# POPstellar: transaction id example implementation\n",
"This is a simple, general-purpose implementation of the transaction hashing algorithm for documentation purposes. The algorithm receives a transaction in JSON representation and outputs a SHA-256 digest of it."
],
"metadata": {
"id": "Jr3iEbQ9f0Tr"
}
},
{
"cell_type": "code",
"source": [
"def collect_strings(obj):\n",
" '''retrieve the string representation of every field in obj.\n",
"\n",
" The resulting fields are ordered following the specification.\n",
" '''\n",
" if isinstance(obj, str):\n",
" yield obj\n",
" elif isinstance(obj, int):\n",
" # use decimal representation for integers\n",
" yield str(obj)\n",
" elif isinstance(obj, list):\n",
" # recurse into array elements in array order\n",
" for e in obj:\n",
" yield from collect_strings(e)\n",
" elif isinstance(obj, dict):\n",
" # recurse into JSON object fields in order of field names\n",
" for k, v in sorted(obj.items()):\n",
" yield from collect_strings(v)\n",
" else:\n",
" raise TypeError(f\"do not know how to collect strings from a {type(obj)}\")"
],
"metadata": {
"id": "ZKz-kvIf0tG0"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import base64, hashlib\n",
"\n",
"def hash_len(strings):\n",
" '''hash a sequence of strings in accordance with the POPstellar protocol spec.\n",
"\n",
" https://github.com/dedis/popstellar/blob/master/docs/protocol.md\n",
" '''\n",
" payload = ''.join(f\"{len(s)}{s}\" for s in strings)\n",
" return base64.urlsafe_b64encode(hashlib.sha256(payload.encode(\"utf-8\")).digest())"
],
"metadata": {
"id": "ouUhhWXYdI3R"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def compute_transaction_id(transaction):\n",
" return hash_len(collect_strings(transaction))"
],
"metadata": {
"id": "qj9NGGZ700Tz"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "r6zHfxAg0hBh"
},
"outputs": [],
"source": [
"import json\n",
"\n",
"example = json.loads(\"\"\"{\n",
"\t \"Version\": 1,\n",
"\t \"TxIn\": [{\n",
"\t\t \"TxOutHash\": \"47DEQpj8HBSa--TImW-5JCeuQeRkm5NMpJWZG3hSuFU=\",\n",
"\t\t \"TxOutIndex\": 0,\n",
"\t\t \"Script\": {\n",
"\t\t\t \"Type\": \"P2PKH\",\n",
"\t\t\t \"Pubkey\": \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\",\n",
"\t\t\t \"Sig\": \"CAFEBABE\"\n",
"\t\t }\n",
"\t }],\n",
"\t \"TxOut\": [{\n",
"\t\t \"Value\": 32,\n",
"\t\t \"Script\": {\n",
"\t\t\t \"Type\": \"P2PKH\",\n",
"\t\t\t \"PubkeyHash\": \"2jmj7l5rSw0yVb-vlWAYkK-YBwk=\"\n",
"\t\t }\n",
"\t }],\n",
"\t \"LockTime\": 0\n",
"}\"\"\")\n"
]
},
{
"cell_type": "code",
"source": [
"list(collect_strings(example))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "3sDRRNUYd3lJ",
"outputId": "2626154b-d046-4178-a7fd-0fee82fca48d"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['0',\n",
" 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',\n",
" 'CAFEBABE',\n",
" 'P2PKH',\n",
" '47DEQpj8HBSa--TImW-5JCeuQeRkm5NMpJWZG3hSuFU=',\n",
" '0',\n",
" '2jmj7l5rSw0yVb-vlWAYkK-YBwk=',\n",
" 'P2PKH',\n",
" '32',\n",
" '1']"
]
},
"metadata": {},
"execution_count": 5
}
]
},
{
"cell_type": "code",
"source": [
"assert compute_transaction_id(example) == b'dBGU54vni3deHEebvJC2LcZbm0chV1GrJDGfMlJSLRc='"
],
"metadata": {
"id": "VR5nNYdpd1qD"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
""
],
"metadata": {
"id": "MMDsrEO3eAer"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment