{"id":17223544,"url":"https://github.com/mlouielu/iota-python","last_synced_at":"2025-04-14T00:23:54.541Z","repository":{"id":50215215,"uuid":"108079133","full_name":"mlouielu/iota-python","owner":"mlouielu","description":"A Pure-Python implementation of IOTA node","archived":false,"fork":false,"pushed_at":"2022-12-08T00:36:54.000Z","size":3810,"stargazers_count":32,"open_issues_count":10,"forks_count":9,"subscribers_count":4,"default_branch":"dev","last_synced_at":"2025-03-27T14:46:45.616Z","etag":null,"topics":["balanced-ternary","cryptocurrency","internet-of-things","iot","iota","rocksdb","tangle"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mlouielu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-24T05:03:05.000Z","updated_at":"2024-04-28T14:56:32.000Z","dependencies_parsed_at":"2023-01-24T07:30:52.605Z","dependency_job_id":null,"html_url":"https://github.com/mlouielu/iota-python","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlouielu%2Fiota-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlouielu%2Fiota-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlouielu%2Fiota-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlouielu%2Fiota-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mlouielu","download_url":"https://codeload.github.com/mlouielu/iota-python/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248731624,"owners_count":21152835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["balanced-ternary","cryptocurrency","internet-of-things","iot","iota","rocksdb","tangle"],"created_at":"2024-10-15T04:08:35.952Z","updated_at":"2025-04-14T00:23:54.482Z","avatar_url":"https://github.com/mlouielu.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"IOTA-Python - A Pure-Python implementation of IOTA node\n=======================================================\n\nThe target of this project is to create a pure Python implementation of IOTA node.\n\n\n## Current Develop Status\n\n* rocksdb: read, write, store (batch)\n* tangle: get, first, latest, next, save, store\n* ISS, snapshot: validate, diff, patch\n* tx_requester: function, but not thread\n* tx_validator: validate, check_solidity\n\nRoadmap:\n\n* Documentation of IRI behavior and description\n* Send TX (tips selection, attach to tangle, broadcast and store)\n* Network node (TCP and UDP)\n\n\n## Getting Started\n\n### Dependencies\n\n* rocksdb\n\nYou can see the rocksdb install guide from\n[facebook/rocksdb - INSTALL.md](https://github.com/facebook/rocksdb/blob/master/INSTALL.md).\n\nFor Arch Linux user, simply typing:\n\n```\n$ yaourt -S rocksdb\n```\n\n### Requirements\n\n* [python-rocksdb-iota](https://github.com/mlouielu/python-rocksdb)\n* [pyota](https://github.com/iotaledger/iota.lib.py)\n\n### Installation of IOTA-Python\n\n#### $ pipenv install iotapy\n\nTo install IOTA-Python, simply run this simple command in your terminal of choice:\n\n```\n$ pipenv install iotapy\n```\n\n#### Get the Source Code\n\nIOTA-Python is actively developed on GitHub, where the code is\n[always available](https://github.com/mlouielu/iota-python).\n\nYou can clone the source code from repository:\n\n```\n$ git clone https://github.com/mlouielu/iota-python\n```\n\nOnce you have a copy of source code, you can install the package easily:\n\n```\n$ cd iota-python\n$ pip install -r requirements.txt\n$ python setup.py install\n```\n\n## Tutorials - About RocksDBProvider\n\nThis is a tutorial of IOTA-Python to read the database from java IRI, and this\nis what IOTA-Python can do now.\n\n### Open IRI rocksdb\n\nRemember, make sure `db_path` and `db_log_path` is point to *your* database path.\nAt this point, IOTA-Python didn't support writing data back to the database (also,\nit have a lock on it, if you want to write it), so `read_only` should also be `True`.\n\n```python\n\u003e\u003e\u003e import iota\n\u003e\u003e\u003e import iotapy\n\u003e\u003e\u003e r = iotapy.storage.providers.rocksdb.RocksDBProvider(\n        db_path='/var/db/iota/mainnetdb',\n        db_log_path='/var/db/iota/mainnetdb.log',\n        read_only=True\n    )\n\u003e\u003e\u003e r.init()   # Absolute remember to init database\n\u003e\u003e\u003e\n```\n\n### Access IRI rocksdb\n\nNow you open the database, you can get the data inside it! IRI using rocksdb\ncolumn family to separate the data stored. For column family list, please visit\nthis [blog post](https://blog.louie.lu/2017/10/31/iota-iri-rocksdb-data-storage-structure/)\n\nNow, we can try to open a transaction, here we got an example transaction hash:\n`GTXDTJVUTVSNHYFPJUOWFKTGQTCMNKZPJDJXSWVQWTXYRDZAVZTX9KFBRIMRQEQLMCMVAUKMZWMHA9999`.\n\nYou can check this tx information at this\n[page](https://thetangle.org/transaction/GTXDTJVUTVSNHYFPJUOWFKTGQTCMNKZPJDJXSWVQWTXYRDZAVZTX9KFBRIMRQEQLMCMVAUKMZWMHA9999)\n\n```python\n\u003e\u003e\u003e txh = iota.TransactionHash('GTXDTJVUTVSNHYFPJUOWFKTGQTCMNKZPJDJXSWVQWTXYRDZAVZTX9KFBRIMRQEQLMCMVAUKMZWMHA9999')\n\u003e\u003e\u003e column_family = 'transaction'\n\u003e\u003e\u003e tx = r.get(txh, column_family)\n\u003e\u003e\u003e tx.tag\nTag(b'EXAMPLEPYTHONLIB99999999999')\n\u003e\u003e\u003e tx.bundle_hash\nBundleHash(b'CRNTWYOGTYKPAHYHNESJOKLRFYQQGCXXUZIZQFTCCLSTZODTRBPZWTX9TVHNDNNIWTULV9GFLAPPSTCC9')\n\u003e\u003e\u003e tx.signature_message_fragment\nFragment(b'RBTC9D9DCDFAEACCWCXCGDEAXCGDEAPCEAHDTCGDHDEAUCFDCDADEAZBMDHDWCCDBD999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999')\n\u003e\u003e\u003e tx.signature_message_fragment.as_string()\n'Hello! This is a test from Python'\n\u003e\u003e\u003e tx.as_json_compatible()\n{\n    'hash_': ...,\n    'signature_message_fragment': ...,\n    'address': Address(b'9TPHVCFLAZTZSDUWFBLCJOZICJKKPVDMAASWJZNFFBKRDDTEOUJHR9JVGTJNI9IYNVISZVXARWJFKUZWC'),\n    'value': 0,\n    'legacy_tag': ...,\n    'timestamp': 1508993435,\n    'current_index': 0,\n    'last_index': 0,\n    'bundle_hash': ...,\n    'trunk_transaction_hash': ...,\n    'branch_transaction_hash': ...,\n    'tag': Tag(b'EXAMPLEPYTHONLIB99999999999'),\n    'attachment_timestamp': 1508993445508,\n    'attachment_timestamp_lower_bound': 0,\n    'attachment_timestamp_upper_bound': 12,\n    'nonce': Nonce(b'HYNAKUFLKW9UZXXIDJFGUMUDDVX')\n}\n\u003e\u003e\u003e\n```\n\nIf you are using method such as `RocksDBProvider.get`, `RocksDBProvider.latest`,\nplease use the following column family name:\n\n```\naddress\napprovee\nbundle\nmilestone\nstate_diff\ntag\ntransaction\ntransaction_metadata\n```\n\n\nThe full list of column family name can be found at `RocksDBProvider.column_family_names`,\nbut this list is used for low level database access, it only used at `RocksDBProvider.db`.\n\n```\nb'default'\nb'transaction'\nb'transaction-metadata'\nb'milestone'\nb'stateDiff'\nb'address'\nb'approvee'\nb'bundle'\nb'tag'\n```\n\nExample of `RocksDBProvider` methods:\n\n```python\n# Get address' transaction record\n\u003e\u003e\u003e adr = iota.Address('9TPHVCFLAZTZSDUWFBLCJOZICJKKPVDMAASWJZNFFBKRDDTEOUJHR9JVGTJNI9IYNVISZVXARWJFKUZWC')\n\u003e\u003e\u003e r.get(adr,'address')\n\u003cgenerator object get at 0x7eff2b341518\u003e\n\n# Get next address (in database)\n\u003e\u003e\u003e r.next(adr, 'address')\n(Address(b'9BPQJPGAMDVKAQ9FDPQSVINPMHSIUUXKYMIZQGPBDGGEUZGLEVFIWUYO9MEIPOYUBYVQGJCFYRWTQENCZ'), \u003cgenerator object get at 0x7eff2b3415c8\u003e)\n\n# Get first milestone\n\u003e\u003e\u003e r.first('milestone')\n(243001, (243001, TransactionHash(b'9PPVIKDMKUDXTYJFF9YNWUPPMOYZTYKRBFGLGDCNNNIMWAMGVJGEHOCOUDYRVYPPSDKDKDQXUBMYA9999')))\n\n# Get latest milestone\n\u003e\u003e\u003e r.latest('milestone')\n(265486, (265486, TransactionHash(b'TFWZVEQZGQGBUBKMFA9YKBVDGBWWMXWCGGYYAGPZKGXWKJQRUNSMXJBSVVGYRJKCS9GNWULQSMAGZ9999')))\n\n# Get next milestone\n\u003e\u003e\u003e key, value = r.first('milestone')\n\u003e\u003e\u003e r.next(key, 'milestone')\n(243002, (243002, TransactionHash(b'XHIOO9EJ9H9ULPJM9MIJSTPHNPIUAAJ9NLYHZLHDBCSECCJVRGDWHTRUEUIQXWVLBYOCBNHFWWWPA9999')))\n```\n\nLow level db access (something you don't need to touch at this moment):\n\n```python\n\u003e\u003e\u003e column_handler = r.db.column_family_handles[b'transaction-metadata']\n\u003e\u003e\u003e txh = iota.TransactionHash('GTXDTJVUTVSNHYFPJUOWFKTGQTCMNKZPJDJXSWVQWTXYRDZAVZTX9KFBRIMRQEQLMCMVAUKMZWMHA9999')\n\u003e\u003e\u003e key = iotapy.storage.converter.from_trits_to_binary(txh.as_trits())\n\u003e\u003e\u003e value = r.db.get(key, column_handler)\nb\"6\\x8d\\xd6\\xb2v\\xf7\\xde9\\xcb\\xab\\x07\\x1f\\xb9\\xfc\\x1e@s\\xcfpU\\xb8\\x17\\xad2\u003c!!:\\x0e\\xc6\\xef\\xe6Z\\xc5=\\x8e\\tl\\x8a\\xfb\\x98\\xd3\\x18\\x94Y\u003c\\x9e\\xdc\\x03\\x03\\x87\\xda\\xad\\xc3\\xec\\xd5\\xb1\\xf1\\x9c_W*%3\\xe32\\x1d\\xac\\x9dQ\\xe4\\xc0\\x19T\\x98\\xf5`\\xeb\\x0f\\xda\\xa3\\xe36\\x9f\\x8e\\x98\\xd8\\xdfJt\\xfe\\xb6v\\x9d\\x10\\xea\\x1c\\x00\\xdc\\xf6\u003e3Wf\\xd52\\xb5\\xe0\\xc4\\xb7\\xd5\\xb6\\xcb\\xb7\\xc1\\xdb$\\xad%\\xd4\\xa2\\xf3\\xefI'\\xd5\\xa7Y\\xe2\\xa5]G\\x9e\\xb82\\xd7\\x1f\u0026\\x9cR4\\xa7\\x13\\xff\\x00\\x00\\x00!\\x0c;\\xa2\\x1b\\xc6-\\xa0\\xd5\\xbe\\xaa*\\xb1\\x95\\xbcUI\\xb5l\\x89\\xa1\\xe3\\xacn\\x90@\\x10\\xdf\\xf9Un\\xb7\\xb1\\x93\\x9b\\xc7\\x017:o\\xba\\xd8\\xfdq\\xff\\xe2\\x00\\x00\\x00\\xb4T\\xa1\\xa01\\xc0\\xb7\\xd8U\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Y\\xf1i\\x9b\\xb4T\\xa1\\xa01\\xc0\\xb7\\xd8U\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01_W\\x04\\xae\\x84\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00Y\\xf1i\\xa5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x03\\xd6\\xe0local\"\n\u003e\u003e\u003e\n```\n\n### EXPLOSION! An example of exploring the IRI database!\n\n![](https://pm1.narvii.com/6258/7f113d43b699f954c3d65df5aa5f397936363099_hq.jpg)\n\n*EXPLOSION!*\n\nGlade you are here, now you gain the full access power of the IRI database.\n\nWe all know that IOTA is a DAG, that is, theoretically speaking, we can start\nfrom a transaction, and go to its parent, and its parent, and its parent...and\nwe will finally get to the genesis address / node / block whatever.\n\nHere is a small script that I trying to find this answer:\n\n```python\nimport time\nimport iota\nimport iotapy\n\n\n# Initialize the database\nr = iotapy.storage.providers.rocksdb.RocksDBProvider(\n        db_path='/var/db/iota/mainnetdb',\n        db_log_path='/var/db/iota/mainnetdb.log',\n        read_only=True)\nr.init()\n\n\n# We will start from this transaction\ntxh = iota.TransactionHash('UNUK99RCIWLUQ9WMUT9MPQSZCHTUMGN9IWOCOXWMNPICCCQKLLNIIE9UIFGKZLHRI9QAOEQXQJLL99999')\ntx = r.get(txh, 'transaction')\n\n# Stop at here\nEMPTY = iota.TransactionHash('9' * 81)\n\n# Go to find the genesis!\ni = 0\nwhile True:\n    i += 1\n    if i % 100 == 0:\n        print(txh, time.ctime(tx.timestamp))\n\n    # Branch is outside the bundle and trunk is in the bundle\n    # So we choose branch at here\n    if tx.branch_transaction_hash != EMPTY:\n        txh = tx.branch_transaction_hash\n        tx = r.get(tx.branch_transaction_hash, 'transaction')\n    else:\n        # This is the end of the journey\n        print(\"\\nProbably the genesis?\")\n        print(txh)\n        break\n\n```\n\nIt will run like:\n\n```\nNQRZKAE9CDFGJUPOMTHCVPOQE9LENTSHNJYDXCWZJ9IRXKLWTGRIHYZCZWSEIOKQFVBBEBNTXHNBA9999 Thu Oct 26 11:23:31 2017\nKMRPH9BVZVFRCEGDEROQBMZTNOQECYRKIJJ9MWGNOUMWVPLFIJ9PRANLDXSTZCVJGHTXTYCWYGJFZ9999 Thu Oct 26 08:40:52 2017\nJQLXELCKS9QSNWZNHJJICAQMGZRTGFPGNRRNJWTBEPZWKEHLJINXVLPOMMQCMQSOEUZGRHSKBNWEA9999 Thu Oct 26 06:40:31 2017\nIOKLUAGDGKSU9RGHZXCQJIBRTFPCNVCIVG9TQNIGE9DVIYIUDCEVTMPYBZQXHNYLNSNFTXDWNH9BA9999 Thu Oct 26 05:41:28 2017\nAUEDLXAJZPW9URCQZABSRNJGYOOSDG9OFHUMXINMVULHOIVWOBDLSSS9DPNTSXHTDKG9MGKMUESD99999 Thu Oct 26 04:38:37 2017\nDZRYEISPEUXXVQMGBSPVMOFFTWPDYQ9EWVYZUQTNX9NPSEWRGNMSZMY9BOTABSLPCTKMIGWAAIPJA9999 Thu Oct 26 03:45:03 2017\nUPAIBMKZEOTUEHHLEYZEEKZFLDGWHWJ9UZLGLRV9NGZPWSGWY9DPITWSDZPQQZDBOYFJDLJYTDKXZ9999 Thu Oct 26 02:51:53 2017\nMZPRET9XVFBK9LQZLFNN9UGQLLBYAVGAKJGODQIKVZWHPDLZQLOTFMMGEAGSGWGPEYBLJLLJJXOEZ9999 Thu Oct 26 02:08:16 2017\nXPMVSHVFNKYSTKPSHLPHDQCKEGWTERKEHTDRUKIQRE9KDDQVAQHUOQHYOPTRZGIIQHLYGYCPTLAEA9999 Thu Oct 26 01:17:58 2017\nMHDQIXDMBOFHCOMLGNHPSJGNIXIDAQQNW9CJKSXPYIOIITQES99KNYTPNPOQBTVZQXYOKBVEIZB999999 Thu Oct 26 00:37:14 2017\n...\nGXWKBVNFPFX99PGDCH9EQZMLHITMBFAPDQRNNGNGOOXYXEEYYDDDFWJRDQINOEJFSITMEUY9VMVO99999 Tue Oct 24 06:37:13 2017\nUAPTGGCKCGCPWGVQEKBCPKNQUWOPVRBAFAQYHSDU9AJMVINJFVZSM9URBYUAIHCPKOJRBWSOOSHLZ9999 Tue Oct 24 06:16:17 2017\nFPPJWECLHTF9HGGEMNH9FUIAVYJWDOIOXYFRRJ9S9HENTSESTGJYLYOSNNJGKDOUOGXOWFURNDNEZ9999 Tue Oct 24 05:56:10 2017\nHSDV9SKUYCBWNXFIHKLNAXEVPDTGLSPMTMTXCYISS9M9SPL9DERO9GCQLNWY9KBIHOLPYBCTCYECA9999 Tue Oct 24 05:35:44 2017\nLQPVJDHGQPILXVUPCCZGJMCAQHROJLHQKBILEUDBKQAEHMHEOEK9GMRDWEKVRXRB99TOYQQLTZDGZ9999 Tue Oct 24 05:14:13 2017\nFOCMONRMEOBQEBDOJOQPOOPLRIYCI9PMSJXXNEWAZPBRCDGZTZB9KI9SSMKKFBGBDONMILXWOBEFA9999 Tue Oct 24 04:53:03 2017\nBEFSRMKVEWXXHERTONXCQLOAVQYVRPFFZCQIDGUOLLZCFLTRPRHEVYNAPQFKGJOCDAJYNVUJDQIRZ9999 Tue Oct 24 04:32:48 2017\nQVHPAOWGDFTTLYQERDRNBBNCJJCWTJSDBIKBLDYZOLJ9PWFWFWUXP9DGPKTLRZDFZNLFRYXSZF9O99999 Tue Oct 24 04:12:07 2017\n\nProbably the genesis?\n9PPVIKDMKUDXTYJFF9YNWUPPMOYZTYKRBFGLGDCNNNIMWAMGVJGEHOCOUDYRVYPPSDKDKDQXUBMYA9999\n```\n\nCheck this transaction on [thetangle](https://thetangle.org/transaction/9PPVIKDMKUDXTYJFF9YNWUPPMOYZTYKRBFGLGDCNNNIMWAMGVJGEHOCOUDYRVYPPSDKDKDQXUBMYA9999)\n\n## Documentation\n\n~~Source code is your best friend~~\n\nDocumentation is still under construct.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlouielu%2Fiota-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmlouielu%2Fiota-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlouielu%2Fiota-python/lists"}