{"id":28629862,"url":"https://github.com/codebox/blockchain","last_synced_at":"2025-08-26T02:04:06.767Z","repository":{"id":140514324,"uuid":"119175139","full_name":"codebox/blockchain","owner":"codebox","description":"Minimum Viable Blockchain in Python","archived":false,"fork":false,"pushed_at":"2018-04-01T09:33:56.000Z","size":100,"stargazers_count":10,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-12T12:13:47.389Z","etag":null,"topics":["blockchain","python"],"latest_commit_sha":null,"homepage":"https://codebox.net/pages/blockchain","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codebox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-01-27T15:15:35.000Z","updated_at":"2025-04-02T05:49:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"2c1e7202-f785-4415-bbc4-92163846fc46","html_url":"https://github.com/codebox/blockchain","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/codebox/blockchain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebox%2Fblockchain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebox%2Fblockchain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebox%2Fblockchain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebox%2Fblockchain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codebox","download_url":"https://codeload.github.com/codebox/blockchain/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebox%2Fblockchain/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272160241,"owners_count":24883779,"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","status":"online","status_checked_at":"2025-08-26T02:00:07.904Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["blockchain","python"],"created_at":"2025-06-12T12:13:44.896Z","updated_at":"2025-08-26T02:04:06.760Z","avatar_url":"https://github.com/codebox.png","language":"Python","readme":"# Minimum Viable Blockchain\nThis project contains a pair of Python applications, referred to as the _Wallet_ and the _Miner_. Together, these applications satisfy the requirements for a [minimum viable blockchain](https://www.igvita.com/2014/05/05/minimum-viable-block-chain/#properties). The applications form a decentralised peer-to-peer network, that allows the formation of distributed consensus regarding the validity of transactions that take place within it. Any number of wallets or miners may join or leave the network at any time.\n\n## Wallet Application\nThe wallet application is run as follows:\n```\n\u003e python -m blockchain.wallet.main\n``` \nRunning the wallet without any arguments (as shown above) will display a list of the various operations which the wallet can perform:\n```\nINFO: Usage: python /Users/rob/code/github/blockchain/src/blockchain/wallet/main.py \n        (new-address \u003caddress name\u003e | list-addresses | send \u003cfrom address\u003e \u003camount\u003e \u003cto address\u003e | sync)\n```\nThese operations are described in detail below.\n\n### new-address\nCreates a new address, from which payments can be sent and received. Each address has an associated public/private key pair stored in a [.pem file](http://how2ssl.com/articles/working_with_pem_files/). These files are all that is required to access any funds associated with a payment address, and therefore should be kept secret, and backed-up securely. When creating a new payment address, a name must be selected. The name must be locally unique (i.e. it must be different to all your other address names) but it doesn't matter if someone else on the network has chosen the same name for one of their addresses. \n\nRun the wallet supplying the `new-address` argument followed by the name, for example:\n```\n\u003e python -m blockchain.wallet.main new-address robs-address\n```\nThe wallet should display a message something like this:\n```\nINFO: Generated key [robs-address] with address 415d29e1529662a44148db9a83ae5e89f06395ab4c888aa578656ca31f01837a. \nKey saved in ./robs-address.pem\n```\n\n### list-addresses\nDisplays a list of all the local addresses that have been created, together with their current balances. \n\nRun the wallet supplying the `list-addresses` argument, as follows:\n```\n\u003e python -m blockchain.wallet.main list-addresses\n```\nThe wallet should display something like this:\n```\nKey Name         Balance      Pending      Address                                                         \n---------------- ------------ ------------ ----------------------------------------------------------------\nrobs-address                0    +0.000000 415d29e1529662a44148db9a83ae5e89f06395ab4c888aa578656ca31f01837a\n\n```\nThe _Balance_ column shows the confirmed balance associated with each address, this balance is calculated using all the incoming and outgoing payments for this address that have been added to the blockchain. The total of any payments issued from this address, but not yet added into the blockchain, is shown in the _Pending_ column. The long value shown in the _Address_ column is the globally unique name associated with this address. This name is generated automatically when a new address is created, and should be used by other wallets when making payments to this address.\n\n### send\nSends a payment from one address to another. \n\nRun the wallet with the `send` argument, followed by the sending address, the amount, and the receiving address, in that order.\n\nFor example, to send a payment of '10' from `robs-address` to the remote address `e699496067b860f1cadcb7a4c7cc502a4e758b42cf624ac7fb40c65a0aa1edce`, run the following command:\n```\n\u003e python -m blockchain.wallet.main send robs-address 10 e699496067b860f1cadcb7a4c7cc502a4e758b42cf624ac7fb40c65a0aa1edce\n```\nThe sending address can be specified using either the local address name, as in the example above, or the global address name as displayed by the `list-addresses` command.\n\nThe receiving address should use the global address name of the recipient, unless funds are being transferred between 2 local addresses, in which case the local name can be used instead.\n\nWhen the send command is issued, information concerning the transaction is sent to the network via a UDP broadcast, and will be re-broadcast at intervals when synchronising (see below) until the transaction is added to the blockchain by a mining node. \n\n### sync\nSynchronises the wallet with the network. This operation will continue until the user cancels it by pressing `Ctrl-C`.\n\nThe synchronisation process is started by running the wallet with the `sync` argument, as shown:\n```\n\u003e python -m blockchain.wallet.main sync\n```\n\nDuring synchronisation 2 tasks are performed:\n\n1. The wallet listens for status broadcasts from mining nodes. These broadcasts announce the length of the blockchain currently held by the miner. If a wallet receives a broadcast claiming a longer blockchain than the one that the wallet currently holds, then the wallet will request the additional blocks from the miner.\n2. The wallet re-broadcasts details of any payments that it has made, which have not yet been included in the blockchain. This ensures that payments are processed even if no miners were online when the payment was originally made.\n\n## Miner Application\nThe miner application is run as follows:\n```\n\u003e python -m blockchain.miner.main\n``` \nThe miner will run continuously until the user terminates it using `Ctrl-C`, status updates will be written to stdout.\n\nThe miner performs a number of tasks, described below\n\n### Mining Blocks\nThis is the most important task that a miner performs. Miners listen for network broadcasts from wallets, containing details of new transactions that have been made. Miners collect these transactions into blocks, and when a block contains enough new transactions the miner attempts to 'mine' the block. Mining consists of performing a CPU-intensive, hash-based [proof-of-work calculation](https://en.wikipedia.org/wiki/Proof-of-work_system) which is difficult to complete, but simple to verify. Miners are incentivised to perform this work by the inclusion of a 'mining-reward' transaction in each new block. Before starting to mine a block the miner adds a new transaction into the list, paying the designated reward into an address that they control. If multiple miners are present on the network then they race to be the first to mine the new block. A mined block effectively forms a tamper-proof record of the transactions that are contained within it - any attempt to alter the contents of the block will require the proof-of-work calculation to be re-performed. Since blocks also include a reference to the previous block in the blockchain, attempting to alter an older block would require the proof-of-work calculation to be re-performed not only for that block, but for all subsequent blocks in the blockchain. In order to complete such an alteration successfully, an attacker would need to control more than 50% of the CPU power on the network.\n \n### Sending/Receiving Status Broadcasts\nMiners regularly broadcast the length of their copy of the blockchain. A miner who has just mined a new block will have a blockchain that is 1-block longer than anyone else on the network. As other participants on the network receive the broadcast informing them of the new block, they will request a copy of the block from the miner who created it. Any miner who was in the process of mining a new block will stop their current mining task, download the new block, and then begin mining again on top of that new block. It is of course possible that 2 miners both complete their mining at about the same time, and both start advertising their new (different) blocks to the network. This results in a temporary 'fork' in the blockchain, with some miners mining on top of one block, and some mining on top of the other. However, this situation will be automatically resolved when the next block is mined - the first branch of the fork to have an additional block mined on top of it will become the new longest blockchain, and all parties on the network will adopt this as the basis for further mining.\n\n### Running a Block Server\nMiners must be able to provide details of newly mined blocks to other wallets and miners on the network. When a miner mines a new block they will receive many requests for that block from their peers. As the new block is distributed among other miners, and those miners themselves begin to broadcast the new longer blockchain, the requests to download the new block will become distributed among all the miners who have already downloaded it, reducing the load on the originating miner. \n\nA block server may also receive requests for more than 1 block, from wallets or miners who have been inactive for long periods, during which time multiple new blocks have been mined. When a new miner or wallet joins the network for the first time, they will request the entire blockchain from one of the active mining nodes.\n\n## Notes\n### Configuration\nThere are various parameters used by the wallet and miner applications which can be configured to alter the characteristics of the network. These parameters are stored in the `config.py` file, details below:\n\n#### difficulty\nControls the difficulty of the proof-of-work calculation performed when mining a block. The numeric value corresponds to the number of 0-bits that must be present at the start of the SHA256 hash of the contents of a valid mined block. The task of mining consists of adding a numeric value (called a _nonce_) into a block, hashing the block, and checking whether the hash has this many 0-bits at the start of it. The nonce value is incremented until a satisfactory hash is obtained, at which point the block is considered to be mined. Increasing the difficulty by 1 will, on average, double the time it takes to mine blocks.  \n\n#### block_size\nThe number of transactions which must be present in a block before it can be mined.\n\n#### block_reward\nThe amount of funds that a miner is allowed to allocate to themselves if they successfully mine a new block.\n\n#### key_size\nThe number of bits in the cryptographic keys used to sign transactions. [Larger values increase security](https://crypto.stackexchange.com/questions/19655/what-is-the-history-of-recommended-rsa-key-sizes) but require more CPU processing time.\n\n#### status_broadcast_interval_seconds\nThe interval (in seconds) between status broadcasts issued by mining nodes.\n\n#### transaction_broadcast_interval_seconds\nThe interval (in seconds) between transaction broadcasts issued by wallets.\n\n#### status_broadcast_port\nThe UDP port number used by miners for sending status broadcasts. All members of the network must use the same value for this parameter.\n\n#### block_server_port\nThe TCP port used by a mining node for its block server. Each miner may use a different port number, allowing multiple miners to run on the same host. Miners include the port number of their block server in the status broadcast.\n\n#### transaction_port\nThe UDP port number used by wallets to announce new transactions to the network. All members of the network must use the same value for this parameter.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodebox%2Fblockchain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodebox%2Fblockchain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodebox%2Fblockchain/lists"}