├── .gitignore ├── LICENSE.txt ├── README.md ├── build.gradle ├── checkstyle-suppressions.xml ├── docs ├── en │ └── usage.md └── jp │ └── usage.md ├── google-checks.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── simulator └── src ├── dist ├── conf │ ├── scenario.txt │ └── simulator.conf └── output │ └── graph │ └── .gitkeep └── main └── java └── simblock ├── block ├── Block.java ├── Coinage.java ├── ProofOfWorkBlock.java └── SamplePoSBlock.java ├── node ├── Node.java ├── consensus │ ├── AbstractConsensusAlgo.java │ ├── ProofOfWork.java │ └── SampleProofOfStake.java └── routing │ ├── AbstractRoutingTable.java │ └── BitcoinCoreTable.java ├── settings ├── NetworkConfiguration.java └── SimulationConfiguration.java ├── simulator ├── Main.java ├── Network.java ├── Simulator.java └── Timer.java └── task ├── AbstractMessageTask.java ├── AbstractMintingTask.java ├── BlockMessageTask.java ├── CmpctBlockMessageTask.java ├── GetBlockTxnMessageTask.java ├── InvMessageTask.java ├── MiningTask.java ├── RecMessageTask.java ├── SampleStakingTask.java └── Task.java /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA related files 2 | *.iml 3 | *.ipr 4 | *.iws 5 | 6 | # Ecipse related files 7 | .settings/ 8 | .classpath 9 | .project 10 | bin/ 11 | 12 | # Gradle related files 13 | .gradle/ 14 | build/ 15 | 16 | # Simulator related files 17 | blockList.txt 18 | nodeList.txt 19 | out.txt 20 | 21 | # To manage directory structure by git 22 | /simulator/src/dist/output/* 23 | !/simulator/src/dist/output/graph/ 24 | /simulator/src/dist/output/graph/* 25 | !/simulator/src/dist/output/graph/.gitkeep 26 | 27 | #for MacOS 28 | .DS_Store 29 | 30 | # Intellij idea 31 | 32 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 33 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 34 | 35 | # User-specific stuff 36 | .idea/**/workspace.xml 37 | .idea/**/tasks.xml 38 | .idea/**/usage.statistics.xml 39 | .idea/**/dictionaries 40 | .idea/**/shelf 41 | 42 | # Generated files 43 | .idea/**/contentModel.xml 44 | 45 | # Sensitive or high-churn files 46 | .idea/**/dataSources/ 47 | .idea/**/dataSources.ids 48 | .idea/**/dataSources.local.xml 49 | .idea/**/sqlDataSources.xml 50 | .idea/**/dynamic.xml 51 | .idea/**/uiDesigner.xml 52 | .idea/**/dbnavigator.xml 53 | 54 | # Gradle 55 | .idea/**/gradle.xml 56 | .idea/**/libraries 57 | 58 | # Gradle and Maven with auto-import 59 | # When using Gradle or Maven with auto-import, you should exclude module files, 60 | # since they will be recreated, and may cause churn. Uncomment if using 61 | # auto-import. 62 | # .idea/artifacts 63 | # .idea/compiler.xml 64 | # .idea/jarRepositories.xml 65 | # .idea/modules.xml 66 | # .idea/*.iml 67 | # .idea/modules 68 | # *.iml 69 | # *.ipr 70 | 71 | # CMake 72 | cmake-build-*/ 73 | 74 | # Mongo Explorer plugin 75 | .idea/**/mongoSettings.xml 76 | 77 | # File-based project format 78 | *.iws 79 | 80 | # IntelliJ 81 | out/ 82 | 83 | # mpeltonen/sbt-idea plugin 84 | .idea_modules/ 85 | 86 | # JIRA plugin 87 | atlassian-ide-plugin.xml 88 | 89 | # Cursive Clojure plugin 90 | .idea/replstate.xml 91 | 92 | # Crashlytics plugin (for Android Studio and IntelliJ) 93 | com_crashlytics_export_strings.xml 94 | crashlytics.properties 95 | crashlytics-build.properties 96 | fabric.properties 97 | 98 | # Editor-based Rest Client 99 | .idea/httpRequests 100 | 101 | # Android studio 3.1+ serialized cache file 102 | .idea/caches/build_file_checksums.ser 103 | 104 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is SimBlock? 2 | 3 | SimBlock is an open source blockchain network simulator, developed by Distributed Systems Group, Tokyo Institute of Technology. 4 | 5 | https://dsg-titech.github.io/simblock/ 6 | 7 | - [User Guide (English)](https://github.com/dsg-titech/simblock/blob/master/docs/en/usage.md) 8 | - [User Guide (Japanese)](https://github.com/dsg-titech/simblock/blob/master/docs/jp/usage.md) 9 | 10 | SimBlock has a visualization tool, by which you can see the transition of block propagation. 11 | 12 | - [SimBlock Visualizer](https://github.com/dsg-titech/simblock-visualizer) 13 | 14 | ## License 15 | 16 | SimBlock is licensed under the Apache License, Version2.0. 17 | 18 | ## Contact 19 | 20 | E-mail: dsg-titech at googlegroups.com 21 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.plugins.ide.idea.model.* 2 | import org.gradle.plugins.ide.eclipse.model.* 3 | 4 | plugins { 5 | id 'idea' 6 | id 'eclipse' 7 | id 'com.diffplug.spotless' version '6.0.0' 8 | } 9 | 10 | def srcDir = 'src/main/java' 11 | def confDir = 'src/dist/conf' 12 | def outDir = 'build/classes/java/main' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | subprojects { 19 | apply plugin: 'java' 20 | apply plugin: 'application' 21 | apply plugin: 'idea' 22 | apply plugin: 'eclipse' 23 | 24 | applicationDefaultJvmArgs = ["-Dfile.encoding=UTF-8"] 25 | 26 | idea.module { 27 | sourceDirs += file(srcDir) 28 | outputDir = file(outDir) 29 | inheritOutputDirs = false 30 | iml { 31 | whenMerged { module -> 32 | module.getDependencies().add(new ModuleLibrary([new Path('file://$MODULE_DIR$/' + confDir)] as Set, [] as Set, [] as Set, [] as Set, null)) 33 | } 34 | } 35 | } 36 | 37 | eclipse { 38 | jdt.file { 39 | withProperties { prop -> 40 | prop.clear() 41 | prop.put("eclipse.preferences.version", "1") 42 | prop.put("encoding/", "UTF-8") 43 | } 44 | } 45 | project { 46 | natures 'org.eclipse.jdt.core.javanature' 47 | buildCommand 'org.eclipse.jdt.core.javabuilder' 48 | } 49 | classpath.file { 50 | whenMerged { classpath -> 51 | classpath.entries.clear() 52 | classpath.entries.add(new Output(outDir)) 53 | classpath.entries.add(new Container('org.eclipse.jdt.launching.JRE_CONTAINER')) 54 | classpath.entries.add(new SourceFolder(srcDir, null)) 55 | classpath.entries.add(new Library(fileReference(confDir))) 56 | } 57 | } 58 | } 59 | 60 | //For reading files when run from gradle. 61 | run.doFirst { 62 | classpath += files(confDir) 63 | } 64 | 65 | //For reading files when run from scripts. 66 | startScripts { 67 | classpath += files(confDir) 68 | doLast { 69 | def windowsScriptFile = file getWindowsScript() 70 | def unixScriptFile = file getUnixScript() 71 | windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\conf', '%APP_HOME%\\conf') 72 | unixScriptFile.text = unixScriptFile.text.replace('$APP_HOME/lib/conf', '$APP_HOME/conf') 73 | } 74 | } 75 | } 76 | 77 | allprojects { 78 | def defaultEncoding = 'UTF-8' 79 | tasks.withType(AbstractCompile)*.options*.encoding = defaultEncoding 80 | tasks.withType(GroovyCompile)*.groovyOptions*.encoding = defaultEncoding 81 | } 82 | 83 | project(':simulator') { 84 | mainClassName = 'simblock.simulator.Main' 85 | 86 | def distSettings = { 87 | archiveBaseName = 'simblock' 88 | exclude('output/graph/*.*') 89 | exclude('output/*.*') 90 | } 91 | 92 | distZip { 93 | configure distSettings 94 | } 95 | 96 | distTar { 97 | configure distSettings 98 | } 99 | 100 | startScripts { 101 | applicationName = 'runSimBlock' 102 | } 103 | 104 | spotless { 105 | java { 106 | target '**/*.java' 107 | googleJavaFormat() 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/en/usage.md: -------------------------------------------------------------------------------- 1 | # SimBlock User Guide 2 | 3 | ## 1. Environment requirements 4 | SimBlock is available on operating systems such as Windows, MacOS, Ubuntu Linux or any Unix platform that supports Java. 5 | It requires JDK and Gradle with the following versions. 6 | 7 | Note that the repository of SimBlock includes Gradle wrapper so that you can also install Gradle automatically (we mention it later). 8 | 9 | | Software | Version | 10 | |:-----------|:------------| 11 | | JDK | 1.8.0 or later | 12 | | Gradle | 5.1.1 or later | 13 | 14 | ## 2. Download 15 | Download the SimBlock repository as a zip file from GitHub and unzip, or clone the repository. 16 | 17 | Release list: [https://github.com/dsg-titech/simblock/releases](https://github.com/dsg-titech/simblock/releases) 18 | Command for clone: `$ git clone git@github.com:dsg-titech/simblock.git` 19 | 20 | ### 2-a. Directory structure 21 | The structure of the unzipped or cloned directory is as follows: 22 | 23 | ``` 24 | simblock 25 | +-- docs 26 | +-- gradle 27 | | +-- wrapper 28 | +-- simulator 29 | +-- src 30 | +-- dist 31 | | +-- conf 32 | | +-- out 33 | | +-- graph 34 | +-- main 35 | +-- java 36 | +-- SimBlock 37 | +-- ... 38 | : 39 | ``` 40 | 41 | | Directory | Description | 42 | |:-----------|:------------| 43 | | *docs* | Documents about SimBlock (e.g., user manual) | 44 | | *gradle/wrapper* | For Gradle wrapper | 45 | | *simulator/src/dist/conf* | Directory in which to place the files that simulator reads | 46 | | *simulator/src/dist/out* | Directory where files output by simulator are stored | 47 | | *simulator/src/main/java/SimBlock* | Source codes | 48 | 49 | ## 3. Build 50 | 51 | Hereafter, the name of the root directory of the unzipped or cloned repository is denoted as *\*. 52 | 53 | First, open a terminal software (e.g., xterm, command prompt, etc.) and move to *\*. 54 | 55 | ### 3-a. If Gradle is installed 56 | You can build by the following Gradle command, if you have already installed Gradle. 57 | 58 | `$ gradle build` 59 | 60 | If successful, *build* directory will be created under *\/simulator*. 61 | 62 | ``` 63 | 64 | +-- simulator 65 | +-- build 66 | +-- classes 67 | +-- distributions 68 | +-- libs 69 | +-- scripts 70 | +-- tmp 71 | ``` 72 | 73 | | Directory | Description | 74 | |:-----------|:------------| 75 | | *simulator/build/classes* | Directory where built class files are stored | 76 | | *simulator/build/distributions* | Directory where distribution archive files (zip, tar) are stored | 77 | | *simulator/build/libs* | Directory where jar files are stored | 78 | | *simulator/build/scripts* | Directory where startup scripts are stored | 79 | 80 | Note that the startup scripts in *simulator/build/scripts* are generated for inclusion in the distribution archive; 81 | if you run the scripts with the directory structure as it is, an error will occur. 82 | 83 | ### 3-b. If Gradle is not installed 84 | You can use *gradlew*(*gradlew.bat*, for Windows user)in *\* instead of running Gradle command. 85 | 86 | `$ gradlew build` 87 | 88 | This is a program called Gradle wrapper, which will automatically install Gradle if it is not installed and call it. 89 | 90 | ### 3-c. Discard build products 91 | The following Gradle command will delete the files generated by the above build process. 92 | 93 | `$ gradle clean` 94 | 95 | You can also instruct the execution of *clean* and *build* at one time as follows: 96 | 97 | `$ gradle clean build` 98 | 99 | In this case, *build* is executed after *clean*. 100 | 101 | ## 4. Run SimBlock 102 | There are two main ways to run SimBlock: by using Gradle command and by using build products. 103 | 104 | ### 4-a. Run with Gradle command 105 | Run following Gradle command in *\*, then the simulator starts up. 106 | 107 | `$ gradle :simulator:run` 108 | 109 | Output files of the simulator will be stored in *\/simulator/src/dist/output*. 110 | 111 | ### 4-b. Run with build product 112 | Extract the distribution archive (zip, tar) of *\/simulator/build/distributions*. 113 | Then, the following directory structure will be created. 114 | 115 | ``` 116 | SimBlock 117 | +-- bin 118 | +-- conf 119 | +-- lib 120 | +-- output 121 | ``` 122 | 123 | A script for execution is in *bin* directory. 124 | 125 | By executing *runSimBlock* (*runSimBlock.bat* for Windows) in the terminal, the simulator starts up. 126 | 127 | Output files of the simulator will be stored in *output* directory. 128 | 129 | ### 4-c. Other ways 130 | The extracted distribution archive contains the jar file of SimBlock (*lib/simulator.jar*). 131 | Of course, it is also possible to execute this jar file directly with the java command. 132 | Note that it is required to set the classpath appropriately. 133 | 134 | You can also run SimBlock on IDEs, such as Eclipse. 135 | It is explained later in the section of "Import to IDE". 136 | 137 | ## 5. Simulator parameter 138 | | Parameter | Location of definition | Description | 139 | |:-----------|:------------|:------------| 140 | | List of region | *BlockChainSimulator.settings.NetworkConfiguration#REGION_LIST* | Regions where nodes can exist. | 141 | | List of latency | *BlockChainSimulator.settings.NetworkConfiguration#LATENCY* | List of latency assigned to each region. (unit: millisecond) | 142 | | List of upload bandwidth | *BlockChainSimulator.settings.NetworkConfiguration#UPLOAD_BANDWIDTH* | List of upload bandwidth assigned to each region. (unit: bit per second) | 143 | | List of download bandwidth | *BlockChainSimulator.settings.NetworkConfiguration#DOWNLOAD_BANDWIDTH* | List of download bandwidth assigned to each region. (unit: bit per second) | 144 | | Distribution of region | *BlockChainSimulator.settings.NetworkConfiguration#REGION_DISTRIBUTION* | The distribution of node's region. Each value means the rate of the number of nodes in the corresponding region to the number of all nodes. | 145 | | Distribution of degree | *BlockChainSimulator.settings.SimulationConfiguration#DEGREE_DISTRIBUTION* | The cumulative distribution of number of outbound links. Cf. Andrew Miller et al., "Discovering bitcoin's public topology and influential nodes", 2015. | 146 | | Number of nodes | *BlockChainSimulator.settings.SimulationConfiguration#NUM_OF_NODES* | The number of nodes participating in the blockchain network. | 147 | | Routing table | *BlockChainSimulator.settings.SimulationConfiguration#TABLE* | The kind of routing tables. | 148 | | Block interval | *BlockChainSimulator.settings.SimulationConfiguration#INTERVAL* | The expected value of block generation interval. The difficulty of mining is automatically adjusted by this value and the sum of mining power. (unit: millisecond) | 149 | | Average mining power | *BlockChainSimulator.settings.SimulationConfiguration#AVERAGE_MINING_POWER* | The average mining power of each node. Mining power corresponds to Hash Rate in Bitcoin, and is the number of mining (hash calculation) executed per millisecond. | 150 | | Standard deviation of mining power | *BlockChainSimulator.settings.SimulationConfiguration#STDEV_OF_MINING_POWER* | The mining power of each node is determined randomly according to the normal distribution whose average is AVERAGE_MINING_POWER and standard deviation is STDEV_OF_MINING_POWER. | 151 | | Max block Height | *BlockChainSimulator.settings.SimulationConfiguration#END_BLOCK_HEIGHT* | The block height when a simulation ends. | 152 | | Block size | *BlockChainSimulator.settings.SimulationConfiguration#BLOCK_SIZE* | Block size. (unit: byte) | 153 | | CBR usage rate | *BlockChainSimulator.settings.SimulationConfiguration#CBR_USAGE_RATE* | The usage rate of compact block relay (CBR) protocol. | 154 | | Churn node rate | *BlockChainSimulator.settings.SimulationConfiguration#CHURN_NODE_RATE* | The rate of nodes that cause churn. | 155 | | Compact block size | *BlockChainSimulator.settings.SimulationConfiguration#COMPACT_BLOCK_SIZE* | Compact block size(unit: byte)| 156 | | CBR failure rate for control node | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_RATE_FOR_CONTROL_NODE* | CBR failure rate for a node that always connect network. | 157 | | CBR failure rate for churn node | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_RATE_FOR_CHURN_NODE* | CBR failure rate for a node that causes churn. | 158 | | CBR failure block size distribution for control node | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE* | The distribution of data size that a control node receives when fails CBR. | 159 | | CBR failure block size distribution for churn node | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE* | The distribution of data size that a churn node receives when fails CBR. | 160 | 161 | *SimBlock.settings* package has two classes which have these parameters: *NetworkConfiguration.java* and *SimulationConfiguration.java*. 162 | The former has parameters related to network parameters, and the latter has blockchain parameters. 163 | By changing these parameters and doing build, you can conduct different patterns of simulation. 164 | 165 | ## 6. Output 166 | The simulator outputs the simulation results to standard output and some files. 167 | The file output location is *\/simulator/src/dist/out* for execution by Gradle command. 168 | *SimBlock/output* for run with build product. 169 | 170 | output contents are as follows: 171 | 172 | - Standard output and *out.txt* 173 | - The following is listed under block ID 174 | - <node ID, propagation time> 175 | - Propagation time: The time from when the block of the block ID is generated to when the node of the node ID is reached. 176 | - *Blocklist.txt* 177 | - <fork information, block height, block ID> 178 | - Fork information: One of "OnChain" and "Orphan". "OnChain" denote block is on Main chain. "Orphan" denote block is an orphan block. 179 | - *graph/* 180 | - *${number}.txt*: Network information when block height is ${number} 181 | - <node ID, node ID> 182 | - Connection from left node ID to right node ID. 183 | - *output.json* 184 | - This file is listing occurred events. By uploading this file into [SimBlock Visualizer](https://github.com/dsg-titech/simblock-visualizer), you can see the visualization. 185 | - <event, content> 186 | - Event 187 | - add-link: Add a node to neighbor nodes. 188 | - remove-link: Remove a node from neighbor nodes. 189 | - flow-block: Block transmmission. 190 | - simulation-end: Simulation end. 191 | - content 192 | - timestamp: Order of events. 193 | - block-id: Block id. 194 | - transmission-timestamp: Timestamp when a block is transmitted. 195 | - reception-timestamp: Timestamp when a block is recieved. 196 | - begin-node-id: Source node. 197 | - end-node-id: End node. 198 | 199 | ## 7. Import to IDE 200 | By using Gradle, you can generate configuration files of an IDE and easily import them into it. 201 | 202 | ### 7-a. For IntelliJ IDEA 203 | By executing the following Gradle command, configuration files for IntelliJ IDEA are generated. 204 | 205 | `$ gradle idea` 206 | 207 | Generated files are listed as follows: 208 | 209 | | File | 210 | |:-----------| 211 | | *\/\.iml* | 212 | | *\/\.ipr* | 213 | | *\/\.iws* | 214 | | *\/simulator/simulator.iml* | 215 | 216 | With IntelliJ IDEA, select **File -> Open** and select *\.ipr*. 217 | *\/simulator* will be imported as a module. 218 | 219 | Then, you can run the simulator with the IDE. 220 | For example, select *\/simulator/src/main/java/SimBlock/simulator/Main.java* from the tool window of the project structure, 221 | right click and execute **Run 'Main.main ()'**. 222 | Output files will be stored in *\/simulator/src/dist/output*. Do not import as Gradle project if offered. 223 | 224 | #### Discard products 225 | The following Gradle command will delete the files generated by `$ gradle idea`. 226 | Note that *\.iws* file will not be deleted. Also, if the project is left open in the IDE, the deleted files may be automatically regenerated by the IDE.) 227 | 228 | `$ gradle cleanIdea` 229 | 230 | You can also instruct the execution of *cleanIdea* and *idea* at one time as follows: 231 | 232 | `$ gradle cleanIdea idea` 233 | 234 | In this case, *idea* is executed after *cleanIdea*. 235 | 236 | ### 7-b. For Eclipse 237 | By executing the following Gradle command, configuration files for Eclipse are generated. 238 | 239 | `$ gradle eclipse` 240 | 241 | Generated files are listed as follows: 242 | 243 | | File | 244 | |:-----------| 245 | | *\/.project* | 246 | | *\/simulator/.classpath* | 247 | | *\/simulator/.project* | 248 | | *\/simulator/.settings* | 249 | 250 | With Eclipse, select **File -> Open Projects from File System** and select *\* as **Import source**. 251 | Check the listed two Eclipse projects, and click **Finish**. 252 | *\/simulator* and *\* will be imported as a project respectively. 253 | 254 | Then, you can run the simulator with the IDE. 255 | For example, select the simulator project from Package Explorer, right-click and execute **Run As -> Java Application** to start the simulator. 256 | Output files will be stored in *\/simulator/src/dist/output*. 257 | 258 | #### Discard products 259 | The following Gradle command will delete the files generated by `$ gradle eclipse`. 260 | 261 | `$ gradle cleanEclipse` 262 | 263 | You can also instruct the execution of *cleanEclipse* and *eclipse* at one time as follows: 264 | 265 | `$ gradle cleanEclipse eclipse` 266 | 267 | In this case, *eclipse* is executed after *cleanEclipse*. 268 | -------------------------------------------------------------------------------- /docs/jp/usage.md: -------------------------------------------------------------------------------- 1 | # SimBlockユーザガイド 2 | 3 | ## 1. 環境準備 4 | Windows、Linux、MacOS等のJavaをサポートするオペレーティングシステムで利用可能です。 5 | SimBlockの利用には、以下に示すバージョンのJDKとGradleが必要です。 6 | 7 | なお、SimBlockの公開リポジトリにはGradle wrapperを同梱してありますので、Gradleは利用時に自動インストールすることもできます(手順は後述します)。 8 | 9 | | ソフトウェア | バージョン | 10 | |:-----------|:------------| 11 | | JDK | 1.8.0以降 | 12 | | Gradle | 5.1.1以降 | 13 | 14 | ## 2. ダウンロード 15 | GitHub上からZIPファイルをダウンロードして解凍するか、もしくは、SimBlockのリポジトリをクローンします。 16 | 17 | リリース一覧: [https://github.com/dsg-titech/simblock/releases](https://github.com/dsg-titech/simblock/releases) 18 | クローンコマンド: `$ git clone git@github.com:dsg-titech/simblock.git` 19 | 20 | ### 2-a. ディレクトリ構成 21 | 解凍/クローンしたディレクトリの内部は、以下のような構成になっています。 22 | 23 | ``` 24 | simblock 25 | +-- docs 26 | +-- gradle 27 | | +-- wrapper 28 | +-- simulator 29 | +-- src 30 | +-- dist 31 | | +-- conf 32 | | +-- out 33 | | +-- graph 34 | +-- main 35 | +-- java 36 | +-- SimBlock 37 | +-- ... 38 | : 39 | ``` 40 | 41 | | ディレクトリ | 説明 | 42 | |:-----------|:------------| 43 | | *docs* | マニュアル類 | 44 | | *gradle/wrapper* | Gradle wapper用のディレクトリ | 45 | | *simulator/src/dist/conf* | シミュレータが読み込むファイルを置くディレクトリ | 46 | | *simulator/src/dist/out* | シミュレータが出力するファイルが格納されるディレクトリ | 47 | | *simulator/src/main/java/SimBlock* | シミュレータ本体のソースコード | 48 | 49 | ## 3. ビルド 50 | 以降では、解凍/クローンしたリポジトリのルートディレクトリの名前を、 *\* と表記します。 51 | ターミナル(xterm、コマンドプロンプト等)を開き、 *\* に移動します。 52 | 53 | ### 3-a. Gradleをインストール済みの場合 54 | Gradleをインストール済みの場合、以下のGradleコマンドを実行することでSimBlockをビルドできます。 55 | 56 | `$ gradle build` 57 | 58 | 成功すると、 *\/simulator* 配下に *build* ディレクトリが生成されます。 59 | *build* ディレクトリは以下のような構成になっています。 60 | 61 | ``` 62 | 63 | +-- simulator 64 | +-- build 65 | +-- classes 66 | +-- distributions 67 | +-- libs 68 | +-- scripts 69 | +-- tmp 70 | ``` 71 | 72 | | ディレクトリ | 説明 | 73 | |:-----------|:------------| 74 | | *simulator/build/classes* | ビルドされたクラスファイル群が格納されるディレクトリ | 75 | | *simulator/build/distributions* | 配布用アーカイブ(zip, tar)が格納されるディレクトリ | 76 | | *simulator/build/libs* | jarファイルが格納されるディレクトリ | 77 | | *simulator/build/scripts* | 起動スクリプトが格納されるディレクトリ | 78 | 79 | なお、 *simulator/build/scripts* の起動スクリプトは、配布用アーカイブに含めるために生成されているものであり、このディレクトリ構成のまま実行してもエラーになりますのでご注意ください。 80 | 81 | ### 3-b. Gradleを未インストールの場合 82 | Gradleをインストールしていない場合、Gradleコマンドを実行する代わりに、 *\* にある *gradlew*(Windowsの場合は *gradlew.bat* )を使うことができます。 83 | 84 | `$ gradlew build` 85 | 86 | これはGradle wrapperと呼ばれるプログラムで、Gradleがインストールされていない場合には自動でインストールを行い、インストールしたGradleを呼び出してくれます。 87 | つまり、Gradleコマンドの代わりに *gradlew* ( *gradlew.bat* )を使うことができます。 88 | 89 | ### 3-c. ビルド生成物の破棄 90 | 以下のGradleコマンドを実行すると、Gradleのビルドによって生成されたファイル群が削除されます。 91 | 92 | `$ gradle clean` 93 | 94 | ビルドを実行する前に一度cleanしたい場合は、以下のようにまとめて実行を指示することもできます。 95 | 96 | `$ gradle clean build` 97 | 98 | この場合、clean→build、の順序で実行されます。 99 | 100 | ## 4. 実行 101 | シミュレータを実行する手段は大きく2つあります。 102 | Gradleコマンドによる実行と、ビルド生成物を用いた実行です。 103 | 104 | ### 4-a. Gradleコマンドによる実行 105 | *\* にて、以下のGradleコマンドを実行することで、シミュレータが起動します。 106 | 107 | `$ gradle :simulator:run` 108 | 109 | シミュレータが出力するファイルは、 *\/simulator/src/dist/output* ディレクトリ配下に格納されます。 110 | 111 | ### 4-b. ビルド生成物を用いた実行 112 | *\/simulator/build/distributions* の配布用アーカイブ(zip, tar)を解凍します。 113 | すると、以下のようなディレクトリ構成が現れます。 114 | 115 | ``` 116 | SimBlock 117 | +-- bin 118 | +-- conf 119 | +-- lib 120 | +-- output 121 | ``` 122 | 123 | この、 *bin* ディレクトリの中に、実行用のスクリプトが入っています。 124 | ターミナルから、 *runSimBlock* (Windowsの場合は *runSimBlock.bat* )を実行することで、シミュレータが起動します。 125 | シミュレータが出力するファイルは、 *output* ディレクトリ配下に格納されます。 126 | 127 | ### 4-c. その他の実行方法 128 | 配布用アーカイブを解凍した中には、シミュレータのjarファイルが含まれています( *lib/simulator.jar* )。 129 | このjarファイルを直接javaコマンドで実行することも、もちろん可能です。ただし、クラスパス等を適切に設定する必要があります。 130 | 131 | また、Eclipse等のIDE上から実行することもできます。 132 | これについては、後述するIDEへの取り込みの中で説明します。 133 | 134 | ## 5. シミュレータのパラメータ設定 135 | | パラメータ | 場所 | 説明 | 136 | |:-----------|:------------|:------------| 137 | | 地域名 | *BlockChainSimulator.settings.NetworkConfiguration#REGION_LIST* | ノードの存在する地域の一覧。デフォルトでは6地域。 | 138 | | 各地域の遅延 | *BlockChainSimulator.settings.NetworkConfiguration#LATENCY* | 地域ごとの遅延。 (単位: millisecond) | 139 | | 各地域の送信帯域 | *BlockChainSimulator.settings.NetworkConfiguration#UPLOAD_BANDWIDTH* | 地域ごとの送信帯域幅。 (単位: bit per second) | 140 | | 各地域の受信帯域 | *BlockChainSimulator.settings.NetworkConfiguration#DOWNLOAD_BANDWIDTH* | 地域ごとの受信帯域幅。 (単位: bit per second) | 141 | | 地域分布 | *BlockChainSimulator.settings.NetworkConfiguration#REGION_DISTRIBUTION* | ノードの地域分布。各値は、全ノード数に対する当該地域のノード数の割合を表す。 | 142 | | 次数分布 | *BlockChainSimulator.settings.SimulationConfiguration#DEGREE_DISTRIBUTION* | アウトバウンドの個数を表す。詳しくはMirror論文参照(Andrew Miller et al., "Discovering bitcoin's public topology and influential nodes", 2015.) | 143 | | ノード数 | *BlockChainSimulator.settings.SimulationConfiguration#NUM_OF_NODES* | ブロックチェーンネットワーク参加ノード総数。 | 144 | | ルーティングテーブル | *BlockChainSimulator.settings.SimulationConfiguration#TABLE* | ルーティングテーブルの種類を表す。 | 145 | | ブロック生成間隔 | *BlockChainSimulator.settings.SimulationConfiguration#INTERVAL* | ブロック生成間隔の期待値。この値と、下記マイニングパワーの総量から、マイニングの難しさ(difficulty)が自動調整される。 (単位: millisecond) | 146 | | 平均マイニングパワー | *BlockChainSimulator.settings.SimulationConfiguration#AVERAGE_MINING_POWER* | 各ノードが持つマイニングパワーの平均値。マイニングパワーはBitcoinにおけるHash Rateに相当し、ミリ秒あたりに実行できるマイニング(ハッシュ計算)回数を表す。 | 147 | | マイニングパワーの標準偏差 | *BlockChainSimulator.settings.SimulationConfiguration#STDEV_OF_MINING_POWER* | 各ノードのマイニングパワーは、平均がAVERAGE_MINING_POWER、標準偏差がSTDEV_OF_MINING_POWERであるような正規分布に沿ってランダムに決定される。 | 148 | | ブロック高 | *BlockChainSimulator.settings.SimulationConfiguration#END_BLOCK_HEIGHT* | 何ブロック生成後にシミュレーションを終えるかを表す。 | 149 | | ブロックサイズ | *BlockChainSimulator.settings.SimulationConfiguration#BLOCK_SIZE* | ブロックサイズ。 (単位: byte) | 150 | | CBR使用率 | *BlockChainSimulator.settings.SimulationConfiguration#CBR_USAGE_RATE* | コンパクトブロックリレー (CBR) プロトコルを使っているノードの割合 | 151 | | チャーンノード率 | *BlockChainSimulator.settings.SimulationConfiguration#CHURN_NODE_RATE* | チャーンノード(チャーンを起こすノード)の割合。 | 152 | | コンパクトブロックサイズ | *BlockChainSimulator.settings.SimulationConfiguration#COMPACT_BLOCK_SIZE* | コンパクトブロックサイズ。(単位: byte)| 153 | | コントロールノードのCBR失敗率 | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_RATE_FOR_CONTROL_NODE* | コントロールノード(常時ネットワークに接続するノード)がコンパクトブロックリレーに失敗する確率。 | 154 | | チャーンノードのCBR失敗率 | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_RATE_FOR_CHURN_NODE* | チャーンノードがコンパクトブロックリレーに失敗する確率。 | 155 | | CBR失敗時のブロックサイズの分布 | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE* | コンパクトブロックリレー失敗時にコントロールノードがピアからダウンロードするデータサイズの分布。 | 156 | | CBR失敗時のブロックサイズの分布 | *BlockChainSimulator.settings.SimulationConfiguration#CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE* | コンパクトブロックリレー失敗時にチャーンノードがピアからダウンロードするデータサイズの分布。 | 157 | 158 | シミュレータのパラメータは *SimBlock.settings* パッケージ内の2つのクラス、 *NetworkConfiguration* と *SimulationConfiguration* に書かれています。 159 | 前者はネットワーク関係のパラメータを、後者はブロックチェーンネットワークに関するパラメタを保持しています。 160 | ユーザーはこれらのファイル内の変数の値を書き換えてビルドすることで、シミュレーションの設定を変えることができます。 161 | 162 | ## 6. シミュレータの出力 163 | シミュレータは、シミュレーションの実行結果を標準出力およびファイルに出力します。 164 | ファイル出力の場所は、Gradleコマンドによる実行の場合は *\/simulator/src/dist/out* 、 165 | ビルド生成物を用いた実行の場合は *SimBlock/output* です。 166 | 167 | 出力される内容は以下のとおりです。 168 | 169 | - 標準出力および *out.txt* 170 | - ブロックIDの行が出力された後に、以下が列挙されます。 171 | - <ノードID, 時間> 172 | - 時間 : 当該ブロックIDのブロックが、生成されてから当該ノードIDのノードに到達するまでの時間。 173 | - *Blocklist.txt* 174 | - <フォーク情報, ブロック高, ブロックID> 175 | - フォーク情報 : 「OnChain」「Orphan」のいずれか。前者がメインチェーン、後者がフォークを表します。 176 | - *graph* ディレクトリ配下 177 | - 数字.txt : 「数字」のブロック高のときのネットワーク情報 178 | - <ノードID, ノードID> 179 | - 左のノードIDから右のノードIDへのコネクションを意味します。 180 | - *output.json* 181 | - 発生したイベントの情報が列挙されます。本ファイルを[SimBlock Visualizer](https://github.com/dsg-titech/simblock-visualizer)に読み込ませることで、可視化を実行できます。 182 | - <イベントの種類, データ内容> 183 | - イベントの種類 184 | - add-link : 隣接ノードの追加。 185 | - remove-link : 隣接ノードの除去。 186 | - flow-block : ブロックの送信。 187 | - simulation-end : シミュレーションの終了。 188 | - データ内容 189 | - timestamp : イベントの時系列を表すタイムスタンプ。 190 | - block-id : ブロックのID。 191 | - transmission-timestamp : 送信時のタイムスタンプ。 192 | - reception-timestamp : 受信時のタイムスタンプ。 193 | - begin-node-id : 起点ノード。 194 | - end-node-id : 終点ノード。 195 | 196 | ## 7. IDEへの取り込み 197 | Gradleを使って、IDEの設定ファイルを生成し、簡単にIDEにインポートすることができます。 198 | 199 | ### 7-a. IntelliJ IDEAの場合 200 | 以下のGradleコマンドを実行すれば、IntelliJ IDEA用の各種設定ファイルを生成できます。 201 | 202 | `$ gradle idea` 203 | 204 | 成功すると、以下のファイル群が生成されます。 205 | 206 | | ファイル | 207 | |:-----------| 208 | | *\/\.iml* | 209 | | *\/\.ipr* | 210 | | *\/\.iws* | 211 | | *\/simulator/simulator.iml* | 212 | 213 | IntelliJ IDEAを起動し、 **File -> Open** から *\.ipr* を選択すれば、プロジェクトとして開くことができます。 214 | *\/simulator* はモジュールとしてインポートされる形になります。 215 | ここまでくれば、IDE上からシミュレータを実行可能です。 216 | 例えば、プロジェクト構造のツールウィンドウから *\/simulator/src/main/java/SimBlock/simulator/Main.java* を選択し、右クリックして **Run 'Main.main()'** を実行することで、シミュレータが起動します。 217 | シミュレータが出力するファイルは、 *\/simulator/src/dist/output* ディレクトリ配下に格納されます。 218 | 219 | #### 生成物の破棄 220 | 以下のGradleコマンドを実行すると、Gradleのideaタスクによって生成されたファイル群が削除されます。 221 | (※ *\.iws* ファイルは削除されません。また、IDEでプロジェクトを開いた状態のままの場合、削除されたファイルをIDE側で自動的に再生成する場合があります。) 222 | 223 | `$ gradle cleanIdea` 224 | 225 | ideaタスクを実行する前に一度cleanIdeaしたい場合は、以下のようにまとめて実行を指示することもできます。 226 | 227 | `$ gradle cleanIdea idea` 228 | 229 | この場合、cleanIdea→idea、の順序で実行されます。 230 | 231 | ### 7-b. Eclipseの場合 232 | 以下のGradleコマンドを実行すれば、Eclipse用の各種設定ファイルを生成できます。 233 | 234 | `$ gradle eclipse` 235 | 236 | 成功すると、以下のファイル・ディレクトリ群が生成されます。 237 | 238 | | ファイル | 239 | |:-----------| 240 | | *\/.project* | 241 | | *\/simulator/.classpath* | 242 | | *\/simulator/.project* | 243 | | *\/simulator/.settings* | 244 | 245 | Eclipseを起動し、 **File -> Open Projects from File System** にて、 **Import source** として *\* を選択し、リストアップされる2つのEclipse projectにチェックを付けて **Finish** ボタンを押します。 246 | *\/simulator* と *\* がそれぞれプロジェクトとしてインポートされる形になります。 247 | ここまでくれば、IDE上からシミュレータを実行可能です。 248 | 例えば、パッケージエクスプローラから simulator プロジェクトを選択し、右クリックして **Run As -> Java Application** を実行することで、シミュレータが起動します。 249 | シミュレータが出力するファイルは、 *\/simulator/src/dist/output* ディレクトリ配下に格納されます。 250 | 251 | #### 生成物の破棄 252 | 以下のGradleコマンドを実行すると、Gradleのeclipseタスクによって生成されたファイル群が削除されます。 253 | 254 | `$ gradle cleanEclipse` 255 | 256 | eclipseタスクを実行する前に一度cleanEclipseしたい場合は、以下のようにまとめて実行を指示することもできます。 257 | 258 | `$ gradle cleanEclipse eclipse` 259 | 260 | この場合、cleanEclipse→eclipse、の順序で実行されます。 261 | 262 | -------------------------------------------------------------------------------- /google-checks.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | 73 | 74 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 90 | 91 | 92 | 93 | 94 | 97 | 98 | 99 | 100 | 101 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 118 | 120 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 167 | 168 | 169 | 170 | 172 | 173 | 174 | 175 | 177 | 178 | 179 | 180 | 182 | 183 | 184 | 185 | 187 | 188 | 189 | 190 | 192 | 193 | 194 | 195 | 197 | 198 | 199 | 200 | 202 | 203 | 204 | 205 | 207 | 208 | 209 | 210 | 212 | 213 | 214 | 215 | 217 | 219 | 221 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 251 | 252 | 253 | 255 | 256 | 257 | 258 | 263 | 264 | 265 | 266 | 269 | 270 | 271 | 272 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 324 | 325 | 326 | 327 | 328 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsg-titech/simblock/8a1285aa37b832385b0be2ae6f804885a4a7031f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':simulator' 2 | -------------------------------------------------------------------------------- /simulator/src/dist/conf/scenario.txt: -------------------------------------------------------------------------------- 1 | 0 MakeAndJoinTask 1 3 1 1000 BitcoinCoreTable 2 | 0 MakeAndJoinTask 2 3 1 1000 BitcoinCoreTable 3 | 0 MakeAndJoinTask 3 3 1 1000 BitcoinCoreTable 4 | 0 MakeAndJoinTask 4 3 1 1000 BitcoinCoreTable 5 | 0 MakeAndJoinTask 5 3 1 1000 BitcoinCoreTable 6 | 0 MakeAndJoinTask 6 3 1 1000 BitcoinCoreTable 7 | 0 MakeAndJoinTask 7 3 1 1000 BitcoinCoreTable 8 | 0 MakeAndJoinTask 8 3 1 1000 BitcoinCoreTable 9 | 0 MakeAndJoinTask 9 3 1 1000 BitcoinCoreTable 10 | 0 MakeAndJoinTask 10 3 1 1000 BitcoinCoreTable -------------------------------------------------------------------------------- /simulator/src/dist/conf/simulator.conf: -------------------------------------------------------------------------------- 1 | # Do not remove this file. 2 | -------------------------------------------------------------------------------- /simulator/src/dist/output/graph/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsg-titech/simblock/8a1285aa37b832385b0be2ae6f804885a4a7031f/simulator/src/dist/output/graph/.gitkeep -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/block/Block.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.block; 18 | 19 | import simblock.node.Node; 20 | 21 | /** The representation of a block. */ 22 | public class Block { 23 | /** The current height of the block. */ 24 | private final int height; 25 | 26 | /** The parent {@link Block}. */ 27 | private final Block parent; 28 | 29 | /** The {@link Node} that minted the block. */ 30 | private final Node minter; 31 | 32 | /** Minting timestamp, absolute time since the beginning of the simulation. */ 33 | private final long time; 34 | 35 | /** Block unique id. */ 36 | private final int id; 37 | 38 | /** Latest known block id. */ 39 | private static int latestId = 0; 40 | 41 | /** 42 | * Instantiates a new Block. 43 | * 44 | * @param parent the parent 45 | * @param minter the minter 46 | * @param time the time 47 | */ 48 | public Block(Block parent, Node minter, long time) { 49 | this.height = parent == null ? 0 : parent.getHeight() + 1; 50 | this.parent = parent; 51 | this.minter = minter; 52 | this.time = time; 53 | this.id = latestId; 54 | latestId++; 55 | } 56 | 57 | /** 58 | * Get height int. 59 | * 60 | * @return the int 61 | */ 62 | public int getHeight() { 63 | return this.height; 64 | } 65 | 66 | /** 67 | * Get parent block. 68 | * 69 | * @return the block 70 | */ 71 | public Block getParent() { 72 | return this.parent; 73 | } 74 | 75 | /** 76 | * Get minter node. 77 | * 78 | * @return the node 79 | */ 80 | @SuppressWarnings("unused") 81 | public Node getMinter() { 82 | return this.minter; 83 | } 84 | 85 | /** 86 | * Get time. 87 | * 88 | * @return the time 89 | */ 90 | // TODO what format 91 | public long getTime() { 92 | return this.time; 93 | } 94 | 95 | /** 96 | * Gets the block id. 97 | * 98 | * @return the id 99 | */ 100 | // TODO what format 101 | public int getId() { 102 | return this.id; 103 | } 104 | 105 | /** 106 | * Generates the genesis block. The parent is set to null and the time is set to 0 107 | * 108 | * @param minter the minter 109 | * @return the block 110 | */ 111 | @SuppressWarnings("unused") 112 | public static Block genesisBlock(Node minter) { 113 | return new Block(null, minter, 0); 114 | } 115 | 116 | /** 117 | * Recursively searches for the block at the provided height. 118 | * 119 | * @param height the height 120 | * @return the block with the provided height 121 | */ 122 | public Block getBlockWithHeight(int height) { 123 | if (this.height == height) { 124 | return this; 125 | } else { 126 | return this.parent.getBlockWithHeight(height); 127 | } 128 | } 129 | 130 | /** 131 | * Checks if the provided block is on the same chain as self. 132 | * 133 | * @param block the block to be checked 134 | * @return true if block are on the same chain false otherwise 135 | */ 136 | public boolean isOnSameChainAs(Block block) { 137 | if (block == null) { 138 | return false; 139 | } else if (this.height <= block.height) { 140 | return this.equals(block.getBlockWithHeight(this.height)); 141 | } else { 142 | return this.getBlockWithHeight(block.height).equals(block); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/block/Coinage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.block; 18 | 19 | import java.math.BigDecimal; 20 | import java.math.BigInteger; 21 | 22 | /** The type Coinage tracks the age of coins. */ 23 | public class Coinage implements Cloneable { 24 | private BigInteger coins; 25 | private long age; 26 | 27 | /** 28 | * Instantiates a new Coinage. 29 | * 30 | * @param coins the coins 31 | * @param age the age 32 | */ 33 | public Coinage(BigInteger coins, long age) { 34 | this.coins = coins; 35 | this.age = age; 36 | } 37 | 38 | /** 39 | * Gets coins. 40 | * 41 | * @return the coins 42 | */ 43 | public BigInteger getCoins() { 44 | return this.coins; 45 | } 46 | 47 | /** 48 | * Gets age. 49 | * 50 | * @return the age 51 | */ 52 | public long getAge() { 53 | return this.age; 54 | } 55 | 56 | /** Increase age. */ 57 | public void increaseAge() { 58 | this.age++; 59 | } 60 | 61 | /** Reset age. */ 62 | public void resetAge() { 63 | this.age = 0; 64 | } 65 | 66 | /** 67 | * Reward gained for consensus maintenance. 68 | * 69 | * @param reward the reward 70 | */ 71 | public void reward(double reward) { 72 | this.coins = 73 | this.coins.add( 74 | new BigDecimal(this.getCoinage()).multiply(new BigDecimal(reward)).toBigInteger()); 75 | } 76 | 77 | /** 78 | * Gets coin age, i.e. the coins amount multiplied by age. 79 | * 80 | * @return the coinage 81 | */ 82 | // TODO what is coin age 83 | public BigInteger getCoinage() { 84 | return this.getCoins().multiply(BigInteger.valueOf(this.getAge())); 85 | } 86 | 87 | @Override 88 | public Coinage clone() { 89 | Coinage ret = null; 90 | try { 91 | ret = (Coinage) super.clone(); 92 | } catch (CloneNotSupportedException e) { 93 | e.printStackTrace(); 94 | } 95 | return ret; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/block/ProofOfWorkBlock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.block; 18 | 19 | import static simblock.simulator.Simulator.getSimulatedNodes; 20 | import static simblock.simulator.Simulator.getTargetInterval; 21 | 22 | import java.math.BigInteger; 23 | import simblock.node.Node; 24 | 25 | /** The type Proof of work block. */ 26 | public class ProofOfWorkBlock extends Block { 27 | private final BigInteger difficulty; 28 | private final BigInteger totalDifficulty; 29 | private final BigInteger nextDifficulty; 30 | private static BigInteger genesisNextDifficulty; 31 | 32 | /** 33 | * Instantiates a new Proof of work block. 34 | * 35 | * @param parent the parent 36 | * @param minter the minter 37 | * @param time the time 38 | * @param difficulty the difficulty 39 | */ 40 | public ProofOfWorkBlock(ProofOfWorkBlock parent, Node minter, long time, BigInteger difficulty) { 41 | super(parent, minter, time); 42 | this.difficulty = difficulty; 43 | 44 | if (parent == null) { 45 | this.totalDifficulty = BigInteger.ZERO.add(difficulty); 46 | this.nextDifficulty = ProofOfWorkBlock.genesisNextDifficulty; 47 | } else { 48 | this.totalDifficulty = parent.getTotalDifficulty().add(difficulty); 49 | // TODO: difficulty adjustment 50 | this.nextDifficulty = parent.getNextDifficulty(); 51 | } 52 | } 53 | 54 | /** 55 | * Gets difficulty. 56 | * 57 | * @return the difficulty 58 | */ 59 | public BigInteger getDifficulty() { 60 | return this.difficulty; 61 | } 62 | 63 | /** 64 | * Gets total difficulty. 65 | * 66 | * @return the total difficulty 67 | */ 68 | public BigInteger getTotalDifficulty() { 69 | return this.totalDifficulty; 70 | } 71 | 72 | /** 73 | * Gets next difficulty. 74 | * 75 | * @return the next difficulty 76 | */ 77 | public BigInteger getNextDifficulty() { 78 | return this.nextDifficulty; 79 | } 80 | 81 | /** 82 | * Generates the genesis block, gets the total mining power and adjusts the difficulty of the next 83 | * block accordingly. 84 | * 85 | * @param minter the minter 86 | * @return the genesis block 87 | */ 88 | public static ProofOfWorkBlock genesisBlock(Node minter) { 89 | long totalMiningPower = 0; 90 | for (Node node : getSimulatedNodes()) { 91 | totalMiningPower += node.getMiningPower(); 92 | } 93 | genesisNextDifficulty = BigInteger.valueOf(totalMiningPower * getTargetInterval()); 94 | return new ProofOfWorkBlock(null, minter, 0, BigInteger.ZERO); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/block/SamplePoSBlock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.block; 18 | 19 | import static simblock.settings.SimulationConfiguration.AVERAGE_COINS; 20 | import static simblock.settings.SimulationConfiguration.STAKING_REWARD; 21 | import static simblock.settings.SimulationConfiguration.STDEV_OF_COINS; 22 | import static simblock.simulator.Main.random; 23 | import static simblock.simulator.Simulator.getSimulatedNodes; 24 | import static simblock.simulator.Simulator.getTargetInterval; 25 | 26 | import java.math.BigInteger; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | import simblock.node.Node; 30 | 31 | /** The type Sample proof of stake block. */ 32 | public class SamplePoSBlock extends Block { 33 | private final Map coinages; 34 | private static Map genesisCoinages; 35 | private final BigInteger difficulty; 36 | private final BigInteger totalDifficulty; 37 | private final BigInteger nextDifficulty; 38 | 39 | /** 40 | * Instantiates a new Sample proof of stake block. 41 | * 42 | * @param parent the parent 43 | * @param minter the minter 44 | * @param time the time 45 | * @param difficulty the difficulty 46 | */ 47 | public SamplePoSBlock(SamplePoSBlock parent, Node minter, long time, BigInteger difficulty) { 48 | super(parent, minter, time); 49 | 50 | this.coinages = new HashMap<>(); 51 | if (parent == null) { 52 | for (Node node : getSimulatedNodes()) { 53 | this.coinages.put(node, genesisCoinages.get(node).clone()); 54 | } 55 | } else { 56 | for (Node node : getSimulatedNodes()) { 57 | this.coinages.put(node, parent.getCoinage(node).clone()); 58 | this.coinages.get(node).increaseAge(); 59 | } 60 | this.coinages.get(minter).reward(STAKING_REWARD); 61 | this.coinages.get(minter).resetAge(); 62 | } 63 | 64 | BigInteger totalCoinage = BigInteger.ZERO; 65 | for (Node node : getSimulatedNodes()) { 66 | totalCoinage = totalCoinage.add(this.coinages.get(node).getCoinage()); 67 | } 68 | 69 | this.difficulty = difficulty; 70 | if (parent == null) { 71 | this.totalDifficulty = BigInteger.ZERO.add(difficulty); 72 | } else { 73 | this.totalDifficulty = parent.getTotalDifficulty().add(difficulty); 74 | } 75 | this.nextDifficulty = 76 | totalCoinage 77 | .multiply(BigInteger.valueOf(getTargetInterval())) 78 | .divide(BigInteger.valueOf(1000)); 79 | } 80 | 81 | /** 82 | * Gets coinage. 83 | * 84 | * @param node the node 85 | * @return the coinage 86 | */ 87 | // TODO Coinage is related to proof of stake obviously 88 | public Coinage getCoinage(Node node) { 89 | return this.coinages.get(node); 90 | } 91 | 92 | /** 93 | * Gets difficulty. 94 | * 95 | * @return the difficulty 96 | */ 97 | public BigInteger getDifficulty() { 98 | return this.difficulty; 99 | } 100 | 101 | /** 102 | * Gets total difficulty. 103 | * 104 | * @return the total difficulty 105 | */ 106 | public BigInteger getTotalDifficulty() { 107 | return this.totalDifficulty; 108 | } 109 | 110 | /** 111 | * Gets next difficulty. 112 | * 113 | * @return the next difficulty 114 | */ 115 | public BigInteger getNextDifficulty() { 116 | return this.nextDifficulty; 117 | } 118 | 119 | private static Coinage genCoinage() { 120 | double r = random.nextGaussian(); 121 | BigInteger coins = BigInteger.valueOf(Math.max((int) (r * STDEV_OF_COINS + AVERAGE_COINS), 0)); 122 | return new Coinage(coins, 1); 123 | } 124 | 125 | /** 126 | * Genesis block sample proof of stake block. 127 | * 128 | * @param minter the minter 129 | * @return the sample proof of stake block 130 | */ 131 | public static SamplePoSBlock genesisBlock(Node minter) { 132 | genesisCoinages = new HashMap<>(); 133 | for (Node node : getSimulatedNodes()) { 134 | genesisCoinages.put(node, genCoinage()); 135 | } 136 | return new SamplePoSBlock(null, minter, 0, BigInteger.ZERO); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/Node.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node; 18 | 19 | import static simblock.settings.SimulationConfiguration.BLOCK_SIZE; 20 | import static simblock.settings.SimulationConfiguration.CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE; 21 | import static simblock.settings.SimulationConfiguration.CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE; 22 | import static simblock.settings.SimulationConfiguration.CBR_FAILURE_RATE_FOR_CHURN_NODE; 23 | import static simblock.settings.SimulationConfiguration.CBR_FAILURE_RATE_FOR_CONTROL_NODE; 24 | import static simblock.settings.SimulationConfiguration.COMPACT_BLOCK_SIZE; 25 | import static simblock.simulator.Main.OUT_JSON_FILE; 26 | import static simblock.simulator.Main.random; 27 | import static simblock.simulator.Network.getBandwidth; 28 | import static simblock.simulator.Simulator.arriveBlock; 29 | import static simblock.simulator.Timer.getCurrentTime; 30 | import static simblock.simulator.Timer.putTask; 31 | import static simblock.simulator.Timer.removeTask; 32 | 33 | import java.util.ArrayList; 34 | import java.util.HashSet; 35 | import java.util.Set; 36 | import simblock.block.Block; 37 | import simblock.node.consensus.AbstractConsensusAlgo; 38 | import simblock.node.routing.AbstractRoutingTable; 39 | import simblock.task.AbstractMessageTask; 40 | import simblock.task.AbstractMintingTask; 41 | import simblock.task.BlockMessageTask; 42 | import simblock.task.CmpctBlockMessageTask; 43 | import simblock.task.GetBlockTxnMessageTask; 44 | import simblock.task.InvMessageTask; 45 | import simblock.task.RecMessageTask; 46 | 47 | /** A class representing a node in the network. */ 48 | public class Node { 49 | /** Unique node ID. */ 50 | private final int nodeID; 51 | 52 | /** Region assigned to the node. */ 53 | private final int region; 54 | 55 | /** Mining power assigned to the node. */ 56 | private final long miningPower; 57 | 58 | /** A nodes routing table. */ 59 | private AbstractRoutingTable routingTable; 60 | 61 | /** The consensus algorithm used by the node. */ 62 | private AbstractConsensusAlgo consensusAlgo; 63 | 64 | /** Whether the node uses compact block relay. */ 65 | private boolean useCBR; 66 | 67 | /** The node causes churn. */ 68 | private boolean isChurnNode; 69 | 70 | /** The current block. */ 71 | private Block block; 72 | 73 | /** Orphaned blocks known to node. */ 74 | private final Set orphans = new HashSet<>(); 75 | 76 | /** The current minting task */ 77 | private AbstractMintingTask mintingTask = null; 78 | 79 | /** In the process of sending blocks. */ 80 | // TODO verify 81 | private boolean sendingBlock = false; 82 | 83 | // TODO 84 | private final ArrayList messageQue = new ArrayList<>(); 85 | // TODO 86 | private final Set downloadingBlocks = new HashSet<>(); 87 | 88 | /** Processing time of tasks expressed in milliseconds. */ 89 | private final long processingTime = 2; 90 | 91 | /** 92 | * Instantiates a new Node. 93 | * 94 | * @param nodeID the node id 95 | * @param numConnection the number of connections a node can have 96 | * @param region the region 97 | * @param miningPower the mining power 98 | * @param routingTableName the routing table name 99 | * @param consensusAlgoName the consensus algorithm name 100 | * @param useCBR whether the node uses compact block relay 101 | * @param isChurnNode whether the node causes churn 102 | */ 103 | public Node( 104 | int nodeID, 105 | int numConnection, 106 | int region, 107 | long miningPower, 108 | String routingTableName, 109 | String consensusAlgoName, 110 | boolean useCBR, 111 | boolean isChurnNode) { 112 | this.nodeID = nodeID; 113 | this.region = region; 114 | this.miningPower = miningPower; 115 | this.useCBR = useCBR; 116 | this.isChurnNode = isChurnNode; 117 | 118 | try { 119 | this.routingTable = 120 | (AbstractRoutingTable) 121 | Class.forName(routingTableName).getConstructor(Node.class).newInstance(this); 122 | this.consensusAlgo = 123 | (AbstractConsensusAlgo) 124 | Class.forName(consensusAlgoName).getConstructor(Node.class).newInstance(this); 125 | this.setNumConnection(numConnection); 126 | } catch (Exception e) { 127 | e.printStackTrace(); 128 | } 129 | } 130 | 131 | /** 132 | * Gets the node id. 133 | * 134 | * @return the node id 135 | */ 136 | public int getNodeID() { 137 | return this.nodeID; 138 | } 139 | 140 | /** 141 | * Gets the region ID assigned to a node. 142 | * 143 | * @return the region 144 | */ 145 | public int getRegion() { 146 | return this.region; 147 | } 148 | 149 | /** 150 | * Gets mining power. 151 | * 152 | * @return the mining power 153 | */ 154 | public long getMiningPower() { 155 | return this.miningPower; 156 | } 157 | 158 | /** 159 | * Gets the consensus algorithm. 160 | * 161 | * @return the consensus algorithm. See {@link AbstractConsensusAlgo} 162 | */ 163 | @SuppressWarnings("unused") 164 | public AbstractConsensusAlgo getConsensusAlgo() { 165 | return this.consensusAlgo; 166 | } 167 | 168 | /** 169 | * Gets routing table. 170 | * 171 | * @return the routing table 172 | */ 173 | public AbstractRoutingTable getRoutingTable() { 174 | return this.routingTable; 175 | } 176 | 177 | /** 178 | * Gets the current block. 179 | * 180 | * @return the block 181 | */ 182 | public Block getBlock() { 183 | return this.block; 184 | } 185 | 186 | /** 187 | * Gets all orphans known to node. 188 | * 189 | * @return the orphans 190 | */ 191 | public Set getOrphans() { 192 | return this.orphans; 193 | } 194 | 195 | /** 196 | * Gets the number of connections a node can have. 197 | * 198 | * @return the number of connection 199 | */ 200 | @SuppressWarnings("unused") 201 | public int getNumConnection() { 202 | return this.routingTable.getNumConnection(); 203 | } 204 | 205 | /** 206 | * Sets the number of connections a node can have. 207 | * 208 | * @param numConnection the n connection 209 | */ 210 | public void setNumConnection(int numConnection) { 211 | this.routingTable.setNumConnection(numConnection); 212 | } 213 | 214 | /** 215 | * Gets the nodes neighbors. 216 | * 217 | * @return the neighbors 218 | */ 219 | public ArrayList getNeighbors() { 220 | return this.routingTable.getNeighbors(); 221 | } 222 | 223 | /** 224 | * Adds the node as a neighbor. 225 | * 226 | * @param node the node to be added as a neighbor 227 | * @return the success state of the operation 228 | */ 229 | @SuppressWarnings("UnusedReturnValue") 230 | public boolean addNeighbor(Node node) { 231 | return this.routingTable.addNeighbor(node); 232 | } 233 | 234 | /** 235 | * Removes the neighbor form the node. 236 | * 237 | * @param node the node to be removed as a neighbor 238 | * @return the success state of the operation 239 | */ 240 | @SuppressWarnings("unused") 241 | public boolean removeNeighbor(Node node) { 242 | return this.routingTable.removeNeighbor(node); 243 | } 244 | 245 | /** Initializes the routing table. */ 246 | public void joinNetwork() { 247 | this.routingTable.initTable(); 248 | } 249 | 250 | /** Mint the genesis block. */ 251 | public void genesisBlock() { 252 | Block genesis = this.consensusAlgo.genesisBlock(); 253 | this.receiveBlock(genesis); 254 | } 255 | 256 | /** 257 | * Adds a new block to the to chain. If node was minting that task instance is abandoned, and the 258 | * new block arrival is handled. 259 | * 260 | * @param newBlock the new block 261 | */ 262 | public void addToChain(Block newBlock) { 263 | // If the node has been minting 264 | if (this.mintingTask != null) { 265 | removeTask(this.mintingTask); 266 | this.mintingTask = null; 267 | } 268 | // Update the current block 269 | this.block = newBlock; 270 | printAddBlock(newBlock); 271 | // Observe and handle new block arrival 272 | arriveBlock(newBlock, this); 273 | } 274 | 275 | /** 276 | * Logs the provided block to the logfile. 277 | * 278 | * @param newBlock the block to be logged 279 | */ 280 | private void printAddBlock(Block newBlock) { 281 | OUT_JSON_FILE.print("{"); 282 | OUT_JSON_FILE.print("\"kind\":\"add-block\","); 283 | OUT_JSON_FILE.print("\"content\":{"); 284 | OUT_JSON_FILE.print("\"timestamp\":" + getCurrentTime() + ","); 285 | OUT_JSON_FILE.print("\"node-id\":" + this.getNodeID() + ","); 286 | OUT_JSON_FILE.print("\"block-id\":" + newBlock.getId()); 287 | OUT_JSON_FILE.print("}"); 288 | OUT_JSON_FILE.print("},"); 289 | OUT_JSON_FILE.flush(); 290 | } 291 | 292 | /** 293 | * Add orphans. 294 | * 295 | * @param orphanBlock the orphan block 296 | * @param validBlock the valid block 297 | */ 298 | // TODO check this out later 299 | public void addOrphans(Block orphanBlock, Block validBlock) { 300 | if (orphanBlock != validBlock) { 301 | this.orphans.add(orphanBlock); 302 | this.orphans.remove(validBlock); 303 | if (validBlock == null || orphanBlock.getHeight() > validBlock.getHeight()) { 304 | this.addOrphans(orphanBlock.getParent(), validBlock); 305 | } else if (orphanBlock.getHeight() == validBlock.getHeight()) { 306 | this.addOrphans(orphanBlock.getParent(), validBlock.getParent()); 307 | } else { 308 | this.addOrphans(orphanBlock, validBlock.getParent()); 309 | } 310 | } 311 | } 312 | 313 | /** Generates a new minting task and registers it */ 314 | public void minting() { 315 | AbstractMintingTask task = this.consensusAlgo.minting(); 316 | this.mintingTask = task; 317 | if (task != null) { 318 | putTask(task); 319 | } 320 | } 321 | 322 | /** 323 | * Send inv. 324 | * 325 | * @param block the block 326 | */ 327 | public void sendInv(Block block) { 328 | for (Node to : this.routingTable.getNeighbors()) { 329 | AbstractMessageTask task = new InvMessageTask(this, to, block); 330 | putTask(task); 331 | } 332 | } 333 | 334 | /** 335 | * Receive block. 336 | * 337 | * @param block the block 338 | */ 339 | public void receiveBlock(Block block) { 340 | if (this.consensusAlgo.isReceivedBlockValid(block, this.block)) { 341 | if (this.block != null && !this.block.isOnSameChainAs(block)) { 342 | // If orphan mark orphan 343 | this.addOrphans(this.block, block); 344 | } 345 | // Else add to canonical chain 346 | this.addToChain(block); 347 | // Generates a new minting task 348 | this.minting(); 349 | // Advertise received block 350 | this.sendInv(block); 351 | } else if (!this.orphans.contains(block) && !block.isOnSameChainAs(this.block)) { 352 | // TODO better understand - what if orphan is not valid? 353 | // If the block was not valid but was an unknown orphan and is not on the same 354 | // chain as the 355 | // current block 356 | this.addOrphans(block, this.block); 357 | arriveBlock(block, this); 358 | } 359 | } 360 | 361 | /** 362 | * Receive message. 363 | * 364 | * @param message the message 365 | */ 366 | public void receiveMessage(AbstractMessageTask message) { 367 | Node from = message.getFrom(); 368 | 369 | if (message instanceof InvMessageTask) { 370 | Block block = ((InvMessageTask) message).getBlock(); 371 | if (!this.orphans.contains(block) && !this.downloadingBlocks.contains(block)) { 372 | if (this.consensusAlgo.isReceivedBlockValid(block, this.block)) { 373 | AbstractMessageTask task = new RecMessageTask(this, from, block); 374 | putTask(task); 375 | downloadingBlocks.add(block); 376 | } else if (!block.isOnSameChainAs(this.block)) { 377 | // get new orphan block 378 | AbstractMessageTask task = new RecMessageTask(this, from, block); 379 | putTask(task); 380 | downloadingBlocks.add(block); 381 | } 382 | } 383 | } 384 | 385 | if (message instanceof RecMessageTask) { 386 | this.messageQue.add((RecMessageTask) message); 387 | if (!sendingBlock) { 388 | this.sendNextBlockMessage(); 389 | } 390 | } 391 | 392 | if (message instanceof GetBlockTxnMessageTask) { 393 | this.messageQue.add((GetBlockTxnMessageTask) message); 394 | if (!sendingBlock) { 395 | this.sendNextBlockMessage(); 396 | } 397 | } 398 | 399 | if (message instanceof CmpctBlockMessageTask) { 400 | Block block = ((CmpctBlockMessageTask) message).getBlock(); 401 | float CBRfailureRate = 402 | this.isChurnNode ? CBR_FAILURE_RATE_FOR_CHURN_NODE : CBR_FAILURE_RATE_FOR_CONTROL_NODE; 403 | boolean success = random.nextDouble() > CBRfailureRate ? true : false; 404 | if (success) { 405 | downloadingBlocks.remove(block); 406 | this.receiveBlock(block); 407 | } else { 408 | AbstractMessageTask task = new GetBlockTxnMessageTask(this, from, block); 409 | putTask(task); 410 | } 411 | } 412 | 413 | if (message instanceof BlockMessageTask) { 414 | Block block = ((BlockMessageTask) message).getBlock(); 415 | downloadingBlocks.remove(block); 416 | this.receiveBlock(block); 417 | } 418 | } 419 | 420 | /** Gets block size when the node fails compact block relay. */ 421 | private long getFailedBlockSize() { 422 | if (this.isChurnNode) { 423 | int index = random.nextInt(CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE.length); 424 | return (long) (BLOCK_SIZE * CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE[index]); 425 | } else { 426 | int index = random.nextInt(CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE.length); 427 | return (long) (BLOCK_SIZE * CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE[index]); 428 | } 429 | } 430 | 431 | /** Send next block message. */ 432 | // send a block to the sender of the next queued recMessage 433 | public void sendNextBlockMessage() { 434 | if (this.messageQue.size() > 0) { 435 | Node to = this.messageQue.get(0).getFrom(); 436 | long bandwidth = getBandwidth(this.getRegion(), to.getRegion()); 437 | 438 | AbstractMessageTask messageTask; 439 | 440 | if (this.messageQue.get(0) instanceof RecMessageTask) { 441 | Block block = ((RecMessageTask) this.messageQue.get(0)).getBlock(); 442 | // If use compact block relay. 443 | if (this.messageQue.get(0).getFrom().useCBR && this.useCBR) { 444 | // Convert bytes to bits and divide by the bandwidth expressed as bit per 445 | // millisecond, add 446 | // processing time. 447 | long delay = COMPACT_BLOCK_SIZE * 8 / (bandwidth / 1000) + processingTime; 448 | 449 | // Send compact block message. 450 | messageTask = new CmpctBlockMessageTask(this, to, block, delay); 451 | } else { 452 | // Else use lagacy protocol. 453 | long delay = BLOCK_SIZE * 8 / (bandwidth / 1000) + processingTime; 454 | messageTask = new BlockMessageTask(this, to, block, delay); 455 | } 456 | } else if (this.messageQue.get(0) instanceof GetBlockTxnMessageTask) { 457 | // Else from requests missing transactions. 458 | Block block = ((GetBlockTxnMessageTask) this.messageQue.get(0)).getBlock(); 459 | long delay = getFailedBlockSize() * 8 / (bandwidth / 1000) + processingTime; 460 | messageTask = new BlockMessageTask(this, to, block, delay); 461 | } else { 462 | throw new UnsupportedOperationException(); 463 | } 464 | 465 | sendingBlock = true; 466 | this.messageQue.remove(0); 467 | putTask(messageTask); 468 | } else { 469 | sendingBlock = false; 470 | } 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/consensus/AbstractConsensusAlgo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node.consensus; 18 | 19 | import simblock.block.Block; 20 | import simblock.node.Node; 21 | import simblock.task.AbstractMintingTask; 22 | 23 | /** The type Abstract consensus algorithm. */ 24 | public abstract class AbstractConsensusAlgo { 25 | private final Node selfNode; 26 | 27 | /** 28 | * Instantiates a new Abstract consensus algo. 29 | * 30 | * @param selfNode the self node 31 | */ 32 | public AbstractConsensusAlgo(Node selfNode) { 33 | this.selfNode = selfNode; 34 | } 35 | 36 | /** 37 | * Gets the node using this consensus algorithm. 38 | * 39 | * @return the self node 40 | */ 41 | public Node getSelfNode() { 42 | return this.selfNode; 43 | } 44 | 45 | /** 46 | * Minting abstract minting task. 47 | * 48 | * @return the abstract minting task 49 | */ 50 | public abstract AbstractMintingTask minting(); 51 | 52 | /** 53 | * Tests if the receivedBlock is valid with regards to the current block. 54 | * 55 | * @param receivedBlock the received block 56 | * @param currentBlock the current block 57 | * @return true if block is valid false otherwise 58 | */ 59 | public abstract boolean isReceivedBlockValid(Block receivedBlock, Block currentBlock); 60 | 61 | /** 62 | * Gets the genesis block. 63 | * 64 | * @return the genesis block 65 | */ 66 | public abstract Block genesisBlock(); 67 | } 68 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/consensus/ProofOfWork.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node.consensus; 18 | 19 | import static simblock.simulator.Main.random; 20 | 21 | import java.math.BigInteger; 22 | import simblock.block.Block; 23 | import simblock.block.ProofOfWorkBlock; 24 | import simblock.node.Node; 25 | import simblock.task.MiningTask; 26 | 27 | /** The type Proof of work. */ 28 | @SuppressWarnings("unused") 29 | public class ProofOfWork extends AbstractConsensusAlgo { 30 | /** 31 | * Instantiates a new Proof of work consensus algorithm. 32 | * 33 | * @param selfNode the self node 34 | */ 35 | public ProofOfWork(Node selfNode) { 36 | super(selfNode); 37 | } 38 | 39 | /** Mints a new block by simulating Proof of Work. */ 40 | @Override 41 | public MiningTask minting() { 42 | Node selfNode = this.getSelfNode(); 43 | ProofOfWorkBlock parent = (ProofOfWorkBlock) selfNode.getBlock(); 44 | BigInteger difficulty = parent.getNextDifficulty(); 45 | double u = random.nextDouble(); 46 | return new MiningTask( 47 | selfNode, 48 | (long) (-Math.log(1 - u) * difficulty.doubleValue() / selfNode.getMiningPower()), 49 | difficulty); 50 | } 51 | 52 | /** 53 | * Tests if the receivedBlock is valid with regards to the current block. The receivedBlock is 54 | * valid if it is an instance of a Proof of Work block and the received block needs to have a 55 | * bigger difficulty than its parent next difficulty and a bigger total difficulty compared to the 56 | * current block. 57 | * 58 | * @param receivedBlock the received block 59 | * @param currentBlock the current block 60 | * @return true if block is valid false otherwise 61 | */ 62 | @Override 63 | public boolean isReceivedBlockValid(Block receivedBlock, Block currentBlock) { 64 | if (!(receivedBlock instanceof ProofOfWorkBlock)) { 65 | return false; 66 | } 67 | ProofOfWorkBlock recPoWBlock = (ProofOfWorkBlock) receivedBlock; 68 | ProofOfWorkBlock currPoWBlock = (ProofOfWorkBlock) currentBlock; 69 | int receivedBlockHeight = receivedBlock.getHeight(); 70 | ProofOfWorkBlock receivedBlockParent = 71 | receivedBlockHeight == 0 72 | ? null 73 | : (ProofOfWorkBlock) receivedBlock.getBlockWithHeight(receivedBlockHeight - 1); 74 | 75 | // TODO - dangerous to split due to short circuit operators being used, 76 | // refactor? 77 | return (receivedBlockHeight == 0 78 | || recPoWBlock.getDifficulty().compareTo(receivedBlockParent.getNextDifficulty()) >= 0) 79 | && (currentBlock == null 80 | || recPoWBlock.getTotalDifficulty().compareTo(currPoWBlock.getTotalDifficulty()) > 0); 81 | } 82 | 83 | @Override 84 | public ProofOfWorkBlock genesisBlock() { 85 | return ProofOfWorkBlock.genesisBlock(this.getSelfNode()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/consensus/SampleProofOfStake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node.consensus; 18 | 19 | import static simblock.simulator.Main.random; 20 | 21 | import java.math.BigInteger; 22 | import simblock.block.Block; 23 | import simblock.block.SamplePoSBlock; 24 | import simblock.node.Node; 25 | import simblock.task.SampleStakingTask; 26 | 27 | /** The type Sample proof of stake. */ 28 | @SuppressWarnings("unused") 29 | public class SampleProofOfStake extends AbstractConsensusAlgo { 30 | /** 31 | * Instantiates a new Sample proof of stake. 32 | * 33 | * @param selfNode the self node 34 | */ 35 | public SampleProofOfStake(Node selfNode) { 36 | super(selfNode); 37 | } 38 | 39 | @Override 40 | public SampleStakingTask minting() { 41 | Node selfNode = this.getSelfNode(); 42 | SamplePoSBlock parent = (SamplePoSBlock) selfNode.getBlock(); 43 | BigInteger difficulty = parent.getNextDifficulty(); 44 | double p = parent.getCoinage(selfNode).getCoinage().doubleValue() / difficulty.doubleValue(); 45 | double u = random.nextDouble(); 46 | return p <= Math.pow(2, -53) 47 | ? null 48 | : new SampleStakingTask( 49 | selfNode, (long) (Math.log(u) / Math.log(1.0 - p) * 1000), difficulty); 50 | } 51 | 52 | @SuppressWarnings("CheckStyle") 53 | @Override 54 | public boolean isReceivedBlockValid(Block receivedBlock, Block currentBlock) { 55 | if (!(receivedBlock instanceof SamplePoSBlock)) { 56 | return false; 57 | } 58 | SamplePoSBlock recPoSBlock = (SamplePoSBlock) receivedBlock; 59 | SamplePoSBlock currPoSBlock = (SamplePoSBlock) currentBlock; 60 | int receivedBlockHeight = receivedBlock.getHeight(); 61 | SamplePoSBlock receivedBlockParent = 62 | receivedBlockHeight == 0 63 | ? null 64 | : (SamplePoSBlock) receivedBlock.getBlockWithHeight(receivedBlockHeight - 1); 65 | 66 | // TODO - dangerous to split due to short circuit operators being used, 67 | // refactor? 68 | return (receivedBlockHeight == 0 69 | || recPoSBlock.getDifficulty().compareTo(receivedBlockParent.getNextDifficulty()) >= 0) 70 | && (currentBlock == null 71 | || recPoSBlock.getTotalDifficulty().compareTo(currPoSBlock.getTotalDifficulty()) > 0); 72 | } 73 | 74 | @Override 75 | public SamplePoSBlock genesisBlock() { 76 | return SamplePoSBlock.genesisBlock(this.getSelfNode()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/routing/AbstractRoutingTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node.routing; 18 | 19 | import java.util.ArrayList; 20 | import simblock.node.Node; 21 | 22 | /** An abstraction of the a routing table used by a {@link Node}. */ 23 | public abstract class AbstractRoutingTable { 24 | private final Node selfNode; 25 | private int numConnection = 8; 26 | 27 | /** 28 | * Instantiates a new Abstract routing table. 29 | * 30 | * @param selfNode the self node 31 | */ 32 | public AbstractRoutingTable(Node selfNode) { 33 | this.selfNode = selfNode; 34 | } 35 | 36 | /** 37 | * Gets self node. 38 | * 39 | * @return the self node 40 | */ 41 | protected Node getSelfNode() { 42 | return selfNode; 43 | } 44 | 45 | /** 46 | * Sets the number of possible active connections. 47 | * 48 | * @param numConnection the n connection 49 | */ 50 | public void setNumConnection(int numConnection) { 51 | this.numConnection = numConnection; 52 | } 53 | 54 | /** 55 | * Gets the number of possible active connections. 56 | * 57 | * @return the connection 58 | */ 59 | public int getNumConnection() { 60 | return this.numConnection; 61 | } 62 | 63 | /** Table initialization. */ 64 | public abstract void initTable(); 65 | 66 | /** 67 | * Gets neighbors. 68 | * 69 | * @return the neighbors 70 | */ 71 | public abstract ArrayList getNeighbors(); 72 | 73 | /** 74 | * Add a neighbor to the list of neighbors. 75 | * 76 | * @param node the node 77 | * @return the success state of the operation 78 | */ 79 | public abstract boolean addNeighbor(Node node); 80 | 81 | /** 82 | * Remove the neighbor from the list of neighbors. 83 | * 84 | * @param node the node 85 | * @return the success state of the operation 86 | */ 87 | public abstract boolean removeNeighbor(Node node); 88 | 89 | /** 90 | * Add inbound boolean. 91 | * 92 | * @param from the from 93 | * @return the boolean 94 | */ 95 | // TODO possibly incoming requests - just the hook I need 96 | public boolean addInbound(Node from) { 97 | return false; 98 | } 99 | 100 | /** 101 | * Remove inbound boolean. 102 | * 103 | * @param from the from 104 | * @return the boolean 105 | */ 106 | // TODO possibly incoming requests - just the hook I need 107 | public boolean removeInbound(Node from) { 108 | return false; 109 | } 110 | 111 | /** Accept block. */ 112 | // TODO unclear what this does 113 | public void acceptBlock() {} 114 | } 115 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/node/routing/BitcoinCoreTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.node.routing; 18 | 19 | import static simblock.simulator.Main.OUT_JSON_FILE; 20 | import static simblock.simulator.Main.random; 21 | import static simblock.simulator.Simulator.getSimulatedNodes; 22 | import static simblock.simulator.Timer.getCurrentTime; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import simblock.node.Node; 27 | 28 | /** 29 | * The implementation of the {@link AbstractRoutingTable} representing the Bitcoin core routing 30 | * table. 31 | */ 32 | @SuppressWarnings("unused") 33 | public class BitcoinCoreTable extends AbstractRoutingTable { 34 | 35 | /** The list of outbound connections. */ 36 | private final ArrayList outbound = new ArrayList<>(); 37 | 38 | /** The list of inbound connections. */ 39 | private final ArrayList inbound = new ArrayList<>(); 40 | 41 | /** 42 | * Instantiates a new Bitcoin core table. 43 | * 44 | * @param selfNode the self node 45 | */ 46 | public BitcoinCoreTable(Node selfNode) { 47 | super(selfNode); 48 | } 49 | 50 | /** 51 | * Gets all known outbound and inbound nodes. 52 | * 53 | * @return a list of known neighbors 54 | */ 55 | public ArrayList getNeighbors() { 56 | ArrayList neighbors = new ArrayList<>(); 57 | neighbors.addAll(outbound); 58 | neighbors.addAll(inbound); 59 | return neighbors; 60 | } 61 | 62 | /** 63 | * Initializes a new BitcoinCore routing table. From a pool of all available nodes, choose 64 | * candidates at random and fill the table using the allowed outbound connections amount. 65 | */ 66 | // TODO this should be done using the bootstrap node 67 | public void initTable() { 68 | ArrayList candidates = new ArrayList<>(); 69 | for (int i = 0; i < getSimulatedNodes().size(); i++) { 70 | candidates.add(i); 71 | } 72 | Collections.shuffle(candidates, random); 73 | for (int candidate : candidates) { 74 | if (this.outbound.size() < this.getNumConnection()) { 75 | this.addNeighbor(getSimulatedNodes().get(candidate)); 76 | } else { 77 | break; 78 | } 79 | } 80 | } 81 | 82 | /** 83 | * Adds the provided node to the list of outbound connections of self node.The provided node will 84 | * not be added if it is the self node, it exists as an outbound connection of the self node, it 85 | * exists as an inbound connection of the self node or the self node does not allow for additional 86 | * outbound connections. Otherwise, the self node will add the provided node to the list of 87 | * outbound connections and the provided node will add the self node to the list of inbound 88 | * connections. 89 | * 90 | * @param node the node to be connected to the self node. 91 | * @return the success state 92 | */ 93 | public boolean addNeighbor(Node node) { 94 | if (node == getSelfNode() 95 | || this.outbound.contains(node) 96 | || this.inbound.contains(node) 97 | || this.outbound.size() >= this.getNumConnection()) { 98 | return false; 99 | } else if (this.outbound.add(node) && node.getRoutingTable().addInbound(getSelfNode())) { 100 | printAddLink(node); 101 | return true; 102 | } else { 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * Remove the provided node from the list of outbound connections of the self node and the self 109 | * node from the list inbound connections from the provided node. 110 | * 111 | * @param node the node to be disconnected from the self node. 112 | * @return the success state of the operation 113 | */ 114 | public boolean removeNeighbor(Node node) { 115 | if (this.outbound.remove(node) && node.getRoutingTable().removeInbound(getSelfNode())) { 116 | printRemoveLink(node); 117 | return true; 118 | } 119 | return false; 120 | } 121 | 122 | /** 123 | * Adds the provided node as an inbound connection. 124 | * 125 | * @param from the node to be added as an inbound connection 126 | * @return the success state of the operation 127 | */ 128 | public boolean addInbound(Node from) { 129 | if (this.inbound.add(from)) { 130 | printAddLink(from); 131 | return true; 132 | } 133 | return false; 134 | } 135 | 136 | /** 137 | * Removes the provided node as an inbound connection. 138 | * 139 | * @param from the node to be removed as an inbound connection 140 | * @return the success state of the operation 141 | */ 142 | public boolean removeInbound(Node from) { 143 | if (this.inbound.remove(from)) { 144 | printRemoveLink(from); 145 | return true; 146 | } 147 | return false; 148 | } 149 | 150 | // TODO add example 151 | private void printAddLink(Node endNode) { 152 | OUT_JSON_FILE.print("{"); 153 | OUT_JSON_FILE.print("\"kind\":\"add-link\","); 154 | OUT_JSON_FILE.print("\"content\":{"); 155 | OUT_JSON_FILE.print("\"timestamp\":" + getCurrentTime() + ","); 156 | OUT_JSON_FILE.print("\"begin-node-id\":" + getSelfNode().getNodeID() + ","); 157 | OUT_JSON_FILE.print("\"end-node-id\":" + endNode.getNodeID()); 158 | OUT_JSON_FILE.print("}"); 159 | OUT_JSON_FILE.print("},"); 160 | OUT_JSON_FILE.flush(); 161 | } 162 | 163 | // TODO add example 164 | private void printRemoveLink(Node endNode) { 165 | OUT_JSON_FILE.print("{"); 166 | OUT_JSON_FILE.print("\"kind\":\"remove-link\","); 167 | OUT_JSON_FILE.print("\"content\":{"); 168 | OUT_JSON_FILE.print("\"timestamp\":" + getCurrentTime() + ","); 169 | OUT_JSON_FILE.print("\"begin-node-id\":" + getSelfNode().getNodeID() + ","); 170 | OUT_JSON_FILE.print("\"end-node-id\":" + endNode.getNodeID()); 171 | OUT_JSON_FILE.print("}"); 172 | OUT_JSON_FILE.print("},"); 173 | OUT_JSON_FILE.flush(); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/settings/NetworkConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.settings; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | /** The type Network configuration allows to configure network latency and bandwidth. */ 24 | public class NetworkConfiguration { 25 | /** Regions where nodes can exist. */ 26 | public static final List REGION_LIST = 27 | new ArrayList<>( 28 | Arrays.asList( 29 | "NORTH_AMERICA", "EUROPE", "SOUTH_AMERICA", "ASIA_PACIFIC", "JAPAN", "AUSTRALIA")); 30 | 31 | /** 32 | * LATENCY[i][j] is average latency from REGION_LIST[i] to REGION_LIST[j] Unit: millisecond, for 33 | * year 2015 34 | */ 35 | private static final long[][] LATENCY_2015 = { 36 | {36, 119, 255, 310, 154, 208}, 37 | {119, 12, 221, 242, 266, 350}, 38 | {255, 221, 137, 347, 256, 269}, 39 | {310, 242, 347, 99, 172, 278}, 40 | {154, 266, 256, 172, 9, 163}, 41 | {208, 350, 269, 278, 163, 22} 42 | }; 43 | /** 44 | * LATENCY[i][j] is average latency from REGION_LIST[i] to REGION_LIST[j] Unit: millisecond, for 45 | * year 2019 46 | */ 47 | private static final long[][] LATENCY_2019 = { 48 | {32, 124, 184, 198, 151, 189}, 49 | {124, 11, 227, 237, 252, 294}, 50 | {184, 227, 88, 325, 301, 322}, 51 | {198, 237, 325, 85, 58, 198}, 52 | {151, 252, 301, 58, 12, 126}, 53 | {189, 294, 322, 198, 126, 16} 54 | }; 55 | 56 | /** List of latency assigned to each region. (unit: millisecond) */ 57 | public static final long[][] LATENCY = LATENCY_2019; 58 | 59 | /** 60 | * List of download bandwidth assigned to each region, and last element is Inter-regional 61 | * bandwidth. (unit: bit per second) for year 2015 62 | */ 63 | private static final long[] DOWNLOAD_BANDWIDTH_2015 = { 64 | 25000000, 24000000, 6500000, 10000000, 17500000, 14000000, 6 * 1000000 65 | }; 66 | /** 67 | * List of download bandwidth assigned to each region, and last element is Inter-regional 68 | * bandwidth. (unit: bit per second) for year 2019 69 | */ 70 | private static final long[] DOWNLOAD_BANDWIDTH_2019 = { 71 | 52000000, 40000000, 18000000, 22800000, 22800000, 29900000, 6 * 1000000 72 | }; 73 | 74 | /** 75 | * List of download bandwidth assigned to each region, and last element is Inter-regional 76 | * bandwidth. (unit: bit per second) 77 | */ 78 | public static final long[] DOWNLOAD_BANDWIDTH = DOWNLOAD_BANDWIDTH_2019; 79 | 80 | /** 81 | * List of upload bandwidth assigned to each region. (unit: bit per second), and last element is 82 | * Inter-regional bandwidth for year 2015 83 | */ 84 | private static final long[] UPLOAD_BANDWIDTH_2015 = { 85 | 4700000, 8100000, 1800000, 5300000, 3400000, 5200000, 6 * 1000000 86 | }; 87 | 88 | /** 89 | * List of upload bandwidth assigned to each region. (unit: bit per second), and last element is 90 | * Inter-regional bandwidth for year 2019 91 | */ 92 | private static final long[] UPLOAD_BANDWIDTH_2019 = { 93 | 19200000, 20700000, 5800000, 15700000, 10200000, 11300000, 6 * 1000000 94 | }; 95 | 96 | /** 97 | * List of upload bandwidth assigned to each region. (unit: bit per second), and last element is 98 | * Inter-regional bandwidth. 99 | */ 100 | public static final long[] UPLOAD_BANDWIDTH = UPLOAD_BANDWIDTH_2019; 101 | 102 | /** Region distribution Bitcoin 2015. */ 103 | private static final double[] REGION_DISTRIBUTION_BITCOIN_2015 = { 104 | 0.3869, 0.5159, 0.0113, 105 | 0.0574, 0.0119, 0.0166 106 | }; 107 | 108 | /** Region distribution Bitcoin 2019. */ 109 | private static final double[] REGION_DISTRIBUTION_BITCOIN_2019 = { 110 | 0.3316, 0.4998, 0.0090, 111 | 0.1177, 0.0224, 0.0195 112 | }; 113 | 114 | /** Region distribution Litecoin. */ 115 | // TODO year 116 | private static final double[] REGION_DISTRIBUTION_LITECOIN = { 117 | 0.3661, 0.4791, 0.0149, 0.1022, 0.0238, 0.0139 118 | }; 119 | 120 | /** Region distribution Dogecoin. */ 121 | // TODO year 122 | private static final double[] REGION_DISTRIBUTION_DOGECOIN = { 123 | 0.3924, 0.4879, 0.0212, 0.0697, 0.0106, 0.0182 124 | }; 125 | 126 | /** 127 | * The distribution of node's region. Each value means the rate of the number of nodes in the 128 | * corresponding region to the number of all nodes. 129 | */ 130 | public static final double[] REGION_DISTRIBUTION = REGION_DISTRIBUTION_BITCOIN_2019; 131 | 132 | /** The cumulative distribution of number of outbound links for Bitcoin 2015. */ 133 | private static final double[] DEGREE_DISTRIBUTION_BITCOIN_2015 = { 134 | 0.025, 0.050, 0.075, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.97, 135 | 0.97, 0.98, 0.99, 0.995, 1.0 136 | }; 137 | 138 | /** The cumulative distribution of number of outbound links for Litecoin. */ 139 | // TODO year 140 | private static final double[] DEGREE_DISTRIBUTION_LITECOIN = { 141 | 0.01, 0.02, 0.04, 0.07, 0.09, 0.14, 0.20, 0.28, 0.39, 0.5, 0.6, 0.69, 0.76, 0.81, 0.85, 0.87, 142 | 0.89, 0.92, 0.93, 1.0 143 | }; 144 | 145 | /** The cumulative distribution of number of outbound links for Dogecoin. */ 146 | private static final double[] DEGREE_DISTRIBUTION_DOGECOIN = { 147 | 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.0, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 148 | 1.00, 1.00, 1.00, 1.0 149 | }; 150 | 151 | /** 152 | * The cumulative distribution of number of outbound links. Cf. Andrew Miller et al., "Discovering 153 | * bitcoin's public topology and influential nodes", 2015. 154 | */ 155 | public static final double[] DEGREE_DISTRIBUTION = DEGREE_DISTRIBUTION_BITCOIN_2015; 156 | } 157 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/settings/SimulationConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.settings; 18 | 19 | /** The type Simulation configuration allows for specific simulation instance configuration. */ 20 | public class SimulationConfiguration { 21 | /** The number of nodes participating in the blockchain network. */ 22 | // TODO revert 23 | public static final int NUM_OF_NODES = 300; // 600;//800;//6000; 24 | // public static final int NUM_OF_NODES = 600;//600;//800;//6000; 25 | 26 | /** The kind of routing table. */ 27 | public static final String TABLE = "simblock.node.routing.BitcoinCoreTable"; 28 | 29 | /** The consensus algorithm to be used. */ 30 | // TODO not documented in markdown 31 | // TODO return to PoW 32 | public static final String ALGO = "simblock.node.consensus.ProofOfWork"; 33 | 34 | /** 35 | * The expected value of block generation interval. The difficulty of mining is automatically 36 | * adjusted by this value and the sum of mining power. (unit: millisecond) 37 | */ 38 | public static final long INTERVAL = 1000 * 60 * 10; // 1000*60;//1000*30*5;//1000*60*10; 39 | 40 | /** 41 | * The average mining power of each node. Mining power corresponds to Hash Rate in Bitcoin, and is 42 | * the number of mining (hash calculation) executed per millisecond. 43 | */ 44 | public static final long AVERAGE_MINING_POWER = 400000; 45 | 46 | /** 47 | * The mining power of each node is determined randomly according to the normal distribution whose 48 | * average is AVERAGE_MINING_POWER and standard deviation is STDEV_OF_MINING_POWER. 49 | */ 50 | public static final long STDEV_OF_MINING_POWER = 100000; 51 | 52 | /** The constant AVERAGE_COINS. */ 53 | // TODO 54 | public static final int AVERAGE_COINS = 4000; 55 | /** The constant STDEV_OF_COINS. */ 56 | // TODO 57 | public static final int STDEV_OF_COINS = 2000; 58 | 59 | /** The reward a PoS minter gets for staking. */ 60 | public static final double STAKING_REWARD = 0.01; 61 | 62 | /** The block height when a simulation ends. */ 63 | // TODO revert 64 | // public static final int END_BLOCK_HEIGHT = 100; 65 | public static final int END_BLOCK_HEIGHT = 3; 66 | 67 | /** Block size. (unit: byte). */ 68 | public static final long BLOCK_SIZE = 535000; // 6110;//8000;//535000;//0.5MB 69 | 70 | /** The usage rate of compact block relay (CBR) protocol. */ 71 | public static final float CBR_USAGE_RATE = 0.964f; 72 | /** The rate of nodes that cause churn. */ 73 | public static final float CHURN_NODE_RATE = 0.976f; 74 | /** Compact block size. (unit: byte) */ 75 | public static final long COMPACT_BLOCK_SIZE = 18 * 1000; // 18KB 76 | /** CBR failure rate for a node that always connect network. */ 77 | public static final float CBR_FAILURE_RATE_FOR_CONTROL_NODE = 0.13f; 78 | /** CBR failure rate for a node that causes churn. */ 79 | public static final float CBR_FAILURE_RATE_FOR_CHURN_NODE = 0.27f; 80 | 81 | /** The distribution of data size that a control node receives when fails CBR. */ 82 | public static final float[] CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CONTROL_NODE = { 83 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 84 | 0.01f, 0.01f, 85 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 86 | 0.01f, 0.01f, 87 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 88 | 0.01f, 0.01f, 89 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 90 | 0.01f, 0.01f, 91 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 92 | 0.01f, 0.01f, 93 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 94 | 0.01f, 0.01f, 95 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 96 | 0.01f, 0.01f, 97 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 98 | 0.01f, 0.01f, 99 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 100 | 0.01f, 0.01f, 101 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 102 | 0.01f, 0.01f, 103 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 104 | 0.01f, 0.01f, 105 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 106 | 0.01f, 0.01f, 107 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 108 | 0.01f, 0.01f, 109 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 110 | 0.01f, 0.01f 111 | }; 112 | /** The distribution of data size that a churn node receives when fails CBR. */ 113 | public static final float[] CBR_FAILURE_BLOCK_SIZE_DISTRIBUTION_FOR_CHURN_NODE = { 114 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 115 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 116 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 117 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 118 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 119 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 120 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 121 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 122 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 123 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 124 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 125 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 126 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 127 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 128 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 129 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 130 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 131 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 132 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 133 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 134 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 135 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 136 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 137 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 138 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 139 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 140 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 141 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 142 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 143 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 144 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 145 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 146 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 147 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 148 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 149 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 150 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 151 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 152 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 153 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 154 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 155 | 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 156 | 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 157 | 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 158 | 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 159 | 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 160 | 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 161 | 0.02f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 162 | 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 163 | 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 0.03f, 164 | 0.03f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 165 | 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 166 | 0.04f, 0.04f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 167 | 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.06f, 0.06f, 0.06f, 168 | 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 0.06f, 169 | 0.06f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 0.07f, 170 | 0.07f, 0.07f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 0.08f, 171 | 0.08f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.1f, 0.1f, 172 | 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.11f, 0.11f, 0.11f, 0.11f, 0.11f, 0.11f, 0.11f, 173 | 0.11f, 0.11f, 0.12f, 0.12f, 0.12f, 0.12f, 0.12f, 0.12f, 0.12f, 0.12f, 0.13f, 0.13f, 0.13f, 174 | 0.13f, 0.13f, 0.13f, 0.13f, 0.14f, 0.14f, 0.14f, 0.14f, 0.14f, 0.14f, 0.14f, 0.15f, 0.15f, 175 | 0.15f, 0.15f, 0.15f, 0.15f, 0.16f, 0.16f, 0.16f, 0.16f, 0.16f, 0.16f, 0.17f, 0.17f, 0.17f, 176 | 0.17f, 0.17f, 0.18f, 0.18f, 0.18f, 0.18f, 0.18f, 0.19f, 0.19f, 0.19f, 0.19f, 0.19f, 0.2f, 0.2f, 177 | 0.2f, 0.2f, 0.21f, 0.21f, 0.21f, 0.21f, 0.22f, 0.22f, 0.22f, 0.22f, 0.23f, 0.23f, 0.23f, 0.23f, 178 | 0.24f, 0.24f, 0.24f, 0.24f, 0.25f, 0.25f, 0.25f, 0.26f, 0.26f, 0.26f, 0.27f, 0.27f, 0.27f, 179 | 0.28f, 0.28f, 0.28f, 0.29f, 0.29f, 0.29f, 0.3f, 0.3f, 0.3f, 0.31f, 0.31f, 0.31f, 0.32f, 0.32f, 180 | 0.32f, 0.33f, 0.33f, 0.34f, 0.34f, 0.35f, 0.35f, 0.36f, 0.36f, 0.37f, 0.37f, 0.38f, 0.38f, 181 | 0.39f, 0.39f, 0.4f, 0.4f, 0.41f, 0.41f, 0.42f, 0.42f, 0.43f, 0.43f, 0.44f, 0.44f, 0.45f, 0.45f, 182 | 0.46f, 0.46f, 0.47f, 0.47f, 0.48f, 0.48f, 0.49f, 0.5f, 0.51f, 0.52f, 0.53f, 0.54f, 0.55f, 0.56f, 183 | 0.57f, 0.58f, 0.59f, 0.6f, 0.61f, 0.62f, 0.63f, 0.64f, 0.65f, 0.66f, 0.67f, 0.68f, 0.69f, 0.7f, 184 | 0.71f, 0.72f, 0.73f, 0.74f, 0.75f, 0.76f, 0.77f, 0.78f, 0.79f, 0.8f, 0.81f, 0.82f, 0.83f, 0.84f, 185 | 0.85f, 0.86f, 0.87f, 0.88f, 0.89f, 0.9f, 0.91f, 0.92f, 0.93f, 0.94f, 0.95f, 0.96f 186 | }; 187 | } 188 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/simulator/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.simulator; 18 | 19 | import static simblock.settings.SimulationConfiguration.ALGO; 20 | import static simblock.settings.SimulationConfiguration.AVERAGE_MINING_POWER; 21 | import static simblock.settings.SimulationConfiguration.CBR_USAGE_RATE; 22 | import static simblock.settings.SimulationConfiguration.CHURN_NODE_RATE; 23 | import static simblock.settings.SimulationConfiguration.END_BLOCK_HEIGHT; 24 | import static simblock.settings.SimulationConfiguration.INTERVAL; 25 | import static simblock.settings.SimulationConfiguration.NUM_OF_NODES; 26 | import static simblock.settings.SimulationConfiguration.STDEV_OF_MINING_POWER; 27 | import static simblock.settings.SimulationConfiguration.TABLE; 28 | import static simblock.simulator.Network.getDegreeDistribution; 29 | import static simblock.simulator.Network.getRegionDistribution; 30 | import static simblock.simulator.Network.printRegion; 31 | import static simblock.simulator.Simulator.addNode; 32 | import static simblock.simulator.Simulator.getSimulatedNodes; 33 | import static simblock.simulator.Simulator.printAllPropagation; 34 | import static simblock.simulator.Simulator.setTargetInterval; 35 | import static simblock.simulator.Timer.getCurrentTime; 36 | import static simblock.simulator.Timer.getTask; 37 | import static simblock.simulator.Timer.runTask; 38 | 39 | import java.io.BufferedWriter; 40 | import java.io.File; 41 | import java.io.FileWriter; 42 | import java.io.IOException; 43 | import java.io.PrintWriter; 44 | import java.net.URI; 45 | import java.net.URISyntaxException; 46 | import java.util.ArrayList; 47 | import java.util.Collections; 48 | import java.util.HashSet; 49 | import java.util.List; 50 | import java.util.Random; 51 | import java.util.Set; 52 | import simblock.block.Block; 53 | import simblock.node.Node; 54 | import simblock.task.AbstractMintingTask; 55 | 56 | /** The type Main represents the entry point. */ 57 | public class Main { 58 | /** The constant to be used as the simulation seed. */ 59 | public static Random random = new Random(10); 60 | 61 | /** The initial simulation time. */ 62 | public static long simulationTime = 0; 63 | /** Path to config file. */ 64 | public static URI CONF_FILE_URI; 65 | /** Output path. */ 66 | public static URI OUT_FILE_URI; 67 | 68 | static { 69 | try { 70 | CONF_FILE_URI = ClassLoader.getSystemResource("simulator.conf").toURI(); 71 | OUT_FILE_URI = CONF_FILE_URI.resolve(new URI("../output/")); 72 | } catch (URISyntaxException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | 77 | /** The output writer. */ 78 | // TODO use logger 79 | public static PrintWriter OUT_JSON_FILE; 80 | 81 | /** The constant STATIC_JSON_FILE. */ 82 | // TODO use logger 83 | public static PrintWriter STATIC_JSON_FILE; 84 | 85 | static { 86 | try { 87 | OUT_JSON_FILE = 88 | new PrintWriter( 89 | new BufferedWriter(new FileWriter(new File(OUT_FILE_URI.resolve("./output.json"))))); 90 | STATIC_JSON_FILE = 91 | new PrintWriter( 92 | new BufferedWriter(new FileWriter(new File(OUT_FILE_URI.resolve("./static.json"))))); 93 | } catch (IOException e) { 94 | e.printStackTrace(); 95 | } 96 | } 97 | 98 | /** 99 | * The entry point. 100 | * 101 | * @param args the input arguments 102 | */ 103 | public static void main(String[] args) { 104 | final long start = System.currentTimeMillis(); 105 | setTargetInterval(INTERVAL); 106 | 107 | // start json format 108 | OUT_JSON_FILE.print("["); 109 | OUT_JSON_FILE.flush(); 110 | 111 | // Log regions 112 | printRegion(); 113 | 114 | // Setup network 115 | constructNetworkWithAllNodes(NUM_OF_NODES); 116 | 117 | // Initial block height, we stop at END_BLOCK_HEIGHT 118 | int currentBlockHeight = 1; 119 | 120 | // Iterate over tasks and handle 121 | while (getTask() != null) { 122 | if (getTask() instanceof AbstractMintingTask) { 123 | AbstractMintingTask task = (AbstractMintingTask) getTask(); 124 | if (task.getParent().getHeight() == currentBlockHeight) { 125 | currentBlockHeight++; 126 | } 127 | if (currentBlockHeight > END_BLOCK_HEIGHT) { 128 | break; 129 | } 130 | // Log every 100 blocks and at the second block 131 | // TODO use constants here 132 | if (currentBlockHeight % 100 == 0 || currentBlockHeight == 2) { 133 | writeGraph(currentBlockHeight); 134 | } 135 | } 136 | // Execute task 137 | runTask(); 138 | } 139 | 140 | // Print propagation information about all blocks 141 | printAllPropagation(); 142 | 143 | // TODO logger 144 | System.out.println(); 145 | 146 | Set blocks = new HashSet<>(); 147 | 148 | // Get the latest block from the first simulated node 149 | Block block = getSimulatedNodes().get(0).getBlock(); 150 | 151 | // Update the list of known blocks by adding the parents of the aforementioned 152 | // block 153 | while (block.getParent() != null) { 154 | blocks.add(block); 155 | block = block.getParent(); 156 | } 157 | 158 | Set orphans = new HashSet<>(); 159 | int averageOrphansSize = 0; 160 | // Gather all known orphans 161 | for (Node node : getSimulatedNodes()) { 162 | orphans.addAll(node.getOrphans()); 163 | averageOrphansSize += node.getOrphans().size(); 164 | } 165 | averageOrphansSize = averageOrphansSize / getSimulatedNodes().size(); 166 | 167 | // Record orphans to the list of all known blocks 168 | blocks.addAll(orphans); 169 | 170 | ArrayList blockList = new ArrayList<>(blocks); 171 | 172 | // Sort the blocks first by time, then by hash code 173 | blockList.sort( 174 | (a, b) -> { 175 | int order = Long.signum(a.getTime() - b.getTime()); 176 | if (order != 0) { 177 | return order; 178 | } 179 | order = System.identityHashCode(a) - System.identityHashCode(b); 180 | return order; 181 | }); 182 | 183 | // Log all orphans 184 | // TODO move to method and use logger 185 | for (Block orphan : orphans) { 186 | System.out.println(orphan + ":" + orphan.getHeight()); 187 | } 188 | System.out.println(averageOrphansSize); 189 | 190 | /* 191 | * Log in format: 192 | * <fork_information, block height, block ID> 193 | * fork_information: One of "OnChain" and "Orphan". "OnChain" denote block is on 194 | * Main chain. 195 | * "Orphan" denote block is an orphan block. 196 | */ 197 | // TODO move to method and use logger 198 | try { 199 | FileWriter fw = new FileWriter(new File(OUT_FILE_URI.resolve("./blockList.txt")), false); 200 | PrintWriter pw = new PrintWriter(new BufferedWriter(fw)); 201 | 202 | for (Block b : blockList) { 203 | if (!orphans.contains(b)) { 204 | pw.println("OnChain : " + b.getHeight() + " : " + b); 205 | } else { 206 | pw.println("Orphan : " + b.getHeight() + " : " + b); 207 | } 208 | } 209 | pw.close(); 210 | 211 | } catch (IOException ex) { 212 | ex.printStackTrace(); 213 | } 214 | 215 | OUT_JSON_FILE.print("{"); 216 | OUT_JSON_FILE.print("\"kind\":\"simulation-end\","); 217 | OUT_JSON_FILE.print("\"content\":{"); 218 | OUT_JSON_FILE.print("\"timestamp\":" + getCurrentTime()); 219 | OUT_JSON_FILE.print("}"); 220 | OUT_JSON_FILE.print("}"); 221 | // end json format 222 | OUT_JSON_FILE.print("]"); 223 | OUT_JSON_FILE.close(); 224 | 225 | long end = System.currentTimeMillis(); 226 | simulationTime += end - start; 227 | // Log simulation time in milliseconds 228 | System.out.println(simulationTime); 229 | } 230 | 231 | // TODO 以下の初期生成はシナリオを読み込むようにする予定 232 | // ノードを参加させるタスクを作る(ノードの参加と,リンクの貼り始めるタスクは分ける) 233 | // シナリオファイルで上の参加タスクをTimer入れていく. 234 | 235 | // TRANSLATED FROM ABOVE STATEMENT 236 | // The following initial generation will load the scenario 237 | // Create a task to join the node (separate the task of joining the node and the 238 | // task of 239 | // starting to paste the link) 240 | // Add the above participating tasks with a timer in the scenario file. 241 | 242 | /** 243 | * Populate the list using the distribution. 244 | * 245 | * @param distribution the distribution 246 | * @param facum whether the distribution is cumulative distribution 247 | * @return array list 248 | */ 249 | // TODO explanation on facum etc. 250 | public static ArrayList makeRandomListFollowDistribution( 251 | double[] distribution, boolean facum) { 252 | ArrayList list = new ArrayList<>(); 253 | int index = 0; 254 | 255 | if (facum) { 256 | for (; index < distribution.length; index++) { 257 | while (list.size() <= NUM_OF_NODES * distribution[index]) { 258 | list.add(index); 259 | } 260 | } 261 | while (list.size() < NUM_OF_NODES) { 262 | list.add(index); 263 | } 264 | } else { 265 | double acumulative = 0.0; 266 | for (; index < distribution.length; index++) { 267 | acumulative += distribution[index]; 268 | while (list.size() <= NUM_OF_NODES * acumulative) { 269 | list.add(index); 270 | } 271 | } 272 | while (list.size() < NUM_OF_NODES) { 273 | list.add(index); 274 | } 275 | } 276 | 277 | Collections.shuffle(list, random); 278 | return list; 279 | } 280 | 281 | /** 282 | * Populate the list using the rate. 283 | * 284 | * @param rate the rate of true 285 | * @return array list 286 | */ 287 | public static ArrayList makeRandomList(float rate) { 288 | ArrayList list = new ArrayList(); 289 | for (int i = 0; i < NUM_OF_NODES; i++) { 290 | list.add(i < NUM_OF_NODES * rate); 291 | } 292 | Collections.shuffle(list, random); 293 | return list; 294 | } 295 | 296 | /** 297 | * Generates a random mining power expressed as Hash Rate, and is the number of mining (hash 298 | * calculation) executed per millisecond. 299 | * 300 | * @return the number of hash calculations executed per millisecond. 301 | */ 302 | public static long genMiningPower() { 303 | double r = random.nextGaussian(); 304 | 305 | return Math.max((long) (r * STDEV_OF_MINING_POWER + AVERAGE_MINING_POWER), 1); 306 | } 307 | 308 | /** 309 | * Get a random minter of genesis block based on mining power. 310 | * 311 | * @return the node that will mint the genesis block 312 | */ 313 | public static Node getGenesisMinter() { 314 | long totalMiningPower = 0; 315 | for (Node node : getSimulatedNodes()) { 316 | totalMiningPower += node.getMiningPower(); 317 | } 318 | 319 | long randomValue = (long) (random.nextDouble() * totalMiningPower); 320 | long cumulativeMiningPower = 0; 321 | 322 | for (Node node : getSimulatedNodes()) { 323 | cumulativeMiningPower += node.getMiningPower(); 324 | if (randomValue < cumulativeMiningPower) { 325 | return node; 326 | } 327 | } 328 | return null; 329 | } 330 | 331 | /** 332 | * Construct network with the provided number of nodes. 333 | * 334 | * @param numNodes the num nodes 335 | */ 336 | public static void constructNetworkWithAllNodes(int numNodes) { 337 | 338 | // Random distribution of nodes per region 339 | double[] regionDistribution = getRegionDistribution(); 340 | List regionList = makeRandomListFollowDistribution(regionDistribution, false); 341 | 342 | // Random distribution of node degrees 343 | double[] degreeDistribution = getDegreeDistribution(); 344 | List degreeList = makeRandomListFollowDistribution(degreeDistribution, true); 345 | 346 | // List of nodes using compact block relay. 347 | List useCBRNodes = makeRandomList(CBR_USAGE_RATE); 348 | 349 | // List of churn nodes. 350 | List churnNodes = makeRandomList(CHURN_NODE_RATE); 351 | 352 | for (int id = 1; id <= numNodes; id++) { 353 | // Each node gets assigned a region, its degree, mining power, routing table and 354 | // consensus algorithm 355 | Node node = 356 | new Node( 357 | id, 358 | degreeList.get(id - 1) + 1, 359 | regionList.get(id - 1), 360 | genMiningPower(), 361 | TABLE, 362 | ALGO, 363 | useCBRNodes.get(id - 1), 364 | churnNodes.get(id - 1)); 365 | // Add the node to the list of simulated nodes 366 | addNode(node); 367 | 368 | OUT_JSON_FILE.print("{"); 369 | OUT_JSON_FILE.print("\"kind\":\"add-node\","); 370 | OUT_JSON_FILE.print("\"content\":{"); 371 | OUT_JSON_FILE.print("\"timestamp\":0,"); 372 | OUT_JSON_FILE.print("\"node-id\":" + id + ","); 373 | OUT_JSON_FILE.print("\"region-id\":" + regionList.get(id - 1)); 374 | OUT_JSON_FILE.print("}"); 375 | OUT_JSON_FILE.print("},"); 376 | OUT_JSON_FILE.flush(); 377 | } 378 | 379 | // Link newly generated nodes 380 | for (Node node : getSimulatedNodes()) { 381 | node.joinNetwork(); 382 | } 383 | 384 | // Select node based on mining power to mint the genesis block 385 | getGenesisMinter().genesisBlock(); 386 | } 387 | 388 | /** 389 | * Network information when block height is blockHeight, in format: 390 | * 391 | *

nodeID_1, nodeID_2 392 | * 393 | *

meaning there is a connection from nodeID_1 to right nodeID_1. 394 | * 395 | * @param blockHeight the index of the graph and the current block height 396 | */ 397 | // TODO use logger 398 | public static void writeGraph(int blockHeight) { 399 | try { 400 | FileWriter fw = 401 | new FileWriter(new File(OUT_FILE_URI.resolve("./graph/" + blockHeight + ".txt")), false); 402 | PrintWriter pw = new PrintWriter(new BufferedWriter(fw)); 403 | 404 | for (int index = 1; index <= getSimulatedNodes().size(); index++) { 405 | Node node = getSimulatedNodes().get(index - 1); 406 | for (int i = 0; i < node.getNeighbors().size(); i++) { 407 | Node neighbor = node.getNeighbors().get(i); 408 | pw.println(node.getNodeID() + " " + neighbor.getNodeID()); 409 | } 410 | } 411 | pw.close(); 412 | 413 | } catch (IOException ex) { 414 | ex.printStackTrace(); 415 | } 416 | } 417 | } 418 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/simulator/Network.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.simulator; 18 | 19 | import static simblock.settings.NetworkConfiguration.DEGREE_DISTRIBUTION; 20 | import static simblock.settings.NetworkConfiguration.DOWNLOAD_BANDWIDTH; 21 | import static simblock.settings.NetworkConfiguration.LATENCY; 22 | import static simblock.settings.NetworkConfiguration.REGION_DISTRIBUTION; 23 | import static simblock.settings.NetworkConfiguration.REGION_LIST; 24 | import static simblock.settings.NetworkConfiguration.UPLOAD_BANDWIDTH; 25 | import static simblock.simulator.Main.STATIC_JSON_FILE; 26 | import static simblock.simulator.Main.random; 27 | 28 | import java.util.List; 29 | import simblock.settings.NetworkConfiguration; 30 | 31 | /** 32 | * The type Network represents a network split in regions, each node belonging to a region with an 33 | * upload bandwidth and a download bandwidth. Node degrees follow a predefined degree distribution. 34 | */ 35 | // TODO how is this degree distribution calculated and what does the double 36 | // array mean 37 | public class Network { 38 | 39 | /** 40 | * Gets latency according with 20% variance pallet distribution. 41 | * 42 | * @param from the from latency 43 | * @param to the to latency 44 | * @return the calculated latency 45 | */ 46 | public static final long getLatency(int from, int to) { 47 | long mean = LATENCY[from][to]; 48 | double shape = 0.2 * mean; 49 | double scale = mean - 5; 50 | return Math.round(scale / Math.pow(random.nextDouble(), 1.0 / shape)); 51 | } 52 | 53 | /** 54 | * Gets the minimum between the from upload bandwidth and to download bandwidth. 55 | * 56 | * @param from the from index in the {@link NetworkConfiguration#UPLOAD_BANDWIDTH} array. 57 | * @param to the to index in the {@link NetworkConfiguration#UPLOAD_BANDWIDTH} array. 58 | * @return the bandwidth 59 | */ 60 | public static final long getBandwidth(int from, int to) { 61 | return Math.min(UPLOAD_BANDWIDTH[from], DOWNLOAD_BANDWIDTH[to]); 62 | } 63 | 64 | /** 65 | * Gets region list. 66 | * 67 | * @return the {@link NetworkConfiguration#REGION_LIST} list. 68 | */ 69 | public static List getRegionList() { 70 | return REGION_LIST; 71 | } 72 | 73 | /** 74 | * Return the number of nodes in the corresponding region as a portion the number of all nodes. 75 | * 76 | * @return an array the distribution 77 | */ 78 | public static double[] getRegionDistribution() { 79 | return REGION_DISTRIBUTION; 80 | } 81 | 82 | /** 83 | * Get degree distribution double [ ]. 84 | * 85 | * @return the double [ ] 86 | */ 87 | // TODO 88 | public static double[] getDegreeDistribution() { 89 | return DEGREE_DISTRIBUTION; 90 | } 91 | 92 | /** Prints the currently active regions to outfile. */ 93 | // TODO 94 | public static void printRegion() { 95 | STATIC_JSON_FILE.print("{\"region\":["); 96 | 97 | int id = 0; 98 | for (; id < REGION_LIST.size() - 1; id++) { 99 | STATIC_JSON_FILE.print("{"); 100 | STATIC_JSON_FILE.print("\"id\":" + id + ","); 101 | STATIC_JSON_FILE.print("\"name\":\"" + REGION_LIST.get(id) + "\""); 102 | STATIC_JSON_FILE.print("},"); 103 | } 104 | 105 | STATIC_JSON_FILE.print("{"); 106 | STATIC_JSON_FILE.print("\"id\":" + id + ","); 107 | STATIC_JSON_FILE.print("\"name\":\"" + REGION_LIST.get(id) + "\""); 108 | STATIC_JSON_FILE.print("}"); 109 | STATIC_JSON_FILE.print("]}"); 110 | STATIC_JSON_FILE.flush(); 111 | STATIC_JSON_FILE.close(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/simulator/Simulator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.simulator; 18 | 19 | import static simblock.simulator.Timer.getCurrentTime; 20 | 21 | import java.util.ArrayList; 22 | import java.util.LinkedHashMap; 23 | import java.util.Map; 24 | import simblock.block.Block; 25 | import simblock.node.Node; 26 | 27 | /** 28 | * The type Simulator is tasked with maintaining the list of simulated nodes and managing the block 29 | * interval. It observes and manages the arrival of new blocks at the simulation level. 30 | */ 31 | public class Simulator { 32 | 33 | /** A list of nodes that will be used in a simulation. */ 34 | private static final ArrayList simulatedNodes = new ArrayList<>(); 35 | 36 | /** The target block interval in milliseconds. */ 37 | private static long targetInterval; 38 | 39 | /** 40 | * Get simulated nodes list. 41 | * 42 | * @return the array list 43 | */ 44 | public static ArrayList getSimulatedNodes() { 45 | return simulatedNodes; 46 | } 47 | 48 | /** 49 | * Get target block interval. 50 | * 51 | * @return the target block interval in milliseconds 52 | */ 53 | public static long getTargetInterval() { 54 | return targetInterval; 55 | } 56 | 57 | /** 58 | * Sets the target block interval. 59 | * 60 | * @param interval - block interval in milliseconds 61 | */ 62 | public static void setTargetInterval(long interval) { 63 | targetInterval = interval; 64 | } 65 | 66 | /** 67 | * Add node to the list of simulated nodes. 68 | * 69 | * @param node the node 70 | */ 71 | public static void addNode(Node node) { 72 | simulatedNodes.add(node); 73 | } 74 | 75 | /** 76 | * Remove node from the list of simulated nodes. 77 | * 78 | * @param node the node 79 | */ 80 | @SuppressWarnings("unused") 81 | public static void removeNode(Node node) { 82 | simulatedNodes.remove(node); 83 | } 84 | 85 | /** 86 | * Add node to the list of simulated nodes and immediately try to add the new node as a neighbor 87 | * to all simulated nodes. 88 | * 89 | * @param node the node 90 | */ 91 | @SuppressWarnings("unused") 92 | public static void addNodeWithConnection(Node node) { 93 | node.joinNetwork(); 94 | addNode(node); 95 | for (Node existingNode : simulatedNodes) { 96 | existingNode.addNeighbor(node); 97 | } 98 | } 99 | 100 | /** A list of observed {@link Block} instances. */ 101 | private static final ArrayList observedBlocks = new ArrayList<>(); 102 | 103 | /** 104 | * A list of observed block propagation times. The map key represents the id of the node that has 105 | * seen the block, the value represents the difference between the current time and the block 106 | * minting time, effectively recording the absolute time it took for a node to witness the block. 107 | */ 108 | private static final ArrayList> observedPropagations = 109 | new ArrayList<>(); 110 | 111 | /** 112 | * Handle the arrival of a new block. For every observed block, propagation information is 113 | * updated, and for a new block propagation information is created. 114 | * 115 | * @param block the block 116 | * @param node the node 117 | */ 118 | public static void arriveBlock(Block block, Node node) { 119 | // If block is already seen by any node 120 | if (observedBlocks.contains(block)) { 121 | // Get the propagation information for the current block 122 | LinkedHashMap propagation = 123 | observedPropagations.get(observedBlocks.indexOf(block)); 124 | // Update information for the new block 125 | propagation.put(node.getNodeID(), getCurrentTime() - block.getTime()); 126 | } else { 127 | // If the block has not been seen by any node and there is no memory allocated 128 | // TODO move magic number to constant 129 | if (observedBlocks.size() > 10) { 130 | // After the observed blocks limit is reached, log and remove old blocks by FIFO 131 | // principle 132 | printPropagation(observedBlocks.get(0), observedPropagations.get(0)); 133 | observedBlocks.remove(0); 134 | observedPropagations.remove(0); 135 | } 136 | // If the block has not been seen by any node and there is additional memory 137 | LinkedHashMap propagation = new LinkedHashMap<>(); 138 | propagation.put(node.getNodeID(), getCurrentTime() - block.getTime()); 139 | // Record the block as seen 140 | observedBlocks.add(block); 141 | // Record the propagation time 142 | observedPropagations.add(propagation); 143 | } 144 | } 145 | 146 | /** 147 | * Print propagation information about the propagation of the provided block in the format: 148 | * 149 | *

node_ID, propagation_time 150 | * 151 | *

propagation_time: The time from when the block of the block ID is generated to when 152 | * the node of the node_ID is reached. 153 | * 154 | * @param block the block 155 | * @param propagation the propagation of the provided block as a list of {@link Node} IDs and 156 | * propagation times 157 | */ 158 | public static void printPropagation(Block block, LinkedHashMap propagation) { 159 | // Print block and its height 160 | // TODO block does not have a toString method, what is printed here 161 | System.out.println(block + ":" + block.getHeight()); 162 | for (Map.Entry timeEntry : propagation.entrySet()) { 163 | System.out.println(timeEntry.getKey() + "," + timeEntry.getValue()); 164 | } 165 | System.out.println(); 166 | } 167 | 168 | /** 169 | * Print propagation information about all blocks, internally relying on {@link 170 | * Simulator#printPropagation(Block, LinkedHashMap)}. 171 | */ 172 | public static void printAllPropagation() { 173 | for (int i = 0; i < observedBlocks.size(); i++) { 174 | printPropagation(observedBlocks.get(i), observedPropagations.get(i)); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/simulator/Timer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.simulator; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import java.util.PriorityQueue; 22 | import simblock.task.Task; 23 | 24 | /** 25 | * The type Timer schedules the execution of simulation tasks stored in a Future Event List (FEL) . 26 | * Each {@link Task} can be scheduled for execution. Tasks that have been run get removed from the 27 | * FEL. 28 | */ 29 | public class Timer { 30 | 31 | /** A sorted queue of scheduled tasks. */ 32 | private static final PriorityQueue taskQueue = new PriorityQueue<>(); 33 | 34 | /** 35 | * A map containing a mapping of all tasks to their ScheduledTask counterparts. When executed, the 36 | * key - value pair is to be removed from the mapping. 37 | */ 38 | // TODO a bit redundant since Task is again stored in ScheduledTask. Is there a 39 | // better approach? 40 | private static final Map taskMap = new HashMap<>(); 41 | /** Initial simulation time in milliseconds. */ 42 | // TODO is it milliseconds? 43 | private static long currentTime = 0L; 44 | 45 | /** Represents a {@link Task} that is scheduled to be executed. */ 46 | private static class ScheduledTask implements Comparable { 47 | private final Task task; 48 | private final long scheduledTime; 49 | 50 | /** 51 | * Instantiates a new ScheduledTask. 52 | * 53 | * @param task - the task to be executed 54 | * @param scheduledTime - the simulation time at which the task is to be executed 55 | */ 56 | private ScheduledTask(Task task, long scheduledTime) { 57 | this.task = task; 58 | this.scheduledTime = scheduledTime; 59 | } 60 | 61 | /** 62 | * Gets the task. 63 | * 64 | * @return the {@link Task} instance 65 | */ 66 | private Task getTask() { 67 | return this.task; 68 | } 69 | 70 | /** 71 | * Gets the scheduled time at which the task is to be executed. 72 | * 73 | * @return the scheduled time 74 | */ 75 | private long getScheduledTime() { 76 | return this.scheduledTime; 77 | } 78 | 79 | /** 80 | * Compares the two scheduled tasks. 81 | * 82 | * @param o other task 83 | * @return 1 if self is executed later, 0 if concurrent and -1 if self is to be executed before. 84 | */ 85 | public int compareTo(ScheduledTask o) { 86 | if (this.equals(o)) { 87 | return 0; 88 | } 89 | int order = Long.signum(this.scheduledTime - o.scheduledTime); 90 | if (order != 0) { 91 | return order; 92 | } 93 | order = System.identityHashCode(this) - System.identityHashCode(o); 94 | return order; 95 | } 96 | } 97 | 98 | /** Runs a {@link ScheduledTask}. */ 99 | public static void runTask() { 100 | // If there are any tasks 101 | if (taskQueue.size() > 0) { 102 | // Get the next ScheduledTask 103 | ScheduledTask currentScheduledTask = taskQueue.poll(); 104 | Task currentTask = currentScheduledTask.getTask(); 105 | currentTime = currentScheduledTask.getScheduledTime(); 106 | // Remove the task from the mapping of all tasks 107 | taskMap.remove(currentTask, currentScheduledTask); 108 | // Execute 109 | currentTask.run(); 110 | } 111 | } 112 | 113 | /** 114 | * Remove task from the mapping of all tasks and from the execution queue. 115 | * 116 | * @param task the task to be removed 117 | */ 118 | public static void removeTask(Task task) { 119 | if (taskMap.containsKey(task)) { 120 | ScheduledTask scheduledTask = taskMap.get(task); 121 | taskQueue.remove(scheduledTask); 122 | taskMap.remove(task, scheduledTask); 123 | } 124 | } 125 | 126 | /** 127 | * Get the {@link Task} from the execution queue to be executed next. 128 | * 129 | * @return the task from the queue or null if task queue is empty. 130 | */ 131 | public static Task getTask() { 132 | if (taskQueue.size() > 0) { 133 | ScheduledTask currentTask = taskQueue.peek(); 134 | return currentTask.getTask(); 135 | } else { 136 | return null; 137 | } 138 | } 139 | 140 | /** 141 | * Schedule task to be executed at the current time incremented by the task duration. 142 | * 143 | * @param task the task 144 | */ 145 | public static void putTask(Task task) { 146 | ScheduledTask scheduledTask = new ScheduledTask(task, currentTime + task.getInterval()); 147 | taskMap.put(task, scheduledTask); 148 | taskQueue.add(scheduledTask); 149 | } 150 | 151 | /** 152 | * Schedule task to be executed at the provided absolute timestamp. 153 | * 154 | * @param task the task 155 | * @param time the time in milliseconds 156 | */ 157 | @SuppressWarnings("unused") 158 | public static void putTaskAbsoluteTime(Task task, long time) { 159 | ScheduledTask scheduledTask = new ScheduledTask(task, time); 160 | taskMap.put(task, scheduledTask); 161 | taskQueue.add(scheduledTask); 162 | } 163 | 164 | /** 165 | * Get current time in milliseconds. 166 | * 167 | * @return the time 168 | */ 169 | public static long getCurrentTime() { 170 | return currentTime; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/AbstractMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import static simblock.simulator.Network.getLatency; 20 | 21 | import simblock.node.Node; 22 | 23 | /** The type Abstract message task. */ 24 | public abstract class AbstractMessageTask implements Task { 25 | /** The sending entity. */ 26 | private final Node from; 27 | /** The receiving entity. */ 28 | private final Node to; 29 | 30 | /** 31 | * Instantiates a new Abstract message task. 32 | * 33 | * @param from the sending entity 34 | * @param to the receiving entity 35 | */ 36 | public AbstractMessageTask(Node from, Node to) { 37 | this.from = from; 38 | this.to = to; 39 | } 40 | 41 | /** 42 | * Get the sending node. 43 | * 44 | * @return the from node 45 | */ 46 | public Node getFrom() { 47 | return this.from; 48 | } 49 | 50 | /** 51 | * Get the receiving node. 52 | * 53 | * @return the to node 54 | */ 55 | public Node getTo() { 56 | return this.to; 57 | } 58 | 59 | /** 60 | * Get the message delay with regards to respective regions. 61 | * 62 | * @return the message sending interval 63 | */ 64 | public long getInterval() { 65 | long latency = getLatency(this.from.getRegion(), this.to.getRegion()); 66 | // Add 10 milliseconds here, why? 67 | // TODO 68 | return latency + 10; 69 | } 70 | 71 | /** Receive message at the to side. */ 72 | public void run() { 73 | this.to.receiveMessage(this); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/AbstractMintingTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import simblock.block.Block; 20 | import simblock.node.Node; 21 | 22 | /** The type Abstract minting task represents . */ 23 | public abstract class AbstractMintingTask implements Task { 24 | /** The node to mint the block. */ 25 | private final Node minter; 26 | /** The parent block. */ 27 | private final Block parent; 28 | 29 | /** Block interval in milliseconds. */ 30 | private final long interval; 31 | 32 | /** 33 | * Instantiates a new Abstract minting task. 34 | * 35 | * @param minter the minter 36 | * @param interval the interval in milliseconds 37 | */ 38 | public AbstractMintingTask(Node minter, long interval) { 39 | this.parent = minter.getBlock(); 40 | this.minter = minter; 41 | this.interval = interval; 42 | } 43 | 44 | /** 45 | * Gets minter. 46 | * 47 | * @return the minter 48 | */ 49 | public Node getMinter() { 50 | return minter; 51 | } 52 | 53 | /** 54 | * Gets the minted blocks parent. 55 | * 56 | * @return the parent 57 | */ 58 | public Block getParent() { 59 | return parent; 60 | } 61 | 62 | @Override 63 | public long getInterval() { 64 | return this.interval; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/BlockMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import static simblock.simulator.Main.OUT_JSON_FILE; 20 | import static simblock.simulator.Network.getLatency; 21 | import static simblock.simulator.Timer.getCurrentTime; 22 | 23 | import simblock.block.Block; 24 | import simblock.node.Node; 25 | 26 | /** The type Block message task. */ 27 | // Bitcoin protocol Wiki: 28 | // https://en.bitcoin.it/wiki/Protocol_documentation#block 29 | public class BlockMessageTask extends AbstractMessageTask { 30 | /** The {@link Block} that is sent. */ 31 | private final Block block; 32 | 33 | /** The block message sending delay in milliseconds. */ 34 | private final long interval; 35 | 36 | /** 37 | * Instantiates a new Block message task. 38 | * 39 | * @param from the sender 40 | * @param to the receiver 41 | * @param block the block instance 42 | * @param delay the delay of the message transmission 43 | */ 44 | public BlockMessageTask(Node from, Node to, Block block, long delay) { 45 | super(from, to); 46 | this.block = block; 47 | this.interval = getLatency(this.getFrom().getRegion(), this.getTo().getRegion()) + delay; 48 | } 49 | 50 | @Override 51 | public long getInterval() { 52 | return this.interval; 53 | } 54 | 55 | /** Sends a new block message from the sender to the receiver and logs the event. */ 56 | @Override 57 | public void run() { 58 | 59 | this.getFrom().sendNextBlockMessage(); 60 | 61 | OUT_JSON_FILE.print("{"); 62 | OUT_JSON_FILE.print("\"kind\":\"flow-block\","); 63 | OUT_JSON_FILE.print("\"content\":{"); 64 | OUT_JSON_FILE.print("\"transmission-timestamp\":" + (getCurrentTime() - this.interval) + ","); 65 | OUT_JSON_FILE.print("\"reception-timestamp\":" + getCurrentTime() + ","); 66 | OUT_JSON_FILE.print("\"begin-node-id\":" + getFrom().getNodeID() + ","); 67 | OUT_JSON_FILE.print("\"end-node-id\":" + getTo().getNodeID() + ","); 68 | OUT_JSON_FILE.print("\"block-id\":" + block.getId()); 69 | OUT_JSON_FILE.print("}"); 70 | OUT_JSON_FILE.print("},"); 71 | OUT_JSON_FILE.flush(); 72 | 73 | super.run(); 74 | } 75 | 76 | /** 77 | * Get block. 78 | * 79 | * @return the block 80 | */ 81 | public Block getBlock() { 82 | return this.block; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/CmpctBlockMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import static simblock.simulator.Main.OUT_JSON_FILE; 20 | import static simblock.simulator.Network.getLatency; 21 | import static simblock.simulator.Timer.getCurrentTime; 22 | 23 | import simblock.block.Block; 24 | import simblock.node.Node; 25 | 26 | /** The type Compact block message task. */ 27 | // Compact block relay protocol Wiki: 28 | // https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki 29 | public class CmpctBlockMessageTask extends AbstractMessageTask { 30 | /** The {@link Block} that is sent. */ 31 | private final Block block; 32 | 33 | /** The block message sending delay in milliseconds. */ 34 | private final long interval; 35 | 36 | /** 37 | * Instantiates a new Compact block message task. 38 | * 39 | * @param from the sender 40 | * @param to the receiver 41 | * @param block the block instance 42 | * @param delay the delay of the message transmission 43 | */ 44 | public CmpctBlockMessageTask(Node from, Node to, Block block, long delay) { 45 | super(from, to); 46 | this.block = block; 47 | this.interval = getLatency(this.getFrom().getRegion(), this.getTo().getRegion()) + delay; 48 | } 49 | 50 | @Override 51 | public long getInterval() { 52 | return this.interval; 53 | } 54 | 55 | /** Sends a new compact block message from the sender to the receiver and logs the event. */ 56 | @Override 57 | public void run() { 58 | 59 | this.getFrom().sendNextBlockMessage(); 60 | 61 | OUT_JSON_FILE.print("{"); 62 | OUT_JSON_FILE.print("\"kind\":\"flow-block\","); 63 | OUT_JSON_FILE.print("\"content\":{"); 64 | OUT_JSON_FILE.print("\"transmission-timestamp\":" + (getCurrentTime() - this.interval) + ","); 65 | OUT_JSON_FILE.print("\"reception-timestamp\":" + getCurrentTime() + ","); 66 | OUT_JSON_FILE.print("\"begin-node-id\":" + getFrom().getNodeID() + ","); 67 | OUT_JSON_FILE.print("\"end-node-id\":" + getTo().getNodeID() + ","); 68 | OUT_JSON_FILE.print("\"block-id\":" + block.getId()); 69 | OUT_JSON_FILE.print("}"); 70 | OUT_JSON_FILE.print("},"); 71 | OUT_JSON_FILE.flush(); 72 | 73 | super.run(); 74 | } 75 | 76 | /** 77 | * Get block. 78 | * 79 | * @return the block 80 | */ 81 | public Block getBlock() { 82 | return this.block; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/GetBlockTxnMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import simblock.block.Block; 20 | import simblock.node.Node; 21 | 22 | /** The type GetBlockTxn message task. */ 23 | // Compact block relay protocol Wiki: 24 | // https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki 25 | public class GetBlockTxnMessageTask extends AbstractMessageTask { 26 | /** The {@link Block} that is sent by from as compact block. */ 27 | private Block block; 28 | 29 | public GetBlockTxnMessageTask(Node from, Node to, Block block) { 30 | super(from, to); 31 | this.block = block; 32 | } 33 | 34 | /** 35 | * Get block. 36 | * 37 | * @return the block 38 | */ 39 | public Block getBlock() { 40 | return this.block; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/InvMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import simblock.block.Block; 20 | import simblock.node.Node; 21 | 22 | /** The type Inv message task, allows a node to advertise its knowledge of a block. */ 23 | // Bitcoin protocol Wiki: https://en.bitcoin.it/wiki/Protocol_documentation#inv 24 | public class InvMessageTask extends AbstractMessageTask { 25 | 26 | /** Block to be advertised. */ 27 | private final Block block; 28 | 29 | /** 30 | * Instantiates a new Inv message task. 31 | * 32 | * @param from the sender 33 | * @param to the receiver 34 | * @param block the block to be advertised 35 | */ 36 | public InvMessageTask(Node from, Node to, Block block) { 37 | super(from, to); 38 | this.block = block; 39 | } 40 | 41 | /** 42 | * Gets block. 43 | * 44 | * @return the block 45 | */ 46 | public Block getBlock() { 47 | return this.block; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/MiningTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import static simblock.simulator.Timer.getCurrentTime; 20 | 21 | import java.math.BigInteger; 22 | import simblock.block.ProofOfWorkBlock; 23 | import simblock.node.Node; 24 | 25 | /** The type Mining task. */ 26 | public class MiningTask extends AbstractMintingTask { 27 | private final BigInteger difficulty; 28 | 29 | /** 30 | * Instantiates a new Mining task. 31 | * 32 | * @param minter the minter 33 | * @param interval the interval 34 | * @param difficulty the difficulty 35 | */ 36 | // TODO how is the difficulty expressed and used here? 37 | public MiningTask(Node minter, long interval, BigInteger difficulty) { 38 | super(minter, interval); 39 | this.difficulty = difficulty; 40 | } 41 | 42 | @Override 43 | public void run() { 44 | ProofOfWorkBlock createdBlock = 45 | new ProofOfWorkBlock( 46 | (ProofOfWorkBlock) this.getParent(), 47 | this.getMinter(), 48 | getCurrentTime(), 49 | this.difficulty); 50 | this.getMinter().receiveBlock(createdBlock); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/RecMessageTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import simblock.block.Block; 20 | import simblock.node.Node; 21 | 22 | /** The type Rec message task receives a block. */ 23 | public class RecMessageTask extends AbstractMessageTask { 24 | 25 | /** The block to be received. */ 26 | private final Block block; 27 | 28 | /** 29 | * Instantiates a new Rec message task. 30 | * 31 | * @param from the sending node 32 | * @param to the receiving node 33 | * @param block the block to be received 34 | */ 35 | public RecMessageTask(Node from, Node to, Block block) { 36 | super(from, to); 37 | this.block = block; 38 | } 39 | 40 | /** 41 | * Gets the block to be received. 42 | * 43 | * @return the block 44 | */ 45 | public Block getBlock() { 46 | return this.block; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/SampleStakingTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | import static simblock.simulator.Timer.getCurrentTime; 20 | 21 | import java.math.BigInteger; 22 | import simblock.block.SamplePoSBlock; 23 | import simblock.node.Node; 24 | 25 | public class SampleStakingTask extends AbstractMintingTask { 26 | private final BigInteger difficulty; 27 | 28 | public SampleStakingTask(Node minter, long interval, BigInteger difficulty) { 29 | super(minter, interval); 30 | this.difficulty = difficulty; 31 | } 32 | 33 | @Override 34 | public void run() { 35 | SamplePoSBlock createdBlock = 36 | new SamplePoSBlock( 37 | (SamplePoSBlock) this.getParent(), this.getMinter(), getCurrentTime(), this.difficulty); 38 | this.getMinter().receiveBlock(createdBlock); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /simulator/src/main/java/simblock/task/Task.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Distributed Systems Group 3 | * 4 | *

Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | *

http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | *

Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package simblock.task; 18 | 19 | /** The interface Task. A task can be run and has its execution duration. */ 20 | public interface Task { 21 | /** 22 | * Gets the execution duration of the task in milliseconds of simulated time. 23 | * 24 | * @return the execution duration of the task 25 | */ 26 | // TODO this is not an interval this is a duration 27 | long getInterval(); 28 | 29 | /** Run the task. */ 30 | void run(); 31 | } 32 | --------------------------------------------------------------------------------