├── .gitignore ├── .idea ├── artifacts │ ├── tomcatWeb3j_war.xml │ └── tomcatWeb3j_war_exploded.xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── deployment.xml ├── dictionaries │ ├── vi.xml │ └── viktor.xml ├── jsLibraryMappings.xml ├── misc.xml ├── modules.xml ├── runConfigurations │ └── bin_www.xml ├── vcs.xml └── webServers.xml ├── Ethereum-IdentityVerification.sublime-project ├── LICENSE ├── README.md ├── Tomcat8.README.md ├── pom.xml ├── server.files ├── check.services.sh ├── etc │ └── nginx │ │ └── sites-available │ │ ├── default │ │ └── default.OLD.001 ├── move.war.on.server.sh ├── start.geth.Rinkeby.sh ├── start.geth.Ropsten.sh └── start.geth.mainnet.sh ├── server.scripts ├── connect.to.server.sh ├── deploy.local.sh └── deploy.to.server.sh ├── smartContract ├── after.smart.contract.change.sh ├── build │ └── contracts │ │ ├── CryptonomicaVerification.json │ │ ├── Migrations.json │ │ └── networks.js ├── contracts │ ├── CryptonomicaVerification.Gas.Estimation.txt │ ├── CryptonomicaVerification.abi │ ├── CryptonomicaVerification.bin │ ├── CryptonomicaVerification.sol │ └── Migrations.sol ├── copy.truffle.artifacts.to.cryptonomica.github.io.sh ├── deploy.CryptonomicaVerification.js ├── drafts │ ├── CryptonomicaInvestorAccreditation.sol │ └── CryptonomicaVerification.NEXT.sol ├── migrations │ └── 1_initial_migration.js ├── nodejs.module.sh ├── package-lock.json ├── package.json ├── smartContract.iml ├── truffle-artifactor.save.js ├── truffle-config.js ├── truffle.js ├── truffle.sh └── web3j.compile.smart.contracts.sh ├── src └── main │ ├── java │ └── net │ │ └── cryptonomica │ │ └── tomcatweb3j │ │ ├── contracts │ │ ├── CryptonomicaVerification.java │ │ └── CryptonomicaVerificationFunctions.java │ │ ├── entities │ │ ├── AddVerificationDataObj.java │ │ ├── DataCurrentNetwork.java │ │ ├── EtherscanTxStatus.java │ │ ├── VerificationRequestDataFromSC.java │ │ └── VerificationStruct.java │ │ ├── servlets │ │ ├── AddVerificationDataServlet.java │ │ ├── GetVerificationRequestDataServlet.java │ │ ├── GetVerificationServlet.java │ │ └── TestServlet.java │ │ └── utilities │ │ ├── ApiKeyUtils.java │ │ ├── Constants.java │ │ ├── DataCurrentNetworkFactory.java │ │ ├── Etherscan.java │ │ ├── PGPTools.java │ │ ├── ServletUtils.java │ │ └── Web3jServices.java │ └── webapp │ ├── WEB-INF │ └── web.xml │ └── index.html └── tomcatWeb3j.iml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | 3 | ### custom 4 | #/smartContract/node_modules/ 5 | /smartContract/old/ 6 | /src/main/java/net/cryptonomica/tomcatweb3j/testing/ 7 | 8 | ### Windows template 9 | # Windows thumbnail cache files 10 | Thumbs.db 11 | ehthumbs.db 12 | ehthumbs_vista.db 13 | 14 | # Folder config file 15 | Desktop.ini 16 | 17 | # Recycle Bin used on file shares 18 | $RECYCLE.BIN/ 19 | 20 | # Windows Installer files 21 | *.cab 22 | *.msi 23 | *.msm 24 | *.msp 25 | 26 | # Windows shortcuts 27 | *.lnk 28 | 29 | ### Maven template 30 | target/ 31 | pom.xml.tag 32 | pom.xml.releaseBackup 33 | pom.xml.versionsBackup 34 | pom.xml.next 35 | release.properties 36 | dependency-reduced-pom.xml 37 | buildNumber.properties 38 | .mvn/timing.properties 39 | 40 | # Exclude maven wrapper 41 | !/.mvn/wrapper/maven-wrapper.jar 42 | 43 | ### Linux template 44 | *~ 45 | 46 | # temporary files which can be created if a process still has a handle open of a deleted file 47 | .fuse_hidden* 48 | 49 | # KDE directory preferences 50 | .directory 51 | 52 | # Linux trash folder which might appear on any partition or disk 53 | .Trash-* 54 | 55 | # .nfs files are created when an open file is removed but is still being accessed 56 | .nfs* 57 | 58 | ### JetBrains template 59 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 60 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 61 | 62 | # User-specific stuff: 63 | .idea/**/workspace.xml 64 | .idea/**/tasks.xml 65 | 66 | # Sensitive or high-churn files: 67 | .idea/**/dataSources/ 68 | .idea/**/dataSources.ids 69 | .idea/**/dataSources.xml 70 | .idea/**/dataSources.local.xml 71 | .idea/**/sqlDataSources.xml 72 | .idea/**/dynamic.xml 73 | .idea/**/uiDesigner.xml 74 | 75 | # Gradle: 76 | .idea/**/gradle.xml 77 | .idea/**/libraries 78 | 79 | # Mongo Explorer plugin: 80 | .idea/**/mongoSettings.xml 81 | 82 | ## File-based project format: 83 | *.iws 84 | 85 | ## Plugin-specific files: 86 | 87 | # IntelliJ 88 | /out/ 89 | 90 | # mpeltonen/sbt-idea plugin 91 | .idea_modules/ 92 | 93 | # JIRA plugin 94 | atlassian-ide-plugin.xml 95 | 96 | # Crashlytics plugin (for Android Studio and IntelliJ) 97 | com_crashlytics_export_strings.xml 98 | crashlytics.properties 99 | crashlytics-build.properties 100 | fabric.properties 101 | 102 | ### macOS template 103 | *.DS_Store 104 | .AppleDouble 105 | .LSOverride 106 | 107 | # Icon must end with two \r 108 | Icon 109 | 110 | 111 | # Thumbnails 112 | ._* 113 | 114 | # Files that might appear in the root of a volume 115 | .DocumentRevisions-V100 116 | .fseventsd 117 | .Spotlight-V100 118 | .TemporaryItems 119 | .Trashes 120 | .VolumeIcon.icns 121 | .com.apple.timemachine.donotpresent 122 | 123 | # Directories potentially created on remote AFP share 124 | .AppleDB 125 | .AppleDesktop 126 | Network Trash Folder 127 | Temporary Items 128 | .apdisk 129 | 130 | ### SublimeText template 131 | # cache files for sublime text 132 | *.tmlanguage.cache 133 | *.tmPreferences.cache 134 | *.stTheme.cache 135 | 136 | # workspace files are user-specific 137 | *.sublime-workspace 138 | 139 | # project files should be checked into the repository, unless a significant 140 | # proportion of contributors will probably not be using SublimeText 141 | # *.sublime-project 142 | 143 | # sftp configuration file 144 | sftp-config.json 145 | 146 | # Package control specific files 147 | Package Control.last-run 148 | Package Control.ca-list 149 | Package Control.ca-bundle 150 | Package Control.system-ca-bundle 151 | Package Control.cache/ 152 | Package Control.ca-certs/ 153 | Package Control.merged-ca-bundle 154 | Package Control.user-ca-bundle 155 | oscrypto-ca-bundle.crt 156 | bh_unicode_properties.cache 157 | 158 | # Sublime-github package stores a github token in this file 159 | # https://packagecontrol.io/packages/sublime-github 160 | GitHub.sublime-settings 161 | 162 | ### Java template 163 | *.class 164 | 165 | # Log file 166 | *.log 167 | 168 | # BlueJ files 169 | *.ctxt 170 | 171 | # Mobile Tools for Java (J2ME) 172 | .mtj.tmp/ 173 | 174 | # Package Files # 175 | *.jar 176 | *.war 177 | *.ear 178 | *.zip 179 | *.tar.gz 180 | *.rar 181 | 182 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 183 | hs_err_pid* 184 | 185 | ### Dropbox template 186 | # Dropbox settings and caches 187 | .dropbox 188 | .dropbox.attr 189 | .dropbox.cache 190 | 191 | ### VisualStudioCode template 192 | .vscode/* 193 | !.vscode/settings.json 194 | !.vscode/tasks.json 195 | !.vscode/launch.json 196 | !.vscode/extensions.json 197 | 198 | ### Node template 199 | # Logs 200 | logs 201 | #*.log 202 | npm-debug.log* 203 | yarn-debug.log* 204 | yarn-error.log* 205 | 206 | # Runtime data 207 | pids 208 | *.pid 209 | *.seed 210 | *.pid.lock 211 | 212 | # Directory for instrumented libs generated by jscoverage/JSCover 213 | lib-cov 214 | 215 | # Coverage directory used by tools like istanbul 216 | coverage 217 | 218 | # nyc test coverage 219 | .nyc_output 220 | 221 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 222 | .grunt 223 | 224 | # Bower dependency directory (https://bower.io/) 225 | bower_components 226 | 227 | # node-waf configuration 228 | .lock-wscript 229 | 230 | # Compiled binary addons (https://nodejs.org/api/addons.html) 231 | build/Release 232 | 233 | # Dependency directories 234 | node_modules/ 235 | jspm_packages/ 236 | 237 | # Typescript v1 declaration files 238 | typings/ 239 | 240 | # Optional npm cache directory 241 | .npm 242 | 243 | # Optional eslint cache 244 | .eslintcache 245 | 246 | # Optional REPL history 247 | .node_repl_history 248 | 249 | # Output of 'npm pack' 250 | *.tgz 251 | 252 | # Yarn Integrity file 253 | .yarn-integrity 254 | 255 | # dotenv environment variables file 256 | .env 257 | 258 | # next.js build output 259 | .next 260 | 261 | -------------------------------------------------------------------------------- /.idea/artifacts/tomcatWeb3j_war.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/target 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/artifacts/tomcatWeb3j_war_exploded.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/target/ROOT 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/deployment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/dictionaries/vi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cryptonomica 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/dictionaries/viktor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ethereum 5 | geth 6 | mainnet 7 | rinkeby 8 | ropsten 9 | struct 10 | uint 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 77 | 78 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations/bin_www.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/webServers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /Ethereum-IdentityVerification.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Cryptonomica 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ethereum-IdentityVerification 2 | 3 | ## Smart contract deployment 4 | 5 | (1) (required) 6 | 7 | 'Owner' of the contract after deployment have to set price for verification in wei: 8 | 9 | ``` 10 | function setPriceForVerification(uint priceInWei) public returns (bool) 11 | ``` 12 | 13 | ## Using smart contract 14 | 15 | 16 | ### String to sign with key 17 | 18 | "I hereby confirm that the address
is my Ethereum address" 19 | 20 | ### Sign this string 21 | 22 | Using any OpenPGP soft sign this string. 23 | 24 | In console: 25 | 26 | ```bash 27 | echo "String to sign" > string.to.sign.plaintext.txt 28 | 29 | gpg2 --clearsign --default-key 'Viktor Ageyev ' string.to.sign.plaintext.txt 30 | ``` 31 | 32 | It has to be a cleartext signed message, like this: 33 | 34 | ``` 35 | -----BEGIN PGP SIGNED MESSAGE----- 36 | Hash: SHA256 37 | 38 | String to sign 39 | -----BEGIN PGP SIGNATURE----- 40 | Version: GnuPG v2 41 | 42 | iQEcBAEBCAAGBQJaAu3fAAoJEGp7IeKETHmA4b4H/03CqZBsqQwzqx4qWY8Xo94r 43 | Ha7fk4FBO1Fe8h+zVT6C3MCZc8ZX2B0SsQafGNZMhugDpUCds+DPO2zf7wguBk+U 44 | SvtQ3xi5iicT0RubcV2hI4jhbL4DvVBv7DeCab44HxAfl7leW3Ft6LAmrR/Hcrc7 45 | njo6Nz3T/NvSFNaQXBK1uP8bCZMhc+zqOg5C9uEAVNtKa2iPTm6vbuQGDdp9UKBg 46 | BI6OrTYF4QGeUlxL2A6DpRiZfX0NXlPXjLL0b34fc05xWVXWJjhAw85VgdQwIgmH 47 | zBQMjW3e9dnDJodrosl+TQ1LGkQLy+R6BPX5JoBDa59F0ncyfO+Z+ILrv+hLLbQ= 48 | =TEa2 49 | -----END PGP SIGNATURE----- 50 | ``` 51 | 52 | # Store signed message in smart contract 53 | 54 | call: 55 | 56 | ``` 57 | function uploadSignedString(string _fingerprint, string _signedString) public payable { 58 | ``` 59 | 60 | ascii armored text containing signed string and the signature have to be properly formatted, i.e.: 61 | 62 | ``` 63 | "-----BEGIN PGP SIGNED MESSAGE-----\n" + 64 | "Hash: SHA256\n" + 65 | "\n" + 66 | "String to sign\n" + 67 | "-----BEGIN PGP SIGNATURE-----\n" + 68 | "Version: GnuPG v2\n" + 69 | "\n" + 70 | "iQEcBAEBCAAGBQJaAu3fAAoJEGp7IeKETHmA4b4H/03CqZBsqQwzqx4qWY8Xo94r\n" + 71 | "Ha7fk4FBO1Fe8h+zVT6C3MCZc8ZX2B0SsQafGNZMhugDpUCds+DPO2zf7wguBk+U\n" + 72 | "SvtQ3xi5iicT0RubcV2hI4jhbL4DvVBv7DeCab44HxAfl7leW3Ft6LAmrR/Hcrc7\n" + 73 | "njo6Nz3T/NvSFNaQXBK1uP8bCZMhc+zqOg5C9uEAVNtKa2iPTm6vbuQGDdp9UKBg\n" + 74 | "BI6OrTYF4QGeUlxL2A6DpRiZfX0NXlPXjLL0b34fc05xWVXWJjhAw85VgdQwIgmH\n" + 75 | "zBQMjW3e9dnDJodrosl+TQ1LGkQLy+R6BPX5JoBDa59F0ncyfO+Z+ILrv+hLLbQ=\n" + 76 | "=TEa2\n" + 77 | "-----END PGP SIGNATURE-----"; 78 | ``` 79 | for input on frontend use textarea input type, not text input type 80 | (see: https://stackoverflow.com/questions/21698065/whats-the-difference-between-textarea-and-input-type-text-in-angularjs ) 81 | 82 | # Request signature verification from cryptonomica.net web-site 83 | 84 | Cryptonomica server requests from smart contract for given Ethereum address: 85 | 86 | 87 | 1) signed string ( mapping(address => string) public signedString; ) 88 | 89 | 2) (yet unverified) fingerprint ( mapping(address => string) public unverifiedFingerprint; ) 90 | 91 | than get PublicKey (if uploaded to Cryptonomica server and verified by Cryptonomica service) for this fingerprint and verify signature 92 | 93 | Code to verify signature: 94 | 95 | ``` 96 | net.cryptonomica.tomcatweb3j.utilities.PGPTools.verifyText(String plainText, PGPPublicKey publicKey) 97 | ``` 98 | 99 | if signature verified (```true```) server send verification data connected to key with given fingerprint 100 | to smart contract. 101 | 102 | Solidity: 103 | ``` 104 | // from 'manager' account only 105 | // (!) Gas requirement: infinite 106 | function addVerificationData( 107 | address _acc, // 108 | string _fingerprint, // "57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 109 | bytes20 _fingerprintBytes20, // "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 110 | uint _keyCertificateValidUntil, // 111 | string _firstName, // 112 | string _lastName, // 113 | uint _birthDate, // 114 | string _nationality) public { 115 | ``` 116 | 117 | Java: 118 | 119 | net.cryptonomica.tomcatweb3j.servlets.AddVerificationDataServlet 120 | 121 | # Get Verification data for Ethereum Address: 122 | 123 | net.cryptonomica.tomcatweb3j.servlets.GetVerificationServlet 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Tomcat8.README.md: -------------------------------------------------------------------------------- 1 | 2 | # install tomcat on ubuntu 3 | 4 | server update: 5 | ```bash 6 | sudo apt update && sudo apt upgrade && sudo apt dist-upgrade && sudo apt autoremove && sudo apt install -f 7 | ``` 8 | 9 | install tomcat8: 10 | ```bash 11 | sudo apt install tomcat8 12 | ``` 13 | 14 | # get info on installed tomcat 15 | 16 | If you don't know where catalina.sh is (or it never gets called), you can usually find it via ps: 17 | 18 | ```bash 19 | ps aux | grep catalina 20 | ``` 21 | 22 | From the ps output, you can see both *catalina.home* and *catalina.base* 23 | 24 | catalina.home is where the Tomcat base files are installed, 25 | and catalina.base is where the running configuration of Tomcat exists. 26 | 27 | run: 28 | 29 | ```bash 30 | /usr/share/tomcat8/bin/version.sh 31 | ``` 32 | output current (2017-12-06) (Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-1041-aws x86_64)): 33 | 34 | Using CATALINA_BASE: /usr/share/tomcat8 35 | Using CATALINA_HOME: /usr/share/tomcat8 36 | Using CATALINA_TMPDIR: /usr/share/tomcat8/temp 37 | Using JRE_HOME: /usr 38 | Using CLASSPATH: /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar 39 | Server version: Apache Tomcat/8.0.32 (Ubuntu) 40 | Server built: Mar 9 2017 21:38:04 UTC 41 | Server number: 8.0.32.0 42 | OS Name: Linux 43 | OS Version: 4.4.0-1041-aws 44 | Architecture: amd64 45 | JVM Version: 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12 46 | JVM Vendor: Oracle Corporation 47 | 48 | # tomcat8 system variables 49 | 50 | /usr/share/tomcat8/bin/catalina.sh : 51 | ```bash 52 | # Do not set the variables in this script. Instead put them into a script 53 | # setenv.sh in CATALINA_BASE/bin to keep your customizations separate. 54 | ``` 55 | 56 | create file: 57 | ```bash 58 | sudo touch /usr/share/tomcat8/bin/setenv.sh 59 | # see: https://unix.stackexchange.com/questions/4335/how-to-insert-text-into-a-root-owned-file-using-sudo 60 | echo "export TEST_VAR=testEnvironmentVariableValue" | sudo tee -a /usr/share/tomcat8/bin/setenv.sh > /dev/null 61 | ``` 62 | or: 63 | ```bash 64 | sudo vim /usr/share/tomcat8/bin/setenv.sh 65 | ``` 66 | 67 | # logging 68 | 69 | logs are in /var/log/tomcat8/ 70 | 71 | ```bash 72 | ls /var/log/tomcat8/ 73 | cat /var/log/tomcat8/catalina.out 74 | cat /var/log/tomcat8/localhost_access_log.2017-12-11.txt 75 | cat /var/log/tomcat8/localhost_access_log.$(date "+%F").txt 76 | 77 | ``` 78 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | net.cryptonomica.tomcatweb3j 5 | tomcatweb3j 6 | war 7 | 1.0 8 | net.cryptonomica.tomcatweb3j 9 | http://tomcatweb3j.cryptonomica.net 10 | 11 | 15 | 16 | javax 17 | javaee-api 18 | 7.0 19 | provided 20 | 21 | 22 | 23 | org.bouncycastle 24 | bcpg-jdk15on 25 | 1.54 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.web3j 56 | core 57 | 58 | 59 | 60 | 3.2.0 61 | 62 | 63 | 66 | 67 | com.google.code.gson 68 | gson 69 | 2.8.1 70 | compile 71 | 72 | 73 | 74 | 75 | 80 | org.apache.commons 81 | commons-lang3 82 | 3.7 83 | 84 | 85 | 86 | 87 | commons-codec 88 | commons-codec 89 | 1.11 90 | 91 | 92 | 93 | 94 | commons-io 95 | commons-io 96 | 2.6 97 | 98 | 99 | 100 | 101 | 106 | org.apache.commons 107 | commons-text 108 | 1.1 109 | 110 | 111 | 112 | junit 113 | junit 114 | 3.8.1 115 | test 116 | 117 | 118 | 119 | 120 | 121 | ROOT 122 | 123 | 124 | 125 | 126 | 127 | 128 | org.apache.maven.plugins 129 | maven-clean-plugin 130 | 3.0.0 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-compiler-plugin 135 | 3.7.0 136 | 137 | 1.8 138 | 1.8 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-install-plugin 144 | 2.5.2 145 | 146 | 147 | 148 | 149 | 150 | 152 | 154 | org.web3j 155 | web3j-maven-plugin 156 | 0.1.2 157 | 158 | 159 | 160 | src/main/resources 161 | 162 | 163 | CryptonomicaVerification.sol 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /server.files/check.services.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # service --status-all 4 | sudo service tomcat8 status 5 | sudo service nginx status -------------------------------------------------------------------------------- /server.files/etc/nginx/sites-available/default: -------------------------------------------------------------------------------- 1 | ## this file: 2 | # /etc/nginx/sites-available/default 3 | # 4 | # You should look at the following URL's in order to grasp a solid understanding 5 | # of Nginx configuration files in order to fully unleash the power of Nginx. 6 | # http://wiki.nginx.org/Pitfalls 7 | # http://wiki.nginx.org/QuickStart 8 | # http://wiki.nginx.org/Configuration 9 | # 10 | # Generally, you will want to move this file somewhere, and start with a clean 11 | # file but keep this around for reference. Or just disable in sites-enabled. 12 | # 13 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 14 | ## 15 | 16 | # -------------- My Settings START: ---------- 17 | 18 | # HTTP server 19 | # see: http://serverfault.com/a/337893 20 | # https://serverfault.com/questions/67316/in-nginx-how-can-i-rewrite-all-http-requests-to-https-while-maintaining-sub-dom/337893#337893 21 | server { 22 | listen 80; 23 | server_name tomcatweb3j.cryptonomica.net; 24 | return 301 https://$server_name$request_uri; 25 | } 26 | 27 | # HTTPS server 28 | # http://nginx.org/en/docs/http/configuring_https_servers.html 29 | server { 30 | listen 443 ssl; 31 | server_name tomcatweb3j.cryptonomica.net; 32 | # add Strict-Transport-Security to prevent man in the middle attacks 33 | add_header Strict-Transport-Security "max-age=31536000"; 34 | 35 | ssl_certificate /etc/nginx/SSL/certificate.pem; 36 | ssl_certificate_key /etc/nginx/SSL/privatekey.pem; 37 | 38 | location / { 39 | proxy_pass http://127.0.0.1:8080; 40 | } 41 | 42 | } 43 | # -------------- My Settings END: ---------- -------------------------------------------------------------------------------- /server.files/etc/nginx/sites-available/default.OLD.001: -------------------------------------------------------------------------------- 1 | ## 2 | # You should look at the following URL's in order to grasp a solid understanding 3 | # of Nginx configuration files in order to fully unleash the power of Nginx. 4 | # http://wiki.nginx.org/Pitfalls 5 | # http://wiki.nginx.org/QuickStart 6 | # http://wiki.nginx.org/Configuration 7 | # 8 | # Generally, you will want to move this file somewhere, and start with a clean 9 | # file but keep this around for reference. Or just disable in sites-enabled. 10 | # 11 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 12 | ## 13 | 14 | # Default server configuration 15 | # 16 | server { 17 | listen 80 default_server; 18 | listen [::]:80 default_server; 19 | 20 | # SSL configuration 21 | # 22 | # listen 443 ssl default_server; 23 | # listen [::]:443 ssl default_server; 24 | # 25 | # Note: You should disable gzip for SSL traffic. 26 | # See: https://bugs.debian.org/773332 27 | # 28 | # Read up on ssl_ciphers to ensure a secure configuration. 29 | # See: https://bugs.debian.org/765782 30 | # 31 | # Self signed certs generated by the ssl-cert package 32 | # Don't use them in a production server! 33 | # 34 | # include snippets/snakeoil.conf; 35 | 36 | root /var/www/html; 37 | 38 | # Add index.php to the list if you are using PHP 39 | index index.html index.htm index.nginx-debian.html; 40 | 41 | server_name _; 42 | 43 | location / { 44 | # First attempt to serve request as file, then 45 | # as directory, then fall back to displaying a 404. 46 | try_files $uri $uri/ =404; 47 | } 48 | 49 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 50 | # 51 | #location ~ \.php$ { 52 | # include snippets/fastcgi-php.conf; 53 | # 54 | # # With php7.0-cgi alone: 55 | # fastcgi_pass 127.0.0.1:9000; 56 | # # With php7.0-fpm: 57 | # fastcgi_pass unix:/run/php/php7.0-fpm.sock; 58 | #} 59 | 60 | # deny access to .htaccess files, if Apache's document root 61 | # concurs with nginx's one 62 | # 63 | #location ~ /\.ht { 64 | # deny all; 65 | #} 66 | } 67 | 68 | 69 | # Virtual Host configuration for example.com 70 | # 71 | # You can move that to a different file under sites-available/ and symlink that 72 | # to sites-enabled/ to enable it. 73 | # 74 | #server { 75 | # listen 80; 76 | # listen [::]:80; 77 | # 78 | # server_name example.com; 79 | # 80 | # root /var/www/example.com; 81 | # index index.html; 82 | # 83 | # location / { 84 | # try_files $uri $uri/ =404; 85 | # } 86 | #} 87 | -------------------------------------------------------------------------------- /server.files/move.war.on.server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this is to be executed on the server (does not need to be executable on local ) 4 | # see: http://stackoverflow.com/questions/305035/how-to-use-ssh-to-run-shell-script-on-a-remote-machine 5 | sudo service tomcat8 stop 6 | sudo rm -rf /var/lib/tomcat8/webapps/ROOT /var/lib/tomcat8/webapps/ROOT.war 7 | sudo cp -vu /home/ubuntu/toDeploy/*.war /var/lib/tomcat8/webapps/ROOT.war 8 | # '/home/ubuntu/toDeploy/ROOT.war' -> '/var/lib/tomcat7/webapps/ROOT.war' 9 | 10 | sudo service tomcat8 start 11 | #sudo service tomcat8 status 12 | #sudo service nginx start 13 | #sudo service nginx status 14 | touch /home/ubuntu/deployment.log 15 | echo $(date "+%FT%T%Z") : $(whoami) >> /home/ubuntu/deployment.log 16 | echo "---------------------" >> /home/ubuntu/deployment.log 17 | tail /home/ubuntu/deployment.log -------------------------------------------------------------------------------- /server.files/start.geth.Rinkeby.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # https://docs.web3j.io/getting_started.html#start-a-client 4 | geth --rpcapi personal,db,eth,net,web3 --rpc --rinkeby 5 | 6 | # geth attach ipc://${HOME}/.ethereum/rinkeby/geth.ipc -------------------------------------------------------------------------------- /server.files/start.geth.Ropsten.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | screen -dmS Geth geth --rpcapi personal,db,eth,net,web3 --rpc --testnet 4 | 5 | # geth attach ipc://${HOME}/.ethereum/testnet/geth.ipc -------------------------------------------------------------------------------- /server.files/start.geth.mainnet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # first run 4 | # screen -dmS Geth geth --fast --cache=2048 --jitvm 5 | #screen -dmS Geth geth --rpcapi personal,db,eth,net,web3 --rpc 6 | screen -dmS Geth geth --rpcapi personal,db,eth,net,web3 --rpc --cache=4096 --nousb 7 | # no need to unlock account, this will be done by web3j 8 | -------------------------------------------------------------------------------- /server.scripts/connect.to.server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ssh -i ${HOME}/.ssh/tomcatWeb3j.pem ubuntu@tomcatweb3j.cryptonomica.net 4 | 5 | # cd /var/log/tomcat8/ 6 | -------------------------------------------------------------------------------- /server.scripts/deploy.local.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # by default: http://localhost:8080/ 4 | 5 | mvn clean 6 | mvn install 7 | 8 | sudo service tomcat8 stop 9 | sudo rm -f ./target/test.war 10 | sudo rm -rf /var/lib/tomcat8/webapps/test 11 | sudo mv ./target/ROOT.war ./target/test.war 12 | sudo cp -vu ./target/test.war /var/lib/tomcat8/webapps/ 13 | 14 | sudo service tomcat8 start 15 | #sudo service tomcat8 status 16 | 17 | -------------------------------------------------------------------------------- /server.scripts/deploy.to.server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mvn clean 4 | mvn install 5 | 6 | scp -i ${HOME}/.ssh/tomcatWeb3j.pem target/*.war ubuntu@tomcatweb3j.cryptonomica.net:/home/ubuntu/toDeploy/ 7 | 8 | # see: http://stackoverflow.com/questions/305035/how-to-use-ssh-to-run-shell-script-on-a-remote-machine 9 | ssh -i ${HOME}/.ssh/tomcatWeb3j.pem ubuntu@tomcatweb3j.cryptonomica.net "echo $(date "+%FT%T%Z") : $(whoami) >> /home/ubuntu/deployment.log" 10 | # see: https://stackoverflow.com/a/1930732/1697878 11 | ssh -i ~/.ssh/tomcatWeb3j.pem ubuntu@tomcatweb3j.cryptonomica.net sh ./move.war.on.server.sh 12 | 13 | mvn clean 14 | -------------------------------------------------------------------------------- /smartContract/after.smart.contract.change.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd ./smartContract 4 | ./web3j.compile.smart.contracts.sh 5 | nodejs ./deploy.CryptonomicaVerification.js 6 | 7 | ### change contract address in 8 | # ./smartContract/build/contracts/networks.js 9 | # net.cryptonomica.tomcatweb3j.utilities.Constants 10 | # on front end 11 | 12 | # ./server.scripts/deploy.to.server.sh 13 | 14 | # truffle compile 15 | # ./copy.truffle.artifacts.to.cryptonomica.github.io.sh 16 | 17 | -------------------------------------------------------------------------------- /smartContract/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [], 7 | "name": "last_completed_migration", 8 | "outputs": [ 9 | { 10 | "name": "", 11 | "type": "uint256" 12 | } 13 | ], 14 | "payable": false, 15 | "stateMutability": "view", 16 | "type": "function" 17 | }, 18 | { 19 | "constant": true, 20 | "inputs": [], 21 | "name": "owner", 22 | "outputs": [ 23 | { 24 | "name": "", 25 | "type": "address" 26 | } 27 | ], 28 | "payable": false, 29 | "stateMutability": "view", 30 | "type": "function" 31 | }, 32 | { 33 | "inputs": [], 34 | "payable": false, 35 | "stateMutability": "nonpayable", 36 | "type": "constructor" 37 | }, 38 | { 39 | "constant": false, 40 | "inputs": [ 41 | { 42 | "name": "completed", 43 | "type": "uint256" 44 | } 45 | ], 46 | "name": "setCompleted", 47 | "outputs": [], 48 | "payable": false, 49 | "stateMutability": "nonpayable", 50 | "type": "function" 51 | }, 52 | { 53 | "constant": false, 54 | "inputs": [ 55 | { 56 | "name": "new_address", 57 | "type": "address" 58 | } 59 | ], 60 | "name": "upgrade", 61 | "outputs": [], 62 | "payable": false, 63 | "stateMutability": "nonpayable", 64 | "type": "function" 65 | } 66 | ], 67 | "bytecode": "0x6060604052341561000f57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102db8061005e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100a05780638da5cb5b146100c9578063fdacd5761461011e575b600080fd5b341561007257600080fd5b61009e600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610141565b005b34156100ab57600080fd5b6100b3610224565b6040518082815260200191505060405180910390f35b34156100d457600080fd5b6100dc61022a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561012957600080fd5b61013f600480803590602001909190505061024f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610220578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b151561020b57600080fd5b6102c65a03f1151561021c57600080fd5b5050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102ac57806001819055505b505600a165627a7a72305820e14ae337878bf2e1201ca2197f8575805066a26421b7098d9d13e015b6a16e9f0029", 68 | "deployedBytecode": "0x606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100a05780638da5cb5b146100c9578063fdacd5761461011e575b600080fd5b341561007257600080fd5b61009e600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610141565b005b34156100ab57600080fd5b6100b3610224565b6040518082815260200191505060405180910390f35b34156100d457600080fd5b6100dc61022a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561012957600080fd5b61013f600480803590602001909190505061024f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610220578190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b151561020b57600080fd5b6102c65a03f1151561021c57600080fd5b5050505b5050565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102ac57806001819055505b505600a165627a7a72305820e14ae337878bf2e1201ca2197f8575805066a26421b7098d9d13e015b6a16e9f0029", 69 | "sourceMap": "26:488:1:-;;;178:58;;;;;;;;221:10;213:5;;:18;;;;;;;;;;;;;;;;;;26:488;;;;;;", 70 | "deployedSourceMap": "26:488:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;347:165;;;;;;;;;;;;;;;;;;;;;;;;;;;;74:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;240:103;;;;;;;;;;;;;;;;;;;;;;;;;;347:165;409:19;161:5;;;;;;;;;;;147:19;;:10;:19;;;143:26;;;442:11;409:45;;460:8;:21;;;482:24;;460:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143:26;347:165;;:::o;74:36::-;;;;:::o;50:20::-;;;;;;;;;;;;;:::o;240:103::-;161:5;;;;;;;;;;;147:19;;:10;:19;;;143:26;;;329:9;302:24;:36;;;;143:26;240:103;:::o", 71 | "source": "pragma solidity ^0.4.17;\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration;\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function Migrations() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address new_address) public restricted {\n Migrations upgraded = Migrations(new_address);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n", 72 | "sourcePath": "/home/viktor/Dropbox/GIT/CRYPTONOMICA/Ethereum-IdentityVerification/smartContract/contracts/Migrations.sol", 73 | "ast": { 74 | "attributes": { 75 | "absolutePath": "/home/viktor/Dropbox/GIT/CRYPTONOMICA/Ethereum-IdentityVerification/smartContract/contracts/Migrations.sol", 76 | "exportedSymbols": { 77 | "Migrations": [ 78 | 789 79 | ] 80 | } 81 | }, 82 | "children": [ 83 | { 84 | "attributes": { 85 | "literals": [ 86 | "solidity", 87 | "^", 88 | "0.4", 89 | ".17" 90 | ] 91 | }, 92 | "id": 734, 93 | "name": "PragmaDirective", 94 | "src": "0:24:1" 95 | }, 96 | { 97 | "attributes": { 98 | "baseContracts": [ 99 | null 100 | ], 101 | "contractDependencies": [ 102 | null 103 | ], 104 | "contractKind": "contract", 105 | "documentation": null, 106 | "fullyImplemented": true, 107 | "linearizedBaseContracts": [ 108 | 789 109 | ], 110 | "name": "Migrations", 111 | "scope": 790 112 | }, 113 | "children": [ 114 | { 115 | "attributes": { 116 | "constant": false, 117 | "name": "owner", 118 | "scope": 789, 119 | "stateVariable": true, 120 | "storageLocation": "default", 121 | "type": "address", 122 | "value": null, 123 | "visibility": "public" 124 | }, 125 | "children": [ 126 | { 127 | "attributes": { 128 | "name": "address", 129 | "type": "address" 130 | }, 131 | "id": 735, 132 | "name": "ElementaryTypeName", 133 | "src": "50:7:1" 134 | } 135 | ], 136 | "id": 736, 137 | "name": "VariableDeclaration", 138 | "src": "50:20:1" 139 | }, 140 | { 141 | "attributes": { 142 | "constant": false, 143 | "name": "last_completed_migration", 144 | "scope": 789, 145 | "stateVariable": true, 146 | "storageLocation": "default", 147 | "type": "uint256", 148 | "value": null, 149 | "visibility": "public" 150 | }, 151 | "children": [ 152 | { 153 | "attributes": { 154 | "name": "uint", 155 | "type": "uint256" 156 | }, 157 | "id": 737, 158 | "name": "ElementaryTypeName", 159 | "src": "74:4:1" 160 | } 161 | ], 162 | "id": 738, 163 | "name": "VariableDeclaration", 164 | "src": "74:36:1" 165 | }, 166 | { 167 | "attributes": { 168 | "name": "restricted", 169 | "visibility": "internal" 170 | }, 171 | "children": [ 172 | { 173 | "attributes": { 174 | "parameters": [ 175 | null 176 | ] 177 | }, 178 | "children": [], 179 | "id": 739, 180 | "name": "ParameterList", 181 | "src": "134:2:1" 182 | }, 183 | { 184 | "children": [ 185 | { 186 | "attributes": { 187 | "falseBody": null 188 | }, 189 | "children": [ 190 | { 191 | "attributes": { 192 | "argumentTypes": null, 193 | "commonType": { 194 | "typeIdentifier": "t_address", 195 | "typeString": "address" 196 | }, 197 | "isConstant": false, 198 | "isLValue": false, 199 | "isPure": false, 200 | "lValueRequested": false, 201 | "operator": "==", 202 | "type": "bool" 203 | }, 204 | "children": [ 205 | { 206 | "attributes": { 207 | "argumentTypes": null, 208 | "isConstant": false, 209 | "isLValue": false, 210 | "isPure": false, 211 | "lValueRequested": false, 212 | "member_name": "sender", 213 | "referencedDeclaration": null, 214 | "type": "address" 215 | }, 216 | "children": [ 217 | { 218 | "attributes": { 219 | "argumentTypes": null, 220 | "overloadedDeclarations": [ 221 | null 222 | ], 223 | "referencedDeclaration": 801, 224 | "type": "msg", 225 | "value": "msg" 226 | }, 227 | "id": 740, 228 | "name": "Identifier", 229 | "src": "147:3:1" 230 | } 231 | ], 232 | "id": 741, 233 | "name": "MemberAccess", 234 | "src": "147:10:1" 235 | }, 236 | { 237 | "attributes": { 238 | "argumentTypes": null, 239 | "overloadedDeclarations": [ 240 | null 241 | ], 242 | "referencedDeclaration": 736, 243 | "type": "address", 244 | "value": "owner" 245 | }, 246 | "id": 742, 247 | "name": "Identifier", 248 | "src": "161:5:1" 249 | } 250 | ], 251 | "id": 743, 252 | "name": "BinaryOperation", 253 | "src": "147:19:1" 254 | }, 255 | { 256 | "id": 744, 257 | "name": "PlaceholderStatement", 258 | "src": "168:1:1" 259 | } 260 | ], 261 | "id": 745, 262 | "name": "IfStatement", 263 | "src": "143:26:1" 264 | } 265 | ], 266 | "id": 746, 267 | "name": "Block", 268 | "src": "137:37:1" 269 | } 270 | ], 271 | "id": 747, 272 | "name": "ModifierDefinition", 273 | "src": "115:59:1" 274 | }, 275 | { 276 | "attributes": { 277 | "constant": false, 278 | "implemented": true, 279 | "isConstructor": true, 280 | "modifiers": [ 281 | null 282 | ], 283 | "name": "Migrations", 284 | "payable": false, 285 | "scope": 789, 286 | "stateMutability": "nonpayable", 287 | "superFunction": null, 288 | "visibility": "public" 289 | }, 290 | "children": [ 291 | { 292 | "attributes": { 293 | "parameters": [ 294 | null 295 | ] 296 | }, 297 | "children": [], 298 | "id": 748, 299 | "name": "ParameterList", 300 | "src": "197:2:1" 301 | }, 302 | { 303 | "attributes": { 304 | "parameters": [ 305 | null 306 | ] 307 | }, 308 | "children": [], 309 | "id": 749, 310 | "name": "ParameterList", 311 | "src": "207:0:1" 312 | }, 313 | { 314 | "children": [ 315 | { 316 | "children": [ 317 | { 318 | "attributes": { 319 | "argumentTypes": null, 320 | "isConstant": false, 321 | "isLValue": false, 322 | "isPure": false, 323 | "lValueRequested": false, 324 | "operator": "=", 325 | "type": "address" 326 | }, 327 | "children": [ 328 | { 329 | "attributes": { 330 | "argumentTypes": null, 331 | "overloadedDeclarations": [ 332 | null 333 | ], 334 | "referencedDeclaration": 736, 335 | "type": "address", 336 | "value": "owner" 337 | }, 338 | "id": 750, 339 | "name": "Identifier", 340 | "src": "213:5:1" 341 | }, 342 | { 343 | "attributes": { 344 | "argumentTypes": null, 345 | "isConstant": false, 346 | "isLValue": false, 347 | "isPure": false, 348 | "lValueRequested": false, 349 | "member_name": "sender", 350 | "referencedDeclaration": null, 351 | "type": "address" 352 | }, 353 | "children": [ 354 | { 355 | "attributes": { 356 | "argumentTypes": null, 357 | "overloadedDeclarations": [ 358 | null 359 | ], 360 | "referencedDeclaration": 801, 361 | "type": "msg", 362 | "value": "msg" 363 | }, 364 | "id": 751, 365 | "name": "Identifier", 366 | "src": "221:3:1" 367 | } 368 | ], 369 | "id": 752, 370 | "name": "MemberAccess", 371 | "src": "221:10:1" 372 | } 373 | ], 374 | "id": 753, 375 | "name": "Assignment", 376 | "src": "213:18:1" 377 | } 378 | ], 379 | "id": 754, 380 | "name": "ExpressionStatement", 381 | "src": "213:18:1" 382 | } 383 | ], 384 | "id": 755, 385 | "name": "Block", 386 | "src": "207:29:1" 387 | } 388 | ], 389 | "id": 756, 390 | "name": "FunctionDefinition", 391 | "src": "178:58:1" 392 | }, 393 | { 394 | "attributes": { 395 | "constant": false, 396 | "implemented": true, 397 | "isConstructor": false, 398 | "name": "setCompleted", 399 | "payable": false, 400 | "scope": 789, 401 | "stateMutability": "nonpayable", 402 | "superFunction": null, 403 | "visibility": "public" 404 | }, 405 | "children": [ 406 | { 407 | "children": [ 408 | { 409 | "attributes": { 410 | "constant": false, 411 | "name": "completed", 412 | "scope": 768, 413 | "stateVariable": false, 414 | "storageLocation": "default", 415 | "type": "uint256", 416 | "value": null, 417 | "visibility": "internal" 418 | }, 419 | "children": [ 420 | { 421 | "attributes": { 422 | "name": "uint", 423 | "type": "uint256" 424 | }, 425 | "id": 757, 426 | "name": "ElementaryTypeName", 427 | "src": "262:4:1" 428 | } 429 | ], 430 | "id": 758, 431 | "name": "VariableDeclaration", 432 | "src": "262:14:1" 433 | } 434 | ], 435 | "id": 759, 436 | "name": "ParameterList", 437 | "src": "261:16:1" 438 | }, 439 | { 440 | "attributes": { 441 | "parameters": [ 442 | null 443 | ] 444 | }, 445 | "children": [], 446 | "id": 762, 447 | "name": "ParameterList", 448 | "src": "296:0:1" 449 | }, 450 | { 451 | "attributes": { 452 | "arguments": [ 453 | null 454 | ] 455 | }, 456 | "children": [ 457 | { 458 | "attributes": { 459 | "argumentTypes": null, 460 | "overloadedDeclarations": [ 461 | null 462 | ], 463 | "referencedDeclaration": 747, 464 | "type": "modifier ()", 465 | "value": "restricted" 466 | }, 467 | "id": 760, 468 | "name": "Identifier", 469 | "src": "285:10:1" 470 | } 471 | ], 472 | "id": 761, 473 | "name": "ModifierInvocation", 474 | "src": "285:10:1" 475 | }, 476 | { 477 | "children": [ 478 | { 479 | "children": [ 480 | { 481 | "attributes": { 482 | "argumentTypes": null, 483 | "isConstant": false, 484 | "isLValue": false, 485 | "isPure": false, 486 | "lValueRequested": false, 487 | "operator": "=", 488 | "type": "uint256" 489 | }, 490 | "children": [ 491 | { 492 | "attributes": { 493 | "argumentTypes": null, 494 | "overloadedDeclarations": [ 495 | null 496 | ], 497 | "referencedDeclaration": 738, 498 | "type": "uint256", 499 | "value": "last_completed_migration" 500 | }, 501 | "id": 763, 502 | "name": "Identifier", 503 | "src": "302:24:1" 504 | }, 505 | { 506 | "attributes": { 507 | "argumentTypes": null, 508 | "overloadedDeclarations": [ 509 | null 510 | ], 511 | "referencedDeclaration": 758, 512 | "type": "uint256", 513 | "value": "completed" 514 | }, 515 | "id": 764, 516 | "name": "Identifier", 517 | "src": "329:9:1" 518 | } 519 | ], 520 | "id": 765, 521 | "name": "Assignment", 522 | "src": "302:36:1" 523 | } 524 | ], 525 | "id": 766, 526 | "name": "ExpressionStatement", 527 | "src": "302:36:1" 528 | } 529 | ], 530 | "id": 767, 531 | "name": "Block", 532 | "src": "296:47:1" 533 | } 534 | ], 535 | "id": 768, 536 | "name": "FunctionDefinition", 537 | "src": "240:103:1" 538 | }, 539 | { 540 | "attributes": { 541 | "constant": false, 542 | "implemented": true, 543 | "isConstructor": false, 544 | "name": "upgrade", 545 | "payable": false, 546 | "scope": 789, 547 | "stateMutability": "nonpayable", 548 | "superFunction": null, 549 | "visibility": "public" 550 | }, 551 | "children": [ 552 | { 553 | "children": [ 554 | { 555 | "attributes": { 556 | "constant": false, 557 | "name": "new_address", 558 | "scope": 788, 559 | "stateVariable": false, 560 | "storageLocation": "default", 561 | "type": "address", 562 | "value": null, 563 | "visibility": "internal" 564 | }, 565 | "children": [ 566 | { 567 | "attributes": { 568 | "name": "address", 569 | "type": "address" 570 | }, 571 | "id": 769, 572 | "name": "ElementaryTypeName", 573 | "src": "364:7:1" 574 | } 575 | ], 576 | "id": 770, 577 | "name": "VariableDeclaration", 578 | "src": "364:19:1" 579 | } 580 | ], 581 | "id": 771, 582 | "name": "ParameterList", 583 | "src": "363:21:1" 584 | }, 585 | { 586 | "attributes": { 587 | "parameters": [ 588 | null 589 | ] 590 | }, 591 | "children": [], 592 | "id": 774, 593 | "name": "ParameterList", 594 | "src": "403:0:1" 595 | }, 596 | { 597 | "attributes": { 598 | "arguments": [ 599 | null 600 | ] 601 | }, 602 | "children": [ 603 | { 604 | "attributes": { 605 | "argumentTypes": null, 606 | "overloadedDeclarations": [ 607 | null 608 | ], 609 | "referencedDeclaration": 747, 610 | "type": "modifier ()", 611 | "value": "restricted" 612 | }, 613 | "id": 772, 614 | "name": "Identifier", 615 | "src": "392:10:1" 616 | } 617 | ], 618 | "id": 773, 619 | "name": "ModifierInvocation", 620 | "src": "392:10:1" 621 | }, 622 | { 623 | "children": [ 624 | { 625 | "attributes": { 626 | "assignments": [ 627 | 776 628 | ] 629 | }, 630 | "children": [ 631 | { 632 | "attributes": { 633 | "constant": false, 634 | "name": "upgraded", 635 | "scope": 788, 636 | "stateVariable": false, 637 | "storageLocation": "default", 638 | "type": "contract Migrations", 639 | "value": null, 640 | "visibility": "internal" 641 | }, 642 | "children": [ 643 | { 644 | "attributes": { 645 | "contractScope": null, 646 | "name": "Migrations", 647 | "referencedDeclaration": 789, 648 | "type": "contract Migrations" 649 | }, 650 | "id": 775, 651 | "name": "UserDefinedTypeName", 652 | "src": "409:10:1" 653 | } 654 | ], 655 | "id": 776, 656 | "name": "VariableDeclaration", 657 | "src": "409:19:1" 658 | }, 659 | { 660 | "attributes": { 661 | "argumentTypes": null, 662 | "isConstant": false, 663 | "isLValue": false, 664 | "isPure": false, 665 | "isStructConstructorCall": false, 666 | "lValueRequested": false, 667 | "names": [ 668 | null 669 | ], 670 | "type": "contract Migrations", 671 | "type_conversion": true 672 | }, 673 | "children": [ 674 | { 675 | "attributes": { 676 | "argumentTypes": [ 677 | { 678 | "typeIdentifier": "t_address", 679 | "typeString": "address" 680 | } 681 | ], 682 | "overloadedDeclarations": [ 683 | null 684 | ], 685 | "referencedDeclaration": 789, 686 | "type": "type(contract Migrations)", 687 | "value": "Migrations" 688 | }, 689 | "id": 777, 690 | "name": "Identifier", 691 | "src": "431:10:1" 692 | }, 693 | { 694 | "attributes": { 695 | "argumentTypes": null, 696 | "overloadedDeclarations": [ 697 | null 698 | ], 699 | "referencedDeclaration": 770, 700 | "type": "address", 701 | "value": "new_address" 702 | }, 703 | "id": 778, 704 | "name": "Identifier", 705 | "src": "442:11:1" 706 | } 707 | ], 708 | "id": 779, 709 | "name": "FunctionCall", 710 | "src": "431:23:1" 711 | } 712 | ], 713 | "id": 780, 714 | "name": "VariableDeclarationStatement", 715 | "src": "409:45:1" 716 | }, 717 | { 718 | "children": [ 719 | { 720 | "attributes": { 721 | "argumentTypes": null, 722 | "isConstant": false, 723 | "isLValue": false, 724 | "isPure": false, 725 | "isStructConstructorCall": false, 726 | "lValueRequested": false, 727 | "names": [ 728 | null 729 | ], 730 | "type": "tuple()", 731 | "type_conversion": false 732 | }, 733 | "children": [ 734 | { 735 | "attributes": { 736 | "argumentTypes": [ 737 | { 738 | "typeIdentifier": "t_uint256", 739 | "typeString": "uint256" 740 | } 741 | ], 742 | "isConstant": false, 743 | "isLValue": false, 744 | "isPure": false, 745 | "lValueRequested": false, 746 | "member_name": "setCompleted", 747 | "referencedDeclaration": 768, 748 | "type": "function (uint256) external" 749 | }, 750 | "children": [ 751 | { 752 | "attributes": { 753 | "argumentTypes": null, 754 | "overloadedDeclarations": [ 755 | null 756 | ], 757 | "referencedDeclaration": 776, 758 | "type": "contract Migrations", 759 | "value": "upgraded" 760 | }, 761 | "id": 781, 762 | "name": "Identifier", 763 | "src": "460:8:1" 764 | } 765 | ], 766 | "id": 783, 767 | "name": "MemberAccess", 768 | "src": "460:21:1" 769 | }, 770 | { 771 | "attributes": { 772 | "argumentTypes": null, 773 | "overloadedDeclarations": [ 774 | null 775 | ], 776 | "referencedDeclaration": 738, 777 | "type": "uint256", 778 | "value": "last_completed_migration" 779 | }, 780 | "id": 784, 781 | "name": "Identifier", 782 | "src": "482:24:1" 783 | } 784 | ], 785 | "id": 785, 786 | "name": "FunctionCall", 787 | "src": "460:47:1" 788 | } 789 | ], 790 | "id": 786, 791 | "name": "ExpressionStatement", 792 | "src": "460:47:1" 793 | } 794 | ], 795 | "id": 787, 796 | "name": "Block", 797 | "src": "403:109:1" 798 | } 799 | ], 800 | "id": 788, 801 | "name": "FunctionDefinition", 802 | "src": "347:165:1" 803 | } 804 | ], 805 | "id": 789, 806 | "name": "ContractDefinition", 807 | "src": "26:488:1" 808 | } 809 | ], 810 | "id": 790, 811 | "name": "SourceUnit", 812 | "src": "0:515:1" 813 | }, 814 | "compiler": { 815 | "name": "solc", 816 | "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" 817 | }, 818 | "networks": {}, 819 | "schemaVersion": "1.0.1", 820 | "updatedAt": "2018-02-20T09:36:02.834Z" 821 | } -------------------------------------------------------------------------------- /smartContract/build/contracts/networks.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // example from: 4 | // https://github.com/trufflesuite/truffle-artifactor#artifactorgenerateoptions-networks 5 | 6 | const networks = { 7 | "1": { // Main network 8 | "networkName": "Main Ethereum Network", 9 | "address": undefined, // contract address 10 | "contractAddress": undefined, 11 | "ownerAddress": undefined, 12 | "etherscanLinkPrefix": undefined 13 | }, 14 | "2": { // Morden network 15 | "networkName": undefined, 16 | "address": undefined, // contract address 17 | "contractAddress": undefined, 18 | "ownerAddress": undefined, 19 | "etherscanLinkPrefix": undefined 20 | }, 21 | "3": { // Ropsten network 22 | "networkName": "Ropsten Test Network", 23 | "address": undefined, // contract address 24 | "contractAddress": undefined, 25 | "ownerAddress": undefined, 26 | "etherscanLinkPrefix": "https://ropsten.etherscan.io/" 27 | }, 28 | "4": { // Rinkeby network 29 | "networkName": undefined, 30 | "address": "0xb9ffed00f17De4CDA41bF30bBe0E11B78E3A2c57", // contract address 31 | "contractAddress": "0xb9ffed00f17De4CDA41bF30bBe0E11B78E3A2c57", 32 | "ownerAddress": "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D", 33 | "etherscanLinkPrefix": "https://rinkeby.etherscan.io/" 34 | }, 35 | "1337": { // private network 36 | "networkName": undefined, 37 | "address": undefined, // contract address 38 | "contractAddress": undefined, 39 | "ownerAddress": undefined, 40 | "etherscanLinkPrefix": undefined 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /smartContract/contracts/CryptonomicaVerification.Gas.Estimation.txt: -------------------------------------------------------------------------------- 1 | 2 | ======= ./contracts/CryptonomicaVerification.sol:CryptonomicaVerification ======= 3 | Gas estimation: 4 | construction: 5 | infinite + 1344000 = infinite 6 | external: 7 | addManager(address): 22545 8 | addVerificationData(address,string,bytes20,uint256,string,string,uint256,string): infinite 9 | addressAttached(bytes20): 1179 10 | birthDate(address): 696 11 | bytes32ToString(bytes32): infinite 12 | changeOwnerAccept(): 23386 13 | changeOwnerStart(address): 22561 14 | fingerprint(address): 785 15 | firstName(address): 960 16 | fixWithdrawalAddress(address): 22971 17 | isManager(address): 1192 18 | keyCertificateValidUntil(address): 740 19 | lastName(address): 784 20 | nationality(address): 1136 21 | owner(): 878 22 | priceForVerificationInWei(): 395 23 | removeManager(address): 22891 24 | revokeVerification(address): infinite 25 | revokedOn(address): 850 26 | setPriceForVerification(uint256): 23192 27 | setWithdrawalAddress(address): 23398 28 | signedString(address): infinite 29 | signedStringUploadedOnUnixTime(address): 674 30 | stringToBytes32(string): infinite 31 | stringToSignExample(): infinite 32 | unverifiedFingerprint(address): infinite 33 | uploadSignedString(string,bytes20,string): infinite 34 | verification(address): infinite 35 | verificationAddedOn(address): 652 36 | withdrawAllToWithdrawalAddress(): infinite 37 | withdrawalAddress(): 1164 38 | withdrawalAddressFixed(): 767 39 | -------------------------------------------------------------------------------- /smartContract/contracts/CryptonomicaVerification.abi: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"_withdrawalAddress","type":"address"}],"name":"fixWithdrawalAddress","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"priceForVerificationInWei","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"unverifiedFingerprint","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawalAddress","type":"address"}],"name":"setWithdrawalAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"signedString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_acc","type":"address"}],"name":"addManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"verificationAddedOn","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"signedStringUploadedOnUnixTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"birthDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwnerStart","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"keyCertificateValidUntil","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"fingerprint","outputs":[{"name":"","type":"bytes20"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"lastName","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_acc","type":"address"},{"name":"_fingerprint","type":"string"},{"name":"_fingerprintBytes20","type":"bytes20"},{"name":"_keyCertificateValidUntil","type":"uint256"},{"name":"_firstName","type":"string"},{"name":"_lastName","type":"string"},{"name":"_birthDate","type":"uint256"},{"name":"_nationality","type":"string"}],"name":"addVerificationData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawalAddressFixed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"revokedOn","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_bytes32","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"verification","outputs":[{"name":"fingerprint","type":"string"},{"name":"keyCertificateValidUntil","type":"uint256"},{"name":"firstName","type":"string"},{"name":"lastName","type":"string"},{"name":"birthDate","type":"uint256"},{"name":"nationality","type":"string"},{"name":"verificationAddedOn","type":"uint256"},{"name":"revokedOn","type":"uint256"},{"name":"signedString","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"changeOwnerAccept","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"firstName","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"manager","type":"address"}],"name":"removeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawAllToWithdrawalAddress","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stringToSignExample","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"source","type":"string"}],"name":"stringToBytes32","outputs":[{"name":"result","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_fingerprint","type":"string"},{"name":"_fingerprintBytes20","type":"bytes20"},{"name":"_signedString","type":"string"}],"name":"uploadSignedString","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes20"}],"name":"addressAttached","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_acc","type":"address"}],"name":"revokeVerification","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"nationality","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"withdrawalAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isManager","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"priceInWei","type":"uint256"}],"name":"setPriceForVerification","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"fromAccount","type":"address"},{"indexed":false,"name":"fingerprint","type":"string"},{"indexed":false,"name":"uploadedString","type":"string"}],"name":"SignedStringUploaded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"forFingerprint","type":"string"},{"indexed":true,"name":"verifiedAccount","type":"address"},{"indexed":false,"name":"verificationAddedByAccount","type":"address"}],"name":"VerificationAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"revocedforAccount","type":"address"},{"indexed":false,"name":"withFingerprint","type":"string"},{"indexed":false,"name":"revokedOnUnixTime","type":"uint256"},{"indexed":true,"name":"revokedBy","type":"address"}],"name":"VerificationRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"startedBy","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"ChangeOwnerStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"added","type":"address"},{"indexed":true,"name":"addedBy","type":"address"}],"name":"ManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"removed","type":"address"},{"indexed":true,"name":"removedBy","type":"address"}],"name":"ManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"uint256"},{"indexed":false,"name":"to","type":"uint256"},{"indexed":true,"name":"changedBy","type":"address"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sumInWei","type":"uint256"},{"indexed":true,"name":"by","type":"address"},{"indexed":false,"name":"success","type":"bool"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":true,"name":"changedBy","type":"address"}],"name":"WithdrawalAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"withdrawalAddressFixedAs","type":"address"},{"indexed":false,"name":"fixedBy","type":"address"}],"name":"WithdrawalAddressFixed","type":"event"}] -------------------------------------------------------------------------------- /smartContract/contracts/CryptonomicaVerification.bin: -------------------------------------------------------------------------------- 1 | 6060604052608060405190810160405280604c81526020017f492068657265627920636f6e6669726d2074686174207468652061646472657381526020017f73203c61646472657373206c6f776572636173653e206973206d79204574686581526020017f7265756d20616464726573730000000000000000000000000000000000000000815250600c9080516200009c92916020019062000103565b506011805460a060020a60ff02191690553415620000b957600080fd5b600e8054600160a060020a033316600160a060020a031991821681179092556000828152600f60205260409020805460ff19166001179055601180549091169091179055620001a8565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200014657805160ff191683800117855562000176565b8280016001018555821562000176579182015b828111156200017657825182559160200191906001019062000159565b506200018492915062000188565b5090565b620001a591905b808211156200018457600081556001016200018f565b90565b611a4080620001b86000396000f3006060604052600436106101955763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166302c29349811461019a57806309905bdb146101cd5780630dc2968c146101f257806321b8092e1461028857806322652e05146102a95780632d06177a146102c857806339b51e7c146102e757806345d6f02e1461030657806347889c4214610325578063546e1959146103445780635b3d0bc11461036357806361b027b01461038257806365455fdc146103c3578063735dca66146103e257806376e57d4b14610528578063836afead1461053b5780638da5cb5b1461055a5780639201de551461058957806392b4e1321461059f5780639538833c1461085a5780639a159bf61461086d578063ac18de431461088c578063b17a98b6146108ab578063c6688445146108be578063cfb51928146108d1578063d008a10b14610922578063d6e87b44146109be578063e998d2fa146109e3578063ec94526914610a02578063f2bcd02214610a21578063f3ae241514610a34578063fb20dc8014610a53575b600080fd5b34156101a557600080fd5b6101b9600160a060020a0360043516610a69565b604051901515815260200160405180910390f35b34156101d857600080fd5b6101e0610b35565b60405190815260200160405180910390f35b34156101fd57600080fd5b610211600160a060020a0360043516610b3b565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561024d578082015183820152602001610235565b50505050905090810190601f16801561027a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561029357600080fd5b6102a7600160a060020a0360043516610beb565b005b34156102b457600080fd5b610211600160a060020a0360043516610c8c565b34156102d357600080fd5b6102a7600160a060020a0360043516610d09565b34156102f257600080fd5b6101e0600160a060020a0360043516610d7d565b341561031157600080fd5b6101e0600160a060020a0360043516610d8f565b341561033057600080fd5b6101e0600160a060020a0360043516610da1565b341561034f57600080fd5b6102a7600160a060020a0360043516610db3565b341561036e57600080fd5b6101e0600160a060020a0360043516610e2c565b341561038d57600080fd5b6103a1600160a060020a0360043516610e3e565b6040516bffffffffffffffffffffffff19909116815260200160405180910390f35b34156103ce57600080fd5b6101e0600160a060020a0360043516610e5f565b34156103ed57600080fd5b6102a760048035600160a060020a03169060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094966bffffffffffffffffffffffff19873516966020808201359750919550606081019450604090810135860180830194503592508291601f83018190048102019051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284378201915050505050509190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528181529291906020840183838082843750949650610e7195505050505050565b341561053357600080fd5b6101b9611144565b341561054657600080fd5b6101e0600160a060020a0360043516611154565b341561056557600080fd5b61056d611166565b604051600160a060020a03909116815260200160405180910390f35b341561059457600080fd5b610211600435611175565b34156105aa57600080fd5b6105be600160a060020a0360043516611231565b60405180806020018a81526020018060200180602001898152602001806020018881526020018781526020018060200186810386528f81815460018160011615610100020316600290048152602001915080546001816001161561010002031660029004801561066f5780601f106106445761010080835404028352916020019161066f565b820191906000526020600020905b81548152906001019060200180831161065257829003601f168201915b505086810385528d54600260001961010060018416150201909116048082526020909101908e9080156106e35780601f106106b8576101008083540402835291602001916106e3565b820191906000526020600020905b8154815290600101906020018083116106c657829003601f168201915b505086810384528c54600260001961010060018416150201909116048082526020909101908d9080156107575780601f1061072c57610100808354040283529160200191610757565b820191906000526020600020905b81548152906001019060200180831161073a57829003601f168201915b505086810383528a54600260001961010060018416150201909116048082526020909101908b9080156107cb5780601f106107a0576101008083540402835291602001916107cb565b820191906000526020600020905b8154815290600101906020018083116107ae57829003601f168201915b505086810382528754600260001961010060018416150201909116048082526020909101908890801561083f5780601f106108145761010080835404028352916020019161083f565b820191906000526020600020905b81548152906001019060200180831161082257829003601f168201915b50509e50505050505050505050505050505060405180910390f35b341561086557600080fd5b6102a761126c565b341561087857600080fd5b6101e0600160a060020a03600435166112f7565b341561089757600080fd5b6102a7600160a060020a0360043516611309565b34156108b657600080fd5b6101b961137a565b34156108c957600080fd5b610211611461565b34156108dc57600080fd5b6101e060046024813581810190830135806020601f820181900481020160405190810160405281815292919060208401838380828437509496506114cc95505050505050565b6102a760046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094966bffffffffffffffffffffffff19873516969095506040808201955060209182013587018083019550359350839250601f83018290048202909101905190810160405281815292919060208401838380828437509496506114d995505050505050565b34156109c957600080fd5b61056d6bffffffffffffffffffffffff19600435166116ff565b34156109ee57600080fd5b6102a7600160a060020a036004351661171a565b3415610a0d57600080fd5b6101e0600160a060020a0360043516611848565b3415610a2c57600080fd5b61056d61185a565b3415610a3f57600080fd5b6101b9600160a060020a0360043516611869565b3415610a5e57600080fd5b6102a760043561187e565b600e5460009033600160a060020a03908116911614610a8757600080fd5b601154600160a060020a03838116911614610aa157600080fd5b60115460a060020a900460ff1615610ab857600080fd5b6011805474ff0000000000000000000000000000000000000000191660a060020a17908190557fff51cf04e7fbddffc521b8673e9282b10a91c659c12eea9ef99182bd9a95ff7190600160a060020a031633604051600160a060020a039283168152911660208201526040908101905180910390a1506001919050565b60105481565b60016020528060005260406000206000915090508054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610be35780601f10610bb857610100808354040283529160200191610be3565b820191906000526020600020905b815481529060010190602001808311610bc657829003601f168201915b505050505081565b600e5433600160a060020a03908116911614610c0657600080fd5b60115460a060020a900460ff1615610c1d57600080fd5b601154600160a060020a033381169183821691167f15fc95cfd5d20b9661cf80c2719d8e3180bee6d89379a03b7b14ca6ac6adea9860405160405180910390a46011805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60096020528060005260406000206000915090508054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610be35780601f10610bb857610100808354040283529160200191610be3565b600e5433600160a060020a03908116911614610d2457600080fd5b600160a060020a038082166000818152600f602052604090819020805460ff1916600117905533909216917f05a4006f300442cf8b7fdb885f5ee958812020bffb5c5a8e655fde64e5f987ed905160405180910390a350565b60076020526000908152604090205481565b600a6020526000908152604090205481565b60056020526000908152604090205481565b600e5433600160a060020a03908116911614610dce57600080fd5b6012805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038381169182179092559033167f856621e76473127fb731503843c14f7b85c6c36fc405c3ea121471425f54fd7960405160405180910390a350565b60026020526000908152604090205481565b6000602081905290815260409020546c010000000000000000000000000281565b60046020526000908152604090205481565b600160a060020a0333166000908152600f602052604090205460ff161515610e9857600080fd5b600160a060020a0388166000908152600a60205260409020541515610ebc57600080fd5b600160a060020a03881660009081526007602052604090205415610edf57600080fd5b600160a060020a0388166000908152600d60205260409020878051610f089291602001906118f6565b50600160a060020a03881660008181526020818152604080832080546c010000000000000000000000008c0473ffffffffffffffffffffffffffffffffffffffff19918216179091556bffffffffffffffffffffffff198b168452600b83528184208054909116851790559282526002808252838320899055600d9091529190206001810187905501848051610fa29291602001906118f6565b50610fac846114cc565b600160a060020a038916600090815260036020818152604080842094909455600d905291902001838051610fe49291602001906118f6565b50610fee836114cc565b600160a060020a0389166000908152600460208181526040808420949094556005808252848420879055600d90915292909120908101849055018180516110399291602001906118f6565b50611043816114cc565b600160a060020a038916600081815260066020818152604080842095909555600781528483204290819055600d909152918490209081019190915590917f2014ad745d5cc240a4565583f1c0cf348b91f892966a154d418c591911ea04bf9190339051600160a060020a03821660208201526040808252835460026000196101006001841615020190911604908201819052819060608201908590801561112b5780601f106111005761010080835404028352916020019161112b565b820191906000526020600020905b81548152906001019060200180831161110e57829003601f168201915b5050935050505060405180910390a25050505050505050565b60115460a060020a900460ff1681565b60086020526000908152604090205481565b600e54600160a060020a031681565b61117d611970565b611185611970565b600060206040518059106111965750595b818152601f19601f8301168101602001604052905091505b602081101561122a578381602081106111c357fe5b1a7f0100000000000000000000000000000000000000000000000000000000000000028282815181106111f257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016111ae565b5092915050565b600d60205260009081526040902060018101546004820154600683015460078401546002850192600386019290916005870191906008880189565b60125433600160a060020a0390811691161461128757600080fd5b601254600e54600160a060020a0391821691167fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60405160405180910390a3601254600e805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b60036020526000908152604090205481565b600e5433600160a060020a0390811691161461132457600080fd5b600160a060020a038082166000818152600f602052604090819020805460ff1916905533909216917f3e902a6ee93dd5b2d48bd1009c7701a481be512b1ef73dbed2f95ea44c59ea88905160405180910390a350565b601154600090600160a060020a03308116803192909116903180156108fc0290604051600060405180830381858888f19350505050151561140b57601154600160a060020a0333811691167f78746de4b42c369479b14075849ee3378535cb810d96e74712e26a7924f7b021836000604051918252151560208201526040908101905180910390a36000915061145d565b601154600160a060020a0333811691167f78746de4b42c369479b14075849ee3378535cb810d96e74712e26a7924f7b021836001604051918252151560208201526040908101905180910390a3600191505b5090565b600c8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610be35780601f10610bb857610100808354040283529160200191610be3565b6000602082015192915050565b6010543410156114e857600080fd5b600160a060020a0333166000908152600a60205260409020541561150b57600080fd5b825160281461151957600080fd5b6bffffffffffffffffffffffff1982166000908152600b6020526040902054600160a060020a03161561154b57600080fd5b600160a060020a03331660009081526001602052604090208380516115749291602001906118f6565b50600160a060020a0333166000908152600d602052604090206008018180516115a19291602001906118f6565b600160a060020a033316600090815260096020526040902081546115d8929060026000196101006001841615020190911604611982565b50600160a060020a0333166000818152600a6020526040908190204290557f3c21c5143ac760b44e24852cca9d3858a3487646fe0fa6c591aa3199cc65531a908590849051808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561165b578082015183820152602001611643565b50505050905090810190601f1680156116885780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b838110156116be5780820151838201526020016116a6565b50505050905090810190601f1680156116eb5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2505050565b600b60205260009081526040902054600160a060020a031681565b80600160a060020a031633600160a060020a031614806117525750600160a060020a0333166000908152600f602052604090205460ff165b151561175d57600080fd5b600160a060020a0380821660008181526008602090815260408083204290819055600d909252918290206007810182905533909416937fc6f2b8565550ea0e6941e2f0f6b7e65e5eb1fdccb33e0c7815af0f3ce5669cff929091905160208101829052604080825283546002600019610100600184161502019091160490820181905281906060820190859080156118365780601f1061180b57610100808354040283529160200191611836565b820191906000526020600020905b81548152906001019060200180831161181957829003601f168201915b5050935050505060405180910390a350565b60066020526000908152604090205481565b601154600160a060020a031681565b600f6020526000908152604090205460ff1681565b600160a060020a0333166000908152600f602052604081205460ff1615156118a557600080fd5b506010805490829055600160a060020a0333167f665d155f71ad96c4a04629d54ef9fb27ef57911253588f2ee93474cd02fa3f53828460405191825260208201526040908101905180910390a25050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061193757805160ff1916838001178555611964565b82800160010185558215611964579182015b82811115611964578251825591602001919060010190611949565b5061145d9291506119f7565b60206040519081016040526000815290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106119bb5780548555611964565b8280016001018555821561196457600052602060002091601f016020900482015b828111156119645782548255916001019190600101906119dc565b611a1191905b8082111561145d57600081556001016119fd565b905600a165627a7a723058205d883535e3010c345f71e8432366745740f31a379d0340e8801b497f4fee1aa90029 -------------------------------------------------------------------------------- /smartContract/contracts/CryptonomicaVerification.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.19; 2 | 3 | /* 4 | developed by cryptonomica.net, 2018 5 | last version: 2018-02-18 6 | github: https://github.com/Cryptonomica/ 7 | */ 8 | 9 | contract CryptonomicaVerification { 10 | 11 | /* ---------------------- Verification Data */ 12 | 13 | // Ethereum address is connected to OpenPGP public key data from Cryptonomica.net 14 | // Ethereum address can be connected to one OpenPGP key only, and one time only 15 | // If OpenPGP key expires, user have to use another Ethereum address for new OpenPGP public key 16 | // But user can verify multiple Ethereum accounts with the same OpenPGP key 17 | 18 | // ---- mappings to store verification data, to make it accessible for other smart contracts 19 | // we store sting data as bytes32 (http://solidity.readthedocs.io/en/develop/types.html#fixed-size-byte-arrays) 20 | // !!! -> up to 32 ASCII letters, 21 | // see: https://ethereum.stackexchange.com/questions/6729/how-many-letters-can-bytes32-keep 22 | 23 | // OpenPGP Message Format https://tools.ietf.org/html/rfc4880#section-12.2 : "A V4 fingerprint is the 160-bit SHA-1 hash ..." 24 | // thus fingerprint is 20 bytes, in hexadecimal 40 symbols string representation 25 | // fingerprints are stored as upper case strings like: 26 | // 57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5 27 | // or as bytes20: "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" from web3.js or Bytes20 from web3j 28 | // see: https://crypto.stackexchange.com/questions/32087/how-to-generate-fingerprint-for-pgp-public-key 29 | mapping(address => bytes20) public fingerprint; // ..............................................................0 30 | 31 | // we use unverifiedFingerprintAsString to store fingerprint provided by user 32 | mapping(address => string) public unverifiedFingerprint; // (!) Gas requirement: infinite 33 | 34 | mapping(address => uint) public keyCertificateValidUntil; // unix time ..........................................1 35 | mapping(address => bytes32) public firstName; // ................................................................2 36 | mapping(address => bytes32) public lastName; // .................................................................3 37 | mapping(address => uint) public birthDate; // unix time .........................................................4 38 | // Nationality - from user passport or id document: 39 | // 2-letter country codes defined in ISO 3166 40 | // like returned by Locale.getISOCountries() in Java (upper case) 41 | // see: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 42 | mapping(address => bytes32) public nationality; // .........................................................5 43 | mapping(address => uint256) public verificationAddedOn; // unix time ............................................6 44 | mapping(address => uint256) public revokedOn; // unix time, returns uint256: 0 if verification is not revoked ...7 45 | // this will be longer than 32 char, and have to be properly formatted (with "\n") 46 | mapping(address => string) public signedString; //.(!) Gas requirement: infinite.................................8 47 | 48 | // unix time online converter: https://www.epochconverter.com 49 | // for coders: http://www.convert-unix-time.com 50 | mapping(address => uint256) public signedStringUploadedOnUnixTime; 51 | 52 | // this allows to search for account connected to fingerprint 53 | // as a key we use fingerprint as bytes32, like 0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5 54 | mapping(bytes20 => address) public addressAttached; // 55 | 56 | // (!) Gas requirement: infinite 57 | string public stringToSignExample = "I hereby confirm that the address
is my Ethereum address"; 58 | 59 | /* the same data as above stored as a struct: 60 | struct will be returned as 'List' in web3j (only one function call needed) */ 61 | mapping(address => Verification) public verification; // (!) Gas requirement: infinite 62 | struct Verification { 63 | // all string have to be <= 32 chars 64 | string fingerprint; // ................................................0 65 | uint keyCertificateValidUntil; // .....................................1 66 | string firstName; // ..................................................2 67 | string lastName;// ....................................................3 68 | uint birthDate; // ...................................................4 69 | string nationality; // ...............................................5 70 | uint verificationAddedOn;// ...........................................6 71 | uint revokedOn; // ....................................................7 72 | string signedString; //................................................8 73 | // uint256 signedStringUploadedOnUnixTime; //... Stack too deep 74 | } 75 | 76 | /* -------------------- Administrative Data */ 77 | address public owner; // smart contract owner (super admin) 78 | mapping(address => bool) public isManager; // list of managers 79 | 80 | uint public priceForVerificationInWei; // see converter on https://etherconverter.online/ 81 | 82 | address public withdrawalAddress; // address to send Ether from this contract 83 | bool public withdrawalAddressFixed = false; // this can be smart contract with manages ETH from this SC 84 | 85 | /* --------------------- Constructor */ 86 | function CryptonomicaVerification() public {// Constructor must be public or internal 87 | owner = msg.sender; 88 | isManager[msg.sender] = true; 89 | withdrawalAddress = msg.sender; 90 | } 91 | 92 | /* -------------------- Utility functions : ---------------------- */ 93 | 94 | // (?) CryptonomicaVerification.stringToBytes32(string memory) : Is constant but potentially should not be. 95 | // probably because of 'using low-level calls' or 'using inline assembly that contains certain opcodes' 96 | // but 'The compiler does not enforce yet that a pure method is not reading from the state.' 97 | // > in fact works as constant 98 | function stringToBytes32(string memory source) public pure returns (bytes32 result) {// (!) Gas requirement: infinite 99 | // require(bytes(source).length <= 32); // causes error, but string have to be max 32 chars 100 | 101 | // https://ethereum.stackexchange.com/questions/9603/understanding-mload-assembly-function 102 | // http://solidity.readthedocs.io/en/latest/assembly.html 103 | // this converts every char to its byte representation 104 | // see hex codes on http://www.asciitable.com/ (7 > 37, a > 61, z > 7a) 105 | // "az7" > 0x617a370000000000000000000000000000000000000000000000000000000000 106 | assembly { 107 | result := mload(add(source, 32)) 108 | } 109 | } 110 | 111 | // see also: 112 | // https://ethereum.stackexchange.com/questions/2519/how-to-convert-a-bytes32-to-string 113 | // https://ethereum.stackexchange.com/questions/1081/how-to-concatenate-a-bytes32-array-to-a-string 114 | // 0x617a370000000000000000000000000000000000000000000000000000000000 > "az7" 115 | function bytes32ToString(bytes32 _bytes32) public pure returns (string){// (!) Gas requirement: infinite 116 | // string memory str = string(_bytes32); 117 | // TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer" 118 | // thus we should convert bytes32 to bytes (to dynamically-sized byte array) 119 | bytes memory bytesArray = new bytes(32); 120 | for (uint256 i; i < 32; i++) { 121 | bytesArray[i] = _bytes32[i]; 122 | } 123 | return string(bytesArray); 124 | } 125 | 126 | /* -------------------- Verification functions : ---------------------- */ 127 | 128 | // from user acc 129 | // (!) Gas requirement: infinite 130 | function uploadSignedString(string _fingerprint, bytes20 _fingerprintBytes20, string _signedString) public payable { 131 | 132 | // check length of the uploaded string, 133 | // it expected to be a 64 chars string signed with OpenPGP standard signature 134 | // bytes: Dynamically-sized byte array, 135 | // see: http://solidity.readthedocs.io/en/develop/types.html#dynamically-sized-byte-array 136 | // if (bytes(_signedString).length > 1000) {// 137 | // revert(); 138 | // // (payable) 139 | // } 140 | // --- not needed: if string is to big -> out of gas 141 | 142 | // check payment : 143 | if (msg.value < priceForVerificationInWei) { 144 | revert(); 145 | // (payable) 146 | } 147 | 148 | // if signed string already uploaded, should revert 149 | if (signedStringUploadedOnUnixTime[msg.sender] != 0) { 150 | revert(); 151 | // (payable) 152 | } 153 | 154 | // fingerprint should be uppercase 40 symbols 155 | if (bytes(_fingerprint).length != 40) { 156 | revert(); 157 | // (payable) 158 | } 159 | 160 | // fingerprint can be connected to one eth address only 161 | if (addressAttached[_fingerprintBytes20] != 0) { 162 | revert(); 163 | // (payable) 164 | } 165 | 166 | // at this stage we can not be sure that key with this fingerprint really owned by user 167 | // thus we store it as 'unverified' 168 | unverifiedFingerprint[msg.sender] = _fingerprint; 169 | 170 | signedString[msg.sender] = verification[msg.sender].signedString = _signedString; 171 | 172 | // uint256 - Unix Time 173 | signedStringUploadedOnUnixTime[msg.sender] = block.timestamp; 174 | 175 | SignedStringUploaded(msg.sender, _fingerprint, _signedString); 176 | 177 | } 178 | 179 | event SignedStringUploaded(address indexed fromAccount, string fingerprint, string uploadedString); 180 | 181 | // from 'manager' account only 182 | // (!) Gas requirement: infinite 183 | function addVerificationData( 184 | address _acc, // 185 | string _fingerprint, // "57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 186 | bytes20 _fingerprintBytes20, // "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 187 | uint _keyCertificateValidUntil, // 188 | string _firstName, // 189 | string _lastName, // 190 | uint _birthDate, // 191 | string _nationality) public { 192 | 193 | // (!!!) only manager can add verification data 194 | require(isManager[msg.sender]); 195 | 196 | // check input 197 | // fingerprint should be uppercase 40 symbols 198 | // require(bytes(_fingerprint).length == 40); 199 | // require(bytes(_firstName).length <= 32); 200 | // require(bytes(_lastName).length <= 32); 201 | // _nationality should be like "IL" or "US" 202 | // require(bytes(_nationality).length == 2); 203 | // >>> if we control manager account we can make checks before sending data to smart contract (cheaper) 204 | 205 | // check if signed string uploaded 206 | require(signedStringUploadedOnUnixTime[_acc] != 0); 207 | // to make possible adding verification only one time: 208 | require(verificationAddedOn[_acc] == 0); 209 | 210 | verification[_acc].fingerprint = _fingerprint; 211 | fingerprint[_acc] = _fingerprintBytes20; 212 | 213 | addressAttached[_fingerprintBytes20] = _acc; 214 | 215 | verification[_acc].keyCertificateValidUntil = keyCertificateValidUntil[_acc] = _keyCertificateValidUntil; 216 | verification[_acc].firstName = _firstName; 217 | firstName[_acc] = stringToBytes32(_firstName); 218 | verification[_acc].lastName = _lastName; 219 | lastName[_acc] = stringToBytes32(_lastName); 220 | verification[_acc].birthDate = birthDate[_acc] = _birthDate; 221 | verification[_acc].nationality = _nationality; 222 | nationality[_acc] = stringToBytes32(_nationality); 223 | verification[_acc].verificationAddedOn = verificationAddedOn[_acc] = block.timestamp; 224 | 225 | VerificationAdded( 226 | verification[_acc].fingerprint, 227 | _acc, 228 | // keyCertificateValidUntil[_acc], 229 | // verification[_acc].firstName, 230 | // verification[_acc].lastName, 231 | // birthDate[_acc], 232 | // verification[_acc].nationality, 233 | msg.sender 234 | ); 235 | // return true; 236 | } 237 | 238 | event VerificationAdded ( 239 | string forFingerprint, 240 | address indexed verifiedAccount, // (1) indexed 241 | // uint keyCertificateValidUntilUnixTime, 242 | // string userFirstName, 243 | // string userLastName, 244 | // uint userBirthDate, 245 | // string userNationality, 246 | address verificationAddedByAccount 247 | ); 248 | 249 | // from user or 'manager' account 250 | function revokeVerification(address _acc) public {// (!) Gas requirement: infinite 251 | require(msg.sender == _acc || isManager[msg.sender]); 252 | 253 | verification[_acc].revokedOn = revokedOn[_acc] = block.timestamp; 254 | 255 | // event 256 | VerificationRevoked( 257 | _acc, 258 | verification[_acc].fingerprint, 259 | block.timestamp, 260 | msg.sender 261 | ); 262 | } 263 | 264 | event VerificationRevoked ( 265 | address indexed revocedforAccount, // (1) indexed 266 | string withFingerprint, 267 | uint revokedOnUnixTime, 268 | address indexed revokedBy // (2) indexed 269 | ); 270 | 271 | /* -------------------- Administrative functions : ---------------------- */ 272 | 273 | // to avoid mistakes: owner (super admin) should be changed in two steps 274 | // change is valid when accepted from new owner address 275 | address private newOwner; 276 | // only owner 277 | function changeOwnerStart(address _newOwner) public { 278 | require(msg.sender == owner); 279 | newOwner = _newOwner; 280 | ChangeOwnerStarted(msg.sender, _newOwner); 281 | } // 282 | event ChangeOwnerStarted (address indexed startedBy, address indexed newOwner); 283 | // only by new owner 284 | function changeOwnerAccept() public { 285 | require(msg.sender == newOwner); 286 | // event here: 287 | OwnerChanged(owner, newOwner); 288 | owner = newOwner; 289 | } // 290 | event OwnerChanged(address indexed from, address indexed to); 291 | 292 | // only owner 293 | function addManager(address _acc) public { 294 | require(msg.sender == owner); 295 | isManager[_acc] = true; 296 | ManagerAdded(_acc, msg.sender); 297 | } // 298 | event ManagerAdded (address indexed added, address indexed addedBy); 299 | // only owner 300 | function removeManager(address manager) public { 301 | require(msg.sender == owner); 302 | isManager[manager] = false; 303 | ManagerRemoved(manager, msg.sender); 304 | } // 305 | event ManagerRemoved(address indexed removed, address indexed removedBy); 306 | 307 | // only by manager 308 | function setPriceForVerification(uint priceInWei) public { 309 | // see converter on https://etherconverter.online 310 | require(isManager[msg.sender]); 311 | uint oldPrice = priceForVerificationInWei; 312 | priceForVerificationInWei = priceInWei; 313 | PriceChanged(oldPrice, priceForVerificationInWei, msg.sender); 314 | } // 315 | event PriceChanged(uint from, uint to, address indexed changedBy); 316 | 317 | // !!! can be called by any user or contract 318 | // check for re-entrancy vulnerability http://solidity.readthedocs.io/en/develop/security-considerations.html#re-entrancy 319 | // >>> since we are making a withdrawal to our own contract only there is no possible attack using re-entrancy vulnerability, 320 | function withdrawAllToWithdrawalAddress() public returns (bool) {// (!) Gas requirement: infinite 321 | // http://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether 322 | // about
.send(uint256 amount) and
.transfer(uint256 amount) 323 | // see: http://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=transfer#address-related 324 | // https://ethereum.stackexchange.com/questions/19341/address-send-vs-address-transfer-best-practice-usage 325 | uint sum = this.balance; 326 | if (!withdrawalAddress.send(this.balance)) {// makes withdrawal and returns true or false 327 | Withdrawal(withdrawalAddress, sum, msg.sender, false); 328 | return false; 329 | } 330 | Withdrawal(withdrawalAddress, sum, msg.sender, true); 331 | return true; 332 | } // 333 | event Withdrawal(address indexed to, uint sumInWei, address indexed by, bool success); 334 | 335 | // only owner 336 | function setWithdrawalAddress(address _withdrawalAddress) public { 337 | require(msg.sender == owner); 338 | require(!withdrawalAddressFixed); 339 | WithdrawalAddressChanged(withdrawalAddress, _withdrawalAddress, msg.sender); 340 | withdrawalAddress = _withdrawalAddress; 341 | } // 342 | event WithdrawalAddressChanged(address indexed from, address indexed to, address indexed changedBy); 343 | 344 | // only owner 345 | function fixWithdrawalAddress(address _withdrawalAddress) public returns (bool) { 346 | require(msg.sender == owner); 347 | require(withdrawalAddress == _withdrawalAddress); 348 | 349 | // prevents event if already fixed 350 | require(!withdrawalAddressFixed); 351 | 352 | withdrawalAddressFixed = true; 353 | WithdrawalAddressFixed(withdrawalAddress, msg.sender); 354 | return true; 355 | } // 356 | // this event can be fired one time only 357 | event WithdrawalAddressFixed(address withdrawalAddressFixedAs, address fixedBy); 358 | 359 | } 360 | -------------------------------------------------------------------------------- /smartContract/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /smartContract/copy.truffle.artifacts.to.cryptonomica.github.io.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cp -vf ./build/contracts/CryptonomicaVerification.json ../../cryptonomica.github.io/app/ethereum/ 4 | cp -vf ./build/contracts/networks.js ../../cryptonomica.github.io/app/ethereum/ 5 | cp -vf ./contracts/CryptonomicaVerification.sol ../../cryptonomica.github.io/app/ethereum/ 6 | cp -vf ./contracts/CryptonomicaVerification.abi ../../cryptonomica.github.io/app/ethereum/ 7 | ls -latF ../../cryptonomica.github.io/app/ethereum/ 8 | -------------------------------------------------------------------------------- /smartContract/deploy.CryptonomicaVerification.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* ------------------------------------------------------------*/ 4 | // to have access to node, run with --rpc , and unlock account: 5 | // geth --testnet --rpc --unlock 0 6 | // for testrpc, just run: 7 | // testrpc 8 | // for rinkeby: 9 | // geth --rinkeby --rpc --rpcapi db,eth,net,web3,personal --unlock "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D" 10 | // 11 | // JS console 12 | // MainNet: 13 | // geth attach 14 | // testrpc: 15 | // geth attach http://localhost:8545 16 | // Ropsten: 17 | // geth attach ipc://${HOME}/.ethereum/testnet/geth.ipc 18 | // Rinkeby: 19 | // geth attach ipc://${HOME}/.ethereum/rinkeby/geth.ipc 20 | /* ------------------------------------------------------------*/ 21 | 22 | var rinkebyOwnerAddress = "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D"; 23 | var ownerAddress = rinkebyOwnerAddress; 24 | 25 | // https://log4js-node.github.io/log4js-node/ 26 | // https://github.com/log4js-node/log4js-node 27 | var log4js = require('log4js'); 28 | log4js.configure({ 29 | appenders: { 30 | everything: {type: 'file', filename: 'all-the-logs.log'} 31 | }, 32 | categories: { 33 | default: {appenders: ['everything'], level: 'debug'} 34 | } 35 | }); 36 | var logger = log4js.getLogger(); 37 | logger.level = 'debug'; 38 | logger.debug("**********************"); 39 | logger.debug("log4js logger started"); 40 | 41 | const fs = require("fs"); 42 | 43 | // https://github.com/ethereum/solc-js 44 | // https://www.npmjs.com/package/solc 45 | const solc = require('solc'); 46 | 47 | // https://www.npmjs.com/package/jsonfile 48 | var jsonfile = require('jsonfile'); 49 | 50 | // web3 instantiation 51 | // see: https://github.com/ethereum/web3.js/blob/master/example/node-app.js 52 | // https://github.com/ethereum/wiki/wiki/JavaScript-API#adding-web3 53 | // (!) use "web3": "^0.20.1" like truffle-contract uses, not the last version! 54 | var Web3 = require('web3'); 55 | var web3 = new Web3(); 56 | web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); 57 | 58 | // Web3.js API Reference: 59 | // https://github.com/ethereum/wiki/wiki/JavaScript-API#web3js-api-reference 60 | if (web3.isConnected()) { 61 | web3.version.getNetwork(function (error, result) { 62 | if (error) { 63 | console.log(error); 64 | logger.debug(error); 65 | } else { 66 | console.log("web3.version.getNetwork:", result); 67 | logger.debug("web3.version.getNetwork:", result); 68 | 69 | web3.eth.defaultAccount = ownerAddress; 70 | 71 | // // https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcontract 72 | // var source = fs.readFileSync('./contracts/CryptonomicaVerification.sol', 'utf8'); 73 | // console.log(source); 74 | // var compiledContract = solc.compile(source, 1); // setting 1 as second parameter activates the optimiser 75 | // // console.log(compiledContract); 76 | // var contractName; 77 | // for (var property in compiledContract.contracts) { 78 | // contractName = property; 79 | // } 80 | // console.log(contractName); 81 | // var abi = compiledContract.contracts[contractName].interface; 82 | // var bytecode = compiledContract.contracts[contractName].bytecode; 83 | // console.log(bytecode); 84 | // // var gasEstimate = web3.eth.estimateGas({data: bytecode}); 85 | // // var Contract = web3.eth.contract(JSON.parse(abi)); 86 | 87 | var bin = fs.readFileSync('./contracts/CryptonomicaVerification.bin', 'utf8'); 88 | var bytecode = '0x' + bin; 89 | 90 | var abi = JSON.parse( 91 | fs.readFileSync('./contracts/CryptonomicaVerification.abi', 'utf8') 92 | ); 93 | 94 | // https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcontract 95 | var Contract = web3.eth.contract(abi); 96 | // Deploy contract syncronous: The address will be added as soon as the contract is mined. 97 | // Additionally you can watch the transaction by using the "transactionHash" property 98 | var contractInstance = Contract.new( 99 | { 100 | data: bytecode, 101 | gas: 6000000, // << 102 | from: ownerAddress 103 | } 104 | ); 105 | 106 | console.log(contractInstance); 107 | console.log('contractInstance.transactionHash: ', contractInstance.transactionHash); // The hash of the transaction, which created the contract 108 | console.log('contractInstance.address: ', contractInstance.address); // undefined at start, but will be auto-filled later 109 | // verification on etherscan works 110 | 111 | logger.debug('contractInstance.transactionHash: ', contractInstance.transactionHash); 112 | logger.debug('contractInstance.address: ', contractInstance.address); 113 | 114 | } 115 | } 116 | ); 117 | } else { 118 | console.log('web3 is not connected to Ethereum node'); 119 | logger.debug('web3 is not connected to Ethereum node'); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /smartContract/drafts/CryptonomicaInvestorAccreditation.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.19; 2 | 3 | contract CryptonomicaInvestorAccreditation { 4 | 5 | function CryptonomicaInvestorAccreditation(){ 6 | // 7 | } 8 | 9 | /* -------------------- Investor Verification -------------------- */ 10 | mapping(address => bool) public isAccreditedInvestor; 11 | mapping(address => string) public investorVerifiedByStr; // description of a person who verified investor status 12 | mapping(address => address) public investorVerificationAddedByAddress; // eth address of a person who verified investor status 13 | mapping(address => uint) public investorVerificationAddedOn; // 14 | mapping(address => uint) public investorVerificationValidUntil; // 0 - if not set 15 | mapping(address => uint) public investorVerificationRevokedOn; // 0 - if not revoked 16 | mapping(address => bool) public canVerifyInvestors; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /smartContract/drafts/CryptonomicaVerification.NEXT.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.19; 2 | 3 | /* 4 | developed by cryptonomica.net, 2018 5 | last version: 2018-02-18 6 | github: https://github.com/Cryptonomica/ 7 | */ 8 | 9 | contract CryptonomicaVerification { 10 | 11 | /* ---------------------- Verification Data */ 12 | 13 | // Ethereum address is connected to OpenPGP public key data from Cryptonomica.net 14 | // Ethereum address can be connected to one OpenPGP key only, and one time only 15 | // If OpenPGP key expires, user have to use another Ethereum address for new OpenPGP public key 16 | // But user can verify multiple Ethereum accounts with the same OpenPGP key 17 | 18 | // ---- mappings to store verification data, to make it accessible for other smart contracts 19 | // we store sting data as bytes32 (http://solidity.readthedocs.io/en/develop/types.html#fixed-size-byte-arrays) 20 | // !!! -> up to 32 ASCII letters, 21 | // see: https://ethereum.stackexchange.com/questions/6729/how-many-letters-can-bytes32-keep 22 | 23 | // OpenPGP Message Format https://tools.ietf.org/html/rfc4880#section-12.2 : "A V4 fingerprint is the 160-bit SHA-1 hash ..." 24 | // thus fingerprint is 20 bytes, in hexadecimal 40 symbols string representation 25 | // fingerprints are stored as upper case strings like: 26 | // 57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5 27 | // or as bytes20: "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" from web3.js or Bytes20 from web3j 28 | // see: https://crypto.stackexchange.com/questions/32087/how-to-generate-fingerprint-for-pgp-public-key 29 | mapping(address => bytes20) public fingerprint; // ..............................................................0 30 | 31 | // we use unverifiedFingerprintAsString to store fingerprint provided by user 32 | mapping(address => string) public unverifiedFingerprint; // (!) Gas requirement: infinite 33 | 34 | mapping(address => uint) public keyCertificateValidUntil; // unix time ..........................................1 35 | mapping(address => bytes32) public firstName; // ................................................................2 36 | mapping(address => bytes32) public lastName; // .................................................................3 37 | mapping(address => uint) public birthDate; // unix time .........................................................4 38 | // Nationality - from user passport or id document: 39 | // 2-letter country codes defined in ISO 3166 40 | // like returned by Locale.getISOCountries() in Java (upper case) 41 | // see: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 42 | mapping(address => bytes32) public nationality; // .........................................................5 43 | mapping(address => uint256) public verificationAddedOn; // unix time ............................................6 44 | mapping(address => uint256) public revokedOn; // unix time, returns uint256: 0 if verification is not revoked ...7 45 | // this will be longer than 32 char, and have to be properly formatted (with "\n") 46 | mapping(address => string) public signedString; //.(!) Gas requirement: infinite.................................8 47 | 48 | // unix time online converter: https://www.epochconverter.com 49 | // for coders: http://www.convert-unix-time.com 50 | mapping(address => uint256) public signedStringUploadedOnUnixTime; 51 | 52 | // this allows to search for account connected to fingerprint 53 | // as a key we use fingerprint as bytes32, like 0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5 54 | mapping(bytes20 => address) public addressAttached; // 55 | 56 | // (!) Gas requirement: infinite 57 | string public stringToSignExample = "I hereby confirm that the address
is my Ethereum address"; 58 | 59 | /* the same data as above stored as a struct: 60 | struct will be returned as 'List' in web3j (only one function call needed) */ 61 | mapping(address => Verification) public verification; // (!) Gas requirement: infinite 62 | struct Verification { 63 | // all string have to be <= 32 chars 64 | string fingerprint; // ................................................0 65 | uint keyCertificateValidUntil; // .....................................1 66 | string firstName; // ..................................................2 67 | string lastName;// ....................................................3 68 | uint birthDate; // ...................................................4 69 | string nationality; // ...............................................5 70 | uint verificationAddedOn;// ...........................................6 71 | uint revokedOn; // ....................................................7 72 | string signedString; //................................................8 73 | // uint256 signedStringUploadedOnUnixTime; //... Stack too deep 74 | } 75 | 76 | /* -------------------- Administrative Data */ 77 | address public owner; // smart contract owner (super admin) 78 | mapping(address => bool) public isManager; // list of managers 79 | 80 | uint public priceForVerificationInWei; // see converter on https://etherconverter.online/ 81 | 82 | address public withdrawalAddress; // address to send Ether from this contract 83 | bool public withdrawalAddressFixed = false; // this can be smart contract with manages ETH from this SC 84 | 85 | /* --------------------- Constructor */ 86 | function CryptonomicaVerification() public {// Constructor must be public or internal 87 | owner = msg.sender; 88 | isManager[msg.sender] = true; 89 | withdrawalAddress = msg.sender; 90 | } 91 | 92 | /* -------------------- Utility functions : ---------------------- */ 93 | 94 | // (?) CryptonomicaVerification.stringToBytes32(string memory) : Is constant but potentially should not be. 95 | // probably because of 'using low-level calls' or 'using inline assembly that contains certain opcodes' 96 | // but 'The compiler does not enforce yet that a pure method is not reading from the state.' 97 | // > in fact works as constant 98 | function stringToBytes32(string memory source) public pure returns (bytes32 result) {// (!) Gas requirement: infinite 99 | // require(bytes(source).length <= 32); // causes error, but string have to be max 32 chars 100 | 101 | // https://ethereum.stackexchange.com/questions/9603/understanding-mload-assembly-function 102 | // http://solidity.readthedocs.io/en/latest/assembly.html 103 | // this converts every char to its byte representation 104 | // see hex codes on http://www.asciitable.com/ (7 > 37, a > 61, z > 7a) 105 | // "az7" > 0x617a370000000000000000000000000000000000000000000000000000000000 106 | assembly { 107 | result := mload(add(source, 32)) 108 | } 109 | } 110 | 111 | // see also: 112 | // https://ethereum.stackexchange.com/questions/2519/how-to-convert-a-bytes32-to-string 113 | // https://ethereum.stackexchange.com/questions/1081/how-to-concatenate-a-bytes32-array-to-a-string 114 | // 0x617a370000000000000000000000000000000000000000000000000000000000 > "az7" 115 | function bytes32ToString(bytes32 _bytes32) public pure returns (string){// (!) Gas requirement: infinite 116 | // string memory str = string(_bytes32); 117 | // TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer" 118 | // thus we should convert bytes32 to bytes (to dynamically-sized byte array) 119 | bytes memory bytesArray = new bytes(32); 120 | for (uint256 i; i < 32; i++) { 121 | bytesArray[i] = _bytes32[i]; 122 | } 123 | return string(bytesArray); 124 | } 125 | 126 | /* -------------------- Verification functions : ---------------------- */ 127 | 128 | // from user acc 129 | // (!) Gas requirement: infinite 130 | function uploadSignedString(string _fingerprint, bytes20 _fingerprintBytes20, string _signedString) public payable { 131 | 132 | // check length of the uploaded string, 133 | // it expected to be a 64 chars string signed with OpenPGP standard signature 134 | // bytes: Dynamically-sized byte array, 135 | // see: http://solidity.readthedocs.io/en/develop/types.html#dynamically-sized-byte-array 136 | // if (bytes(_signedString).length > 1000) {// 137 | // revert(); 138 | // // (payable) 139 | // } 140 | // --- not needed: if string is to big -> out of gas 141 | 142 | // check payment : 143 | if (msg.value < priceForVerificationInWei) { 144 | revert(); 145 | // (payable) 146 | } 147 | 148 | // if signed string already uploaded, should revert 149 | if (signedStringUploadedOnUnixTime[msg.sender] != 0) { 150 | revert(); 151 | // (payable) 152 | } 153 | 154 | // fingerprint should be uppercase 40 symbols 155 | if (bytes(_fingerprint).length != 40) { 156 | revert(); 157 | // (payable) 158 | } 159 | 160 | // fingerprint can be connected to one eth address only 161 | if (addressAttached[_fingerprintBytes20] != 0) { 162 | revert(); 163 | // (payable) 164 | } 165 | 166 | // at this stage we can not be sure that key with this fingerprint really owned by user 167 | // thus we store it as 'unverified' 168 | unverifiedFingerprint[msg.sender] = _fingerprint; 169 | 170 | signedString[msg.sender] = verification[msg.sender].signedString = _signedString; 171 | 172 | // uint256 - Unix Time 173 | signedStringUploadedOnUnixTime[msg.sender] = block.timestamp; 174 | 175 | SignedStringUploaded(msg.sender, _fingerprint, _signedString); 176 | 177 | } 178 | 179 | event SignedStringUploaded(address indexed fromAccount, string fingerprint, string uploadedString); 180 | 181 | // from 'manager' account only 182 | // (!) Gas requirement: infinite 183 | function addVerificationData( 184 | address _acc, // 185 | string _fingerprint, // "57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 186 | bytes20 _fingerprintBytes20, // "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 187 | uint _keyCertificateValidUntil, // 188 | string _firstName, // 189 | string _lastName, // 190 | uint _birthDate, // 191 | string _nationality) public { 192 | 193 | // (!!!) only manager can add verification data 194 | require(isManager[msg.sender]); 195 | 196 | // check input 197 | // fingerprint should be uppercase 40 symbols 198 | // require(bytes(_fingerprint).length == 40); 199 | // require(bytes(_firstName).length <= 32); 200 | // require(bytes(_lastName).length <= 32); 201 | // _nationality should be like "IL" or "US" 202 | // require(bytes(_nationality).length == 2); 203 | // >>> if we control manager account we can make checks before sending data to smart contract (cheaper) 204 | 205 | // check if signed string uploaded 206 | require(signedStringUploadedOnUnixTime[_acc] != 0); 207 | // to make possible adding verification only one time: 208 | require(verificationAddedOn[_acc] == 0); 209 | 210 | verification[_acc].fingerprint = _fingerprint; 211 | fingerprint[_acc] = _fingerprintBytes20; 212 | 213 | addressAttached[_fingerprintBytes20] = _acc; 214 | 215 | verification[_acc].keyCertificateValidUntil = keyCertificateValidUntil[_acc] = _keyCertificateValidUntil; 216 | verification[_acc].firstName = _firstName; 217 | firstName[_acc] = stringToBytes32(_firstName); 218 | verification[_acc].lastName = _lastName; 219 | lastName[_acc] = stringToBytes32(_lastName); 220 | verification[_acc].birthDate = birthDate[_acc] = _birthDate; 221 | verification[_acc].nationality = _nationality; 222 | nationality[_acc] = stringToBytes32(_nationality); 223 | verification[_acc].verificationAddedOn = verificationAddedOn[_acc] = block.timestamp; 224 | 225 | VerificationAdded( 226 | verification[_acc].fingerprint, 227 | _acc, 228 | // keyCertificateValidUntil[_acc], 229 | // verification[_acc].firstName, 230 | // verification[_acc].lastName, 231 | // birthDate[_acc], 232 | // verification[_acc].nationality, 233 | msg.sender 234 | ); 235 | // return true; 236 | } 237 | 238 | event VerificationAdded ( 239 | string forFingerprint, 240 | address indexed verifiedAccount, // (1) indexed 241 | // uint keyCertificateValidUntilUnixTime, 242 | // string userFirstName, 243 | // string userLastName, 244 | // uint userBirthDate, 245 | // string userNationality, 246 | address verificationAddedByAccount 247 | ); 248 | 249 | // from user or 'manager' account 250 | function revokeVerification(address _acc) public {// (!) Gas requirement: infinite 251 | require(msg.sender == _acc || isManager[msg.sender]); 252 | 253 | verification[_acc].revokedOn = revokedOn[_acc] = block.timestamp; 254 | 255 | // event 256 | VerificationRevoked( 257 | _acc, 258 | verification[_acc].fingerprint, 259 | block.timestamp, 260 | msg.sender 261 | ); 262 | } 263 | 264 | event VerificationRevoked ( 265 | address indexed revocedforAccount, // (1) indexed 266 | string withFingerprint, 267 | uint revokedOnUnixTime, 268 | address indexed revokedBy // (2) indexed 269 | ); 270 | 271 | // TODO: add 272 | function checkVerification(address _user) public view returns (bool){ 273 | return (keyCertificateValidUntil(_user) > now) && (revokedOn(_user) == 0); 274 | } 275 | 276 | 277 | /* -------------------- Administrative functions : ---------------------- */ 278 | 279 | // to avoid mistakes: owner (super admin) should be changed in two steps 280 | // change is valid when accepted from new owner address 281 | address private newOwner; 282 | // only owner 283 | function changeOwnerStart(address _newOwner) public { 284 | require(msg.sender == owner); 285 | newOwner = _newOwner; 286 | ChangeOwnerStarted(msg.sender, _newOwner); 287 | } // 288 | event ChangeOwnerStarted (address indexed startedBy, address indexed newOwner); 289 | // only by new owner 290 | function changeOwnerAccept() public { 291 | require(msg.sender == newOwner); 292 | // event here: 293 | OwnerChanged(owner, newOwner); 294 | owner = newOwner; 295 | } // 296 | event OwnerChanged(address indexed from, address indexed to); 297 | 298 | // only owner 299 | function addManager(address _acc) public { 300 | require(msg.sender == owner); 301 | isManager[_acc] = true; 302 | ManagerAdded(_acc, msg.sender); 303 | } // 304 | event ManagerAdded (address indexed added, address indexed addedBy); 305 | // only owner 306 | function removeManager(address manager) public { 307 | require(msg.sender == owner); 308 | isManager[manager] = false; 309 | ManagerRemoved(manager, msg.sender); 310 | } // 311 | event ManagerRemoved(address indexed removed, address indexed removedBy); 312 | 313 | // only by manager 314 | function setPriceForVerification(uint priceInWei) public { 315 | // see converter on https://etherconverter.online 316 | require(isManager[msg.sender]); 317 | uint oldPrice = priceForVerificationInWei; 318 | priceForVerificationInWei = priceInWei; 319 | PriceChanged(oldPrice, priceForVerificationInWei, msg.sender); 320 | } // 321 | event PriceChanged(uint from, uint to, address indexed changedBy); 322 | 323 | // !!! can be called by any user or contract 324 | // check for re-entrancy vulnerability http://solidity.readthedocs.io/en/develop/security-considerations.html#re-entrancy 325 | // >>> since we are making a withdrawal to our own contract only there is no possible attack using re-entrancy vulnerability, 326 | function withdrawAllToWithdrawalAddress() public returns (bool) {// (!) Gas requirement: infinite 327 | // http://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether 328 | // about
.send(uint256 amount) and
.transfer(uint256 amount) 329 | // see: http://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=transfer#address-related 330 | // https://ethereum.stackexchange.com/questions/19341/address-send-vs-address-transfer-best-practice-usage 331 | uint sum = this.balance; 332 | if (!withdrawalAddress.send(this.balance)) {// makes withdrawal and returns true or false 333 | Withdrawal(withdrawalAddress, sum, msg.sender, false); 334 | return false; 335 | } 336 | Withdrawal(withdrawalAddress, sum, msg.sender, true); 337 | return true; 338 | } // 339 | event Withdrawal(address indexed to, uint sumInWei, address indexed by, bool success); 340 | 341 | // only owner 342 | function setWithdrawalAddress(address _withdrawalAddress) public { 343 | require(msg.sender == owner); 344 | require(!withdrawalAddressFixed); 345 | WithdrawalAddressChanged(withdrawalAddress, _withdrawalAddress, msg.sender); 346 | withdrawalAddress = _withdrawalAddress; 347 | } // 348 | event WithdrawalAddressChanged(address indexed from, address indexed to, address indexed changedBy); 349 | 350 | // only owner 351 | function fixWithdrawalAddress(address _withdrawalAddress) public returns (bool) { 352 | require(msg.sender == owner); 353 | require(withdrawalAddress == _withdrawalAddress); 354 | 355 | // prevents event if already fixed 356 | require(!withdrawalAddressFixed); 357 | 358 | withdrawalAddressFixed = true; 359 | WithdrawalAddressFixed(withdrawalAddress, msg.sender); 360 | return true; 361 | } // 362 | // this event can be fired one time only 363 | event WithdrawalAddressFixed(address withdrawalAddressFixedAs, address fixedBy); 364 | 365 | } 366 | -------------------------------------------------------------------------------- /smartContract/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /smartContract/nodejs.module.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # create nodejs module in IntelliJ IDEA, then: 4 | 5 | npm -v 6 | sudo npm install npm@latest -g 7 | 8 | npm uninstall express serve-favicon hbs body-parser cookie-parser morgan debug 9 | # removed 84 packages in 0.729s 10 | rm -r bin public routes views 11 | mkdir contracts 12 | 13 | # (!) use "web3": "^0.20.1" like truffle-contract uses, not the last version! 14 | # use solc-js version as last solc version 15 | npm install log4js jsonfile solc@0.4.19 web3@0.20.1 truffle-artifactor 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /smartContract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smartcontract", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "jsonfile": "^4.0.0", 10 | "log4js": "^2.5.3", 11 | "solc": "^0.4.19", 12 | "truffle-artifactor": "^3.0.3", 13 | "web3": "^0.20.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /smartContract/smartContract.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /smartContract/truffle-artifactor.save.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require("fs"); 4 | 5 | // see: https://github.com/trufflesuite/truffle-contract#full-example 6 | // https://github.com/trufflesuite/truffle-artifactor#example 7 | // https://github.com/trufflesuite/truffle-artifactor 8 | var Artifactor = require("truffle-artifactor"); 9 | var artifactor = new Artifactor("./build"); // no '/' at the end 10 | 11 | console.log(artifactor); 12 | 13 | // for test: 14 | for (var property in artifactor) { 15 | // if (artifactor.hasOwnProperty(property)) { 16 | console.log(property); 17 | // } 18 | } 19 | 20 | var truffleArtifactJSON = JSON.parse( 21 | fs.readFileSync('./build/contracts/CryptonomicaVerification.json', 'utf8') 22 | ); 23 | 24 | artifactor.save(truffleArtifactJSON, 'CryptonomicaVerification.sol.js') 25 | .then(function (result) { 26 | console.log("artifactor.save:", result); 27 | }).catch(function (error) { 28 | console.log("artifactor.save:", error); 29 | } 30 | ); // (!!!) now artifactor.save produces .json file like 'truffle compile' 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /smartContract/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | }; 5 | -------------------------------------------------------------------------------- /smartContract/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See to customize your Truffle configuration! 3 | networks: { 4 | development: { 5 | host: "localhost", 6 | port: 8545, 7 | network_id: "*" // Match any network id 8 | }, 9 | rinkeby: { 10 | host: "localhost", // Connect to geth on the specified 11 | port: 8545, 12 | from: "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D", // <<< address as on server ----------------------- <<< 13 | network_id: 4, 14 | gas: 4612388 // Gas limit used for deploys 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /smartContract/truffle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # http://truffleframework.com 4 | #https://github.com/trufflesuite/truffle 5 | 6 | # install: 7 | # sudo npm install -g truffle 8 | 9 | # init ( see http://truffleframework.com/docs/getting_started/project ): 10 | # truffle init 11 | 12 | 13 | # truffle compile 14 | # Writing artifacts to ./build/contracts 15 | # see: https://github.com/trufflesuite/truffle-contract-schema 16 | 17 | # (!!!) 18 | # truffle deploy 19 | # changes contacts data in ./build/contracts 20 | # contract does not pass code verification on etherscan when deployed via truffle (Truffle v4.0.6) 21 | # (at the same time if deployed with pure web3.js - O.K.) 22 | 23 | ### to deploy on Ropsten: 24 | ## (https://ethereum.stackexchange.com/questions/23279/what-is-steps-to-deploy-the-contract-on-ropsten-network/23320 ) 25 | # geth --fast --cache=1048 --testnet --unlock "0xmyaddress" --rpc --rpcapi "eth,net,web3" --rpccorsdomain '*' --rpcaddr localhost --rpcport 8545 26 | # cd ./src/main/resources/ 27 | # truffle migrate --network ropsten 28 | ## (truffle deploy is an alias for truffle migrate. They both do the same thing) 29 | ## see: https://ethereum.stackexchange.com/questions/23065/truffle-migrate-vs-truffle-deploy 30 | # geth attach ipc://${HOME}/.ethereum/testnet/geth.ipc 31 | 32 | ### Deploying Truffle Contracts to Rinkeby 33 | ## https://blog.abuiles.com/blog/2017/07/09/deploying-truffle-contracts-to-rinkeby/ 34 | # geth --rinkeby --rpc --rpcapi db,eth,net,web3,personal --unlock "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D" 35 | # cd ./src/main/resources/ 36 | # truffle migrate --network rinkeby 37 | ## (truffle deploy is an alias for truffle migrate. They both do the same thing) 38 | ## see: https://ethereum.stackexchange.com/questions/23065/truffle-migrate-vs-truffle-deploy 39 | # geth attach ipc://${HOME}/.ethereum/rinkeby/geth.ipc 40 | -------------------------------------------------------------------------------- /smartContract/web3j.compile.smart.contracts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # see: 4 | ## https://github.com/web3j/web3j#java-smart-contract-wrappers 5 | 6 | echo "------ solc:" 7 | echo "solc ./contracts/CryptonomicaVerification.sol --bin --abi --optimize --gas --overwrite -o ./contracts/" 8 | solc ./contracts/CryptonomicaVerification.sol --bin --abi --optimize --gas --overwrite -o ./contracts/ > ./contracts/CryptonomicaVerification.Gas.Estimation.txt 9 | echo "----- ls ./contracts -a" 10 | ls ./contracts -a 11 | 12 | # 13 | echo "----- web3j:" 14 | ~/LIBs/web3j-3.2.0/bin/web3j solidity generate ./contracts/CryptonomicaVerification.bin ./contracts/CryptonomicaVerification.abi -o ../src/main/java -p net.cryptonomica.tomcatweb3j.contracts 15 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/contracts/CryptonomicaVerificationFunctions.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.contracts; 2 | 3 | import com.google.gson.Gson; 4 | import net.cryptonomica.tomcatweb3j.entities.AddVerificationDataObj; 5 | import net.cryptonomica.tomcatweb3j.entities.DataCurrentNetwork; 6 | import net.cryptonomica.tomcatweb3j.entities.VerificationStruct; 7 | import net.cryptonomica.tomcatweb3j.utilities.DataCurrentNetworkFactory; 8 | import net.cryptonomica.tomcatweb3j.utilities.Web3jServices; 9 | import org.web3j.protocol.Web3j; 10 | import org.web3j.protocol.core.methods.response.Log; 11 | import org.web3j.protocol.core.methods.response.TransactionReceipt; 12 | import org.web3j.tuples.generated.Tuple9; 13 | 14 | import java.io.IOException; 15 | import java.math.BigInteger; 16 | import java.util.List; 17 | import java.util.logging.Logger; 18 | 19 | /* 20 | transaction receipt example: 21 | {"transactionHash":"0xaaaf335e1d981be091995ac4affe3c9f32fb046fc6fad4660090755c76251267","transactionIndex":"0x4","blockHash":"0x070e19f881d84b24b3def54b3485a2c1dd28110936ad7ce52683539f696ed40f","blockNumber":"0x13dc40","cumulativeGasUsed":"0x4befc","gasUsed":"0xb046","from":"0x3fab7ebe4b2c31a75cf89210aedefc093928a87d","to":"0xd0ea44485a8cca314cff417893d18257ec091ef3","logs":[{"removed":false,"logIndex":"0x0","transactionIndex":"0x4","transactionHash":"0xaaaf335e1d981be091995ac4affe3c9f32fb046fc6fad4660090755c76251267","blockHash":"0x070e19f881d84b24b3def54b3485a2c1dd28110936ad7ce52683539f696ed40f","blockNumber":"0x13dc40","address":"0xd0ea44485a8cca314cff417893d18257ec091ef3","data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000","topics":["0x665d155f71ad96c4a04629d54ef9fb27ef57911253588f2ee93474cd02fa3f53","0x0000000000000000000000003fab7ebe4b2c31a75cf89210aedefc093928a87d"]}],"logsBloom":"0x00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000220000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000"} 22 | 23 | * */ 24 | 25 | public class CryptonomicaVerificationFunctions { 26 | 27 | /* --- Logger */ 28 | private static final Logger LOG = Logger.getLogger(CryptonomicaVerificationFunctions.class.getName()); 29 | 30 | /* --- Gson: */ 31 | private static final Gson GSON = new Gson(); 32 | 33 | /* --- Contract instance. (!) can be null */ 34 | private static DataCurrentNetwork dataCurrentNetwork = DataCurrentNetworkFactory.getDataCurrentNetworkInstance(); 35 | private static CryptonomicaVerification cryptonomicaVerification = dataCurrentNetwork.cryptonomicaVerification; 36 | private static Web3j web3j = dataCurrentNetwork.web3j; 37 | 38 | // function setPriceForVerification(uint priceInWei) public returns (bool) 39 | // see: https://etherconverter.online 40 | public static TransactionReceipt setPriceForVerification(Long priceInWei) throws IOException { 41 | 42 | TransactionReceipt transactionReceipt; 43 | 44 | if (cryptonomicaVerification == null) { 45 | // -> to servlet or object/class calling this function 46 | throw new IOException("Contract can not be loaded"); 47 | } 48 | 49 | BigInteger priceInWeiBigInteger = BigInteger.valueOf(priceInWei); 50 | 51 | try { 52 | 53 | transactionReceipt = cryptonomicaVerification.setPriceForVerification(priceInWeiBigInteger).send(); 54 | 55 | LOG.info(GSON.toJson(transactionReceipt)); 56 | int transactionReceiptHashCode = transactionReceipt.hashCode(); 57 | 58 | final List logs = transactionReceipt.getLogs(); 59 | for (Log log : logs) { 60 | System.out.println( 61 | "log.getType(): " + log.getType() 62 | + " log.hashCode(): " + log.hashCode() 63 | + " log.getData(): " + log.getData() 64 | ); 65 | } 66 | 67 | String txHash = transactionReceipt.getTransactionHash(); 68 | final List priceChangedEvents = cryptonomicaVerification.getPriceChangedEvents(transactionReceipt); 69 | System.out.println(priceChangedEvents); 70 | 71 | } catch (Exception e) { 72 | throw new IOException(e.getMessage()); 73 | } 74 | 75 | return transactionReceipt; 76 | } 77 | 78 | public static String getSignedStringFromSC(String userAddress) throws IOException { 79 | 80 | String signedString = null; 81 | 82 | if (cryptonomicaVerification == null) { 83 | // -> to servlet or object/class calling this function 84 | throw new IOException("Contract can not be loaded"); 85 | } 86 | 87 | try { 88 | signedString = cryptonomicaVerification.signedString(userAddress).send(); 89 | LOG.info("signedString for " + userAddress + " : "); 90 | LOG.info(signedString); 91 | 92 | } catch (Exception e) { 93 | LOG.severe(e.getMessage()); 94 | throw new IOException(e.getMessage()); 95 | } 96 | 97 | return signedString; 98 | } 99 | 100 | public static String getUnverifiedFingerprint(String userAddress) throws IOException { 101 | String unverifiedFingerprint = null; 102 | if (cryptonomicaVerification == null) { 103 | // -> to servlet or object/class calling this function 104 | throw new IOException("Contract can not be loaded"); 105 | } 106 | try { 107 | unverifiedFingerprint = cryptonomicaVerification.unverifiedFingerprint(userAddress).send(); 108 | LOG.info("unverifiedFingerprint for " + userAddress + " : "); 109 | LOG.info(unverifiedFingerprint); 110 | 111 | } catch (Exception e) { 112 | LOG.severe(e.getMessage()); 113 | throw new IOException(e.getMessage()); 114 | } 115 | return unverifiedFingerprint; 116 | } 117 | 118 | public static String getAddresFromFingerprint(String fingerprint) throws IOException { 119 | String userAddress = null; 120 | if (cryptonomicaVerification == null) { 121 | // -> to servlet or object/class calling this function 122 | throw new IOException("Contract can not be loaded"); 123 | } 124 | 125 | byte[] fingerprintBytes20 = Web3jServices.bytes20FromHexString(fingerprint).getValue(); 126 | 127 | try { 128 | userAddress = cryptonomicaVerification.addressAttached(fingerprintBytes20).send(); 129 | LOG.info("userAddress for " + fingerprint + " : " + userAddress); 130 | } catch (Exception e) { 131 | LOG.severe(e.getMessage()); 132 | throw new IOException(e.getMessage()); 133 | } 134 | return userAddress; 135 | } 136 | 137 | public static VerificationStruct getVerificationStruct(String userAddress) throws IOException { 138 | 139 | if (cryptonomicaVerification == null) { 140 | // -> to servlet 141 | throw new IOException("Contract can not be loaded"); 142 | } 143 | 144 | VerificationStruct verification = null; 145 | try { 146 | Tuple9 tuple9 = cryptonomicaVerification.verification(userAddress).send(); 147 | verification = new VerificationStruct(tuple9); 148 | } catch (Exception e) { 149 | LOG.severe(e.getMessage()); 150 | throw new IOException(e.getMessage()); 151 | } 152 | 153 | System.out.println(verification); 154 | 155 | return verification; 156 | } 157 | 158 | /* Solidity: 159 | function addVerificationData( 160 | address _acc, // 161 | string _fingerprint, // "57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 162 | bytes20 _fingerprintBytes20, // "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 163 | uint _keyCertificateValidUntil, // 164 | string _firstName, // 165 | string _lastName, // 166 | uint _birthDate, // 167 | string _nationality) public { 168 | */ 169 | public static TransactionReceipt addVerificationData(AddVerificationDataObj addVerificationDataObj) throws IOException { 170 | 171 | if (cryptonomicaVerification == null) { 172 | throw new IOException("Contract can not be loaded"); 173 | } 174 | 175 | TransactionReceipt transactionReceipt = null; 176 | try { 177 | transactionReceipt = cryptonomicaVerification.addVerificationData( 178 | addVerificationDataObj.getAcc(), 179 | addVerificationDataObj.getFingerprint(), 180 | addVerificationDataObj.getFingerprintBytes20(), 181 | addVerificationDataObj.getKeyCertificateValidUntil(), 182 | addVerificationDataObj.getFirstName(), 183 | addVerificationDataObj.getLastName(), 184 | addVerificationDataObj.getBirthDate(), 185 | addVerificationDataObj.getNationality() 186 | ).send(); 187 | 188 | LOG.info(transactionReceipt.getTransactionHash()); 189 | } catch (Exception e) { 190 | LOG.severe(e.getMessage()); 191 | throw new IOException(e.getMessage()); 192 | } 193 | return transactionReceipt; 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/entities/AddVerificationDataObj.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.entities; 2 | 3 | import com.google.gson.Gson; 4 | import net.cryptonomica.tomcatweb3j.utilities.Web3jServices; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.math.BigInteger; 8 | import java.util.logging.Logger; 9 | 10 | public class AddVerificationDataObj { 11 | 12 | /* --- Logger: */ 13 | // https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html 14 | // Find or create a logger for a named subsystem. If a logger has already been created with the given name it is returned. 15 | // Otherwise a new logger is created. 16 | // - When running Tomcat on unixes, the console output is usually redirected to the file named catalina.out 17 | private static final Logger LOG = Logger.getLogger(AddVerificationDataObj.class.getName()); 18 | 19 | /* --- Gson: */ 20 | private static final Gson GSON = new Gson(); 21 | 22 | /* --- data fields */ 23 | 24 | /* Solidity: 25 | function addVerificationData( 26 | address _acc, // 27 | string _fingerprint, // "57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 28 | bytes20 _fingerprintBytes20, // "0x57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5" 29 | uint _keyCertificateValidUntil, // 30 | string _firstName, // 31 | string _lastName, // 32 | uint _birthDate, // 33 | string _nationality) public { 34 | */ 35 | private String acc; 36 | private String fingerprint; 37 | private byte[] fingerprintBytes20; 38 | private BigInteger keyCertificateValidUntil; 39 | private String firstName; 40 | private String lastName; 41 | private BigInteger birthDate; 42 | private String nationality; 43 | 44 | /* --- Constructors */ 45 | 46 | public AddVerificationDataObj() { 47 | } 48 | 49 | public AddVerificationDataObj(HttpServletRequest request) { 50 | this.acc = request.getParameter("acc"); 51 | this.fingerprint = request.getParameter("fingerprint"); 52 | this.fingerprintBytes20 = Web3jServices.bytes20FromHexString(request.getParameter("fingerprint")).getValue(); 53 | // see: https://stackoverflow.com/questions/2646049/what-is-the-most-effective-way-to-create-biginteger-instance-from-int-value 54 | this.keyCertificateValidUntil = BigInteger.valueOf( 55 | // Integer.parseInt(request.getParameter("keyCertificateValidUntil")) 56 | Integer.parseUnsignedInt( 57 | request.getParameter("keyCertificateValidUntil") 58 | ) 59 | ); 60 | this.firstName = request.getParameter("firstName"); 61 | this.lastName = request.getParameter("lastName"); 62 | // see: https://stackoverflow.com/questions/2646049/what-is-the-most-effective-way-to-create-biginteger-instance-from-int-value 63 | try { // >>> to work with old keys, where no birthdate field present 64 | this.birthDate = BigInteger.valueOf( 65 | Integer.parseUnsignedInt(request.getParameter("birthDate") 66 | ) 67 | ); 68 | } catch (Exception e) { 69 | this.birthDate = BigInteger.valueOf(0); 70 | } 71 | 72 | this.nationality = request.getParameter("nationality"); 73 | 74 | LOG.info(this.toString()); 75 | } 76 | 77 | /* --- to String */ 78 | @Override 79 | public String toString() { 80 | return GSON.toJson(this); 81 | } 82 | 83 | /* --- Getters and Setters */ 84 | 85 | public String getAcc() { 86 | return acc; 87 | } 88 | 89 | public void setAcc(String acc) { 90 | this.acc = acc; 91 | } 92 | 93 | public String getFingerprint() { 94 | return fingerprint; 95 | } 96 | 97 | public void setFingerprint(String fingerprint) { 98 | this.fingerprint = fingerprint; 99 | } 100 | 101 | public byte[] getFingerprintBytes20() { 102 | return fingerprintBytes20; 103 | } 104 | 105 | public void setFingerprintBytes20(byte[] fingerprintBytes20) { 106 | this.fingerprintBytes20 = fingerprintBytes20; 107 | } 108 | 109 | public BigInteger getKeyCertificateValidUntil() { 110 | return keyCertificateValidUntil; 111 | } 112 | 113 | public void setKeyCertificateValidUntil(BigInteger keyCertificateValidUntil) { 114 | this.keyCertificateValidUntil = keyCertificateValidUntil; 115 | } 116 | 117 | public String getFirstName() { 118 | return firstName; 119 | } 120 | 121 | public void setFirstName(String firstName) { 122 | this.firstName = firstName; 123 | } 124 | 125 | public String getLastName() { 126 | return lastName; 127 | } 128 | 129 | public void setLastName(String lastName) { 130 | this.lastName = lastName; 131 | } 132 | 133 | public BigInteger getBirthDate() { 134 | return birthDate; 135 | } 136 | 137 | public void setBirthDate(BigInteger birthDate) { 138 | this.birthDate = birthDate; 139 | } 140 | 141 | public String getNationality() { 142 | return nationality; 143 | } 144 | 145 | public void setNationality(String nationality) { 146 | this.nationality = nationality; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/entities/DataCurrentNetwork.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.entities; 2 | 3 | import net.cryptonomica.tomcatweb3j.contracts.CryptonomicaVerification; 4 | import org.web3j.protocol.Web3j; 5 | 6 | public class DataCurrentNetwork { 7 | 8 | public Web3j web3j; 9 | public CryptonomicaVerification cryptonomicaVerification; 10 | public String etherscan; 11 | 12 | /* --- Constructor */ 13 | 14 | public DataCurrentNetwork() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/entities/EtherscanTxStatus.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.entities; 2 | 3 | public class EtherscanTxStatus { 4 | public String status; 5 | public String message; 6 | public Result result; 7 | 8 | private class Result { 9 | public String isError; 10 | public String errDescription; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/entities/VerificationRequestDataFromSC.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.entities; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.io.Serializable; 6 | 7 | public class VerificationRequestDataFromSC implements Serializable { 8 | 9 | private String unverifiedFingerprint; 10 | private String signedString; 11 | 12 | /* ----- Constructors */ 13 | 14 | public VerificationRequestDataFromSC() { 15 | } 16 | 17 | public VerificationRequestDataFromSC(String unverifiedFingerprint, String signedString) { 18 | this.unverifiedFingerprint = unverifiedFingerprint; 19 | this.signedString = signedString; 20 | } 21 | 22 | /* ---- to String */ 23 | @Override 24 | public String toString() { 25 | return new Gson().toJson(this); 26 | } 27 | 28 | /* ----- Getters and Setters */ 29 | 30 | public String getUnverifiedFingerprint() { 31 | return unverifiedFingerprint; 32 | } 33 | 34 | public void setUnverifiedFingerprint(String unverifiedFingerprint) { 35 | this.unverifiedFingerprint = unverifiedFingerprint; 36 | } 37 | 38 | public String getSignedString() { 39 | return signedString; 40 | } 41 | 42 | public void setSignedString(String signedString) { 43 | this.signedString = signedString; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/entities/VerificationStruct.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.entities; 2 | 3 | import com.google.gson.Gson; 4 | import org.web3j.tuples.generated.Tuple9; 5 | 6 | import java.io.Serializable; 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * like struct in smart contract 11 | */ 12 | public class VerificationStruct implements Serializable { 13 | 14 | /* - Solidity: 15 | mapping(address => Verification) public verification; // (!) Gas requirement: infinite 16 | struct Verification { 17 | // all string have to be <= 32 chars 18 | string fingerprint; // ................................................0 19 | uint keyCertificateValidUntil; // .....................................1 20 | string firstName; // ..................................................2 21 | string lastName;// ....................................................3 22 | uint birthDate; // ...................................................4 23 | string nationality; // ...............................................5 24 | uint verificationAddedOn;// ...........................................6 25 | uint revokedOn; // ....................................................7 26 | string signedString; //................................................8 27 | // uint256 signedStringUploadedOnUnixTime; //... Stack too deep 28 | } 29 | */ 30 | 31 | private String fingerprint; // .....................................................0 32 | private Integer keyCertificateValidUntil; // .......................................1 33 | private String firstName; // .......................................................2 34 | private String lastName;// .........................................................3 35 | private Integer birthDate; // .....................................................4 36 | private String nationality; // ....................................................5 37 | private Integer verificationAddedOn;// .............................................6 38 | private Integer revokedOn; // ......................................................7 39 | private String signedString; //.....................................................8 40 | 41 | 42 | /* ----- Constructors */ 43 | 44 | public VerificationStruct() { 45 | } 46 | 47 | public VerificationStruct( 48 | String fingerprint, // .....................................................0 49 | Integer keyCertificateValidUntil, // .......................................1 50 | String firstName, // .......................................................2 51 | String lastName, // ........................................................3 52 | Integer birthDate, // .....................................................4 53 | String nationality, // ....................................................5 54 | Integer verificationAddedOn,// .............................................6 55 | Integer revokedOn, // ......................................................7 56 | String signedString //......................................................8 57 | ) { 58 | this.fingerprint = fingerprint; 59 | this.keyCertificateValidUntil = keyCertificateValidUntil; 60 | this.firstName = firstName; 61 | this.lastName = lastName; 62 | this.birthDate = birthDate; 63 | this.nationality = nationality; 64 | this.verificationAddedOn = verificationAddedOn; 65 | this.revokedOn = revokedOn; 66 | this.signedString = signedString; 67 | } 68 | 69 | /* 70 | public Verification(List verificationStruct) { 71 | this.fingerprint = (String) verificationStruct.get(0).getValue(); 72 | this.keyCertificateValidUntil = (Integer) verificationStruct.get(1).getValue(); 73 | this.firstName = (String) verificationStruct.get(2).getValue(); 74 | this.lastName = (String) verificationStruct.get(3).getValue(); 75 | this.birthDate = (Integer) verificationStruct.get(4).getValue(); 76 | this.nationality = (String) verificationStruct.get(5).getValue(); 77 | this.verificationAddedOn = (Integer) verificationStruct.get(6).getValue(); 78 | this.revokedOn = (Integer) verificationStruct.get(7).getValue(); 79 | }*/ 80 | 81 | public VerificationStruct(Tuple9 tuple9) { 82 | this.fingerprint = tuple9.getValue1(); 83 | this.keyCertificateValidUntil = tuple9.getValue2().intValueExact(); 84 | this.firstName = tuple9.getValue3(); 85 | this.lastName = tuple9.getValue4(); 86 | this.birthDate = tuple9.getValue5().intValueExact(); 87 | this.nationality = tuple9.getValue6(); 88 | this.verificationAddedOn = tuple9.getValue7().intValueExact(); 89 | this.revokedOn = tuple9.getValue8().intValueExact(); 90 | this.signedString = tuple9.getValue9(); 91 | } 92 | 93 | /* ---- to String */ 94 | @Override 95 | public String toString() { 96 | return new Gson().toJson(this); 97 | } 98 | 99 | /* ----- Getters and Setters */ 100 | 101 | public String getFingerprint() { 102 | return fingerprint; 103 | } 104 | 105 | public void setFingerprint(String fingerprint) { 106 | this.fingerprint = fingerprint; 107 | } 108 | 109 | public Integer getKeyCertificateValidUntil() { 110 | return keyCertificateValidUntil; 111 | } 112 | 113 | public void setKeyCertificateValidUntil(Integer keyCertificateValidUntil) { 114 | this.keyCertificateValidUntil = keyCertificateValidUntil; 115 | } 116 | 117 | public String getFirstName() { 118 | return firstName; 119 | } 120 | 121 | public void setFirstName(String firstName) { 122 | this.firstName = firstName; 123 | } 124 | 125 | public String getLastName() { 126 | return lastName; 127 | } 128 | 129 | public void setLastName(String lastName) { 130 | this.lastName = lastName; 131 | } 132 | 133 | public Integer getBirthDate() { 134 | return birthDate; 135 | } 136 | 137 | public void setBirthDate(Integer birthDate) { 138 | this.birthDate = birthDate; 139 | } 140 | 141 | public String getNationality() { 142 | return nationality; 143 | } 144 | 145 | public void setNationality(String nationality) { 146 | this.nationality = nationality; 147 | } 148 | 149 | public Integer getVerificationAddedOn() { 150 | return verificationAddedOn; 151 | } 152 | 153 | public void setVerificationAddedOn(Integer verificationAddedOn) { 154 | this.verificationAddedOn = verificationAddedOn; 155 | } 156 | 157 | public Integer getRevokedOn() { 158 | return revokedOn; 159 | } 160 | 161 | public void setRevokedOn(Integer revokedOn) { 162 | this.revokedOn = revokedOn; 163 | } 164 | 165 | public String getSignedString() { 166 | return signedString; 167 | } 168 | 169 | public void setSignedString(String signedString) { 170 | this.signedString = signedString; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/servlets/AddVerificationDataServlet.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.servlets; 2 | 3 | import com.google.gson.Gson; 4 | import net.cryptonomica.tomcatweb3j.contracts.CryptonomicaVerificationFunctions; 5 | import net.cryptonomica.tomcatweb3j.entities.AddVerificationDataObj; 6 | import net.cryptonomica.tomcatweb3j.utilities.ApiKeyUtils; 7 | import net.cryptonomica.tomcatweb3j.utilities.ServletUtils; 8 | import org.web3j.protocol.core.methods.response.TransactionReceipt; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.annotation.WebServlet; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | import java.util.logging.Logger; 17 | 18 | @WebServlet(name = "AddVerificationDataServlet") 19 | public class AddVerificationDataServlet extends HttpServlet { 20 | 21 | /* --- Logger: */ 22 | // https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html 23 | // Find or create a logger for a named subsystem. If a logger has already been created with the given name it is returned. 24 | // Otherwise a new logger is created. 25 | // - When running Tomcat on unixes, the console output is usually redirected to the file named catalina.out 26 | private static final String className = AddVerificationDataServlet.class.getName(); 27 | private static final Logger LOG = Logger.getLogger(className); 28 | private static final Gson GSON = new Gson(); 29 | 30 | @Override 31 | protected void doPost(HttpServletRequest request, HttpServletResponse response) 32 | throws ServletException, IOException { 33 | 34 | LOG.info("AddVerificationDataServlet POST request received"); 35 | 36 | // (1) check API_KEY (throws Exception) 37 | ApiKeyUtils.checkApiKey(request); // void 38 | 39 | // (2) get data from request 40 | AddVerificationDataObj addVerificationDataObj = new AddVerificationDataObj(request); // logs obj.toString() 41 | 42 | // (3) send transaction to contract and get transaction receipt 43 | TransactionReceipt transactionReceipt = CryptonomicaVerificationFunctions.addVerificationData(addVerificationDataObj); 44 | LOG.info("Tx Hash" + transactionReceipt.getTransactionHash()); 45 | LOG.info(GSON.toJson(transactionReceipt)); 46 | 47 | // (4) send response 48 | ServletUtils.sendJsonResponseFromObject(response, transactionReceipt); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/servlets/GetVerificationRequestDataServlet.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.servlets; 2 | 3 | import net.cryptonomica.tomcatweb3j.contracts.CryptonomicaVerificationFunctions; 4 | import net.cryptonomica.tomcatweb3j.entities.VerificationRequestDataFromSC; 5 | import net.cryptonomica.tomcatweb3j.utilities.ApiKeyUtils; 6 | import net.cryptonomica.tomcatweb3j.utilities.ServletUtils; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | @WebServlet(name = "GetVerificationRequestDataServlet") 16 | public class GetVerificationRequestDataServlet extends HttpServlet { 17 | 18 | 19 | @Override 20 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 21 | 22 | // (1) check API_KEY (throws Exception) 23 | ApiKeyUtils.checkApiKey(request); 24 | 25 | // (2) get data from request 26 | String addressStr = request.getParameter("address"); 27 | 28 | // (3) get data from contract: 29 | String unverifiedFingerprint = CryptonomicaVerificationFunctions.getUnverifiedFingerprint(addressStr); 30 | // 31 | String signedString = CryptonomicaVerificationFunctions.getSignedStringFromSC(addressStr); 32 | // 33 | VerificationRequestDataFromSC verificationRequestDataFromSC = new VerificationRequestDataFromSC( 34 | unverifiedFingerprint, 35 | signedString 36 | ); 37 | // (4) send response 38 | ServletUtils.sendJsonResponseFromObject(response, verificationRequestDataFromSC); // application/json 39 | } 40 | 41 | @Override 42 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 43 | doPost(request, response); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/servlets/GetVerificationServlet.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.servlets; 2 | 3 | import net.cryptonomica.tomcatweb3j.contracts.CryptonomicaVerificationFunctions; 4 | import net.cryptonomica.tomcatweb3j.entities.VerificationStruct; 5 | import net.cryptonomica.tomcatweb3j.utilities.ApiKeyUtils; 6 | import net.cryptonomica.tomcatweb3j.utilities.ServletUtils; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.util.logging.Logger; 15 | 16 | /** 17 | * get verification from the smart contract by eth address or fingerprint 18 | */ 19 | @WebServlet(name = "GetVerificationServlet") 20 | // /getVerification 21 | public class GetVerificationServlet extends HttpServlet { 22 | 23 | /* ---- Logger: */ 24 | private static final Logger LOG = Logger.getLogger(GetVerificationServlet.class.getName()); 25 | 26 | @Override 27 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 28 | 29 | // (1) check API_KEY (throws Exception) 30 | ApiKeyUtils.checkApiKey(request); 31 | 32 | // (2) get data from request 33 | String userEthAddressStr = request.getParameter("address"); 34 | String fingerprintStr = request.getParameter("fingerprint"); 35 | 36 | // (3) get data from contract 37 | VerificationStruct verification = null; 38 | if (userEthAddressStr != null && userEthAddressStr.length() == 42) { 39 | verification = CryptonomicaVerificationFunctions.getVerificationStruct(userEthAddressStr); 40 | // fingerprint is 20 bytes, in hexadecimal 40 symbols string representation. 41 | // fingerprints are stored as upper case strings like: 42 | // 57A5FEE5A34D563B4B85ADF3CE369FD9E77173E5 43 | } else if (fingerprintStr != null && fingerprintStr.length() == 40) { 44 | 45 | String addressString = CryptonomicaVerificationFunctions.getAddresFromFingerprint(fingerprintStr); 46 | verification = CryptonomicaVerificationFunctions.getVerificationStruct(userEthAddressStr); 47 | } else { 48 | throw new IOException("Wrong request data"); 49 | } 50 | 51 | LOG.info(verification.toString()); 52 | 53 | // (4) send response 54 | ServletUtils.sendJsonResponseFromObject(response, verification); // 55 | } 56 | 57 | @Override 58 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 59 | doPost(request, response); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/servlets/TestServlet.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.servlets; 2 | 3 | import net.cryptonomica.tomcatweb3j.entities.DataCurrentNetwork; 4 | import net.cryptonomica.tomcatweb3j.utilities.DataCurrentNetworkFactory; 5 | import net.cryptonomica.tomcatweb3j.utilities.ServletUtils; 6 | import org.web3j.protocol.Web3j; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.util.Date; 15 | 16 | /* 17 | * --- for tests 18 | * */ 19 | 20 | @WebServlet(name = "TestServlet") 21 | // tomcatweb3j.cryptonomica.net/testServlet 22 | public class TestServlet extends HttpServlet { 23 | 24 | @Override 25 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 26 | // ... 27 | } 28 | 29 | @Override 30 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 31 | 32 | TestServletResponse testServletResponce = new TestServletResponse(); 33 | 34 | DataCurrentNetwork dataCurrentNetwork = DataCurrentNetworkFactory.getDataCurrentNetworkInstance(); 35 | Web3j web3j = dataCurrentNetwork.web3j; 36 | 37 | // (0) 38 | testServletResponce.ethIsSyncing = web3j.ethSyncing().send().isSyncing(); 39 | 40 | // (1) 41 | // https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethblocknumber 42 | // The number of the most recent block 43 | testServletResponce.ethBlockNumber = web3j.ethBlockNumber().send().getBlockNumber().intValue(); 44 | 45 | // (2) 46 | /* 47 | # tomcat8 system variables 48 | /usr/share/tomcat8/bin/catalina.sh : 49 | # Do not set the variables in this script. Instead put them into a script 50 | # setenv.sh in CATALINA_BASE/bin to keep your customizations separate. 51 | sudo touch /usr/share/tomcat8/bin/setenv.sh 52 | # see: https://unix.stackexchange.com/questions/4335/how-to-insert-text-into-a-root-owned-file-using-sudo 53 | echo "export TEST_VAR=testEnvironmentVariableValue" | sudo tee -a /usr/share/tomcat8/bin/setenv.sh > /dev/null 54 | # or: 55 | sudo vim /usr/share/tomcat8/bin/setenv.sh 56 | * */ 57 | testServletResponce.testEnvironmentVariable = System.getenv("TEST_VAR"); 58 | 59 | // (3) 60 | testServletResponce.user = System.getProperty("user.name"); 61 | if (testServletResponce.user.contains("tomcat")) { // on server: tomcat8 62 | testServletResponce.user = "ubuntu"; 63 | } 64 | 65 | // (4) 66 | testServletResponce.timeOnServer = new Date(); 67 | 68 | // send response: 69 | ServletUtils.sendJsonResponseFromObject(response, testServletResponce); // application/json 70 | } 71 | 72 | private class TestServletResponse { 73 | 74 | private Boolean ethIsSyncing; //............................0 75 | private Integer ethBlockNumber; //..........................1 76 | private String testEnvironmentVariable; //..................2 77 | private String user; //.....................................3 78 | private Date timeOnServer; //...............................4 79 | 80 | private TestServletResponse() { 81 | } 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/ApiKeyUtils.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import java.io.IOException; 5 | import java.util.logging.Logger; 6 | 7 | 8 | public class ApiKeyUtils { 9 | 10 | /* --- Logger: */ 11 | // https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html 12 | // Find or create a logger for a named subsystem. If a logger has already been created with the given name it is returned. 13 | // Otherwise a new logger is created. 14 | private static final Logger LOG = Logger.getLogger(ApiKeyUtils.class.getName()); 15 | 16 | private static final String API_KEY = System.getenv("API_KEY"); 17 | 18 | public static void checkApiKey(HttpServletRequest request) throws IOException { 19 | 20 | String apiKey = null; 21 | 22 | String apiKeyHeader = 23 | // returns null if the request does not have a header of that name 24 | request.getHeader("apiKey"); 25 | 26 | String apiKeyParameter = 27 | // returns null if the parameter does not exist 28 | request.getParameter("apiKey"); 29 | 30 | 31 | // get API key: 32 | if (apiKeyHeader == null && apiKeyParameter == null) { 33 | 34 | LOG.warning("API key is missing"); 35 | // Exception -> servlet 36 | throw new IOException("API key is missing in the request"); 37 | 38 | } else if (apiKeyHeader != null) { 39 | 40 | apiKey = apiKeyHeader; 41 | 42 | } else { 43 | 44 | apiKey = apiKeyParameter; 45 | } 46 | 47 | // check API key: 48 | if (!API_KEY.equals(apiKey)) { 49 | LOG.warning("API key is invalid"); 50 | // Exception -> servlet 51 | throw new IOException("API key is invalid"); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/Constants.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | public class Constants { 4 | 5 | // Rinkeby: 6 | public static final String RinkebyContractAddres = "0xb9ffed00f17De4CDA41bF30bBe0E11B78E3A2c57"; 7 | public static final String RinkebyOwnerAddress = "0x3fAB7ebe4B2c31a75Cf89210aeDEfc093928A87D"; 8 | // MainNet: 9 | public static final String MainNetContractAddres = "0x846942953c3b2A898F10DF1e32763A823bf6b27f"; 10 | public static final String MainNetOwnerAddress = "0xDADfa63d05D01f536930F1150238283Fe917D28c"; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/DataCurrentNetworkFactory.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | import net.cryptonomica.tomcatweb3j.contracts.CryptonomicaVerification; 4 | import net.cryptonomica.tomcatweb3j.entities.DataCurrentNetwork; 5 | import org.web3j.crypto.Credentials; 6 | import org.web3j.protocol.Web3j; 7 | import org.web3j.protocol.http.HttpService; 8 | 9 | import java.io.IOException; 10 | import java.math.BigInteger; 11 | import java.util.logging.Logger; 12 | 13 | // import org.web3j.protocol.ipc.UnixIpcService; 14 | 15 | public class DataCurrentNetworkFactory { 16 | 17 | private static final Logger LOG = Logger.getLogger(DataCurrentNetworkFactory.class.getName()); 18 | 19 | // see: https://github.com/conor10/web3j-javamag/blob/master/src/main/java/org/web3j/javamag/HelloWorld.java 20 | private static final BigInteger GAS_PRICE = BigInteger.valueOf(20_000_000_000L); 21 | // private static final BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000); 22 | private static final BigInteger GAS_LIMIT = BigInteger.valueOf(7_800_000); 23 | 24 | public static DataCurrentNetwork getDataCurrentNetworkInstance() { 25 | 26 | DataCurrentNetwork dataCurrentNetwork = new DataCurrentNetwork(); 27 | 28 | Web3j web3 = Web3j.build(new HttpService()); // defaults to http://localhost:8545/ 29 | 30 | /* 31 | String USER = System.getProperty("user.name"); 32 | if (USER.contains("tomcat")) { // on server: tomcat8 33 | USER = "ubuntu"; 34 | } 35 | */ 36 | 37 | try { 38 | 39 | String netVersion = web3.netVersion().send().getNetVersion(); 40 | LOG.info("web3.netVersion().send().getNetVersion(): " + netVersion + " (String)"); 41 | // cat /var/log/tomcat8/catalina.out 42 | // ... 43 | // Dec 11, 2017 4:48:53 AM net.cryptonomica.tomcatweb3j.utilities.DataCurrentNetworkFactory getDataCurrentNetworkInstance 44 | // INFO: web3.netVersion().send().getNetVersion(): 4 (String) 45 | 46 | if (netVersion.equals("1")) { // MainNet 47 | 48 | String cryptonomicaVerificationContractAddress = Constants.MainNetContractAddres; 49 | // web3 = Web3j.build(new UnixIpcService("/home/" + USER + "/.ethereum/geth.ipc")); 50 | Credentials credentials = Credentials.create(System.getenv("MAINNET_PRIVATE_KEY")); 51 | 52 | LOG.info("credentials.getAddress() : " + credentials.getAddress()); 53 | 54 | if (!credentials.getAddress().equalsIgnoreCase(Constants.MainNetOwnerAddress)) { 55 | LOG.severe("(!) check contract owner address"); 56 | } 57 | 58 | dataCurrentNetwork.web3j = web3; 59 | dataCurrentNetwork.cryptonomicaVerification = CryptonomicaVerification.load( 60 | cryptonomicaVerificationContractAddress, 61 | web3, 62 | credentials, 63 | GAS_PRICE, 64 | GAS_LIMIT 65 | ); 66 | dataCurrentNetwork.etherscan = "https://etherscan.io/"; 67 | 68 | } else if (netVersion.equals("3")) { // Ropsten 69 | // ... 70 | } else if (netVersion.equals("4")) { // Rinkeby 71 | 72 | String cryptonomicaVerificationContractAddress = Constants.RinkebyContractAddres; 73 | // web3 = Web3j.build(new UnixIpcService("/home/" + USER + "/.ethereum/rinkeby/geth.ipc")); 74 | Credentials credentials = Credentials.create(System.getenv("RINKEBY_PRIVATE_KEY")); 75 | 76 | dataCurrentNetwork.web3j = web3; 77 | dataCurrentNetwork.cryptonomicaVerification = CryptonomicaVerification.load( 78 | cryptonomicaVerificationContractAddress, 79 | web3, 80 | credentials, 81 | GAS_PRICE, 82 | GAS_LIMIT 83 | ); 84 | dataCurrentNetwork.etherscan = "https://rinkeby.etherscan.io/"; 85 | 86 | } else if (netVersion.length() == 13) { // TestRPC 87 | // ... 88 | } 89 | } catch (IOException e) { 90 | LOG.severe(e.getMessage()); 91 | } 92 | 93 | // (!) can be null 94 | return dataCurrentNetwork; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/Etherscan.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | import com.google.gson.Gson; 4 | import net.cryptonomica.tomcatweb3j.entities.EtherscanTxStatus; 5 | import org.apache.commons.io.IOUtils; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.net.URL; 10 | import java.net.URLConnection; 11 | import java.net.URLEncoder; 12 | 13 | public class Etherscan { 14 | 15 | /* --- Gson: */ 16 | private static final Gson GSON = new Gson(); 17 | 18 | public static EtherscanTxStatus getTransaction(String etherscanBaseUrl, String etherscanApiKey, String txHash) throws IOException { 19 | 20 | // https://rinkeby.etherscan.io/api?module=transaction&action=getstatus&txhash=0x15f8e5ea1079d9a0bb04a4c58ae5fe7654b5b2b4463375ff7ffb490aa0032f3a&apikey=YourApiKeyToken 21 | 22 | String url = etherscanBaseUrl + "api"; // 23 | String charset = java.nio.charset.StandardCharsets.UTF_8.name(); 24 | 25 | String query = String.format("module=%s&action=%s&txhash=%sapikey=%s", 26 | URLEncoder.encode("transaction", charset), 27 | URLEncoder.encode("getstatus", charset), 28 | URLEncoder.encode(txHash, charset), 29 | URLEncoder.encode(etherscanApiKey, charset) 30 | ); 31 | URLConnection connection = new URL(url + "?" + query).openConnection(); 32 | connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7 33 | connection.setRequestProperty("Accept-Charset", charset); 34 | InputStream inputStream = connection.getInputStream(); 35 | 36 | // NB: does not close inputStream, you can use IOUtils.closeQuietly for that 37 | String response = IOUtils.toString(inputStream, java.nio.charset.StandardCharsets.UTF_8); 38 | 39 | EtherscanTxStatus etherscanTxStatus = GSON.fromJson(response, EtherscanTxStatus.class); 40 | 41 | return etherscanTxStatus; 42 | 43 | } 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/PGPTools.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | import com.google.gson.Gson; 4 | import org.bouncycastle.openpgp.*; 5 | import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; 6 | import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.Iterator; 12 | import java.util.logging.Logger; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | 17 | /** 18 | * 19 | */ 20 | public class PGPTools { 21 | 22 | /* ---- Logger */ 23 | private static final Logger LOG = Logger.getLogger(PGPTools.class.getName()); 24 | /* --- Gson: */ 25 | private static final Gson GSON = new Gson(); 26 | 27 | public static PGPPublicKey readPublicKeyFromInputStream(InputStream input) throws IOException, PGPException { 28 | 29 | PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection( 30 | PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator()); 31 | // 32 | // we just loop through the collection till we find a key suitable for encryption, in the real 33 | // world you would probably want to be a bit smarter about this. 34 | Iterator keyRingIter = pgpPub.getKeyRings(); 35 | while (keyRingIter.hasNext()) { 36 | PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next(); 37 | 38 | Iterator keyIter = keyRing.getPublicKeys(); 39 | while (keyIter.hasNext()) { 40 | PGPPublicKey key = (PGPPublicKey) keyIter.next(); 41 | 42 | if (key.isMasterKey()) { // <<< (!!!) check for master key, not for encryption sub-key 43 | // return public key found 44 | return key; 45 | } 46 | } 47 | } 48 | 49 | throw new IllegalArgumentException("Can't find encryption key in key ring."); 50 | } 51 | 52 | 53 | public static PGPPublicKey readPublicKeyFromString(String armoredPublicPGPkeyBlock) 54 | throws IOException, PGPException { 55 | 56 | InputStream in = new ByteArrayInputStream(armoredPublicPGPkeyBlock.getBytes()); 57 | PGPPublicKey pgpPublicKey = readPublicKeyFromInputStream(in); 58 | in.close(); 59 | return pgpPublicKey; 60 | } 61 | 62 | // ---------------------------- NEW (2017-05-29): 63 | public static Boolean verifySignedString( 64 | String signedString, 65 | String pgpPublicKeyAsciiArmored // pgpPublicKeyData.getAsciiArmored().getValue() 66 | ) throws Exception { 67 | PGPPublicKey publicKey = readPublicKeyFromString(pgpPublicKeyAsciiArmored); 68 | Boolean result = verifyText(signedString, publicKey); 69 | return result; 70 | } 71 | 72 | public static Boolean verifyText(String plainText, PGPPublicKey publicKey) throws Exception { 73 | 74 | String pattern = "-----BEGIN PGP SIGNED MESSAGE-----\\r?\\n.*?\\r?\\n\\r?\\n(.*)\\r?\\n(-----BEGIN PGP SIGNATURE-----\\r?\\n.*-----END PGP SIGNATURE-----)"; 75 | 76 | Pattern regex = Pattern.compile(pattern, Pattern.CANON_EQ | Pattern.DOTALL); 77 | 78 | Matcher regexMatcher = regex.matcher(plainText); 79 | 80 | // if input test is a signed plaintext 81 | if (regexMatcher.find()) { 82 | 83 | String signedDataStr = regexMatcher.group(1); 84 | LOG.warning("signedDataStr: "); 85 | LOG.warning(signedDataStr); 86 | 87 | String signatureStr = regexMatcher.group(2); 88 | LOG.warning("signatureStr: "); 89 | LOG.warning(signatureStr); 90 | 91 | ByteArrayInputStream signedDataIn = new ByteArrayInputStream(signedDataStr.getBytes("UTF8")); 92 | ByteArrayInputStream signatureIn = new ByteArrayInputStream(signatureStr.getBytes("UTF8")); 93 | 94 | Boolean result = verifyFile(signedDataIn, signatureIn, publicKey); 95 | LOG.warning("verification result: " + result); 96 | 97 | return result; 98 | } 99 | 100 | throw new Exception("Cannot recognize input data"); 101 | } 102 | 103 | public static Boolean verifyFile( 104 | InputStream signedDataIn, // signed data 105 | InputStream signatureIn, // signature 106 | PGPPublicKey pgpPublicKey) // key 107 | throws Exception { 108 | signatureIn = PGPUtil.getDecoderStream(signatureIn); 109 | //dataIn = PGPUtil.getDecoderStream(dataIn); // not needed 110 | PGPObjectFactory pgpObjectFactory = new PGPObjectFactory( 111 | signatureIn, 112 | new JcaKeyFingerprintCalculator() // <<<< TODO: check if this is correct 113 | ); 114 | 115 | PGPSignatureList pgpSignatureList = null; 116 | Object o; 117 | 118 | // get adn check: pgpObjectFactory.nextObject() 119 | try { 120 | o = pgpObjectFactory.nextObject(); 121 | if (o == null) 122 | throw new Exception("pgpObjectFactory.nextObject() returned null"); 123 | } catch (Exception ex) { 124 | 125 | throw new Exception("Invalid input data"); // 126 | } 127 | 128 | if (o instanceof PGPCompressedData) { 129 | 130 | PGPCompressedData pgpCompressedData = (PGPCompressedData) o; 131 | pgpObjectFactory = new PGPObjectFactory( 132 | pgpCompressedData.getDataStream(), 133 | new JcaKeyFingerprintCalculator() // <<<< TODO: check if this is correct 134 | ); 135 | pgpSignatureList = (PGPSignatureList) pgpObjectFactory.nextObject(); 136 | 137 | } else { 138 | pgpSignatureList = (PGPSignatureList) o; 139 | } 140 | 141 | int ch; 142 | 143 | // A PGP signatureObject 144 | // https://www.borelly.net/cb/docs/javaBC-1.4.8/pg/index.html?org/bouncycastle/openpgp/PGPSignature.html 145 | PGPSignature signatureObject = pgpSignatureList.get(0); 146 | 147 | if (pgpPublicKey == null) 148 | throw new Exception("Cannot find key 0x" 149 | + Integer.toHexString((int) signatureObject.getKeyID()).toUpperCase() 150 | + " in the pubring" 151 | ); 152 | 153 | // signatureObject.initVerify( 154 | // pgpPublicKey, 155 | // "BC" 156 | // ); 157 | // https://www.borelly.net/cb/docs/javaBC-1.4.8/pg/org/bouncycastle/openpgp/PGPSignature.html#initVerify(org.bouncycastle.openpgp.PGPPublicKey,%20java.security.Provider) 158 | // Deprecated. use init(PGPContentVerifierBuilderProvider, PGPPublicKey) 159 | 160 | signatureObject.init( 161 | new JcaPGPContentVerifierBuilderProvider(), 162 | pgpPublicKey 163 | ); 164 | 165 | while ((ch = signedDataIn.read()) >= 0) { 166 | signatureObject.update((byte) ch); 167 | } 168 | 169 | if (signatureObject.verify()) { 170 | return Boolean.TRUE; 171 | } else { 172 | return Boolean.FALSE; 173 | } 174 | 175 | } // end of verifyFile() 176 | 177 | 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/ServletUtils.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | 4 | import com.google.gson.Gson; 5 | 6 | import javax.servlet.http.Cookie; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.PrintWriter; 11 | import java.util.Enumeration; 12 | import java.util.logging.Logger; 13 | 14 | /** 15 | * utilities to use in servlets 16 | */ 17 | public class ServletUtils { 18 | 19 | /* ---- Logger: */ 20 | private static final Logger LOG = Logger.getLogger(ServletUtils.class.getName()); 21 | /* --- Gson: */ 22 | private static final Gson GSON = new Gson(); 23 | 24 | public static String getRequestParameters(HttpServletRequest request) { 25 | 26 | // see: http://edwin.baculsoft.com/2014/04/logging-http-request-parameters-using-http-servlet/ 27 | 28 | String result = "{"; 29 | 30 | Enumeration enumeration = request.getParameterNames(); 31 | while (enumeration.hasMoreElements()) { 32 | String parametername = enumeration.nextElement(); 33 | result += "\"" + parametername + "\":\"" + request.getParameter(parametername) + "\","; 34 | } 35 | result = removeLastComma(result) + "}"; 36 | // LOG.warning(result); 37 | return result; 38 | } // end of getRequestParameters() 39 | 40 | public static String getCookies(HttpServletRequest request) { 41 | String result = "["; 42 | Cookie[] cookies = request.getCookies(); 43 | if (cookies == null) { 44 | result += ""; 45 | } else { 46 | for (Cookie cookie : cookies) { 47 | result += "{" 48 | + "\"name\": \"" + cookie.getName() + "\"," 49 | + "\"value\": \"" + cookie.getValue() + "\"," 50 | + "\"domain\": \"" + cookie.getDomain() + "\"," 51 | + "\"path\": \"" + cookie.getPath() + "\"," 52 | + "\"comment\": \"" + cookie.getComment() 53 | + "},"; 54 | } 55 | result = removeLastComma(result); 56 | } 57 | result += "]"; 58 | // LOG.warning(result); 59 | return result; 60 | } // end of getCookies() 61 | 62 | public static String getRequestHeaders(HttpServletRequest request) { 63 | 64 | String result = "{"; 65 | 66 | Enumeration headerNames = request.getHeaderNames(); 67 | while (headerNames.hasMoreElements()) { 68 | String headerName = headerNames.nextElement(); 69 | result += "\"" + headerName + "\":\"" + request.getHeader(headerName) + "\","; 70 | } 71 | result = removeLastComma(result) + "}"; 72 | // LOG.warning(result); 73 | return result; 74 | } // end of getRequestHeaderNames() 75 | 76 | private static String removeLastComma(String str) { 77 | int commaIndex = str.lastIndexOf(","); // -1 if there is no such occurrence. 78 | if (commaIndex > 0 && commaIndex == str.length() - 1) { 79 | str = str.substring(0, commaIndex); 80 | } 81 | return str; 82 | } 83 | 84 | public static String getAllRequestData(HttpServletRequest request) { 85 | 86 | String headerNamesStr = ServletUtils.getRequestHeaders(request); 87 | String requestParametersStr = ServletUtils.getRequestParameters(request); 88 | String cookiesStr = ServletUtils.getCookies(request); 89 | String requestDataSrt = "{\"request\": " 90 | // 91 | + "{" 92 | + "\"requestHeaders\": " + headerNamesStr + "," 93 | + "\"requestParameters\": " + requestParametersStr + "," 94 | + "\"cookies\":" + cookiesStr 95 | + "}" 96 | // 97 | + "}"; 98 | return requestDataSrt; 99 | } 100 | 101 | public static void sendTxtResponse(HttpServletResponse response, final String text) throws IOException { 102 | 103 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types 104 | response.setContentType("text/plain"); 105 | 106 | response.setCharacterEncoding("UTF-8"); 107 | PrintWriter pw = response.getWriter(); //get the stream to write the data 108 | pw.println(text); 109 | pw.close(); //closing the stream 110 | 111 | } // end of sendTxtResponse() 112 | 113 | private static void sendJsonResponse(HttpServletResponse response, final String jsonStr) throws IOException { 114 | 115 | response.setContentType("application/json"); 116 | response.setCharacterEncoding("UTF-8"); 117 | PrintWriter pw = response.getWriter(); //get the stream to write the data 118 | pw.println(jsonStr); 119 | pw.close(); //closing the stream 120 | 121 | } // end of sendJsonResponse() 122 | 123 | public static void sendJsonResponseFromObject(HttpServletResponse response, Object object) throws IOException { 124 | LOG.info("object:"); 125 | LOG.info(object.getClass() + ": " + object.toString()); 126 | String jsonStr = GSON.toJson(object); 127 | LOG.info(jsonStr); 128 | sendJsonResponse(response, jsonStr); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/net/cryptonomica/tomcatweb3j/utilities/Web3jServices.java: -------------------------------------------------------------------------------- 1 | package net.cryptonomica.tomcatweb3j.utilities; 2 | 3 | import org.apache.commons.codec.binary.StringUtils; 4 | import org.web3j.abi.datatypes.generated.Bytes32; 5 | import org.web3j.abi.datatypes.generated.Bytes20; 6 | import org.web3j.crypto.Hash; 7 | 8 | import javax.xml.bind.DatatypeConverter; 9 | 10 | 11 | public class Web3jServices { 12 | 13 | // see: 14 | // https://github.com/web3j/web3j/blob/master/utils/src/main/java/org/web3j/crypto/Hash.java#L12 15 | public static String keccak256FromHexEncodedInputDataAsString(String hexInput) { 16 | return Hash.sha3(hexInput); 17 | } 18 | 19 | // see code of: 20 | // https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#toString-byte:A- 21 | // this uses the same idea 22 | // to convert byte[] to representation like '0xf463b5590fa2a73f5296122649ed544fd1c3eeb35a63b71a883a31e330d22412' 23 | public static String bytesArrayToHexString(byte[] a) { 24 | if (a == null) 25 | return "null"; 26 | int iMax = a.length - 1; 27 | if (iMax == -1) 28 | return "[]"; 29 | StringBuilder b = new StringBuilder(); 30 | b.append("0x"); 31 | for (int i = 0; ; i++) { 32 | b.append( 33 | Integer.toHexString(a[i]) 34 | ); 35 | if (i == iMax) 36 | return b.toString(); 37 | } 38 | } 39 | 40 | /* 41 | * see: 42 | * https://ethereum.stackexchange.com/questions/23549/convert-string-to-bytes32-in-web3j 43 | * */ 44 | public static Bytes32 stringToBytes32(String string) { 45 | byte[] byteValue = string.getBytes(); 46 | byte[] byteValueLen32 = new byte[32]; 47 | System.arraycopy(byteValue, 0, byteValueLen32, 0, byteValue.length); 48 | return new Bytes32(byteValueLen32); 49 | } 50 | 51 | public static String bytes32toString(Bytes32 bytes32) { 52 | return StringUtils.newStringUsAscii(bytes32.getValue()); 53 | } 54 | 55 | // 56 | public static byte[] hexStringToByteArray(String hexString) { 57 | if (hexString.length() % 2 != 0) { 58 | throw new IllegalArgumentException("hex string length should be even"); 59 | } 60 | byte[] bytes = new byte[hexString.length() / 2]; 61 | for (int i = 0; i < bytes.length; i++) { 62 | int index = i * 2; 63 | int b = Integer.parseInt( 64 | hexString.substring(index, index + 2), // string 65 | 16 // radix 66 | ); 67 | bytes[i] = (byte) b; 68 | } 69 | return bytes; 70 | } 71 | 72 | // // https://stackoverflow.com/a/5942951/1697878 73 | public static byte[] hexStringToByteArrayDatatypeConverter(String hexString) { 74 | return DatatypeConverter.parseHexBinary(hexString); 75 | } 76 | 77 | // https://stackoverflow.com/a/5942951/1697878 78 | public static String byteArrayToHexString(byte[] bytes) { 79 | return DatatypeConverter.printHexBinary(bytes); 80 | } 81 | 82 | /* 83 | * hexString - string like "0D13CC9610D9C5757C06D48D54273971EB45F1E8" 84 | * we can use this to store OpenPGP key fingerprint as bytes20 in smart contract 85 | * */ 86 | public static Bytes20 bytes20FromHexString(String hexString){ 87 | byte[] bytes = DatatypeConverter.parseHexBinary(hexString); 88 | Bytes20 bytes20 = new Bytes20(bytes); 89 | return bytes20; 90 | } 91 | 92 | public static String byteArrayAsSting(byte[] bytes) { 93 | StringBuilder stringBuilder = new StringBuilder(); 94 | stringBuilder.append("["); 95 | for (byte b : bytes) { 96 | stringBuilder.append( 97 | // Byte.toString(b)// with negative numbers 98 | Byte.toUnsignedInt(b) // to get always positive value (Java8) 99 | ); 100 | stringBuilder.append(" "); 101 | } 102 | // remove last " " 103 | stringBuilder.delete(stringBuilder.lastIndexOf(" "), stringBuilder.lastIndexOf(" ") + 1); 104 | stringBuilder.append("]"); 105 | return stringBuilder.toString(); 106 | // result like: [13 19 204 150 16 217 197 117 124 6 212 141 84 39 57 113 235 69 241 232] 107 | } 108 | 109 | // see: https://stackoverflow.com/a/2817883/1697878 110 | public static String byteArrayAsHexSting(byte[] bytes) { 111 | StringBuilder stringBuilder = new StringBuilder(); 112 | stringBuilder.append("["); 113 | for (byte b : bytes) { 114 | stringBuilder.append( 115 | String.format("%02X", b) 116 | ); 117 | stringBuilder.append(" "); 118 | } 119 | // remove last " " 120 | stringBuilder.delete(stringBuilder.lastIndexOf(" "), stringBuilder.lastIndexOf(" ") + 1); 121 | stringBuilder.append("]"); 122 | return stringBuilder.toString(); 123 | // result like: [0D 13 CC 96 10 D9 C5 75 7C 06 D4 8D 54 27 39 71 EB 45 F1 E8] 124 | } 125 | 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | net.cryptonomica.tomcatweb3j 13 | 14 | 15 | 16 | 17 | GetVerificationRequestDataServlet 18 | net.cryptonomica.tomcatweb3j.servlets.GetVerificationRequestDataServlet 19 | 20 | 21 | GetVerificationRequestDataServlet 22 | /GetVerificationRequestDataServlet 23 | 24 | 25 | 26 | GetVerification 27 | net.cryptonomica.tomcatweb3j.servlets.GetVerificationServlet 28 | 29 | 30 | GetVerification 31 | /getVerification 32 | 33 | 34 | 35 | addVerificationData 36 | net.cryptonomica.tomcatweb3j.servlets.AddVerificationDataServlet 37 | 38 | 39 | addVerificationData 40 | /addVerificationData 41 | 42 | 43 | 44 | TestServlet 45 | net.cryptonomica.tomcatweb3j.servlets.TestServlet 46 | 47 | 48 | TestServlet 49 | /testServlet 50 | 51 | 52 | 53 | 54 | 55 | index.html 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cryptonomica/Ethereum-IdentityVerification 6 | 7 | 8 |
9 |
10 | see:
11 | 12 | https://github.com/Cryptonomica/Ethereum-IdentityVerification 13 | 14 |
15 |
16 | index.html version: 002 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /tomcatWeb3j.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | --------------------------------------------------------------------------------