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 |