[
  {
    "path": ".classpath",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER\"/>\n\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.junit.JUNIT_CONTAINER/4\"/>\n\t<classpathentry kind=\"output\" path=\"bin\"/>\n</classpath>\n"
  },
  {
    "path": ".gitignore",
    "content": "/bin/\n"
  },
  {
    "path": ".project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>Bitcoin</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "README.md",
    "content": "# Bitcoin\nAn example Bitcoin implementation which can be used to learn about Bitcoin/Blockchain. This implementations is for educational use only.\n\n# Overview.\n\n## Wallet\n\nThe Wallet is how peers interact with the Bitcoin peer-to-peer network. The Wallet generates a public key and a private key which it uses to sign each Transaction. The pulic key is the send-to address used by the Bitcoin network. Each Wallet has the ability to send coins from your account to another account and it also has the ability to confirm Transactions (except it's own) which it receives from the Bitcoin peer-to-peer network.\n\n```\n    Wallet {\n      sendCoin(entity, value); // Creates a new Transaction\n      handleTransaction(Transaction); // Receives a unconfirmed Transaction\n      handleConfirmation(Transaction); // Receives a confirmed Transaction and adds to blockchain\n    }\n```\n\n## Transaction\n\nTransactions are just a collection of input transactions, output transactions, a value, and a signature. \n\n```\n    Transaction {\n        byte[] header;\n        Transaction[] inputs;\n        Transaction[] outputs;\n        long value;\n        byte[] signature;\n    }\n```\n\nSee the [Transaction Class](https://github.com/phishman3579/Bitcoin/blob/master/src/com/jwetherell/bitcoin/data_model/Transaction.java) for reference.\n\n#### The Wallet also has a number of Transaction rules:\n\n* Once a Transaction has been used as an input, it cannot be used again. \n* All inputs on a Transaction have to be completely consumed on a transaction.\n\nNote: To send a Bitcoin transaction, you have to already own a Bitcoin. Getting an initial Bitcoin is usually done by trading something for a number of Bitcoins. One caveat of, having to own a Bitcoin to make a transaction, is the first transaction. The first transaction is called the genesis transaction, it is the only transaction which does not need input transactions.\n\n### An example Transaction\n\nIf Justin wants to send 6 coins to George:\n\nLedger:\n\n|  Justin's unused Transactions  |  George's unused Transaction  |\n|  ----------------------------- | ----------------------------- | \n| Transaction #1 : 5 Coins       |                               |\n| Transaction #2 : 3 Coins       |                               |\n| Transaction #3 : 7 Coins       |                               |\n\n```\n    Aggregate Transaction #4 {\n      byte[]        header      \"6 coins for George and 2 coins to Justin\"\n      Transaction[] input       { Transaction #1, Transaction #2 }\n      Transaction[] output      { Transaction #5, Transaction #6 }\n      int           value       0\n      byte[]        signature   \"Justin's signature based on the Header\"\n    }\n```\nNote: The 'value' on the Aggregate Transaction (#4) is a reward for anyone who confirms the Transaction. The higher the reward, the better chance the Transaction will be processed quicker.\n\n```\n    Transaction #5 {\n      byte[]        header      \"2 coins to Justin\"\n      Transaction[] input       { Transaction #1, Transaction #2 }\n      Transaction[] output      { }\n      int           value       2\n      byte[]        signature   \"Justin's signature based on the Header\"\n    }\n\n    Transaction #6 {\n      byte[]        header      \"6 coins for George\"\n      Transaction[] input       { Transaction #1, Transaction #2 }\n      Transaction[] output      { }\n      int           value       6\n      byte[]        signature   \"Justin's signature based on the Header\"\n    }\n```\n\nThe Aggregate Transaction (#4) will remove Transaction #1 and #2 from Justin's unused Transactions. Since the total of all inputs is 8 coins, which is 2 more than what Justin wants to send to George, the output will contain a Transaction which sends 2 coins back to Justin.\n\nThe Wallet will use it's private key to sign the Header of the Aggregate Transactions (#4) and it will also sign each of the output Transactions (#5 & #6). It will then send Transaction #4 to the Bitcoin network for confirmation. \n\nEach peer on the Bitcoin network will receive the Transaction and try to confirm it. \n\nTo confirm a Transaction, a Peer will:\n* Check the Signature of Transaction against the public key of the sender. \n\nIf it passes:\n* Send the confirmed Transaction to the Bitcoin network.\n\n## Block\n\nThe confirmed Transaction (#4) is added to a pool of confirmed Transactions. Peers (also called Miners) will gather confirmed Transactions from the pool and put them into a Block. A Block contains a number of confirmed Transactions, the Miner's signature, and a couple of other fields used for \"Proof of work\" processing.\n\n```\n    Block {\n      Transaction[]     transactions\n      int               nonce\n      int               zeros\n      byte[]            previousHash\n      byte[]            nextHash\n      byte[]            signature\n    }\n```\n\nSee the [Block Class](https://github.com/phishman3579/Bitcoin/blob/master/src/com/jwetherell/bitcoin/data_model/Block.java) for reference.\n\nMiners will create a single 'block hash' from all the confirmed Transactions in the Block. They will then go through the process of \"Proof of work\". The goal of the \"Proof of work\" is to create a hash which begins with a random number of zeros (see the 'zeros' field). \"Proof of work\" is designed to be processor intensive which adds randomness to the time it takes to process a Block. A Miner will take the 'block hash' and append a random integer (called a 'nonce') to it. It will then create a new hash from 'block hash + nonce' and see if it satisfies the \"Proof of work\", this process will repeat until it finds a 'nonce' which satisfies the \"Proof of work\"\n\nSee the [Proof of work](https://github.com/phishman3579/Bitcoin/blob/master/src/com/jwetherell/bitcoin/ProofOfWork.java) for reference.\n\nOnce a Miner finds a 'nonce' which satisfies the \"Proof of work\", it will:\n* Create another hash (see 'nextHash') using the Blockchain's current hash (see 'previousHash') and the 'block hash' \n* Send the Block to the Bitcoin network.\n\n```\n    Block #1 {\n      Transaction[]     transactions    { Transaction #4 }\n      int               nonce           453;\n      int               zeros           3;\n      byte[]            previousHash    \"Blockchain hash #1\";\n      byte[]            nextHash        \"Blockchain hash #2\";\n      byte[]            signature       \"Miner's signature\";\n    }\n```\nPeers on the Bitcoin network will receive the Block and start confirming it. \n\nTo confirm the Block, A Peer will:\n* Make sure the 'nonce' satisfies the \"Proof of work\"\n* Check the Block's signature \n* Check the signature of each Trasaction in the Block.\n\nIf everything passes:\n* Add the block to it's Blockchain.\n* Send the confirmed Block to the Bitcoin network\n\n## Blockchain\n\nThe Blockchain is a simple structure which contains a list of confirmed Blocks, a list of Transactions in chronological order, a list of unused Transactions, and the current hash.\n\nNote: all transactions in the same block are said to have happened at the same time.\n\n```\n    Blockchain {\n        List<Block>         blockchain\n        List<Transactions>  transactions\n        List<Transaction>   unused\n        byte[]              currentHash\n    }\n```\n\nSee the [Blockchain](https://github.com/phishman3579/Bitcoin/blob/master/src/com/jwetherell/bitcoin/BlockChain.java) for reference.\n\n\nWhen the Peer adds the Block to the Blockchain, the Blockchain will:\n* Check to see if the 'previousHash' from the Block matches it's 'currentHash', \n* Check to see if the input Transactions from all the Transactions in the Block are 'unused'\n\nIf everything passes:\n* The Block is added to the 'blockChain'\n* The Transaction is added to the 'transactions' list\n* All 'input' transactions are removed from the 'unused' list\n* All the 'output' transactions are added to the 'unused' list\n* The 'currentHash' is updated to 'nextHash' from the current Block.\n\n```\n    Blockchain {\n        List<Block>         blockchain      { Block #0 }\n        List<Transactions>  transactions    { Transaction #0 }\n        List<Transaction>   unused          { Transaction #1, Transaction #2, Transaction #3 }\n        byte[]              currentHash     \"Blockchain hash #1\"\n    }\n```\n\nUpdated Blockchain.\n\n```\n    Blockchain {\n        List<Block>         blockchain      { Block #0, Block #1 };\n        List<Transactions>  transactions    { Transaction #0, Transaction #4 }\n        List<Transaction>   unused          { Transaction #3, Transaction #5, Transaction #6 }\n        byte[]              currentHash     \"Blockchain hash #2\"\n    }\n```\n\nLedger:\n\n|  Justin's unused Transactions  |  George's unused Transaction  |\n|  ----------------------------- | ----------------------------- | \n| Transaction #3 : 7 Coins       | Transaction #6 : 6 Coins      |\n| Transaction #5 : 2 Coins       |                               |\n|                                |                               |\n\nBased off of [1](http://www.michaelnielsen.org/ddi/how-the-bitcoin-protocol-actually-works/) and [2](http://www.imponderablethings.com/2013/07/how-bitcoin-works-under-hood.html)\n\nAlso see the [original paper](https://bitcoin.org/bitcoin.pdf)\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/Blockchain.java",
    "content": "package com.jwetherell.bitcoin;\n\nimport java.nio.ByteBuffer;\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.PrivateKey;\nimport java.security.PublicKey;\nimport java.security.SecureRandom;\nimport java.security.Signature;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\nimport com.jwetherell.bitcoin.common.Constants;\nimport com.jwetherell.bitcoin.common.HashUtils;\nimport com.jwetherell.bitcoin.data_model.Block;\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\npublic class Blockchain {\n\n    public static final String              NO_ONE              = \"no one\";\n    public static final Signature           NO_ONE_SIGNATURE;\n    public static final byte[]              NO_ONE_PUB_KEY;\n    static {\n        try {\n            final KeyPairGenerator gen = KeyPairGenerator.getInstance(\"DSA\", \"SUN\");\n            final SecureRandom random = SecureRandom.getInstance(\"SHA1PRNG\", \"SUN\");\n            gen.initialize(512, random);\n\n            final KeyPair pair = gen.generateKeyPair();\n            final PrivateKey privateKey = pair.getPrivate();\n            NO_ONE_SIGNATURE = Signature.getInstance(\"SHA1withDSA\", \"SUN\");\n            NO_ONE_SIGNATURE.initSign(privateKey);\n\n            final PublicKey publicKey = pair.getPublic();\n            NO_ONE_PUB_KEY = publicKey.getEncoded();\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    public static final String              GENESIS_NAME        = \"genesis\";\n\n    protected static final boolean          DEBUG               = Boolean.getBoolean(\"debug\");\n\n    private static final byte[]             INITIAL_HASH        = new byte[0];\n\n    private static final Transaction        GENESIS_TRANS;\n    private static final Block              GENESIS_BLOCK;\n    static {\n        // To start the blockchain, we have an initial transaction which has no inputs and one output which\n        // is given to the genesis entity. This is the only transaction which has no inputs.\n        final Transaction[] empty = new Transaction[0];\n        final Transaction[] output = new Transaction[1];\n        final String outputMsg = \"Genesis gets 50 coins.\";\n        output[0] = Transaction.newSignedTransaction(NO_ONE_SIGNATURE, NO_ONE, GENESIS_NAME, outputMsg, 50, empty, empty);\n\n        final String msg = \"Genesis transfer.\";\n        GENESIS_TRANS = Transaction.newSignedTransaction(NO_ONE_SIGNATURE, NO_ONE, GENESIS_NAME, msg, 0, empty, output);\n\n        final ByteBuffer buffer = ByteBuffer.allocate(GENESIS_TRANS.getBufferLength());\n        GENESIS_TRANS.toBuffer(buffer);\n        buffer.flip();\n\n        final byte[] bytes = buffer.array();\n        final byte[] nextHash = Blockchain.getNextHash(Blockchain.INITIAL_HASH, bytes);\n\n        final Transaction[] trans = new Transaction[]{ GENESIS_TRANS };\n        GENESIS_BLOCK = new Block(NO_ONE, Blockchain.INITIAL_HASH, nextHash, trans, 0);\n        GENESIS_BLOCK.confirmed = true;\n    }\n\n    private final List<Block>               blockchain          = new CopyOnWriteArrayList<Block>();\n    private final List<Transaction>         transactions        = new CopyOnWriteArrayList<Transaction>();\n    private final List<Transaction>         unused              = new CopyOnWriteArrayList<Transaction>();\n\n    private final String                    owner;\n\n    private volatile byte[]                 latestHash          = INITIAL_HASH;\n\n    public Blockchain(String owner) {\n        this.owner = owner;\n        // transfer initial coins to genesis entity\n        this.addBlock(GENESIS_NAME, GENESIS_BLOCK);\n    }\n\n    public int getLength() {\n        return blockchain.size();\n    }\n\n    public Block getBlock(int blockNumber) {\n        if (blockNumber>=blockchain.size())\n            return null;\n        return blockchain.get(blockNumber);\n    }\n\n    public List<Transaction> getUnused() {\n        return unused;\n    }\n\n    public Block getNextBlock(String name, Transaction[] transactions) {\n        int length = 0;\n        for (Transaction transaction : transactions)\n            length += transaction.getBufferLength();\n        final byte[] bytes = new byte[length];\n        final ByteBuffer bb = ByteBuffer.wrap(bytes);\n\n        for (Transaction transaction : transactions) {\n            final ByteBuffer buffer = ByteBuffer.allocate(transaction.getBufferLength());\n            transaction.toBuffer(buffer);\n            buffer.flip();\n            bb.put(buffer.array());\n        }\n\n        final byte[] nextHash = getNextHash(latestHash, bytes);\n        return (new Block(name, latestHash, nextHash, transactions, this.blockchain.size()));\n    }\n\n    public Constants.Status checkHash(Block block) {\n        if (block.blockLength > this.blockchain.size()) {\n            // This block is in the future\n            if (DEBUG)\n                System.out.println(owner+\" found a future block. lengths=\"+this.blockchain.size()+\"\\n\"+\"block={\\n\"+block.toString()+\"\\n}\");\n            return Constants.Status.FUTURE_BLOCK;\n        }\n\n        int length = 0;\n        for (Transaction transaction : block.transactions)\n            length += transaction.getBufferLength();\n        final byte[] bytes = new byte[length];\n        final ByteBuffer bb = ByteBuffer.wrap(bytes);\n\n        for (Transaction transaction : block.transactions) {\n            final ByteBuffer buffer = ByteBuffer.allocate(transaction.getBufferLength());\n            transaction.toBuffer(buffer);\n            buffer.flip();\n            bb.put(buffer.array());\n        }\n\n        // Calculate what I think the next has should be\n        final byte[] nextHash = getNextHash(latestHash, bytes);\n\n        // Store the previous and next hash from the block\n        final byte[] incomingPrev = block.prev;\n        final byte[] incomingHash = block.hash;\n\n        if (!(Arrays.equals(incomingHash, nextHash))) {\n            // This block has a different 'next' hash then I expect, someone is out of sync\n            if (DEBUG) {\n                StringBuilder builder = new StringBuilder();\n                builder.append(owner).append(\" Invalid hash in block\\n\");\n                builder.append(\"confirmed=\"+block.confirmed).append(\"\\n\");\n                builder.append(\"length=\").append(this.blockchain.size()).append(\"\\n\");\n                builder.append(\"latest=[\"+HashUtils.bytesToHex(latestHash)+\"]\\n\");\n                builder.append(\"next=[\"+HashUtils.bytesToHex(nextHash)+\"]\\n\");\n                builder.append(\"incomingLength=\").append(block.blockLength).append(\"\\n\");\n                builder.append(\"incomingPrev=[\"+HashUtils.bytesToHex(incomingPrev)+\"]\\n\");\n                builder.append(\"incomingNext=[\"+HashUtils.bytesToHex(incomingHash)+\"]\\n\");\n                System.err.println(builder.toString());\n            }\n            return Constants.Status.BAD_HASH;\n        }\n\n        return Constants.Status.SUCCESS;\n    }\n\n    public Constants.Status addBlock(String dataFrom, Block block) {\n        // Already processed this block? Happens if a miner is slow and isn't first to confirm the block\n        if (blockchain.contains(block))\n            return Constants.Status.DUPLICATE;\n\n        // Check to see if the block's hash is what I expect\n        final Constants.Status status = checkHash(block);\n        if (status != Constants.Status.SUCCESS)\n            return status;\n\n        // Get the aggregate transaction for processing\n        for (Transaction transaction : block.transactions) {\n            // Remove the inputs from the unused pool\n            for (Transaction t : transaction.inputs) {\n                boolean exists = unused.remove(t);\n                if (exists == false) {\n                    if (DEBUG)\n                        System.err.println(owner+\" Bad inputs in block from '\"+dataFrom+\"'. block={\\n\"+block.toString()+\"\\n}\");\n                    return Constants.Status.BAD_INPUTS;\n                }\n            }\n        }\n\n        // Add outputs to unused pool\n        for (Transaction transaction : block.transactions) {\n            for (Transaction t : transaction.outputs)\n                unused.add(t);\n        }\n\n        // Update the hash and add the new transaction to the list\n        final byte[] prevHash = latestHash;\n        final byte[] nextHash = block.hash;\n        blockchain.add(block);\n        for (Transaction transaction : block.transactions)\n            transactions.add(transaction);\n        latestHash = nextHash;\n\n        if (DEBUG) {\n            final String prev = HashUtils.bytesToHex(prevHash);\n            final String next = HashUtils.bytesToHex(nextHash);\n            final StringBuilder builder = new StringBuilder();\n            builder.append(owner).append(\" updated hash\").append(\" msg_from='\"+dataFrom+\"'\").append(\" block_from='\"+block.from+\"'\\n\");\n            builder.append(\"blockchain length=\").append(blockchain.size()).append(\"\\n\");\n            builder.append(\"transactions=[\\n\");\n            for (Transaction t : block.transactions) {\n                builder.append(t.toString()).append(\"\\n\");\n            }\n            builder.append(\"]\\n\");\n            builder.append(\"prev=[\").append(prev).append(\"]\\n\");\n            builder.append(\"next=[\").append(next).append(\"]\\n\");\n            System.err.println(builder.toString());\n        }\n\n        return Constants.Status.SUCCESS;\n    }\n\n    public long getBalance(String name) {\n        long result = 0;\n        for (Transaction t : transactions) {\n            // Remove the inputs\n            for (Transaction c : t.inputs) {\n                if (name.equals(c.to))\n                    result -= c.value;\n            }\n            // Add the outputs\n            for (Transaction c : t.outputs) {\n                if (name.equals(c.to))\n                    result += c.value;\n            }\n        }\n        return result;\n    }\n\n    public static final byte[] getNextHash(byte[] hash, byte[] bytes) {\n        final StringBuilder builder = new StringBuilder();\n        builder.append(HashUtils.bytesToHex(hash)).append(HashUtils.bytesToHex(bytes));\n        final String string = builder.toString();\n        final byte[] output = HashUtils.calculateSha256(string);\n        return output;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof Blockchain))\n            return false;\n        final Blockchain other = (Blockchain) o;\n        for (Block b : blockchain) {\n            if (!(other.blockchain.contains(b)))\n                return false;\n        }\n        for (Transaction t : transactions) {\n            if (!(other.transactions.contains(t)))\n                return false;\n        }\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        final StringBuilder builder = new StringBuilder();\n        builder.append(\"hash=[\").append(HashUtils.bytesToHex(latestHash)).append(\"]\\n\");\n        builder.append(\"inputs={\").append(\"\\n\");\n        for (Transaction c : transactions) {\n            for (Transaction i : c.inputs)\n                builder.append('\\t').append(i.value).append(\" from '\").append(i.from).append(\"' to '\").append(i.to).append(\"'\\n\");\n            builder.append(\"}\\n\");\n        }\n        builder.append(\"outputs={\").append(\"\\n\");\n        for (Transaction c : transactions) {\n            for (Transaction i : c.outputs)\n                builder.append('\\t').append(i.value).append(\" from '\").append(i.from).append(\"' to '\").append(i.to).append(\"'\\n\");\n            builder.append(\"}\\n\");\n        }\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/Peer.java",
    "content": "package com.jwetherell.bitcoin;\n\nimport java.nio.ByteBuffer;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\nimport com.jwetherell.bitcoin.common.Constants;\nimport com.jwetherell.bitcoin.common.HashUtils;\nimport com.jwetherell.bitcoin.data_model.Transaction;\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.data_model.Block;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.networking.Multicast;\nimport com.jwetherell.bitcoin.networking.TCP;\n\n/**\n * Class which handles lower level sending and receiving of messages.\n * \n * Thread-Safe (Hopefully)\n */\npublic abstract class Peer {\n\n    protected static final boolean                DEBUG                         = Boolean.getBoolean(\"debug\");\n\n    private static final int                      HEADER_LENGTH                 = 16;\n    private static final String                   WHOIS                         = \"Who is          \";\n    private static final String                   IAM                           = \"I am            \";\n    private static final String                   TRANSACTION                   = \"Transaction     \";\n    private static final String                   TRANSACTION_ACK               = \"Transaction ACK \";\n    private static final String                   BLOCK                         = \"Block           \";\n    private static final String                   CONFIRMATION                  = \"Block Confirm   \";\n    private static final String                   RESEND                        = \"Resend          \";\n    private static final String                   REHASH                        = \"Rehash          \";\n\n    private static final int                      KEY_LENGTH                    = 4;\n    private static final int                      NAME_LENGTH                   = 4;\n\n    private static final String                   EVERY_ONE                     = \"EVERYONE\";\n    private static final byte[]                   NO_SIG                        = new byte[0];\n\n    private final TCP.Peer.RunnableSend           runnableSendTcp               = new TCP.Peer.RunnableSend();\n    private final Multicast.Peer.RunnableSend     runnableSendMulti             = new Multicast.Peer.RunnableSend();\n\n    private final MessageListener                 listener                      = new MessageListener() {\n        /**\n         * {@inheritDoc}\n         */\n        @Override\n        public void onMessage(Receiver recv) {\n            Data data = recv.getQueue().poll();\n            while (data != null) {\n                final String from = data.from;\n\n                final byte[] bytes = data.message.array();\n                final String string = new String(bytes);\n                final String hdr = string.substring(0, HEADER_LENGTH);\n                if (DEBUG) \n                    System.out.println(myName+\" Listener received '\"+hdr+\"' msg\");\n                if (hdr.equals(WHOIS)) {\n                    handleWhois(bytes,data);\n                } else if (hdr.equals(IAM)) {\n                    handleIam(bytes,data);\n                    processTransactionsToSend(from);\n                    processTransactionsToRecv(from);\n                } else if (hdr.equals(TRANSACTION)) {\n                    handleTransaction(from,bytes,data);\n                } else if (hdr.equals(TRANSACTION_ACK)) {\n                    handleTransactionAck(from,bytes,data);\n                } else if (hdr.equals(BLOCK)) {\n                    handleBlock(from,bytes,data);\n                } else if (hdr.equals(CONFIRMATION)) {\n                    handleConfirmation(from,bytes,data);\n                    processFutureBlocksToRecv(from);\n                } else if (hdr.equals(RESEND)) {\n                    handleResend(from,bytes,data);\n                } else if (hdr.equals(REHASH)) {\n                    handleRehash(from,bytes,data);\n                } else {\n                    System.err.println(myName+\" Cannot handle msg. hdr=\"+hdr);\n                }\n\n                // Get next message\n                data = recv.getQueue().poll();\n                Thread.yield();\n            }\n            Thread.yield();\n        }\n    };\n\n    // Keep track of everyone's name -> ip+port\n    private final Map<String,Host>                peers                         = new ConcurrentHashMap<String,Host>();\n\n    // Pending msgs (This happens if we don't know the ip+port OR the public key of a host\n    private final Map<String,Queue<Queued>>       transactionsToSend            = new ConcurrentHashMap<String,Queue<Queued>>();\n    private final Map<String,Queue<Queued>>       transactionsToRecv            = new ConcurrentHashMap<String,Queue<Queued>>();\n    private final Map<String,Queue<Queued>>       futureTransactionsToRecv      = new ConcurrentHashMap<String,Queue<Queued>>();\n\n    private final Map<String,TimerTask>           timerMap                      = new ConcurrentHashMap<String,TimerTask>();\n    private final Timer                           timer                         = new Timer();\n\n    private final Thread                          tcpSendThread;\n    private final Thread                          tcpRecvThread;\n    private final Thread                          multiSendThread;\n    private final Thread                          multiRecvThread;\n\n    // Thread safe queues for sending messages\n    private final Queue<Data>                     sendTcpQueue;\n    private final Queue<Data>                     sendMultiQueue;\n\n    protected final TCP.Peer.RunnableRecv         runnableRecvTcp               = new TCP.Peer.RunnableRecv(listener);\n    protected final Multicast.Peer.RunnableRecv   runnableRecvMulti             = new Multicast.Peer.RunnableRecv(listener);\n    protected final String                        myName;\n\n    protected Peer(String name) {\n        this.myName = name;\n\n        // Receivers\n\n        tcpRecvThread = new Thread(runnableRecvTcp, myName+\" recvTcp\");\n        tcpRecvThread.start();\n\n        multiRecvThread = new Thread(runnableRecvMulti, myName+\" recvMulti\");\n        multiRecvThread.start();\n\n        // Senders\n\n        tcpSendThread = new Thread(runnableSendTcp, myName+\" sendTcp\");\n        sendTcpQueue = runnableSendTcp.getQueue();\n        tcpSendThread.start();\n\n        multiSendThread = new Thread(runnableSendMulti, myName+\" sendMulti\");\n        sendMultiQueue = runnableSendMulti.getQueue();\n        multiSendThread.start();\n\n        while (isReady()==false) {\n            Thread.yield();\n        }\n    }\n\n    public String getName() {\n        return myName;\n    }\n\n    public void shutdown() throws InterruptedException {\n        TCP.Peer.RunnableSend.run = false;\n        TCP.Peer.RunnableRecv.run = false;\n\n        Multicast.Peer.RunnableSend.run = false;\n        Multicast.Peer.RunnableRecv.run = false;\n\n        // Senders\n\n        multiSendThread.interrupt();\n        multiSendThread.join();\n\n        tcpSendThread.interrupt();\n        tcpSendThread.join();\n\n        // Receivers\n\n        tcpRecvThread.interrupt();\n        tcpRecvThread.join();\n\n        multiRecvThread.interrupt();\n        multiRecvThread.join();\n    }\n\n    public boolean isReady() {\n        return (runnableRecvTcp.isReady() && runnableSendTcp.isReady() && runnableRecvMulti.isReady() && runnableSendMulti.isReady());\n    }\n\n    public abstract Blockchain getBlockChain();\n\n    /** Get encoded public key **/\n    protected abstract byte[] getPublicKey();\n\n    private void sendWhois(String who) {\n        final byte[] msg = getWhoisMsg(who);\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), EVERY_ONE, runnableRecvMulti.getHost(), runnableRecvMulti.getPort(), NO_SIG, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendMultiQueue.add(data);\n    }\n\n    private void handleWhois(byte[] bytes, Data data) {\n        final String name = parseWhoisMsg(bytes);\n\n        // If your name and not from myself then shout it out!\n        if (name.equals(this.myName) && !(data.from.equals(this.myName)))\n            sendIam();\n    }\n\n    private void sendIam() {\n        final byte[] msg = getIamMsg(getPublicKey());\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), EVERY_ONE, runnableRecvMulti.getHost(), runnableRecvMulti.getPort(), NO_SIG, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendMultiQueue.add(data);\n    }\n\n    private void handleIam(byte[] bytes, Data data) {\n        final String name = data.from;\n        final byte[] key = parseIamMsg(bytes);\n\n        // Update peers\n        peers.put(name, new Host(data.sourceAddr.getHostAddress(), data.sourcePort));\n\n        // New public key\n        newPublicKey(name, key);\n    }\n\n    /** What do you want to do with a new public key **/\n    protected abstract void newPublicKey(String name, byte[] publicKey);\n\n    /** Sign message with private key **/\n    protected abstract byte[] signMsg(byte[] bytes);\n\n    /** Verify the bytes given the public key and signature **/\n    protected abstract boolean verifyMsg(byte[] publicKey, byte[] signature, byte[] bytes);\n\n    /** Send transaction to the peer named 'to' **/\n    protected void sendTransaction(String to, Transaction transaction) {\n        final Host d = peers.get(to);\n        if (d == null){\n            // Could not find peer, broadcast a whois\n            addTransactionToSend(Queued.State.NEW, to, transaction);\n            sendWhois(to);\n            return;\n        }\n\n        final byte[] msg = getTransactionMsg(transaction);\n        final byte[] sig = signMsg(msg);\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), to, d.ip, d.port, sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendTcpQueue.add(data);\n    }\n\n    private Constants.Status handleTransaction(String dataFrom, byte[] bytes, Data data) {\n        final Transaction trans = parseTransactionMsg(bytes);\n        return handleTransaction(dataFrom, trans, data);\n    }\n\n    private Constants.Status handleTransaction(String dataFrom, Transaction transaction, Data data) {\n        // I shouldn't ACK my own transaction\n        if (transaction.from.equals(myName))\n            return Constants.Status.OWN_TRANSACTION;\n\n        // Let the app logic do what it needs to\n        final Constants.Status status = handleTransaction(dataFrom, transaction, data.signature.array(), data.message.array());\n        if (status == Constants.Status.NO_PUBLIC_KEY) {\n            addTransactionToRecv(Queued.State.NEW, dataFrom, transaction, data);\n            sendWhois(dataFrom);\n            return status;\n        } else if (status != Constants.Status.SUCCESS) {\n            return status;\n        }\n\n        // Send an ACK msg\n        ackTransaction(dataFrom, transaction);\n\n        return status;\n    }\n\n    /** What do you want to do now that you have received a transaction, return the KeyStatus **/\n    protected abstract Constants.Status handleTransaction(String dataFrom, Transaction transaction, byte[] signature, byte[] bytes);\n\n    private void ackTransaction(String to, Transaction transaction) {\n        final Host d = peers.get(to);\n        if (d == null){\n            // Could not find peer, broadcast a whois\n            addTransactionToSend(Queued.State.ACK, to, transaction);\n            sendWhois(to);\n            return;\n        }\n\n        final byte[] msg = getTransactionAckMsg(transaction);\n        final byte[] sig = signMsg(msg);\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), to, d.ip, d.port, sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendTcpQueue.add(data);\n    }\n\n    private void handleTransactionAck(String dataFrom, byte[] bytes, Data data) {\n        final Transaction trans = parseTransactionAckMsg(bytes);\n        handleTransactionAck(dataFrom, trans, data);\n    }\n\n    private void handleTransactionAck(String dataFrom, Transaction transaction, Data data) {\n        // Let the app logic do what it needs to\n        Constants.Status knownPublicKey = handleTransactionAck(dataFrom, transaction, data.signature.array(), data.message.array());\n        if (knownPublicKey == Constants.Status.NO_PUBLIC_KEY) {\n            addTransactionToRecv(Queued.State.ACK, dataFrom, transaction, data);\n            sendWhois(dataFrom);\n            return;\n        } else if (knownPublicKey != Constants.Status.SUCCESS) {\n            return;\n        }\n\n        final Block block = aggegateTransaction(transaction);\n        if (block != null) \n            sendBlock(block, data);\n    }\n\n    /** What do you want to do now that you received an ACK for a sent transaction, return the KeyStatus **/\n    protected abstract Constants.Status handleTransactionAck(String dataFrom, Transaction transaction, byte[] signature, byte[] bytes);\n\n    /** Collect the transactions, either return null or a new Block **/\n    protected abstract Block aggegateTransaction(Transaction transaction);\n\n    protected void sendBlock(Block block, Data data) {\n        final byte[] msg = getBlockMsg(block);\n        final byte[] sig = signMsg(msg);\n        final Data dataToSend = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), data.from, data.sourceAddr.getHostAddress(), data.sourcePort, sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg. confirmed=\"+block.confirmed);\n        }\n        sendTcpQueue.add(dataToSend);\n    }\n\n    private void handleBlock(String dataFrom, byte[] bytes, Data data) {\n        final Block block = parseBlockMsg(bytes);\n        handleBlock(dataFrom, block, data);\n    }\n\n    private void handleBlock(String dataFrom, Block block, Data data) {\n        // I shouldn't handle my own block\n        if (block.from.equals(myName))\n            return;\n\n        final int length = this.getBlockChain().getLength();\n        final Constants.Status status = checkTransaction(data.from, block, data.signature.array(), data.message.array());\n        if (status == Constants.Status.NO_PUBLIC_KEY) {\n            addBlockToRecv(Queued.State.CONFIRM, dataFrom, block, data);\n            sendWhois(dataFrom);\n            return;\n        } else if (status == Constants.Status.BAD_HASH) {\n            sendRehash(block, data);\n            return;\n        } else if (status == Constants.Status.FUTURE_BLOCK) {\n            // If we have a transaction which is in the future, we are likely missing a previous block\n            // Save the block for later processing and ask the network for the missing block.\n            addFutureBlockToRecv(Queued.State.FUTURE, dataFrom, block, data);\n            sendResend(length);\n            return;\n        } else if (status != Constants.Status.SUCCESS) {\n            System.out.println(myName+\" handleBlock() error=\"+status);\n            // Drop all other errors\n            return;\n        }\n\n        // Hash looks good to me, ask everyone else\n        sendConfirmation(block);\n    }\n\n    /** multicast **/\n    protected void sendConfirmation(Block block) {\n        final byte[] msg = getConfirmationMsg(block);\n        final byte[] sig = signMsg(msg);\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), EVERY_ONE, runnableRecvMulti.getHost(), runnableRecvMulti.getPort(), sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending multicast '\"+hdr+\"' msg. confirmed=\"+block.confirmed);\n        }\n        sendMultiQueue.add(data);\n    }\n\n    /** tcp **/\n    protected void sendConfirmation(Block block, Data data) {\n        final byte[] msg = getConfirmationMsg(block);\n        final byte[] sig = signMsg(msg);\n        final Data dataToSend = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), data.from, data.sourceAddr.getHostAddress(), data.sourcePort, sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending unicast '\"+hdr+\"' msg. confirmed=\"+block.confirmed);\n        }\n        sendTcpQueue.add(dataToSend);\n    }\n\n    private void handleConfirmation(String dataFrom, byte[] bytes, Data data) {\n        final Block block = parseConfirmationMsg(bytes);\n        handleConfirmation(dataFrom, block, data);\n    }\n\n    private void handleConfirmation(String dataFrom, Block block, Data data) {\n        if (block.confirmed) {\n            // Yey! we got a confirmation from the community\n\n            final int length = this.getBlockChain().getLength();\n            final Constants.Status status = handleConfirmation(dataFrom, block, data.signature.array(), data.message.array());\n            if (status == Constants.Status.SUCCESS) {\n                // Someone solved the nonce, cancel async task - if we have one\n                final String hex = HashUtils.bytesToHex(block.hash);\n                final TimerTask miner = timerMap.get(hex);\n                if (miner != null)\n                    miner.cancel();\n                return;\n            } else if (status == Constants.Status.NO_PUBLIC_KEY) {\n                addBlockToRecv(Queued.State.CONFIRM, dataFrom, block, data);\n                sendWhois(dataFrom);\n                return;\n            } else if (status == Constants.Status.BAD_HASH) {\n                sendRehash(block, data);\n                return;\n            } else if (status == Constants.Status.FUTURE_BLOCK) {\n                // If we have a transaction which is in the future, we are likely missing a previous block\n                // Save the block for later processing and ask the network for the missing block.\n                addFutureBlockToRecv(Queued.State.FUTURE, dataFrom, block, data);\n                sendResend(length);\n                return;\n            } else if (status != Constants.Status.SUCCESS) {\n                // Drop all other errors\n                return;\n            }\n\n            return;\n        }\n\n        // Don't confirm my own block\n        if (block.from.equals(myName))\n            return;\n\n        final int length = this.getBlockChain().getLength();\n        final Constants.Status status = checkTransaction(dataFrom, block, data.signature.array(), data.message.array());\n        if (status == Constants.Status.NO_PUBLIC_KEY) {\n            addBlockToRecv(Queued.State.CONFIRM, dataFrom, block, data);\n            sendWhois(dataFrom);\n            return;\n        } else if (status == Constants.Status.FUTURE_BLOCK) {\n            // Do not add to 'FutureBlockToRecv' since this block isn't confirmed\n            sendResend(length);\n            return;\n        } else if (status == Constants.Status.BAD_HASH) {\n            sendRehash(block, data);\n            return;\n        } else if (status != Constants.Status.SUCCESS) {\n            // Drop all other errors\n            return;\n        }\n\n        // async task\n        final String hex = HashUtils.bytesToHex(block.hash);\n        final TimerTask miningTask = new MiningTask(this,hex,block);\n        timer.schedule(miningTask, 0);\n    }\n\n    /** What do you want to do now that you received a block, return the HashStatus **/\n    protected abstract Constants.Status checkTransaction(String dataFrom, Block block, byte[] signature, byte[] bytes);\n\n    /** What do you want to do now that you received a valid block, return the HashStatus **/\n    protected abstract Constants.Status handleConfirmation(String dataFrom, Block block, byte[] signature, byte[] bytes);\n\n    /** Mine the nonce sent in the transaction **/\n    protected abstract int mineHash(MiningTask timer, byte[] sha256, long numberOfZerosInPrefix);\n\n    private void sendResend(int blockNumber) {\n        final byte[] msg = getResendBlockMsg(blockNumber);\n        final byte[] sig = signMsg(msg);\n        final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), EVERY_ONE, runnableRecvMulti.getHost(), runnableRecvMulti.getPort(), sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendMultiQueue.add(data);\n    }\n\n    private void handleResend(String dataFrom, byte[] bytes, Data data) {\n        // I shouldn't resend from my own resend msg (flood warning!)\n        if (dataFrom.equals(myName))\n            return;\n\n        final int blockNumber = parseResendBlockMsg(bytes);\n        final int length = this.getBlockChain().getLength();\n        // I don't have the block, cannot help.\n        if (length<=blockNumber)\n            return;\n\n        final Block toSend = this.getBlockChain().getBlock(blockNumber);\n        sendConfirmation(toSend, data);\n    }\n\n    protected void sendRehash(Block block, Data data) {\n        final byte[] msg = getRehashMsg(block);\n        final byte[] sig = signMsg(msg);\n        final Data dataToSend = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), data.from, data.sourceAddr.getHostAddress(), data.sourcePort, sig, msg);\n        if (DEBUG) {\n            final String string = new String(msg);\n            final String hdr = string.substring(0, HEADER_LENGTH);\n            System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n        }\n        sendTcpQueue.add(dataToSend);\n    }\n\n    private void handleRehash(String dataFrom, byte[] bytes, Data data) {\n        final Block block = parseRehashMsg(bytes);\n        // hash was out of sync with the blockchain, reprocess it.\n        for (Transaction t : block.transactions)\n            handleTransactionAck(dataFrom, t, data);\n    }\n\n    private void addTransactionToSend(Queued.State state, String to, Transaction transaction) {\n        final Queued q = new Queued(state, transaction, null);\n        Queue<Queued> l = transactionsToSend.get(to);\n        if (l == null) {\n            l = new ConcurrentLinkedQueue<Queued>();\n            transactionsToSend.put(to, l);\n        }\n        l.add(q);\n    }\n\n    private void processTransactionsToSend(String to) {\n        Queue<Queued> l = transactionsToSend.get(to);\n        if (l==null || l.size()==0)\n            return;\n        while (l.size()>0) {\n            final Queued q = l.poll();\n            if (q == null)\n                return;\n            final Host d = peers.get(to); // Do not use the data object in the queue object\n            final byte[] msg = getTransactionMsg(q.transaction);\n            final byte[] sig = signMsg(msg);\n            final Data data = new Data(myName, runnableRecvTcp.getHost(), runnableRecvTcp.getPort(), to, d.ip, d.port, sig, msg);\n            if (DEBUG) {\n                final String string = new String(msg);\n                final String hdr = string.substring(0, HEADER_LENGTH);\n                System.out.println(myName+\" Sending '\"+hdr+\"' msg\");\n            }\n            sendTcpQueue.add(data);\n        }\n    }\n\n    private void addTransactionToRecv(Queued.State state, String dataFrom, Transaction transaction, Data data) {\n        final Queued q = new Queued(state, transaction, data);\n        Queue<Queued> lc = transactionsToRecv.get(dataFrom);\n        if (lc == null) {\n            lc = new ConcurrentLinkedQueue<Queued>();\n            transactionsToRecv.put(dataFrom, lc);\n        }\n        lc.add(q);\n    }\n\n    private void addBlockToRecv(Queued.State state, String dataFrom, Block block, Data data) {\n        final Queued q = new Queued(state, block, data);\n        Queue<Queued> lc = transactionsToRecv.get(dataFrom);\n        if (lc == null) {\n            lc = new ConcurrentLinkedQueue<Queued>();\n            transactionsToRecv.put(dataFrom, lc);\n        }\n        lc.add(q);\n    }\n\n    private void processTransactionsToRecv(String from) {\n        Queue<Queued> l = transactionsToRecv.get(from);\n        if (l==null || l.size()==0)\n            return;\n        while (l.size()>0) {\n            final Queued q = l.poll();\n            if (q == null)\n                return;\n            if (q.state == Queued.State.CONFIRM)\n                handleConfirmation(from, q.block, q.data);\n            else if (q.state == Queued.State.ACK)\n                handleTransactionAck(from, q.transaction, q.data);\n            else\n                handleTransaction(from, q.transaction, q.data);\n        }\n    }\n\n    private void addFutureBlockToRecv(Queued.State state, String dataFrom, Block block, Data data) {\n        final Queued q = new Queued(state, block, data);\n        Queue<Queued> lc = futureTransactionsToRecv.get(dataFrom);\n        if (lc == null) {\n            lc = new ConcurrentLinkedQueue<Queued>();\n            futureTransactionsToRecv.put(dataFrom, lc);\n        }\n        lc.add(q);\n    }\n\n    private void processFutureBlocksToRecv(String from) {\n        Queue<Queued> l = futureTransactionsToRecv.get(from);\n        if (l==null || l.size()==0)\n            return;\n        while (l.size()>0) {\n            final Queued q = l.poll();\n            if (q == null)\n                return;\n            if (q.state == Queued.State.FUTURE)\n                handleConfirmation(from, q.block, q.data);\n        }\n    }\n\n    private static final class Host {\n\n        private final String    ip;\n        private final int       port;\n\n        private Host(String ip, int port) {\n            this.ip = ip;\n            this.port = port;\n        }\n    }\n\n    private static final class Queued {\n\n        private enum                State {NEW, ACK, CONFIRM, FUTURE};\n\n        private final State         state;\n        private final Transaction   transaction;\n        private final Block         block;\n        private final Data          data;\n\n        private Queued(State state, Transaction transaction, Data data) {\n            if (state == State.CONFIRM)\n                throw new RuntimeException(\"Cannot have a CONFIRM without a Block\");\n            this.state = state;\n            this.transaction = transaction;\n            this.block = null;\n            this.data = data;\n        }\n\n        private Queued(State state, Block block, Data data) {\n            if (state != State.CONFIRM && state != State.FUTURE)\n                throw new RuntimeException(\"Cannot have a non-CONFIRM/FUTURE with a Block\");\n            this.state = state;\n            this.transaction = null;\n            this.block = block;\n            this.data = data;\n        }\n    }\n\n    public static class MiningTask extends TimerTask {\n\n        public volatile boolean run = true;\n\n        private final   Peer    peer;\n        private final   String  hex;\n        private final   Block   block;\n\n        /** unit testing constructor **/\n        public MiningTask() {\n            this.peer = null;\n            this.hex = null;\n            this.block = null;\n        }\n\n        public MiningTask(Peer peer, String hex, Block block) {\n            this.peer = peer;\n            this.hex = hex;\n            this.block = block;\n\n            TimerTask oldTask = peer.timerMap.put(hex, this);\n            if (oldTask != null)\n                oldTask.cancel();\n        }\n\n        @Override\n        public void run() {\n            peer.timerMap.remove(hex);\n\n            // Let's mine this sucker.\n            final int nonce = peer.mineHash(this, block.hash, block.numberOfZeros);\n\n            if (nonce < 0)\n                return;\n\n            // Hash looks good to me and I have computed a nonce, let everyone know\n            block.confirmed = true;\n            block.nonce = nonce;\n\n            // Make sure the block is still valid (hasn't been solved by someone else while we were processing)\n            Constants.Status status = peer.getBlockChain().checkHash(block);\n            if (status != Constants.Status.SUCCESS) {\n                System.err.println(peer.myName +\" NOT sending block, hash is no longer valid.\");\n                return;\n            }\n\n            peer.sendConfirmation(block);\n        }\n\n        @Override\n        public boolean cancel() {\n            peer.timerMap.remove(hex);\n            run = false;\n            return super.cancel();\n        }\n    }\n\n    public static final byte[] getWhoisMsg(String name) {\n        final byte[] bName = name.getBytes();\n        final int nameLength = bName.length;\n        final byte[] msg = new byte[HEADER_LENGTH + NAME_LENGTH + nameLength];\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n\n        buffer.put(WHOIS.getBytes());\n        buffer.putInt(nameLength);\n        buffer.put(bName);\n\n        return msg;\n    }\n\n    public static final String parseWhoisMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final int nLength = buffer.getInt();\n        final byte [] bName = new byte[nLength];\n        buffer.get(bName);\n\n        return new String(bName);\n    }\n\n    public static final byte[] getIamMsg(byte[] publicKey) {\n        final int publicKeyLength = publicKey.length;\n        final byte[] msg = new byte[HEADER_LENGTH + KEY_LENGTH + publicKeyLength];\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n\n        buffer.put(IAM.getBytes());\n\n        buffer.putInt(publicKeyLength);\n        buffer.put(publicKey);\n\n        return msg;\n    }\n\n    public static final byte[] parseIamMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final int kLength = buffer.getInt();\n        final byte [] bKey = new byte[kLength];\n        buffer.get(bKey);\n\n        return bKey;\n    }\n\n    public static final byte[] getTransactionMsg(Transaction transaction) {\n        final byte[] msg = new byte[HEADER_LENGTH + transaction.getBufferLength()];\n        final ByteBuffer transactionBuffer = ByteBuffer.allocate(transaction.getBufferLength());\n        transaction.toBuffer(transactionBuffer);\n        transactionBuffer.flip();\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(TRANSACTION.getBytes());\n\n        buffer.put(transactionBuffer);\n\n        return msg;\n    }\n\n    public static final Transaction parseTransactionMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final Transaction transaction = new Transaction();\n        transaction.fromBuffer(buffer);\n\n        return transaction;\n    }\n\n    public static final byte[] getTransactionAckMsg(Transaction transaction) {\n        final byte[] msg = new byte[HEADER_LENGTH + transaction.getBufferLength()];\n        final ByteBuffer transactionBuffer = ByteBuffer.allocate(transaction.getBufferLength());\n        transaction.toBuffer(transactionBuffer);\n        transactionBuffer.flip();\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(TRANSACTION_ACK.getBytes());\n\n        buffer.put(transactionBuffer);\n\n        return msg;\n    }\n\n    public static final Transaction parseTransactionAckMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final Transaction block = new Transaction();\n        block.fromBuffer(buffer);\n\n        return block;\n    }\n\n    public static final byte[] getBlockMsg(Block block) {\n        final byte[] msg = new byte[HEADER_LENGTH + block.getBufferLength()];\n        final ByteBuffer blockBuffer = ByteBuffer.allocate(block.getBufferLength());\n        block.toBuffer(blockBuffer);\n        blockBuffer.flip();\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(BLOCK.getBytes());\n\n        buffer.put(blockBuffer);\n\n        return msg;\n    }\n\n    public static final Block parseBlockMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final Block block = new Block();\n        block.fromBuffer(buffer);\n\n        return block;\n    }\n\n    public static final byte[] getConfirmationMsg(Block block) {\n        final byte[] msg = new byte[HEADER_LENGTH + block.getBufferLength()];\n        final ByteBuffer blockBuffer = ByteBuffer.allocate(block.getBufferLength());\n        block.toBuffer(blockBuffer);\n        blockBuffer.flip();\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(CONFIRMATION.getBytes());\n\n        buffer.put(blockBuffer);\n\n        return msg;\n    }\n\n    public static final Block parseConfirmationMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final Block block = new Block();\n        block.fromBuffer(buffer);\n\n        return block;\n    }\n\n    public static final byte[] getResendBlockMsg(int blockNumber) {\n        final byte[] msg = new byte[HEADER_LENGTH + 4];\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(RESEND.getBytes());\n\n        buffer.putInt(blockNumber);\n\n        return msg;\n    }\n\n    public static final int parseResendBlockMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final int blockNumber = buffer.getInt();\n\n        return blockNumber;\n    }\n\n    public static final byte[] getRehashMsg(Block block) {\n        final byte[] msg = new byte[HEADER_LENGTH + block.getBufferLength()];\n        final ByteBuffer blockBuffer = ByteBuffer.allocate(block.getBufferLength());\n        block.toBuffer(blockBuffer);\n        blockBuffer.flip();\n\n        final ByteBuffer buffer = ByteBuffer.wrap(msg);\n        buffer.put(REHASH.getBytes());\n\n        buffer.put(blockBuffer);\n\n        return msg;\n    }\n\n    public static final Block parseRehashMsg(byte[] bytes) {\n        final ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        final byte [] bMsgType = new byte[HEADER_LENGTH];\n        buffer.get(bMsgType);\n\n        final Block block = new Block();\n        block.fromBuffer(buffer);\n\n        return block;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        final StringBuilder builder = new StringBuilder();\n        builder.append(\"name=\").append(myName);\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/ProofOfWork.java",
    "content": "package com.jwetherell.bitcoin;\n\nimport java.nio.ByteBuffer;\n\nimport com.jwetherell.bitcoin.Peer.MiningTask;\nimport com.jwetherell.bitcoin.common.HashUtils;\n\npublic class ProofOfWork {\n\n    private static final byte getBit(int ID, int position) {\n       return (byte) ((ID >> position) & (byte)1);\n    }\n\n    /** \n     * Given the sha256 hash, what number can we append to the hash which'll create a hash\n     * which has a leading 'numberOfZerosInPrefix' number of zeros.\n     * \n     * e.g.\n     * if numberOfZerosInPrefix == 3\n     * input = 7982970534e089b839957b7e174725ce1878731ed6d700766e59cb16f1c25e27\n     * solution = 0000fedb24e31adb71559d43a9a3ddc8be7606fa6befe3260b3eee2cf2aeb642\n     * output = 21080\n     * \n     **/\n    public static final int solve(MiningTask task, byte[] sha256, long numberOfZerosInPrefix) {\n        final int length = sha256.length;\n\n        final ByteBuffer buffer = ByteBuffer.allocate(length+4);\n        buffer.put(sha256, 0, length);\n\n        int x = 0;\n        while (task.run && x < Integer.MAX_VALUE) {\n            // append x\n            buffer.putInt(length, x);\n            // calculate new hash\n            final byte[] result = HashUtils.calculateSha256(buffer.array());\n            // wrap in buffer for easier processing\n            final ByteBuffer bb = ByteBuffer.wrap(result);\n\n            boolean wrong = false;\n            boolean done = false;\n            int numOfZeros = 0;\n            for (int i=0; i<bb.limit(); i++) {\n                final byte b = bb.get(i);\n                for (int j=0; j<8; j++) {\n                    final byte a = getBit(b,(i*8)+j);\n                    if (a == 0) {\n                        numOfZeros++;\n                    } else {\n                        wrong = true;\n                        break;\n                    }\n                    if (numOfZeros == numberOfZerosInPrefix) {\n                        done = true;\n                        break;\n                    }\n                }\n                if (done || wrong)\n                    break;\n            }\n            if (done)\n                break;\n            x++;\n        }\n        if (!task.run)\n            return Integer.MIN_VALUE;\n        return x;\n    }\n\n    /** Does the given nonce create a hash which starts with 'numberOfZerosInPrefix' number of zeros **/\n    public static final boolean check(byte[] sha256, int nonce, long numberOfZerosInPrefix) {\n        final int length = sha256.length;\n\n        final ByteBuffer buffer = ByteBuffer.allocate(length+4);\n        buffer.put(sha256, 0, length);\n\n        // append nonce\n        buffer.putInt(length, nonce);\n        // calculate new hash\n        final byte[] result = HashUtils.calculateSha256(buffer.array());\n        // wrap in buffer for easier processing\n        final ByteBuffer bb = ByteBuffer.wrap(result);\n\n        boolean incorrect = false;\n        boolean correct = false;\n        int numOfZeros = 0;\n        for (int i=0; i<bb.limit(); i++) {\n            final byte b = bb.get(i);\n            for (int j=0; j<8; j++) {\n                final byte a = getBit(b,(i*8)+j);\n                if (a == 0) {\n                    numOfZeros++;\n                } else {\n                    incorrect = true;\n                    break;\n                }\n                if (numOfZeros == numberOfZerosInPrefix) {\n                    correct = true;\n                    break;\n                }\n            }\n            if (correct || incorrect)\n                break;\n        }\n        return correct;\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/Wallet.java",
    "content": "package com.jwetherell.bitcoin;\n\nimport java.nio.ByteBuffer;\nimport java.security.KeyFactory;\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.PrivateKey;\nimport java.security.PublicKey;\nimport java.security.SecureRandom;\nimport java.security.Signature;\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.PriorityQueue;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport com.jwetherell.bitcoin.common.Constants;\nimport com.jwetherell.bitcoin.common.HashUtils;\nimport com.jwetherell.bitcoin.common.KeyUtils;\nimport com.jwetherell.bitcoin.data_model.Block;\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\n/**\n * Class which handles the logic of maintaining the wallet including tracking serial numbers and public/private key encryption.\n * \n * Thread-Safe (Hopefully)\n */\npublic class Wallet extends Peer {\n\n    protected final KeyPairGenerator                        gen;\n    protected final SecureRandom                            random;\n    protected final Signature                               enc;\n    protected final Signature                               dec;\n    protected final KeyPair                                 pair;\n    protected final PrivateKey                              privateKey;\n    protected final KeyFactory                              keyFactory;\n    protected final PublicKey                               publicKey;\n    protected final byte[]                                  bPublicKey;\n    { // initialize the private/public key associated with this wallet\n        try {\n            gen = KeyPairGenerator.getInstance(\"DSA\", \"SUN\");\n            random = SecureRandom.getInstance(\"SHA1PRNG\", \"SUN\");\n            gen.initialize(512, random);\n\n            enc = Signature.getInstance(\"SHA1withDSA\", \"SUN\");\n            dec = Signature.getInstance(\"SHA1withDSA\", \"SUN\");\n\n            pair = gen.generateKeyPair();\n            privateKey = pair.getPrivate();\n            enc.initSign(privateKey);\n\n            publicKey = pair.getPublic();\n            bPublicKey = publicKey.getEncoded();\n\n            keyFactory = KeyFactory.getInstance(\"DSA\", \"SUN\");\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    // Number of zeros in prefix of has to compute as the proof of work.\n    private static final int                                NUMBER_OF_ZEROS                 = 32;\n    // Number of transactions to aggregate in a Block\n    private static final int                                NUMBER_OF_TRANSACTIONS_IN_BLOCK = 1;\n    // Empty list\n    private static final Transaction[]                      EMPTY                           = new Transaction[0];\n    // Ranks Transactions by their value\n    private static final Comparator<Transaction>            TRANSACTION_COMPARATOR          = new Comparator<Transaction>() {\n        @Override\n        public int compare(Transaction o1, Transaction o2) {\n            // Higher value is processed quicker\n            if (o1.value > o2.value)\n                return -1;\n            if (o2.value > o1.value)\n                return 1;\n            return 0;\n        }\n    };\n\n    // Keep track of everyone's name -> public key\n    private final Map<String,ByteBuffer>                    publicKeys                      = new ConcurrentHashMap<String,ByteBuffer>();\n    // My BLockChain\n    private final Blockchain                                blockchain;\n    // Ranks transactions by their value to me \n    private final PriorityQueue<Transaction>                transactionQueue                = new PriorityQueue<Transaction>(10, TRANSACTION_COMPARATOR);\n\n    public Wallet(String name) {\n        super(name);\n        // add the initial pub key\n        this.publicKeys.put(Blockchain.NO_ONE, ByteBuffer.wrap(Blockchain.NO_ONE_PUB_KEY));\n        this.publicKeys.put(myName, ByteBuffer.wrap(bPublicKey));\n        // initialize the blockchain\n        this.blockchain = new Blockchain(name);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected byte[] getPublicKey() {\n        return bPublicKey;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public Blockchain getBlockChain() {\n        return blockchain;\n    }\n\n    public long getBalance() {\n        return blockchain.getBalance(myName);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected void newPublicKey(String name, byte[] publicKey) {\n        publicKeys.put(name, ByteBuffer.wrap(publicKey));\n    }\n\n    /**\n     * {@inheritDoc}\n     * \n     * synchronized to protect enc from changing while processing\n     */\n    @Override\n    protected synchronized byte[] signMsg(byte[] bytes) {\n        return KeyUtils.signMsg(enc, bytes);\n    }\n\n    /**\n     * {@inheritDoc}\n     * \n     * synchronized to protect keyfactory/dec from changing while processing\n     */\n    @Override\n    protected synchronized boolean verifyMsg(byte[] publicKey, byte[] signature, byte[] bytes) {\n        return KeyUtils.verifyMsg(keyFactory, dec, publicKey, signature, bytes);\n    }\n\n    // synchronized to protect the blockchain from changing while processing\n    public synchronized void sendCoin(String name, int value) {\n        // Iterate through the our unused transactions to see if we have enough coins\n        final List<Transaction> inputList = new ArrayList<Transaction>();\n        int coins = 0;\n        for (Transaction t : this.blockchain.getUnused()) {\n            if (!(t.to.equals(myName))) \n                continue;\n            coins += t.value;\n            inputList.add(t);\n            if (coins >= value)\n                break;\n        }\n        if (coins < value) {\n            System.err.println(myName+\" Sorry, you do not have enough coins.\");\n            return;\n        }\n        // Convert the list into an array\n        final Transaction[] inputs = new Transaction[inputList.size()];\n        for (int i=0; i<inputList.size(); i++)\n            inputs[i] = inputList.get(i);\n\n        // Since the entire input has to be used up, calculate if we will get any change left over\n        // and send it back to myself.\n        List<Transaction> outputList = new ArrayList<Transaction>();\n        if (coins > value) {\n            // I get some change back, so add myself as an output\n            final int myCoins = coins - value;\n            final String msg = \"I get some change back.\";\n            final Transaction t = Transaction.newSignedTransaction(enc, myName, myName, msg, myCoins, inputs, EMPTY);\n            outputList.add(t);\n        }\n        // Create the transaction for the recipient\n        final String msg = \"Here are some coins for you\";\n        final Transaction t = Transaction.newSignedTransaction(enc, myName, name, msg, value, inputs, EMPTY);\n        outputList.add(t);\n        // Convert the list into an array\n        final Transaction[] outputs = new Transaction[outputList.size()];\n        for (int i=0; i<outputList.size(); i++)\n            outputs[i] = outputList.get(i);\n\n        // Create the aggregate transaction, any value here will be a reward for the miner.\n        final String myMsg = value+\" from \"+myName+\" to \"+name;\n        final Transaction transaction = Transaction.newSignedTransaction(enc, myName, name, myMsg, 0, inputs, outputs);\n\n        super.sendTransaction(name, transaction);\n    }\n\n    /** make sure this message is from who it says it is **/\n    private Constants.Status checkSignature(String dataFrom, byte[] signature, byte[] bytes) {\n        if (!publicKeys.containsKey(dataFrom))\n            return Constants.Status.NO_PUBLIC_KEY;\n\n        final byte[] key = publicKeys.get(dataFrom).array();\n        if (!verifyMsg(key, signature, bytes))\n            return Constants.Status.BAD_SIGNATURE;\n\n        return Constants.Status.SUCCESS;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected Constants.Status handleTransaction(String dataFrom, Transaction transaction, byte[] signature, byte[] bytes) {\n        final Constants.Status status = checkSignature(dataFrom, signature, bytes);\n        if (status != Constants.Status.SUCCESS) {\n            if (DEBUG)\n                System.err.println(myName+\" handleTransaction() from '\"+dataFrom+\"' status=\"+status+\"\\n\"+\"transaction={\\n\"+transaction.toString()+\"\\n}\");\n            return status;\n        }\n\n        return Constants.Status.SUCCESS;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected Constants.Status handleTransactionAck(String dataFrom, Transaction transaction, byte[] signature, byte[] bytes) {\n        final Constants.Status status = checkSignature(dataFrom, signature, bytes);\n        if (status != Constants.Status.SUCCESS) {\n            if (DEBUG)\n                System.err.println(myName+\" handleTransactionAck() from '\"+dataFrom+\"' status=\"+status+\"\\n\"+\"transaction={\\n\"+transaction.toString()+\"\\n}\");\n            return status;\n        }\n\n        return Constants.Status.SUCCESS;\n    }\n\n    /** Create a block given the these Transactions **/\n    private Block getNextBlock(Transaction[] transactions) {\n        Block trans = blockchain.getNextBlock(myName, transactions);\n        // Need to be confirmed\n        trans.confirmed = false;\n        // Number of zeros in prefix of hash to compute\n        trans.numberOfZeros = NUMBER_OF_ZEROS;\n        return trans;\n    }\n\n    /**\n     * {@inheritDoc}\n     * \n     * synchronized to protected queue from changing while processing\n     */\n    @Override\n    protected synchronized Block aggegateTransaction(Transaction transaction) {\n        transactionQueue.add(transaction);\n        if (transactionQueue.size() >= NUMBER_OF_TRANSACTIONS_IN_BLOCK) {\n            Transaction[] transactions = new Transaction[NUMBER_OF_TRANSACTIONS_IN_BLOCK];\n            for (int i=0; i<NUMBER_OF_TRANSACTIONS_IN_BLOCK; i++) {\n                final Transaction t = transactionQueue.poll();\n                transactions[i] = t;\n            }\n            final Block block = getNextBlock(transactions);\n            return block;\n        }\n        return null;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected Constants.Status checkTransaction(String dataFrom, Block block, byte[] signature, byte[] bytes) {\n        final Constants.Status status = checkSignature(dataFrom, signature, bytes);\n        if (status != Constants.Status.SUCCESS) {\n            if (DEBUG)\n                System.err.println(myName+\" checkTransaction() from '\"+dataFrom+\"' status=\"+status+\"\\n\"+\"block={\\n\"+block.toString()+\"\\n}\\n\");\n            return status;\n        }\n\n        return blockchain.checkHash(block);\n    }\n\n    /**\n     * {@inheritDoc}\n     * \n     * synchronized to protect the blockchain from changing while processing\n     */\n    @Override\n    protected synchronized Constants.Status handleConfirmation(String dataFrom, Block block, byte[] signature, byte[] bytes) {\n        // Let's see if the nonce was computed correctly\n        final boolean nonceComputedCorrectly = ProofOfWork.check(block.hash, (int)block.nonce, block.numberOfZeros);\n        if (!nonceComputedCorrectly) {\n            if (DEBUG)\n                System.err.println(myName+\" handleConfirmation() from '\"+dataFrom+\"' Nonce was not computed correctly. block={\\n\"+block.toString()+\"\\n}\");\n            return Constants.Status.INCORRECT_NONCE;\n        }\n\n        // Check signature on the block\n        final Constants.Status status = checkSignature(dataFrom, signature, bytes);\n        if (status != Constants.Status.SUCCESS) {\n            if (DEBUG)\n                System.err.println(myName+\" handleConfirmation() from '\"+dataFrom+\"' status=\"+status+\"\\n\"+\"block={\\n\"+block.toString()+\"\\n}\\n\");\n            return status;\n        }\n\n        for (Transaction trans : block.transactions) {\n        // Check signature on the aggregate transaction and it's inputs/outputs\n            { // Check aggregate transaction\n                final String transactionFrom = trans.from;\n                final byte[] transactionSignature = trans.signature.array();\n                final byte[] transactionBytes = trans.header.getBytes();\n                final Constants.Status transactionStatus = checkSignature(transactionFrom, transactionSignature, transactionBytes);\n                if (transactionStatus != Constants.Status.SUCCESS) {\n                    if (DEBUG)\n                        System.err.println(myName+\" handleConfirmation() from '\"+dataFrom+\"' status=\"+transactionStatus+\"\\n\"+\"transaction={\\n\"+trans.toString()+\"\\n}\\n\");\n                    return status;\n                }\n            }\n\n            { // check signature on inputs\n                for (Transaction i : trans.inputs) {\n                    final String iFrom = i.from;\n                    final byte[] iSignature = i.signature.array();\n                    final byte[] iBytes = i.header.getBytes();\n                    final Constants.Status iStatus = checkSignature(iFrom, iSignature, iBytes);\n                    if (iStatus != Constants.Status.SUCCESS) {\n                        if (DEBUG)\n                            System.err.println(myName+\" handleConfirmation() from '\"+dataFrom+\"' status=\"+iStatus+\"\\n\"+\"transaction={\\n\"+i.toString()+\"\\n}\\n\");\n                        return status;\n                    }\n                }\n            }\n            { // check signature on outputs\n                for (Transaction o : trans.outputs) {\n                    final String oFrom = o.from;\n                    final byte[] oSignature = o.signature.array();\n                    final byte[] oBytes = o.header.getBytes();\n                    final Constants.Status oStatus = checkSignature(oFrom, oSignature, oBytes);\n                    if (oStatus != Constants.Status.SUCCESS) {\n                        if (DEBUG)\n                            System.err.println(myName+\" handleConfirmation() from '\"+dataFrom+\"' status=\"+oStatus+\"\\n\"+\"transaction={\\n\"+o.toString()+\"\\n}\\n\");\n                        return status;\n                    }\n                }\n            }\n        }\n\n        // Everything looks good to me, try and add to blockchain\n        return blockchain.addBlock(dataFrom, block);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    protected int mineHash(MiningTask task, byte[] sha256, long numberOfZerosInPrefix) {\n        final int nonce = ProofOfWork.solve(task, sha256, numberOfZerosInPrefix);\n        if (DEBUG) {\n            String status = \"CANCELLED\";\n            if (nonce >= 0)\n                status = \"SOLVED\";\n            System.err.println(myName+\" mineHash() \"+status+\". nonce=\"+nonce+\"\\n\"+\"sha256=[\"+HashUtils.bytesToHex(sha256)+\"]\\n\");\n        }\n        return nonce;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        final StringBuilder builder = new StringBuilder();\n        builder.append(super.toString()).append(\" blockChain={\").append(blockchain.toString()).append(\"}\");\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/common/Constants.java",
    "content": "package com.jwetherell.bitcoin.common;\n\npublic abstract class Constants {\n\n    public static enum  Status {    \n                                    OWN_TRANSACTION, \n                                    NO_PUBLIC_KEY, \n                                    INCORRECT_NONCE, \n                                    FUTURE_BLOCK, \n                                    BAD_HASH, \n                                    BAD_SIGNATURE, \n                                    BAD_INPUTS, \n                                    DUPLICATE, \n                                    SUCCESS, \n                                    UNKNOWN\n   };\n\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/common/HashUtils.java",
    "content": "package com.jwetherell.bitcoin.common;\n\nimport java.io.UnsupportedEncodingException;\nimport java.security.MessageDigest;\n\npublic abstract class HashUtils {\n\n    public static final byte[] calculateSha256(String text) {\n        byte[] hash2;\n        try {\n            hash2 = calculateSha256(text.getBytes(\"UTF-8\"));\n        } catch (UnsupportedEncodingException e) {\n            throw new RuntimeException(e);\n        }\n        return hash2;\n    }\n\n    public static final byte[] calculateSha256(byte[] utf8Bytes) {\n        byte[] hash2;\n        try {\n            final MessageDigest digest = MessageDigest.getInstance(\"SHA-256\");\n            final byte[] hash1 = digest.digest(utf8Bytes);\n            hash2 = digest.digest(hash1);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n        return hash2;\n    }\n\n    public static final String bytesToHex(byte[] bytes) {\n        final StringBuilder result = new StringBuilder();\n        for (byte byt : bytes) \n            result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1));\n        return result.toString();\n    }\n\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/common/KeyUtils.java",
    "content": "package com.jwetherell.bitcoin.common;\n\nimport java.security.KeyFactory;\nimport java.security.PublicKey;\nimport java.security.Signature;\nimport java.security.spec.X509EncodedKeySpec;\n\npublic abstract class KeyUtils {\n\n    public static final byte[] signMsg(Signature enc, byte[] bytes) {\n        byte[] signed = null;\n        try {\n            enc.update(bytes);\n            signed = enc.sign();\n        } catch (Exception e) {\n            System.err.println(\"Could not encode msg. \"+e);\n        }\n        return signed;\n    }\n\n    public static final boolean verifyMsg(KeyFactory keyFactory, Signature dec, byte[] publicKey, byte[] signature, byte[] bytes) {\n        boolean verified = false;\n        try {\n            PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));\n            dec.initVerify(key);\n            dec.update(bytes);\n            verified = dec.verify(signature);\n        } catch (Exception e) {\n            System.err.println(\"Could not decode msg. \"+e);\n        }\n        return verified;\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/data_model/Block.java",
    "content": "package com.jwetherell.bitcoin.data_model;\n\nimport java.nio.ByteBuffer;\nimport java.util.Arrays;\n\nimport com.jwetherell.bitcoin.common.HashUtils;\n\npublic class Block {\n\n    private static final int    FROM_LENGTH             = 4;\n    private static final int    BOOLEAN_LENGTH          = 2;\n    private static final int    NUM_OF_ZEROS_LENGTH     = 4;\n    private static final int    NONCE_LENGTH            = 4;\n    private static final int    BLOCK_LENGTH            = 4;\n    private static final int    LENGTH_LENGTH           = 4;\n\n    public String               from;\n    public boolean              confirmed               = false;\n    public int                  numberOfZeros;\n    public int                  nonce;\n    public int                  blockLength;\n    public Transaction[]        transactions;\n    public byte[]               prev;\n    public byte[]               hash;\n\n    public Block() { }\n\n    public Block(String from, byte[] prevHash, byte[] hash, Transaction[] transactions, int blockLength) {\n        this.from = from;\n        this.prev = prevHash;\n        this.hash = hash;\n        this.transactions = transactions;\n        this.blockLength = blockLength;\n    }\n\n    public int getBufferLength() {\n        int transactionsLength = 0;\n        for (Transaction t : transactions)\n            transactionsLength += LENGTH_LENGTH + t.getBufferLength();\n        return  FROM_LENGTH + from.length() +\n                BOOLEAN_LENGTH + \n                NUM_OF_ZEROS_LENGTH +\n                NONCE_LENGTH +\n                BLOCK_LENGTH +\n                LENGTH_LENGTH + prev.length + \n                LENGTH_LENGTH + hash.length + \n                LENGTH_LENGTH + transactionsLength;\n    }\n\n    public void toBuffer(ByteBuffer buffer) {\n        final byte[] fBytes = from.getBytes();\n        buffer.putInt(fBytes.length);\n        buffer.put(fBytes);\n        \n        buffer.putChar(getBoolean(confirmed));\n        buffer.putInt(numberOfZeros);\n        buffer.putInt(nonce);\n        buffer.putInt(blockLength);\n\n        buffer.putInt(prev.length);\n        buffer.put(prev);\n\n        buffer.putInt(hash.length);\n        buffer.put(hash);\n\n        buffer.putInt(transactions.length);\n        for (Transaction t : transactions) {\n            buffer.putInt(t.getBufferLength());\n            t.toBuffer(buffer);\n        }\n    }\n\n    public void fromBuffer(ByteBuffer buffer) {\n        final int fLength = buffer.getInt();\n        final byte[] fBytes = new byte[fLength];\n        buffer.get(fBytes, 0, fLength);\n        from = new String(fBytes);\n\n        confirmed = parseBoolean(buffer.getChar());\n        numberOfZeros = buffer.getInt();\n        nonce = buffer.getInt();\n        blockLength = buffer.getInt();\n\n        { // previous hash\n            final int length = buffer.getInt();\n            prev = new byte[length];\n            buffer.get(prev);\n        }\n\n        { // next hash\n            final int length = buffer.getInt();\n            hash = new byte[length];\n            buffer.get(hash);\n        }\n\n        int tLength = buffer.getInt();\n        transactions =  new Transaction[tLength];\n        for (int i=0; i < tLength; i++) {\n            int length = buffer.getInt();\n            final byte[] bytes = new byte[length];\n            buffer.get(bytes);\n            final ByteBuffer bb = ByteBuffer.wrap(bytes);\n            final Transaction t = new Transaction();\n            t.fromBuffer(bb);\n            transactions[i] = t;\n        }\n    }\n\n    private static final char getBoolean(boolean bool) {\n        return (bool?'T':'F');\n    }\n\n    private static final boolean parseBoolean(char bool) {\n        return (bool=='T'?true:false);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int hashCode() {\n        int hashCode = 0;\n        hashCode += from.length();\n        if (confirmed)\n            hashCode += 1;\n        hashCode += nonce;\n        hashCode += blockLength;\n        hashCode += numberOfZeros;\n        hashCode += transactions.length;\n        for (Transaction t : transactions)\n            hashCode += t.hashCode();\n        for (byte b : prev)\n            hashCode += b;\n        for (byte b : hash)\n            hashCode += b;\n        return 31 * hashCode;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof Block))\n            return false;\n        Block c = (Block) o;\n        if (!(c.from.equals(from)))\n            return false;\n        if (confirmed != c.confirmed)\n            return false;\n        if (nonce != c.nonce)\n            return false;\n        if (blockLength != c.blockLength)\n            return false;\n        if (numberOfZeros != c.numberOfZeros)\n            return false;\n        if (c.transactions.length != this.transactions.length)\n            return false;\n        { // compare transactions\n            for (int i=0; i<c.transactions.length; i++) {\n                if (!(c.transactions[i].equals(this.transactions[i])))\n                    return false;\n            }\n        }\n        if (!(Arrays.equals(c.prev, prev)))\n            return false;\n        if (!(Arrays.equals(c.hash, hash)))\n            return false;\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        StringBuilder builder = new StringBuilder();\n        builder.append(\"isValid=\").append(confirmed).append(\"\\n\");\n        builder.append(\"numberOfZerosToCompute=\").append(numberOfZeros).append(\"\\n\");\n        builder.append(\"nonce=\").append(nonce).append(\"\\n\");\n        builder.append(\"blockLength=\").append(blockLength).append(\"\\n\");\n        builder.append(\"prev=[\").append(HashUtils.bytesToHex(prev)).append(\"]\\n\");\n        builder.append(\"hash=[\").append(HashUtils.bytesToHex(hash)).append(\"]\\n\");\n        builder.append(\"block={\").append(\"\\n\");\n        for (Transaction t : transactions) {\n            builder.append(\"transaction={\").append(\"\\n\");\n            builder.append(t.toString()).append(\"\\n\");\n            builder.append(\"}\").append(\"\\n\");\n        }\n        builder.append(\"}\");\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/data_model/Data.java",
    "content": "package com.jwetherell.bitcoin.data_model;\n\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.nio.ByteBuffer;\nimport java.util.Arrays;\n\npublic class Data {\n\n    private static final int    LENGTH_LENGTH   = 4;\n    private static final int    FROM_LENGTH     = 4;\n    private static final int    TO_LENGTH       = 4;\n\n    public String               from;\n    public String               to;\n    public InetAddress          sourceAddr;\n    public int                  sourcePort;\n    public InetAddress          destAddr;\n    public int                  destPort;\n    public ByteBuffer           signature;\n    public ByteBuffer           message;\n\n    public Data() { }\n\n    public Data(String from, String sourceAddr, int sourcePort, \n                String to, String destAddr, int destPort, \n                byte[] signature, byte[] bytes) {\n        this.from = from;\n        this.to = to;\n        try {\n            this.sourceAddr = InetAddress.getByName(sourceAddr);\n            this.destAddr = InetAddress.getByName(destAddr);\n        } catch (UnknownHostException e) {\n            throw new RuntimeException(e);\n        }\n        this.sourcePort = sourcePort;\n        this.destPort = destPort;\n\n        this.signature = ByteBuffer.allocate(signature.length);\n        this.signature.put(signature);\n        this.signature.flip();\n\n        this.message = ByteBuffer.allocate(bytes.length);\n        this.message.put(bytes);\n        this.message.flip();\n    }\n\n    public int getBufferLength() {\n        return  FROM_LENGTH + from.getBytes().length +\n                TO_LENGTH + to.getBytes().length +\n                LENGTH_LENGTH + sourceAddr.getHostAddress().getBytes().length + \n                LENGTH_LENGTH + String.valueOf(sourcePort).getBytes().length + \n                LENGTH_LENGTH + destAddr.getHostAddress().getBytes().length + \n                LENGTH_LENGTH + String.valueOf(destPort).getBytes().length + \n                LENGTH_LENGTH + signature.limit() +\n                LENGTH_LENGTH + message.limit();\n    }\n\n    public void toBuffer(ByteBuffer buffer) {\n        final byte[] fBytes = from.getBytes();\n        buffer.putInt(fBytes.length);\n        buffer.put(fBytes);\n\n        final byte[] oBytes = to.getBytes();\n        buffer.putInt(oBytes.length);\n        buffer.put(oBytes);\n\n        { // Source\n            final byte[] hBytes = sourceAddr.getHostAddress().getBytes();\n            final int hLength = hBytes.length;\n            buffer.putInt(hLength);\n            buffer.put(hBytes);\n    \n            final byte[] pBytes = String.valueOf(sourcePort).getBytes();\n            final int pLength = pBytes.length;\n            buffer.putInt(pLength);\n            buffer.put(pBytes);\n        }\n\n        { // Destination\n            final byte[] hBytes = destAddr.getHostAddress().getBytes();\n            final int hLength = hBytes.length;\n            buffer.putInt(hLength);\n            buffer.put(hBytes);\n    \n            final byte[] pBytes = String.valueOf(destPort).getBytes();\n            final int pLength = pBytes.length;\n            buffer.putInt(pLength);\n            buffer.put(pBytes);\n        }\n\n        // Sig\n        buffer.putInt(signature.limit());\n        buffer.put(signature);\n\n        // Data\n        buffer.putInt(message.limit());\n        buffer.put(message);\n    }\n\n    public void fromBuffer(ByteBuffer buffer) {\n        final int fLength = buffer.getInt();\n        final byte[] fBytes = new byte[fLength];\n        buffer.get(fBytes, 0, fLength);\n        from = new String(fBytes);\n\n        final int oLength = buffer.getInt();\n        final byte[] oBytes = new byte[oLength];\n        buffer.get(oBytes, 0, oLength);\n        to = new String(oBytes);\n\n        { // Source\n            final int hLength = buffer.getInt();\n            final byte[] hostBytes = new byte[hLength];\n            buffer.get(hostBytes);\n            final String sHost = new String(hostBytes);\n            try {\n                this.sourceAddr = InetAddress.getByName(sHost);\n            } catch (UnknownHostException e) {\n                throw new RuntimeException(e);\n            }\n    \n            final int pLength = buffer.getInt();\n            final byte[] portBytes = new byte[pLength];\n            buffer.get(portBytes);\n            final String sPort = new String(portBytes);\n            this.sourcePort = Integer.parseInt(sPort);\n        }\n\n        { // Destination\n            final int hLength = buffer.getInt();\n            final byte[] hostBytes = new byte[hLength];\n            buffer.get(hostBytes);\n            final String sHost = new String(hostBytes);\n            try {\n                this.destAddr = InetAddress.getByName(sHost);\n            } catch (UnknownHostException e) {\n                throw new RuntimeException(e);\n            }\n    \n            final int pLength = buffer.getInt();\n            final byte[] portBytes = new byte[pLength];\n            buffer.get(portBytes);\n            final String sPort = new String(portBytes);\n            this.destPort = Integer.parseInt(sPort);\n        }\n\n        // Sig\n        final int sLength = buffer.getInt();\n        final byte[] sBytes = new byte[sLength];\n        buffer.get(sBytes, 0, sLength);\n        this.signature = ByteBuffer.allocate(sBytes.length);\n        this.signature.put(sBytes);\n\n        // Data\n        final int dLength = buffer.getInt();\n        final byte[] dBytes = new byte[dLength];\n        buffer.get(dBytes, 0, dLength);\n        this.message = ByteBuffer.allocate(dBytes.length);\n        this.message.put(dBytes);\n\n        this.message.flip();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof Data))\n            return false;\n        Data d = (Data) o;\n        if (!(d.from.equals(this.from)))\n            return false;\n        if (!(d.to.equals(this.to)))\n            return false;\n        if (!(sourceAddr.equals(d.sourceAddr)))\n            return false;\n        if (sourcePort != d.sourcePort)\n            return false;\n        if (!(destAddr.equals(d.destAddr)))\n            return false;\n        if (destPort != d.destPort)\n            return false;\n        if (!(Arrays.equals(this.signature.array(), d.signature.array())))\n            return false;\n        if (!(Arrays.equals(this.message.array(), d.message.array())))\n            return false;\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        StringBuilder builder = new StringBuilder();\n        builder.append(\"from='\").append(from).append(\"'\\n\");\n        builder.append(\"source=\").append(sourceAddr.getHostAddress()).append(\":\").append(sourcePort).append(\"\\n\");\n        builder.append(\"to='\").append(to).append(\"'\\n\");\n        builder.append(\"destination=\").append(destAddr.getHostAddress()).append(\":\").append(destPort).append(\"\\n\");\n        builder.append(\"data=\").append(new String(message.array()));\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/data_model/Transaction.java",
    "content": "package com.jwetherell.bitcoin.data_model;\n\nimport java.nio.ByteBuffer;\nimport java.security.Signature;\nimport java.util.Arrays;\n\nimport com.jwetherell.bitcoin.common.HashUtils;\nimport com.jwetherell.bitcoin.common.KeyUtils;\n\npublic class Transaction {\n\n    private static final int    FROM_LENGTH         = 4;\n    private static final int    TO_LENGTH           = 4;\n    private static final int    TIMESTAMP_LENGTH    = 8;\n    private static final int    HEADER_LENGTH       = 4;\n    private static final int    VALUE_LENGTH        = 4;\n    private static final int    LENGTH_LENGTH       = 4;\n\n    public String               from;\n    public String               to;\n    public long                 timestamp;\n    public String               header;\n    public int                  value;\n    public ByteBuffer           signature;\n\n    public Transaction[]        inputs;\n    public Transaction[]        outputs;\n\n    public Transaction() { }\n\n    public Transaction(String from, String to, String header, int value, byte[] signature, Transaction[] inputs, Transaction[] outputs) {\n        this.from = from;\n        this.to = to;\n        this.timestamp = 0;\n        this.header = header;\n        this.value = value;\n        final byte[] sig = new byte[signature.length];\n        System.arraycopy(signature, 0, sig, 0, signature.length);\n        this.signature = ByteBuffer.wrap(sig);\n\n        this.inputs = new Transaction[inputs.length];\n        for (int i=0; i<inputs.length; i++)\n            this.inputs[i] = inputs[i];\n\n        this.outputs = new Transaction[outputs.length];\n        for (int i=0; i<outputs.length; i++)\n            this.outputs[i] = outputs[i];\n    }\n\n    /** Create the aggregate Transaction and sign it **/\n    public static final Transaction newSignedTransaction(Signature signature, \n                                                         String from, String to, \n                                                         String header, int value, \n                                                         Transaction[] inputs, Transaction[] outputs)\n    {\n        final byte[] sig = KeyUtils.signMsg(signature, header.getBytes());\n        Transaction transaction = new Transaction(from, to, header, value, sig, inputs, outputs);\n        return transaction;\n    }\n\n    public void updateTimestamp() {\n        this.timestamp = System.currentTimeMillis();\n    }\n\n    public int getBufferLength() {\n        int iLength = 0;\n        for (Transaction t : inputs)\n            iLength += LENGTH_LENGTH + t.getBufferLength();\n\n        int oLength = 0;\n        for (Transaction t : outputs)\n            oLength += LENGTH_LENGTH + t.getBufferLength();\n\n        int length =    LENGTH_LENGTH + signature.limit() +\n                        LENGTH_LENGTH + iLength +\n                        LENGTH_LENGTH + oLength +\n                        TIMESTAMP_LENGTH +\n                        VALUE_LENGTH +\n                        HEADER_LENGTH + header.getBytes().length + \n                        FROM_LENGTH + from.getBytes().length + \n                        TO_LENGTH + to.getBytes().length;\n        return length;\n    }\n\n    public void toBuffer(ByteBuffer buffer) {\n        { // signature\n            buffer.putInt(signature.limit());\n            buffer.put(signature);\n            signature.flip();\n        }\n\n        { // inputs\n            buffer.putInt(inputs.length);\n            for (Transaction t : inputs) {\n                buffer.putInt(t.getBufferLength());\n                t.toBuffer(buffer);\n                // do not flip buffer here\n            }\n        }\n\n        { // outputs\n            buffer.putInt(outputs.length);\n            for (Transaction t : outputs) {\n                buffer.putInt(t.getBufferLength());\n                t.toBuffer(buffer);\n                // do not flip buffer here\n            }\n        }\n\n        buffer.putLong(timestamp);\n        buffer.putInt(value);\n\n        final int mLength = header.length();\n        buffer.putInt(mLength);\n        final byte[] mBytes = header.getBytes();\n        buffer.put(mBytes);\n\n        final byte[] fBytes = from.getBytes();\n        buffer.putInt(fBytes.length);\n        buffer.put(fBytes);\n\n        final byte[] oBytes = to.getBytes();\n        buffer.putInt(oBytes.length);\n        buffer.put(oBytes);\n    }\n\n    public void fromBuffer(ByteBuffer buffer) {\n        { // signature\n            int sLength = buffer.getInt();\n            byte[] bSignature = new byte[sLength];\n            buffer.get(bSignature);\n            this.signature = ByteBuffer.wrap(bSignature);\n        }\n\n        { // inputs\n            int iLength = buffer.getInt();\n            this.inputs = new Transaction[iLength];\n            for (int i=0; i<iLength; i++) {\n                int tLength = buffer.getInt();\n                Transaction t = new Transaction();\n                final byte[] bytes = new byte[tLength];\n                buffer.get(bytes);\n                ByteBuffer bb = ByteBuffer.wrap(bytes);\n                t.fromBuffer(bb);\n                this.inputs[i] = t;\n            }\n        }\n\n        { // ouputs\n            int oLength = buffer.getInt();\n            this.outputs = new Transaction[oLength];\n            for (int i=0; i<oLength; i++) {\n                int tLength = buffer.getInt();\n                Transaction t = new Transaction();\n                final byte[] bytes = new byte[tLength];\n                buffer.get(bytes);\n                ByteBuffer bb = ByteBuffer.wrap(bytes);\n                t.fromBuffer(bb);\n                this.outputs[i] = t;\n            }\n        }\n\n        timestamp = buffer.getLong();\n        value = buffer.getInt();\n\n        final int mLength = buffer.getInt();\n        final byte[] mBytes = new byte[mLength];\n        buffer.get(mBytes, 0, mLength);\n        header = new String(mBytes);\n\n        final int fLength = buffer.getInt();\n        final byte[] fBytes = new byte[fLength];\n        buffer.get(fBytes, 0, fLength);\n        from = new String(fBytes);\n\n        final int tLength = buffer.getInt();\n        final byte[] tBytes = new byte[tLength];\n        buffer.get(tBytes, 0, tLength);\n        to = new String(tBytes);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public int hashCode() {\n        int hashCode = 0;\n        hashCode += from.length();\n        hashCode += to.length();\n        hashCode += timestamp;\n        hashCode += header.length();\n        hashCode += value;\n        for (byte b :signature.array())\n            hashCode += b;\n        for (Transaction t : inputs)\n            hashCode += t.hashCode();\n        for (Transaction t : outputs)\n            hashCode += t.hashCode();\n        return 31 * hashCode;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public boolean equals(Object o) {\n        if (!(o instanceof Transaction))\n            return false;\n        Transaction c = (Transaction) o;\n        { // signature\n            if (c.signature.limit() != this.signature.limit())\n                return false;\n            if (!(Arrays.equals(c.signature.array(), this.signature.array())))\n                return false;\n        }\n        { // inputs\n            if (c.inputs.length != this.inputs.length)\n                return false;\n            for (int i=0; i<c.inputs.length; i++)\n                if (!(c.inputs[i].equals(inputs[i])))\n                    return false;\n        }\n        { // ouputs\n            if (c.outputs.length != this.outputs.length)\n                return false;\n            for (int i=0; i<c.outputs.length; i++)\n                if (!(c.outputs[i].equals(outputs[i])))\n                    return false;\n        }\n        if (c.timestamp != this.timestamp)\n            return false;\n        if (c.value != this.value)\n            return false;\n        if (!(c.from.equals(this.from)))\n            return false;\n        if (!(c.to.equals(this.to)))\n            return false;\n        if (!(c.header.equals(this.header)))\n            return false;\n        return true;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public String toString() {\n        StringBuilder builder = new StringBuilder();\n        builder.append(\"signature=[\").append(HashUtils.bytesToHex(this.signature.array())).append(\"]\\n\");\n        builder.append(\"inputs=\").append(inputs.length).append(\"\\n\");\n        builder.append(\"outputs=\").append(outputs.length).append(\"\\n\");\n        builder.append(\"time='\").append(timestamp).append(\"'\\n\");\n        builder.append(\"value='\").append(value).append(\"'\\n\");\n        builder.append(\"from='\").append(from).append(\"'\\n\");\n        builder.append(\"to='\").append(to).append(\"'\\n\");\n        builder.append(\"header=[\").append(header).append(\"]\");\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/interfaces/MessageListener.java",
    "content": "package com.jwetherell.bitcoin.interfaces;\n\npublic interface MessageListener {\n\n    public void onMessage(Receiver recv);\n\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/interfaces/Receiver.java",
    "content": "package com.jwetherell.bitcoin.interfaces;\n\nimport java.util.Queue;\n\nimport com.jwetherell.bitcoin.data_model.Data;\n\npublic interface Receiver {\n\n    public Queue<Data> getQueue();\n\n    public boolean isReady();\n\n    public String getHost();\n\n    public int getPort();\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/interfaces/Sender.java",
    "content": "package com.jwetherell.bitcoin.interfaces;\n\nimport java.util.Queue;\n\nimport com.jwetherell.bitcoin.data_model.Data;\n\npublic interface Sender {\n\n    public Queue<Data> getQueue();\n\n    public boolean isReady();\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/networking/Multicast.java",
    "content": "package com.jwetherell.bitcoin.networking;\n\nimport java.io.IOException;\nimport java.net.DatagramPacket;\nimport java.net.InetAddress;\nimport java.net.MulticastSocket;\nimport java.net.SocketException;\nimport java.net.SocketTimeoutException;\nimport java.net.UnknownHostException;\nimport java.nio.ByteBuffer;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.interfaces.Sender;\n\npublic class Multicast {\n\n    private static final boolean    DEBUG       = Boolean.getBoolean(\"debug_all\");\n\n    public static final int         PORT        = 5000;\n    public static final String      GROUP       = \"225.4.5.6\";\n\n    public static MulticastSocket createReceiver() throws IOException {\n        // Create the socket and bind it to port 'port'.\n        final MulticastSocket s = new MulticastSocket(PORT);\n        // join the multicast group\n        s.joinGroup(InetAddress.getByName(GROUP));\n        // Now the socket is set up and we are ready to receive packets\n        return s;\n    }\n\n    public static void destoryReceiver(MulticastSocket s) throws UnknownHostException, IOException {\n        if (s == null)\n            return;\n\n        // Leave the multicast group and close the socket\n        s.leaveGroup(InetAddress.getByName(GROUP));\n        s.close();\n    }\n\n    /**\n     * Blocking call\n     */\n    public static boolean recvData(MulticastSocket s, byte[] buffer) throws IOException {\n        s.setSoTimeout(100);\n        // Create a DatagramPacket and do a receive\n        final DatagramPacket pack = new DatagramPacket(buffer, buffer.length);\n        try {\n            s.receive(pack);\n        } catch (SocketTimeoutException e) {\n            return false;\n        }\n        // We have finished receiving data\n        return true;\n    }\n\n    public static MulticastSocket createSender() throws IOException {\n        // Create the socket but we don't bind it as we are only going to send data\n        final MulticastSocket s = new MulticastSocket();\n        // Note that we don't have to join the multicast group if we are only\n        // sending data and not receiving\n        return s;\n    }\n\n    public static void destroySender(MulticastSocket s) throws IOException {\n        if (s == null)\n            return;\n\n        // When we have finished sending data close the socket\n        s.close();\n    }\n\n    public static void sendData(MulticastSocket s, int ourTTL, byte[] buffer) throws IOException {\n        // Create a DatagramPacket \n        final DatagramPacket pack = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(GROUP), PORT);\n        // Get the current TTL, set our TTL, do a send, reset the TTL  \n        final int ttl = s.getTimeToLive(); \n        s.setTimeToLive(ourTTL); \n        s.send(pack); \n        s.setTimeToLive(ttl);\n    }\n\n    public static final class Peer {\n\n        private static final int BUFFER_SIZE = 10*1024;\n\n        public static final class RunnableRecv implements Runnable, Receiver {\n\n            public static volatile boolean                      run         = true;\n\n            private final ConcurrentLinkedQueue<Data>           toRecv      = new ConcurrentLinkedQueue<Data>();\n            private final MessageListener                       listener;\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableRecv(MessageListener listener) {\n                run = true;\n                this.listener = listener;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toRecv;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public String getHost() {\n                return GROUP;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public int getPort() {\n                return PORT;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                MulticastSocket s = null;\n                try {\n                    if (DEBUG)\n                        System.out.println(\"Creating receiver\");\n                    s = Multicast.createReceiver();\n                    final byte[] array = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(array);\n                    isReady = true;\n                    while (run) {\n                        bb.clear();\n                        final boolean p = Multicast.recvData(s, array);\n                        if (!p) {\n                            Thread.yield();\n                            continue;\n                        }\n\n                        final Data data = new Data();\n                        data.fromBuffer(bb);\n\n                        if (DEBUG)\n                            System.out.println(\"Server received '\"+new String(data.message.array())+\"' from \"+data.sourceAddr.getHostAddress()+\":\"+data.sourcePort);\n\n                        toRecv.add(data);\n                        listener.onMessage(this);\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally {\n                    try {\n                        Multicast.destoryReceiver(s);\n                    } catch (UnknownHostException e) {\n                        e.printStackTrace();\n                    } catch (IOException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        };\n\n        public static final class RunnableSend implements Runnable, Sender {\n\n            private static final int                            ttl         = 1;\n\n            public static volatile boolean                      run         = true;\n\n            public final ConcurrentLinkedQueue<Data>            toSend      = new ConcurrentLinkedQueue<Data>();\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableSend() {\n                run = true;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toSend;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                MulticastSocket s = null;\n                try {\n                    if (DEBUG)\n                        System.out.println(\"Creating sender\");\n                    s = Multicast.createSender();\n                    final byte[] buffer = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(buffer);\n                    isReady = true;\n                    while (run) {\n                        if (DEBUG && toSend.size()>1)\n                            System.out.println(\"Client toSend size=\"+toSend.size());\n                        final Data d = toSend.poll();\n                        if (d != null) {\n                            bb.clear();\n                            d.toBuffer(bb);\n                            bb.flip();\n\n                            if (DEBUG)\n                                System.out.println(\"Client (\"+d.sourceAddr.getHostAddress()+\":\"+d.sourcePort+\") sending '\"+new String(d.message.array())+\"'\");\n\n                            Multicast.sendData(s, ttl, buffer);\n                        }\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally {\n                    try {\n                        Multicast.destroySender(s);\n                    } catch (IOException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/networking/TCP.java",
    "content": "package com.jwetherell.bitcoin.networking;\n\nimport java.io.DataOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.ServerSocket;\nimport java.net.Socket;\nimport java.net.SocketException;\nimport java.net.SocketTimeoutException;\nimport java.nio.ByteBuffer;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.interfaces.Sender;\n\npublic class TCP {\n\n    private static final boolean    DEBUG       = Boolean.getBoolean(\"debug_all\");\n\n    public static final String      LOCAL       = \"127.0.0.1\";\n\n    public static int               port        = 2221;\n\n    public static ServerSocket createServer(int port) throws IOException {\n        final ServerSocket serverSocket = new ServerSocket(port);\n        return serverSocket;\n    }\n\n    public static void destoryServer(ServerSocket s) throws IOException {\n        if (s != null)\n            s.close();\n    }\n\n    public static Socket createClient(String host, int port) throws IOException {\n        final Socket outgoingSocket = new Socket(host, port);\n        return outgoingSocket;\n    }\n\n    public static void destoryClient(Socket s) throws IOException {\n        if (s != null)\n            s.close();\n    }\n\n    public static void sendData(Socket socket, byte[] buffer) throws IOException {\n        final OutputStream out = socket.getOutputStream(); \n        final DataOutputStream dos = new DataOutputStream(out);\n        dos.write(buffer);\n        dos.flush();\n        dos.close();\n        out.flush();\n        out.close();\n    }\n\n    /**\n     * Blocking call\n     */\n    public static boolean recvData(ServerSocket serverSocket, byte[] buffer) throws IOException {\n        serverSocket.setSoTimeout(10);\n        Socket incomingSocket = null;\n        try {\n            incomingSocket = serverSocket.accept();\n        } catch (SocketTimeoutException e) {\n            return false;\n        }\n        final InputStream input = incomingSocket.getInputStream();\n        input.read(buffer);\n        input.close();\n        return true;\n    }\n\n    public static final class Peer { \n\n        private static final int        BUFFER_SIZE     = 10*1024;\n\n        private Peer() { }\n\n        public static final class RunnableRecv implements Runnable, Receiver {\n\n            public static volatile boolean                      run         = true;\n\n            private final ConcurrentLinkedQueue<Data>           toRecv      = new ConcurrentLinkedQueue<Data>();\n            private final int                                   port;\n            private final MessageListener                       listener;\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableRecv(MessageListener listener) {\n                run = true;\n                this.port = TCP.port++;\n                this.listener = listener;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toRecv;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public String getHost() {\n                return LOCAL;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public int getPort() {\n                return port;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                ServerSocket s = null;\n                try {\n                    if (DEBUG) \n                        System.out.println(\"Creating server. port=\"+port);\n                    s = TCP.createServer(port);\n                    final byte[] array = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(array);\n                    isReady = true;\n                    while (run) {\n                        bb.clear();\n                        final boolean p = TCP.recvData(s,array);\n                        if (!p) {\n                            Thread.yield();\n                            continue;\n                        }\n\n                        final Data data = new Data();\n                        data.fromBuffer(bb);\n\n                        if (DEBUG) \n                            System.out.println(\"Server (\"+getHost()+\":\"+getPort()+\") received '\"+new String(data.message.array())+\"' from \"+data.sourceAddr.getHostAddress()+\":\"+data.sourcePort);\n\n                        toRecv.add(data);\n                        listener.onMessage(this);\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally {\n                    try {\n                        TCP.destoryServer(s);\n                    } catch (IOException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        };\n\n        public static final class RunnableSend implements Runnable, Sender {\n\n            public static volatile boolean                      run         = true;\n\n            private final ConcurrentLinkedQueue<Data>           toSend      = new ConcurrentLinkedQueue<Data>();\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableSend() {\n                run = true;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toSend;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                Socket s = null;\n                try {\n                    final byte[] buffer = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(buffer);\n                    isReady = true;\n                    while (run) {\n                        if (DEBUG && toSend.size()>1)\n                            System.out.println(\"Client toSend size=\"+toSend.size());\n                        final Data d = toSend.poll();\n                        if (d != null) {\n                            bb.clear();\n                            d.toBuffer(bb);\n                            bb.flip();\n\n                            if (DEBUG) \n                                System.out.println(\"Client (\"+d.sourceAddr.getHostAddress()+\":\"+d.sourcePort+\") sending '\"+new String(d.message.array())+\"'\");\n\n                            s = TCP.createClient(d.destAddr.getHostAddress(), d.destPort);\n                            TCP.sendData(s, buffer);\n                        }\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally { \n                    try {\n                        TCP.destoryClient(s);\n                    } catch (IOException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/networking/UDP.java",
    "content": "package com.jwetherell.bitcoin.networking;\n\nimport java.io.IOException;\nimport java.net.DatagramPacket;\nimport java.net.DatagramSocket;\nimport java.net.InetAddress;\nimport java.net.SocketException;\nimport java.net.SocketTimeoutException;\nimport java.nio.ByteBuffer;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.interfaces.Sender;\n\npublic class UDP {\n\n    private static final boolean    DEBUG       = Boolean.getBoolean(\"debug_all\");\n\n    public static final String      LOCAL       = \"127.0.0.1\";\n\n    public static int               port        = 1111;\n\n    public static DatagramSocket createServer(int port) throws SocketException {\n        final DatagramSocket serverSocket = new DatagramSocket(port);\n        return serverSocket;\n    }\n\n    public static void destoryServer(DatagramSocket s) {\n        if (s != null)\n            s.close();\n    }\n\n    public static DatagramSocket createClient() throws SocketException {\n        final DatagramSocket clientSocket = new DatagramSocket();\n        return clientSocket;\n    }\n\n    public static void destoryClient(DatagramSocket s) {\n        if (s != null)\n            s.close();\n    }\n\n    public static void sendData(DatagramSocket socket, InetAddress IPAddress, int port, byte[] buffer) throws IOException {\n        final DatagramPacket sendPacket = new DatagramPacket(buffer, buffer.length, IPAddress, port);\n        socket.send(sendPacket);\n    }\n\n    /**\n     * Blocking call\n     */\n    public static boolean recvData(DatagramSocket socket, byte[] buffer) throws IOException {\n        socket.setSoTimeout(100);\n        final DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);\n        try {\n            socket.receive(receivePacket);\n        } catch (SocketTimeoutException e) {\n            return false;\n        }\n        return true;\n    }\n\n    public static final class Peer { \n\n        private static final int        BUFFER_SIZE     = 10*1024;\n\n        private Peer() { }\n\n        public static final class RunnableRecv implements Runnable, Receiver {\n\n            public static volatile boolean                      run         = true;\n\n            private final ConcurrentLinkedQueue<Data>           toRecv      = new ConcurrentLinkedQueue<Data>();\n            private final int                                   port;\n            private final MessageListener                       listener;\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableRecv(MessageListener listener) {\n                run = true;\n                this.port = UDP.port++;\n                this.listener = listener;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toRecv;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public String getHost() {\n                return LOCAL;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public int getPort() {\n                return port;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                DatagramSocket s = null;\n                try {\n                    if (DEBUG) \n                        System.out.println(\"Creating server. port=\"+port);\n                    s = UDP.createServer(port);\n                    final byte[] array = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(array);\n                    isReady = true;\n                    while (run) {\n                        bb.clear();\n                        final boolean p = UDP.recvData(s,bb.array());\n                        if (!p) {\n                            Thread.yield();\n                            continue;\n                        }\n\n                        final Data data = new Data();\n                        data.fromBuffer(bb);\n\n                        if (DEBUG) \n                            System.out.println(\"Server (\"+getHost()+\":\"+getPort()+\") received '\"+new String(data.message.array())+\"' from \"+data.sourceAddr.getHostAddress()+\":\"+data.sourcePort);\n\n                        toRecv.add(data);\n                        listener.onMessage(this);\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally {\n                    UDP.destoryServer(s);\n                }\n            }\n        };\n\n        public static final class RunnableSend implements Runnable, Sender {\n\n            public static volatile boolean                      run         = true;\n\n            private final ConcurrentLinkedQueue<Data>           toSend      = new ConcurrentLinkedQueue<Data>();\n\n            private volatile boolean                            isReady     = false;\n\n            public RunnableSend() {\n                run = true;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public Queue<Data> getQueue() {\n                return toSend;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public boolean isReady() {\n                return isReady;\n            }\n\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void run() {\n                DatagramSocket s = null;\n                try {\n                    if (DEBUG) \n                        System.out.println(\"Creating client\");\n                    s = UDP.createClient();\n                    final byte[] buffer = new byte[BUFFER_SIZE];\n                    final ByteBuffer bb = ByteBuffer.wrap(buffer);\n                    isReady = true;\n                    while (run) {\n                        if (DEBUG && toSend.size()>1)\n                            System.out.println(\"Client toSend size=\"+toSend.size());\n                        final Data d = toSend.poll();\n                        if (d != null) {\n                            bb.clear();\n                            d.toBuffer(bb);\n                            bb.flip();\n\n                            if (DEBUG) \n                                System.out.println(\"Client (\"+d.sourceAddr.getHostAddress()+\":\"+d.sourcePort+\") sending '\"+new String(d.message.array())+\"'\");\n\n                            UDP.sendData(s, d.destAddr, d.destPort, buffer);\n                        }\n\n                        Thread.yield();\n                    }\n                } catch (SocketException e) {\n                    e.printStackTrace();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                } finally { \n                    if (s != null)\n                        UDP.destoryClient(s);\n                }\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/AllTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Suite;\nimport org.junit.runners.Suite.SuiteClasses;\n\n//@formatter:off\n@RunWith(Suite.class)\n@SuiteClasses(\n    {\n        com.jwetherell.bitcoin.test.ProofOfWorkTest.class,\n        com.jwetherell.bitcoin.test.BlockChainTest.class,\n        com.jwetherell.bitcoin.test.EncodeDecodeTest.class,\n        com.jwetherell.bitcoin.test.TransactionTest.class,\n        com.jwetherell.bitcoin.test.BlockTest.class,\n        com.jwetherell.bitcoin.test.DataTest.class,\n        com.jwetherell.bitcoin.test.UDPTest.class,\n        com.jwetherell.bitcoin.test.TCPTest.class,\n        com.jwetherell.bitcoin.test.MulticastTest.class,\n        com.jwetherell.bitcoin.test.PeerTest.class,\n        com.jwetherell.bitcoin.test.WalletTest.class,\n    }\n)\n//@formatter:on\n\npublic class AllTest {\n    // Ignore\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/BlockChainTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.nio.ByteBuffer;\nimport java.util.Arrays;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.Blockchain;\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\npublic class BlockChainTest {\n\n    private static final Transaction[]  EMPTY       = new Transaction[0];\n    private static final byte[]         SIGNATURE   = \"sig\".getBytes();\n\n    @Test\n    public void test() {\n\n        final byte[] hash1;\n        {\n            final byte[] hash = \"This is a hash\".getBytes();\n            final Transaction block = new Transaction(\"me\",\"you\",\"msg\",7,SIGNATURE,EMPTY,EMPTY);\n            final ByteBuffer buffer = ByteBuffer.allocate(block.getBufferLength());\n            block.toBuffer(buffer);\n            buffer.flip();\n\n            final byte[] bytes = buffer.array();\n            hash1 = Blockchain.getNextHash(hash, bytes);\n        }\n\n        final byte[] hash2;\n        {\n            byte[] hash = \"This is a hash\".getBytes();\n            final Transaction block = new Transaction(\"me\",\"you\",\"msg\",7,SIGNATURE,EMPTY,EMPTY);\n            final ByteBuffer buffer = ByteBuffer.allocate(block.getBufferLength());\n            block.toBuffer(buffer);\n            buffer.flip();\n\n            final byte[] bytes = buffer.array();\n            hash2 = Blockchain.getNextHash(hash, bytes);\n        }\n\n        Assert.assertTrue(Arrays.equals(hash1, hash2));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/BlockTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.nio.ByteBuffer;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Transaction;\nimport com.jwetherell.bitcoin.data_model.Block;\n\npublic class BlockTest {\n\n    private static final Transaction[]  EMPTY       = new Transaction[0];\n    private static final byte[]         SIGNATURE   = \"sig\".getBytes();\n\n\n    @Test\n    public void testSerialization() {\n        final String f = \"me\";\n        final String t = \"you\";\n        final String m = \"Here is a coin for you!\";\n\n        final Transaction trans = new Transaction(f, t, m, 10, SIGNATURE, EMPTY, EMPTY);\n        final Transaction[] transactions = new Transaction[]{ trans };\n        byte[] prev = \"I am a hash!\".getBytes();\n        byte[] hash = \"I am also a hash!\".getBytes();\n        final Block block = new Block(f,prev,hash,transactions,1);\n        final ByteBuffer buffer = ByteBuffer.allocate(block.getBufferLength());\n        block.toBuffer(buffer);\n        buffer.flip();\n\n        final Block block2 = new Block();\n        block2.fromBuffer(buffer);\n\n        Assert.assertTrue(block.equals(block2));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/DataTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.nio.ByteBuffer;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Data;\n\npublic class DataTest {\n\n    @Test\n    public void testSerialization() {\n        final String from = \"me\";\n        final String sHost = \"127.0.0.1\";\n        final int sPort = 1024;\n        final String to = \"you\";\n        final String dHost = \"localhost\";\n        final int dPort = 1025;\n        final byte[] sig = \"sig\".getBytes();\n        final byte[] msg = \"This is a message\".getBytes();\n\n        final Data d1 = new Data(from,sHost,sPort,to,dHost,dPort,sig,msg);\n        final ByteBuffer buffer = ByteBuffer.allocate(d1.getBufferLength());\n        d1.toBuffer(buffer);\n        buffer.flip();\n\n        final Data d2 = new Data();\n        d2.fromBuffer(buffer);\n\n        Assert.assertTrue(d1.equals(d2));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/EncodeDecodeTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.security.KeyFactory;\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.PrivateKey;\nimport java.security.PublicKey;\nimport java.security.SecureRandom;\nimport java.security.Signature;\nimport java.security.spec.X509EncodedKeySpec;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class EncodeDecodeTest {\n    \n    @Test\n    public void test1() {\n        byte[] data = \"hello.\".getBytes();\n\n        /* Test generating and verifying a DSA signature */\n        try {\n            /* generate a key pair */\n            final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"DSA\");\n            keyGen.initialize(1024, new SecureRandom());\n            final KeyPair pair = keyGen.generateKeyPair();\n\n            /* create a Signature object to use for signing and verifying */\n            final Signature dsa = Signature.getInstance(\"SHA/DSA\"); \n\n            /* initialize the Signature object for signing */\n            final PrivateKey priv = pair.getPrivate();\n            dsa.initSign(priv);\n\n            /* Update and sign the data */\n            dsa.update(data);\n\n            /* Now that all the data to be signed has been read in, sign it */\n            final byte[] sig = dsa.sign();\n\n            /* Verify the signature */\n\n            /* Initialize the Signature object for verification */\n            final PublicKey pub = pair.getPublic();\n            dsa.initVerify(pub);\n\n            /* Update and verify the data */\n            dsa.update(data);\n\n            final boolean verified = dsa.verify(sig);\n            Assert.assertTrue(verified);\n        } catch (Exception e) {\n            System.err.println(\"Caught exception \" + e.toString());\n        }\n    }\n    \n    @Test\n    public void test2() {\n        byte[] data = \"hello.\".getBytes();\n\n        /* Test generating and verifying a DSA signature */\n        try {\n            /* generate a key pair */\n            final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"DSA\");\n            keyGen.initialize(1024, new SecureRandom());\n            final KeyPair pair = keyGen.generateKeyPair();\n\n            /* create a Signature object to use\n             * for signing and verifying */\n            final Signature dsa = Signature.getInstance(\"SHA/DSA\"); \n\n            /* initialize the Signature object for signing */\n            final PrivateKey priv = pair.getPrivate();\n            dsa.initSign(priv);\n\n            /* Update and sign the data */\n            dsa.update(data);\n\n            /* Now that all the data to be signed has been read in, sign it */\n            final byte[] sig = dsa.sign();\n\n            /* Verify the signature */\n\n            /* Initialize the Signature object for verification */\n            final PublicKey pub = pair.getPublic();\n            /* Encode the public key into a byte array */\n            final byte[] encoded = pub.getEncoded();\n            /* Get the public key from the encoded byte array */\n            final PublicKey fromEncoded = KeyFactory.getInstance(\"DSA\", \"SUN\").generatePublic(new X509EncodedKeySpec(encoded));\n            dsa.initVerify(fromEncoded);\n\n            /* Update and verify the data */\n            dsa.update(data);\n\n            final boolean verified = dsa.verify(sig);\n            Assert.assertTrue(verified);\n        } catch (Exception e) {\n            System.err.println(\"Caught exception \" + e.toString());\n        }\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/MulticastTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.networking.Multicast;\n\npublic class MulticastTest {\n\n    private static final boolean DEBUG = Boolean.getBoolean(\"debug\");\n\n    @Test(timeout=5000)\n    public void test() throws InterruptedException {\n        final String from = \"me\";\n        final String to = \"you\";\n        final byte[] sig = \"sig\".getBytes();\n        final byte[] toSend = \"Hello world.\".getBytes();\n        final MessageListener listener = new MessageListener() {\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void onMessage(Receiver recv) {\n                Data d = recv.getQueue().poll();\n                while (d != null) {\n                    final byte[] data = d.message.array();\n                    if (DEBUG)\n                        System.out.println(\"Listener received '\"+new String(data)+\"'\");\n                    Assert.assertTrue(isEquals(toSend,data,toSend.length));\n                    d = recv.getQueue().poll();\n                }\n                Multicast.Peer.RunnableRecv.run = false;\n                Multicast.Peer.RunnableSend.run = false;\n            }\n        };\n\n        // Start both the sender and receiver\n        final Multicast.Peer.RunnableRecv recv = new Multicast.Peer.RunnableRecv(listener);\n        final Thread r = new Thread(recv,\"recv\");\n        r.start();     \n\n        final Multicast.Peer.RunnableSend send = new Multicast.Peer.RunnableSend();\n        final Thread s = new Thread(send,\"send\");\n        s.start();\n\n        // Wait for everyone to initialize\n        while (recv.isReady()==false || send.isReady()==false) {\n            Thread.yield();\n        }\n\n        final Data data = new Data(from, recv.getHost(), recv.getPort(), to, recv.getHost(), recv.getPort(), sig, toSend);\n        send.getQueue().add(data);\n\n        // Wait for threads to finish\n        r.join();\n        s.join();\n    }\n\n    private static final boolean isEquals(byte[] a, byte[] b, int length) {\n        for (int i=0; i<length; i++)\n            if (a[i] != b[i])\n                return false;\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/PeerTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.util.Arrays;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.Peer;\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\npublic class PeerTest {\n\n    private static final Transaction[]  EMPTY       = new Transaction[0];\n    private static final byte[]         SIGNATURE   = \"sig\".getBytes();\n\n    @Test\n    public void testHello() {\n        final byte[] key = \"key\".getBytes();\n        final byte[] p1 = Peer.getIamMsg(key);\n        final byte[] k = Peer.parseIamMsg(p1);\n\n        Assert.assertTrue(Arrays.equals(key, k));\n    }\n\n    @Test\n    public void testWhois() {\n        final String hello = \"hello\";\n        final byte[] p1 = Peer.getWhoisMsg(hello);\n        final String result = Peer.parseWhoisMsg(p1);\n\n        Assert.assertTrue(hello.equals(result));\n    }\n\n    @Test\n    public void testTransaction() {\n        final Transaction c1 = new Transaction(\"me\",\"you\",\"I give you 1 coin\", 1, SIGNATURE, EMPTY, EMPTY);\n        byte[] b = Peer.getTransactionMsg(c1);\n        final Transaction c2 = Peer.parseTransactionMsg(b);\n\n        Assert.assertTrue(c1.equals(c2));\n    }\n\n    @Test\n    public void testTransactionAck() {\n        final Transaction c1 = new Transaction(\"me\",\"you\",\"I give you 2 coins\", 2, SIGNATURE, EMPTY, EMPTY);\n        byte[] b = Peer.getTransactionAckMsg(c1);\n        final Transaction c2 = Peer.parseTransactionAckMsg(b);\n\n        Assert.assertTrue(c1.equals(c2));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/ProofOfWorkTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.Peer;\nimport com.jwetherell.bitcoin.ProofOfWork;\nimport com.jwetherell.bitcoin.common.HashUtils;\n\npublic class ProofOfWorkTest {\n\n    private Peer.MiningTask task = new Peer.MiningTask();\n\n    @Test\n    public void test() {\n        final int numberOfZerosInPrefix = 32;\n        final byte[] sha256 = HashUtils.calculateSha256(\"Hello world!\");\n        task.run = true;\n        final int nonce = ProofOfWork.solve(task, sha256, numberOfZerosInPrefix);\n\n        Assert.assertTrue(ProofOfWork.check(sha256, nonce, numberOfZerosInPrefix));\n    }\n\n    @Test\n    public void test2() {\n        final int numberOfZerosInPrefix = 32;\n        final byte[] sha256 = HashUtils.calculateSha256(\"Hello, I am a very nice hash. I work well with others and whatnot.\");\n        task.run = true;\n        final int nonce = ProofOfWork.solve(task, sha256, numberOfZerosInPrefix);\n\n        Assert.assertTrue(ProofOfWork.check(sha256, nonce, numberOfZerosInPrefix));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/TCPTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.networking.TCP;\n\npublic class TCPTest {\n\n    private static final boolean DEBUG = Boolean.getBoolean(\"debug\");\n\n    @Test(timeout=5000)\n    public void test() throws InterruptedException {\n        final String from = \"me\";\n        final String to = \"you\";\n        final byte[] sig = \"sig\".getBytes();\n        final byte[] toSend = \"Hello world.\".getBytes();\n        final MessageListener listener = new MessageListener() {\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void onMessage(Receiver recv) {\n                Data d = recv.getQueue().poll();\n                while (d != null) {\n                    final byte[] data = d.message.array();\n                    if (DEBUG)\n                        System.out.println(\"Listener received '\"+new String(data)+\"'\");\n                    Assert.assertTrue(isEquals(toSend,data,toSend.length));\n                    d = recv.getQueue().poll();\n                }\n                TCP.Peer.RunnableRecv.run = false;\n                TCP.Peer.RunnableSend.run = false;\n            }\n        };\n\n        // Start both the sender and receiver\n        final TCP.Peer.RunnableRecv recv = new TCP.Peer.RunnableRecv(listener);\n        final Thread r = new Thread(recv,\"recv\");\n        r.start();     \n\n        final TCP.Peer.RunnableSend send = new TCP.Peer.RunnableSend();\n        final Thread s = new Thread(send,\"send\");\n        s.start();\n\n        // Wait for everyone to initialize\n        while (recv.isReady()==false || send.isReady()==false) {\n            Thread.yield();\n        }\n\n        final Data data = new Data(from, recv.getHost(), recv.getPort(), to, recv.getHost(), recv.getPort(), sig, toSend);\n        send.getQueue().add(data);\n\n        // Wait for threads to finish\n        r.join();\n        s.join();\n    }\n\n    private static final boolean isEquals(byte[] a, byte[] b, int length) {\n        for (int i=0; i<length; i++)\n            if (a[i] != b[i])\n                return false;\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/TransactionTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.nio.ByteBuffer;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\npublic class TransactionTest {\n\n    private static final Transaction[]  EMPTY       = new Transaction[0];\n    private static final byte[]         SIGNATURE   = \"sig\".getBytes();\n\n    @Test\n    public void testSerialization() {\n        final String f = \"me\";\n        final String t = \"you\";\n\n        final Transaction[] inputs = new Transaction[2];\n        inputs[0] = new Transaction(f, t, \"Here is a coin for you!\", 1, SIGNATURE, EMPTY, EMPTY);\n        inputs[1] = new Transaction(f, t, \"Here is 2 coins for you!\", 2, SIGNATURE, EMPTY, EMPTY);\n\n        final Transaction[] outputs = new Transaction[1];\n        outputs[0] = new Transaction(t, f, \"Here is three coins for you!\", 3, SIGNATURE, EMPTY, EMPTY);\n\n        final Transaction trans = new Transaction(f, t, \"Here is a transaction\", 0, SIGNATURE, inputs, outputs);\n        final ByteBuffer buffer = ByteBuffer.allocate(trans.getBufferLength());\n        trans.toBuffer(buffer);\n        buffer.flip();\n\n        final Transaction trans2 = new Transaction();\n        trans2.fromBuffer(buffer);\n\n        Assert.assertTrue(trans.equals(trans2));\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/UDPTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.interfaces.MessageListener;\nimport com.jwetherell.bitcoin.interfaces.Receiver;\nimport com.jwetherell.bitcoin.networking.UDP;\n\npublic class UDPTest {\n\n    private static final boolean DEBUG = Boolean.getBoolean(\"debug\");\n\n    @Test(timeout=5000)\n    public void test() throws InterruptedException {\n        final String from = \"me\";\n        final String to = \"you\";\n        final byte[] sig = \"sig\".getBytes();\n        final byte[] toSend = \"Hello world.\".getBytes();\n        final MessageListener listener = new MessageListener() {\n            /**\n             * {@inheritDoc}\n             */\n            @Override\n            public void onMessage(Receiver recv) {\n                Data d = recv.getQueue().poll();\n                while (d != null) {\n                    final byte[] data = d.message.array();\n                    if (DEBUG)\n                        System.out.println(\"Listener received '\"+new String(data)+\"'\");\n                    Assert.assertTrue(isEquals(toSend,data,toSend.length));\n                    d = recv.getQueue().poll();\n                }\n                UDP.Peer.RunnableRecv.run = false;\n                UDP.Peer.RunnableSend.run = false;\n            }\n        };\n\n        // Start both the sender and receiver\n        final UDP.Peer.RunnableRecv recv = new UDP.Peer.RunnableRecv(listener);\n        final Thread r = new Thread(recv,\"recv\");\n        r.start();     \n\n        final UDP.Peer.RunnableSend send = new UDP.Peer.RunnableSend();\n        final Thread s = new Thread(send,\"send\");\n        s.start();\n\n        // Wait for everyone to initialize\n        while (recv.isReady()==false || send.isReady()==false) {\n            Thread.yield();\n        }\n\n        final Data data = new Data(from ,recv.getHost(), recv.getPort(), to, recv.getHost(), recv.getPort(), sig, toSend);\n        send.getQueue().add(data);\n\n        // Wait for threads to finish\n        r.join();\n        s.join();\n    }\n\n    private static final boolean isEquals(byte[] a, byte[] b, int length) {\n        for (int i=0; i<length; i++)\n            if (a[i] != b[i])\n                return false;\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/com/jwetherell/bitcoin/test/WalletTest.java",
    "content": "package com.jwetherell.bitcoin.test;\n\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.PrivateKey;\nimport java.security.SecureRandom;\nimport java.security.Signature;\n\nimport org.junit.After;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.jwetherell.bitcoin.Blockchain;\nimport com.jwetherell.bitcoin.Wallet;\nimport com.jwetherell.bitcoin.data_model.Block;\nimport com.jwetherell.bitcoin.data_model.Data;\nimport com.jwetherell.bitcoin.data_model.Transaction;\n\npublic class WalletTest {\n\n    // Create genesis entity\n    private Wallet              genesis;\n\n    @Before\n    public void startGenesis() {\n        genesis = new Wallet(Blockchain.GENESIS_NAME);\n    }\n\n    @After\n    public void stopGenersis() throws InterruptedException {\n        genesis.shutdown();\n        genesis = null;\n    }\n\n    private static final void distributeGenesisCoins(Wallet genesis, Wallet... wallets) throws InterruptedException {\n        long balance = genesis.getBalance();\n        final int each = (int) (balance/wallets.length);\n\n        for (Wallet w : wallets) {\n            balance -= each;\n            // Distribute genesis coins\n            genesis.sendCoin(w.getName(), each);\n            while (genesis.getBalance()!=balance || w.getBalance()!=each)\n                Thread.yield();\n        }\n    }\n\n    @Test(timeout=10000)\n    public void testBadSignature() throws InterruptedException {\n        final String n1 = \"n1\";\n        final String n2 = \"n2\";\n        final String n3 = \"n3\";\n        final BadKeyWallet p1 = new BadKeyWallet(n1);\n        final Wallet p2 = new Wallet(n2);\n        final Wallet p3 = new Wallet(n3);\n\n        // Distribute genesis coins evenly\n        distributeGenesisCoins(genesis,p1,p2,p3);\n        // genesis=2, p1=16, p2=16, p3=16\n\n        // Switch to use the 'bad' key\n        p1.switchKeys();\n\n        // Send coin (which'll be rejected for a bad signature)\n        p1.sendCoin(n2,10);\n        // p1=16, p2=16, p3=16\n\n        while (p1.getBalance()!=16 || p2.getBalance()!=16 || p3.getBalance()!=16) {\n            Thread.yield();\n        }\n\n        p2.sendCoin(n3,2);\n        // p1=16, p2=14, p3=18\n\n        while (p1.getBalance()!=16 || p2.getBalance()!=14 || p3.getBalance()!=18) {\n            Thread.yield();\n        }\n\n        Assert.assertTrue(p1.getBalance()==16);\n        Assert.assertTrue(p2.getBalance()==14);\n        Assert.assertTrue(p3.getBalance()==18);\n\n        Thread.yield();\n\n        p1.shutdown();\n        p2.shutdown();\n        p3.shutdown();\n    }\n\n    @Test(timeout=10000)\n    public void testCoinExchangers2() throws InterruptedException {\n        final String n1 = \"n1\";\n        final String n2 = \"n2\";\n        final Wallet p1 = new Wallet(n1);\n        final Wallet p2 = new Wallet(n2);\n\n        // Distribute genesis coins evenly\n        distributeGenesisCoins(genesis,p1,p2);\n        // genesis=0, p1=25, p2=25\n\n        p1.sendCoin(n2, 3);\n        // genesis=0, p1=22, p2=28\n\n        while (p1.getBalance()!=22 || p2.getBalance()!=28) {\n            Thread.yield();\n        }\n\n        p2.sendCoin(n1, 7);\n        // genesis=0, p1=29, p2=21\n\n        while (genesis.getBalance()!=0 || p1.getBalance()!=29 || p2.getBalance()!=21) {\n            Thread.yield();\n        }\n\n        Assert.assertTrue(genesis.getBalance()==0);\n        Assert.assertTrue(p1.getBalance()==29);\n        Assert.assertTrue(p2.getBalance()==21);\n\n        Thread.yield();\n\n        p1.shutdown();\n        p2.shutdown();\n    }\n\n    @Test(timeout=10000)\n    public void testCoinExchangers3() throws InterruptedException {\n        final String n1 = \"n1\";\n        final String n2 = \"n2\";\n        final String n3 = \"n3\";\n        final Wallet p1 = new Wallet(n1);\n        final Wallet p2 = new Wallet(n2);\n        final Wallet p3 = new Wallet(n3);\n\n        // Distribute genesis coins evenly\n        distributeGenesisCoins(genesis,p1,p2,p3);\n        // genesis=2, p1=16, p2=16, p3=16\n\n        p1.sendCoin(n2, 3);\n        // p1=13, p2=19, p3=16\n\n        while (p1.getBalance()!=13 || p2.getBalance()!=19 || p3.getBalance()!=16) {\n            Thread.yield();\n        }\n\n        p2.sendCoin(n3, 7);\n        // p1=13, p2=12, p3=23\n\n        while (p1.getBalance()!=13 || p2.getBalance()!=12 || p3.getBalance()!=23) {\n            Thread.yield();\n        }\n\n        p3.sendCoin(n1, 11);\n        // p1=24, p2=12, p3=12\n\n        while (genesis.getBalance()!=2 || p1.getBalance()!=24 || p2.getBalance()!=12 || p3.getBalance()!=12) {\n            Thread.yield();\n        }\n\n        Assert.assertTrue(genesis.getBalance()==2);\n        Assert.assertTrue(p1.getBalance()==24);\n        Assert.assertTrue(p2.getBalance()==12);\n        Assert.assertTrue(p3.getBalance()==12);\n\n        Thread.yield();\n\n        p1.shutdown();\n        p2.shutdown();\n        p3.shutdown();\n    }\n\n    @Test(timeout=10000)\n    public void testBadHash() throws InterruptedException {\n        final Transaction[] EMPTY = new Transaction[0];\n        final String n1 = \"n1\";\n        final String n2 = \"n2\";\n        final BadHashWallet p1 = new BadHashWallet(n1);\n        final BadHashWallet p2 = new BadHashWallet(n2);\n\n        // Distribute genesis coins evenly\n        distributeGenesisCoins(genesis,p1,p2);\n        // genesis=0, p1=25, p2=25\n\n        // Send coin\n        p1.sendCoin(n2,10);\n        // p1=15, p2=35\n\n        while (p1.getBalance()!=15 || p2.getBalance()!=35) {\n            Thread.yield();\n        }\n\n        // This block has a bad hash\n        final Transaction transaction = Transaction.newSignedTransaction(p1.getSignature(), n1, n2, \"Please reject me!\", 1, EMPTY, EMPTY);\n        final byte[] prev = \"This is a bad hash\".getBytes();\n        final byte[] hash = \"This is a VERY bad hash\".getBytes();\n        final Transaction[] trans = new Transaction[]{ transaction };\n        final Block block = new Block(n1, prev, hash, trans, 0);\n        // Dummy data object, only care about the destination host and port\n        final Data data = new Data(p1.getName(), p1.getHost(), p1.getPort(), p2.getName(), p2.getHost(), p2.getPort(), \"\".getBytes(), \"\".getBytes());\n        p1.sendBlock(block, data);\n        // p1=15, p2=35 (nothing changes)\n\n        while (p1.getBalance()!=15 || p2.getBalance()!=35) {\n            Thread.yield();\n        }\n\n        // This should be accepted\n        p1.sendCoin(n2,10);\n        // p1=5, p2=45\n\n        while (genesis.getBalance()!=0 || p1.getBalance()!=5 || p2.getBalance()!=45) {\n            Thread.yield();\n        }\n\n        Assert.assertTrue(genesis.getBalance()==0);\n        Assert.assertTrue(p1.getBalance()==5);\n        Assert.assertTrue(p2.getBalance()==45);\n\n        Thread.yield();\n\n        p1.shutdown();\n        p2.shutdown();\n    }\n\n    private static class BadHashWallet extends Wallet {\n\n        public BadHashWallet(String name) {\n            super(name);\n        }\n\n        public Signature getSignature() {\n            return enc;\n        }\n\n        public String getHost() {\n            return runnableRecvTcp.getHost();\n        }\n\n        public int getPort() {\n            return runnableRecvTcp.getPort();\n        }\n\n        /** Really only here to open up the method for JUnits **/\n        public void sendBlock(Block block, Data data) {\n            super.sendBlock(block, data);\n        }\n    }\n\n    private static class BadKeyWallet extends Wallet {\n\n        private final KeyPairGenerator              gen;\n        private final SecureRandom                  random;\n        private final Signature                     enc;\n        private final KeyPair                       pair;\n        private final PrivateKey                    privateKey;\n        {\n            try {\n                gen = KeyPairGenerator.getInstance(\"DSA\", \"SUN\");\n                random = SecureRandom.getInstance(\"SHA1PRNG\", \"SUN\");\n                gen.initialize(512, random);\n\n                enc = Signature.getInstance(\"SHA1withDSA\", \"SUN\");\n\n                pair = gen.generateKeyPair();\n                privateKey = pair.getPrivate();\n                enc.initSign(privateKey);\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n        }\n\n        private boolean                             switchToBadKey = false;;\n\n        public BadKeyWallet(String name) {\n            super(name);\n        }\n\n        public void switchKeys() {\n            switchToBadKey = !switchToBadKey;\n        }\n\n        @Override\n        protected byte[] signMsg(byte[] bytes) {\n            if (!switchToBadKey)\n                return super.signMsg(bytes);\n\n            byte[] signed = null;\n            try {\n                enc.update(bytes);\n                signed = enc.sign();\n            } catch (Exception e) {\n                System.err.println(\"Could not encode msg. \"+e);\n            }\n            return signed;\n        }\n    }\n}\n"
  }
]