diff --git a/.env b/.env index f593e7d..3c70349 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -RUN_ENV=prod -COMPOSE_PROFILE=prod \ No newline at end of file +RUN_ENV=dev +COMPOSE_PROFILES=dev \ No newline at end of file diff --git a/.gitignore b/.gitignore index c2d3e19..9bfb28e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/ +config-dev/ build/ .idea/** config/blockchain-service.env diff --git a/README.md b/README.md index 9375b40..2454a2d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ La stack choisi pour ce projet est `go`, la blockchain `ethereum` et `solidity` Si vous trouvez des bugs sur cette version n'hésitez pas à faire une `issue` -Le smart-contract à été déployé sur Ropsten en test à cette [adresse](https://ropsten.etherscan.io/address/0x29a5c09219a5c71a81d26922d708e472677f4548) `0x29a5c09219a5c71a81d26922d708e472677f4548` +Le smart-contract à été déployé sur Ropsten en test à cette [adresse](https://ropsten.etherscan.io/address/0x524e9d84B91889E5D5d8489c24E24A89e592A1e1) `0x524e9d84B91889E5D5d8489c24E24A89e592A1e1` La branche dev en cours est [dev/go/eth](https://github.com/42School/blockchain-service/tree/dev/go/eth). @@ -45,6 +45,8 @@ Le port par défaut de l'API est `8080`. L'API contains à ce jour 3 routes différentes: +- `/metrics` permet de récupérer des metriques pour Prometheus. + - `/create-diploma` permet de crée un nouveau diplôme dans la blockchain. ⚠️ Token requis - Méthode `POST` @@ -120,8 +122,8 @@ L'API contains à ce jour 3 routes différentes: "Data": { "Hash":"", - "Level":21, - "Skills":[21.57,21.42,21.2,21.42,6.61,4.16,9.02,9.02,9.02,3.6,2.22,5.5,1.45,4.34] + "Level":21.00, + "Skills":[{"slug":"Security","level":16.42},{"slug":"Unix","level":13.87},{},{}] } } ``` @@ -136,7 +138,7 @@ L'API contains à ce jour 3 routes différentes: [ { "Level": 2100, - "Skills": [857,542,620,942,661,416,902,902,902,360,222,550,145, ...], + "Skills": [{"Slug":"Security","Level":1642},{"Slug":"Unix","Level":1387},...], "Hash": [xxx,xx,xx,xx,xx,xxx,x,xx,xxx,xx,xxx,xx,xxx,xx,xx,xx,xxx,xx,xxx,xx, ...], "Signature": { @@ -147,7 +149,7 @@ L'API contains à ce jour 3 routes différentes: }, { "Level": 2100, - "Skills": [857,542,620,942,661,416,902,902,902,360,222,550,145, ...], + "Skills": [{"Slug":"Security","Level":1642},{"Slug":"Unix","Level":1387},...], "Hash": [xxx,xx,xx,xx,xx,xxx,x,xx,xxx,xx,xxx,xx,xxx,xx,xx,xx,xxx,xx,xxx,xx, ...], "Signature": { diff --git a/contracts/FtDiploma.sol b/contracts/FtDiploma.sol index b33567a..b89ec5c 100644 --- a/contracts/FtDiploma.sol +++ b/contracts/FtDiploma.sol @@ -10,7 +10,7 @@ contract FtDiploma { string public constant name = "42 Alumni"; string public constant symbol = "42A"; string public constant linkOfRepo = "github.com/42School/blockchain-service"; - address public constant ftPubAddress = ; + address public constant ftPubAddress = 0x7e12234E994384A757E2689aDdB2A463ccD3B47d; event Publish42Diploma(address ftPubAddress, string _link); event CreateDiploma(bytes32 student); @@ -21,9 +21,21 @@ contract FtDiploma { bytes32 s; } + struct Skill { + string name; + uint64 level; + } + + struct Diplomas { + uint64 level; + Skill[30] skills; + bytes32 hash; + Sign signature; + } + struct Diploma { uint64 level; - uint64[30] skills; + mapping(uint64 => Skill) skills; bytes32 hash; Sign signature; } @@ -35,26 +47,41 @@ contract FtDiploma { emit Publish42Diploma(ftPubAddress, linkOfRepo); } - function createDiploma(uint64 _level, uint64[30] memory _skills, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) public { + function createDiploma(uint64 _level, uint64[30] memory _skillLevel, string[30] memory _skillSlug, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) public { require(ecrecover(_studentHash, _v, _r, _s) == ftPubAddress, "FtDiploma: Is not 42 sign this diploma."); require(hashToDiploma[_studentHash].level == 0, "FtDiploma: The diploma already exists."); - hashToDiploma[_studentHash] = Diploma(_level, _skills, _studentHash, Sign(_v, _r, _s)); + Diploma storage dp = hashToDiploma[_studentHash]; + dp.level = _level; + dp.hash = _studentHash; + dp.signature = Sign(_v, _r, _s); + for (uint64 i = 0; i < 30; i++) { + dp.skills[i] = Skill(_skillSlug[i], _skillLevel[i]); + } intToHash.push(_studentHash); emit CreateDiploma(_studentHash); } - function getDiploma(bytes32 _studentHash) public view returns (uint64 level, uint64[30] memory skills) { - Diploma memory _getDiploma = hashToDiploma[_studentHash]; + function getDiploma(bytes32 _studentHash) public view returns (uint64, Skill[] memory) { + Diploma storage _getDiploma = hashToDiploma[_studentHash]; uint64 levelDiploma = _getDiploma.level; - uint64[30] memory skillsDiploma = _getDiploma.skills; - return (levelDiploma, skillsDiploma); + Skill[] memory skills = new Skill[](30); + for (uint64 i = 0; i < 30; i++) { + skills[i] = _getDiploma.skills[i]; + } + return (levelDiploma, skills); } - function getAllDiploma() public view returns (Diploma[] memory) { + function getAllDiploma() public view returns (Diplomas[] memory) { require(msg.sender == ftPubAddress, "FtDiploma: Is not 42."); - Diploma[] memory diplomas = new Diploma[](intToHash.length); + Diplomas[] memory diplomas = new Diplomas[](intToHash.length); for (uint256 i = 0; i < intToHash.length; i++) { - diplomas[i] = hashToDiploma[intToHash[i]]; + Diploma storage dp = hashToDiploma[intToHash[i]]; + diplomas[i].level = dp.level; + for (uint64 y = 0; y < 30; y++) { + diplomas[i].skills[y] = dp.skills[y]; + } + diplomas[i].hash = dp.hash; + diplomas[i].signature = dp.signature; } return (diplomas); } diff --git a/docker-compose.yml b/docker-compose.yml index e71d05c..8c9ca51 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,36 @@ services: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example +# eth-client: +# image: ethereum/client-go:latest +# hostname: geth +# ports: +# - "30303:30303" +# expose: +# - "8545" +# - "8546" +# - "6060" +# - "8080" +# networks: +# - back +# volumes: +# - ~/Library/Ethereum:/root/.ethereum/ +# command: +# - --ropsten +## - --light.serve=20 +# - --syncmode +# - "fast" +## - --rpc +# - --ws +# - --ws.port=8546 +# - --ws.addr=0.0.0.0 +# - --ws.api +# - admin,debug,web3,eth,txpool,personal,ethash,net +# - --ws.origins="*" +# - --metrics +# - --metrics.addr=0.0.0.0 +# - --metrics.port=6060 + app: image: blockchain-service ports: @@ -28,7 +58,7 @@ services: networks: - back env_file: - - config/blockchain-service.env + - config-dev/blockchain-service.env environment: RUN_ENV: "${RUN_ENV}" depends_on: @@ -46,5 +76,4 @@ services: ME_CONFIG_MONGODB_ADMINPASSWORD: example depends_on: - mongo - profiles: - - dev \ No newline at end of file + profiles: ["dev"] \ No newline at end of file diff --git a/go.mod b/go.mod index 69d3d85..e4a5699 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,9 @@ require ( github.com/ethereum/go-ethereum v1.9.25 github.com/google/uuid v1.2.0 github.com/gorilla/mux v1.8.0 + github.com/prometheus/client_golang v1.10.0 + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.7.0 go.mongodb.org/mongo-driver v1.4.5 golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013 ) diff --git a/go.sum b/go.sum index e51d19e..2ab54cf 100644 --- a/go.sum +++ b/go.sum @@ -34,41 +34,58 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0 h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -79,24 +96,36 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -104,24 +133,32 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -149,8 +186,12 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -173,9 +214,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -188,8 +230,10 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -201,29 +245,57 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989 h1:giknQ4mEuDFmmHSrGcbargOuLHQGtywqo4mheITex54= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw= github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= @@ -233,19 +305,29 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -253,56 +335,130 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 h1:ZeU+auZj1iNzN8iVhff6M38Mfu73FQiJve/GEXYJBjE= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -311,14 +467,26 @@ github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9Ac github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= @@ -326,19 +494,25 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1 github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= @@ -346,22 +520,36 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.4.5 h1:TLtO+iD8krabXxvY1F1qpBOHgOxhLWR7XsT7kQeRmMY= go.mongodb.org/mongo-driver v1.4.5/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= @@ -403,16 +591,23 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -443,15 +638,19 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -464,19 +663,22 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -484,29 +686,34 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -520,6 +727,8 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -527,6 +736,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -548,10 +758,10 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -569,6 +779,7 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -580,6 +791,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -604,10 +816,15 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -629,28 +846,35 @@ google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -661,3 +885,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/main.go b/main.go index 3a5d92e..58332ec 100644 --- a/main.go +++ b/main.go @@ -5,15 +5,30 @@ import ( "github.com/42School/blockchain-service/src/account" "github.com/42School/blockchain-service/src/async" "github.com/42School/blockchain-service/src/dao/api" + "github.com/42School/blockchain-service/src/metrics" "github.com/42School/blockchain-service/src/rest" "github.com/42School/blockchain-service/src/tools" + log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readpref" - "log" "net/http" + "os" ) +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.TextFormatter{ForceColors: true, TimestampFormat : "2006-01-02 15:04:05", FullTimestamp:true, PadLevelText: true}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + if tools.Env == "dev" || tools.Env == "DEV" || tools.Env == "Dev" { + log.SetLevel(log.DebugLevel) + } +} + +// MongoStart connect the blockchain-service with a MongoDB and create 1 database 'queue' with 2 table 'retry' & 'check' func MongoStart() error { url := "mongodb://" + tools.MongoIp + ":" + tools.MongoPort credential := options.Credential{ @@ -29,27 +44,32 @@ func MongoStart() error { return err } tools.RetryDB = client.Database("queue").Collection("retry") - tools.ToCheckDB = client.Database("queue").Collection("valide") + tools.ToCheckDB = client.Database("queue").Collection("check") return nil } func main() { - go async.ValideHash() + go async.CheckHash() go async.RetryDiploma() - go async.ReadStdin() err := MongoStart() if err != nil { - tools.LogsError(err) + log.WithError(err).Fatal("Mongo Connection Failed.") return } err = api.InitApi() if err != nil { - tools.LogsError(err) + log.WithError(err).Fatal("Intra.42 API Connection Failed.") return } async.RestoreQueue() account.CreateAccountsManager() router := rest.InitRouter() - tools.LogsMsg("Blockchain Service is running !") - log.Fatal(http.ListenAndServe(":8080", router)) + metrics.RecordMetrics() + log.Info("Blockchain Service is running !") + err = http.ListenAndServe(":8080", router) + if err != nil { + log.WithError(err).Fatal("HTTP Server doesn't running.") + } + + } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js new file mode 100644 index 0000000..c5bc4cf --- /dev/null +++ b/migrations/2_deploy_contracts.js @@ -0,0 +1,5 @@ +const FtDiploma = artifacts.require("FtDiploma"); + + module.exports = function(deployer) { + deployer.deploy(FtDiploma); + }; diff --git a/src/account/account.go b/src/account/account.go index e1ba0b5..8f3b2b3 100644 --- a/src/account/account.go +++ b/src/account/account.go @@ -8,17 +8,18 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + log "github.com/sirupsen/logrus" "io/ioutil" "strings" ) type Account struct { - KeyStoreFile string - Password string + KeyStoreFile string + Password string } var KeyStore *keystore.KeyStore -var CurrentAccount int = 0 +var CurrentAccount = 0 var Accounts []Account func ParseAccounts() { @@ -57,7 +58,7 @@ func GetWriterAccount() (common.Address, *ecdsa.PrivateKey, error) { if errDecrypt != nil { return common.Address{}, nil, errDecrypt } - tools.LogsDev("private key writer: " + hexutil.Encode(crypto.FromECDSA(key.PrivateKey))) + log.WithFields(log.Fields{"private_key": hexutil.Encode(crypto.FromECDSA(key.PrivateKey))}).Debug("The private key of the wallet writer") return key.Address, key.PrivateKey, nil } @@ -65,9 +66,9 @@ func ChangeAccount() { // Send Mail of Current Account address, _, _ := GetWriterAccount() tools.SendMail("Empty Account", address.Hex()) - if CurrentAccount + 1 == len(Accounts) { + if CurrentAccount+1 == len(Accounts) { CurrentAccount = 0 } else { CurrentAccount = CurrentAccount + 1 } -} \ No newline at end of file +} diff --git a/src/async/async.go b/src/async/async.go index e470561..66de3f8 100644 --- a/src/async/async.go +++ b/src/async/async.go @@ -1,23 +1,21 @@ package async import ( - "bufio" "context" - "fmt" "github.com/42School/blockchain-service/src/dao/contracts" "github.com/42School/blockchain-service/src/dao/diplomas" + "github.com/42School/blockchain-service/src/metrics" "github.com/42School/blockchain-service/src/tools" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/ethclient" + log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/bson" - "log" "net/http" - "os" "strings" "time" ) -func ValideHash() { +func CheckHash() { url := tools.FtEndPoint + tools.ValidationPath for { time.Sleep(10 * time.Minute) @@ -29,6 +27,7 @@ func ValideHash() { data := "{'Status': true, 'Message': 'The " + strHash + " diploma is definitely inscribed on Ethereum.', 'Data': {" + strHash + "}}" client, _ := ethclient.Dial(tools.NetworkLink) receipt, err := client.TransactionReceipt(context.Background(), check.Tx.Hash()) + metrics.PrometheusBlockDuration(receipt.BlockHash, check.SendTime) if err == nil { if receipt.Status == 1 { contracts.CheckSecurity(client, check.Tx, check.StudentHash) @@ -37,6 +36,8 @@ func ValideHash() { tools.ToCheckHash.Remove(e) txByte, _ := check.Tx.MarshalJSON() tools.ToCheckDB.DeleteOne(context.TODO(), bson.M{"tx": txByte, "studenthash": check.StudentHash}) + metrics.GaugeCheckQueue.Dec() + metrics.CounterDiplomaSuccess.Inc() e = copyList.Front() continue } @@ -51,6 +52,7 @@ func ValideHash() { tools.ToCheckHash.Remove(e) txByte, _ := check.Tx.MarshalJSON() tools.ToCheckDB.DeleteOne(context.TODO(), bson.M{"tx": txByte, "studenthash": check.StudentHash}) + metrics.GaugeCheckQueue.Dec() e = copyList.Front() continue } @@ -63,58 +65,31 @@ func ValideHash() { } } -func RetryDiploma () { +func RetryDiploma() { url := tools.FtEndPoint + tools.RetryPath for { time.Sleep(30 * time.Minute) - if tools.SecuritySystem == false { - copyList := tools.RetryQueue - for e := copyList.Front(); e != nil; { - if e != nil { - diploma, _ := e.Value.(diplomas.Diploma) - tools.LogsDev("Retry the diploma: " + diploma.String()) - hash, bool := diploma.EthWriting() - if bool == true { - data := "{'Status':true,'Message':'The writing in blockchain has been done, it will be confirmed in 10 min.','Data':{'Hash': " + hash + ",'Level':0,'Skills':[]}}" - http.Post(url, "Content-Type: application/json", strings.NewReader(data)) - tools.RetryQueue.Remove(e) - tools.RetryDB.DeleteOne(context.TODO(), diploma) - e = copyList.Front() - } else { - e = e.Next() - } + copyList := tools.RetryQueue + for e := copyList.Front(); e != nil; { + if e != nil { + diploma, _ := e.Value.(diplomas.Diploma) + log.WithFields(diploma.LogFields()).Debug("Try to retry a diploma") + hash, bool := diploma.EthWriting() + if bool == true { + data := "{'Status':true,'Message':'The writing in blockchain has been done, it will be confirmed in 10 min.','Data':{'Hash': " + hash + ",'Level':0,'Skills':[]}}" + http.Post(url, "Content-Type: application/json", strings.NewReader(data)) + tools.RetryQueue.Remove(e) + tools.RetryDB.DeleteOne(context.TODO(), diploma) + metrics.GaugeRetryQueue.Dec() + e = copyList.Front() + } else { + diploma.Counter += 1 + log.Info(diploma.Counter) + tools.RetryQueue.InsertBefore(diploma, e) + tools.RetryQueue.Remove(e) + e = e.Next() } } } } } - -func ReadStdin() { - scanner := bufio.NewScanner(os.Stdin) - var cmd = false - for { - if cmd { - fmt.Print("> ") - } - scanner.Scan() - if err := scanner.Err(); err != nil { - log.Println(err) - } else { - text := scanner.Text() - if text == "CMD" || text == "cmd" || text == "Cmd"{ - fmt.Println("Please enter your command:") - fmt.Println(" - 'disable security system': to disable the security system") - fmt.Println(" - 'exit' or 'Exit' or 'EXIT': to exit the CMD mode") - cmd = true - } else if text == "disable security system" && cmd { - cmd = false - tools.SecuritySystem = false - fmt.Println("The security system has been disabled !") - fmt.Println("Goodbye of cmd mode") - } else if text == "Exit" || text == "exit" || text == "EXIT" { - cmd = false - fmt.Println("Goodbye of cmd mode") - } - } - } -} \ No newline at end of file diff --git a/src/async/queue.go b/src/async/queue.go index 569291d..c6180b6 100644 --- a/src/async/queue.go +++ b/src/async/queue.go @@ -3,19 +3,22 @@ package async import ( "context" "github.com/42School/blockchain-service/src/dao/diplomas" + "github.com/42School/blockchain-service/src/metrics" "github.com/42School/blockchain-service/src/tools" "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" + "time" ) type verifHashDB struct { - Id uuid.UUID - Tx []byte + Id uuid.UUID + Tx []byte StudentHash []byte + SendTime time.Time } -func RestoreQueue() { +func restoreRetryQueue() { cursor, err := tools.RetryDB.Find(context.TODO(), bson.M{}) if err != nil { tools.LogsError(err) @@ -29,7 +32,11 @@ func RestoreQueue() { } tools.RetryQueue.PushBack(dp) } - cursor, err = tools.ToCheckDB.Find(context.TODO(), bson.M{}) + metrics.GaugeRetryQueue.Set(float64(tools.RetryQueue.Len())) +} + +func restoreCheckQueue() { + cursor, err := tools.ToCheckDB.Find(context.TODO(), bson.M{}) if err != nil { tools.LogsError(err) return @@ -45,9 +52,16 @@ func RestoreQueue() { toCheck.StudentHash = toGet.StudentHash err = tx.UnmarshalJSON(toGet.Tx) toCheck.Tx = &tx + toCheck.SendTime = toGet.SendTime if err != nil { continue } tools.ToCheckHash.PushBack(toCheck) } + metrics.GaugeCheckQueue.Set(float64(tools.ToCheckHash.Len())) +} + +func RestoreQueue() { + restoreRetryQueue() + restoreCheckQueue() } diff --git a/src/dao/api/get-cursus-user.go b/src/dao/api/get-cursus-user.go index 8f43105..7c935bb 100644 --- a/src/dao/api/get-cursus-user.go +++ b/src/dao/api/get-cursus-user.go @@ -3,38 +3,32 @@ package api import ( "context" "encoding/json" + "github.com/42School/blockchain-service/src/dao/diplomas" "github.com/42School/blockchain-service/src/tools" + log "github.com/sirupsen/logrus" "strconv" ) -type skillsApi struct { - Name string `json:"name"` - Level float64 `json:"level"` -} - type cursusUser struct { - Level float64 `json:"level"` - Skills []skillsApi `json:"skills"` + Level float64 `json:"level"` + Skills []diplomas.Skill `json:"skills"` } -func GetCursusUser(cursusId int) (float64, []float64, error) { +func GetCursusUser(cursusId int) (float64, []diplomas.Skill, error) { var cursus cursusUser - var skills []float64 server := FtApi.Client(context.Background()) url := "https://api.intra.42.fr/v2/cursus_users/" + strconv.Itoa(cursusId) rest, err := server.Get(url) if err != nil { tools.LogsError(err) - return 0, skills, err + return 0, []diplomas.Skill{}, err } err = json.NewDecoder(rest.Body).Decode(&cursus) if err != nil { tools.LogsError(err) - return 0, skills, err + return 0, []diplomas.Skill{}, err } level := cursus.Level - for i := 0; i < len(cursus.Skills); i++ { - skills = append(skills, cursus.Skills[i].Level) - } - return level, skills, nil -} \ No newline at end of file + log.Info(cursus.Skills) + return level, cursus.Skills, nil +} diff --git a/src/dao/api/init.go b/src/dao/api/init.go index 31baca9..ba98b2b 100644 --- a/src/dao/api/init.go +++ b/src/dao/api/init.go @@ -1,10 +1,10 @@ package api import ( + "context" "github.com/42School/blockchain-service/src/tools" "golang.org/x/oauth2" "golang.org/x/oauth2/clientcredentials" - "context" "os" ) @@ -12,11 +12,11 @@ var FtApi *clientcredentials.Config func InitApi() error { FtApi = &clientcredentials.Config{ - ClientID: os.Getenv("APP_CLIENT_ID"), + ClientID: os.Getenv("APP_CLIENT_ID"), ClientSecret: os.Getenv("APP_CLIENT_SECRET"), - TokenURL: "https://api.intra.42.fr/oauth/token", - AuthStyle: oauth2.AuthStyleInParams, - Scopes: []string{"public"}, + TokenURL: "https://api.intra.42.fr/oauth/token", + AuthStyle: oauth2.AuthStyleInParams, + Scopes: []string{"public"}, } _, err := FtApi.Token(context.Background()) if err != nil { @@ -25,4 +25,3 @@ func InitApi() error { } return nil } - diff --git a/src/dao/api/webhook-to-diploma.go b/src/dao/api/webhook-to-diploma.go index 272f5d3..6aa985d 100644 --- a/src/dao/api/webhook-to-diploma.go +++ b/src/dao/api/webhook-to-diploma.go @@ -4,16 +4,17 @@ import ( "encoding/json" "github.com/42School/blockchain-service/src/dao/diplomas" "github.com/42School/blockchain-service/src/tools" + log "github.com/sirupsen/logrus" "io" "time" ) type WebhookData struct { - Login string `json:"login"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - BirthDate string `json:"birth_date"` - AlumnizedCursusUser int `json:"alumnized_cursus_user"` + Login string `json:"login"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + BirthDate string `json:"birth_date"` + AlumnizedCursusUser int `json:"alumnized_cursus_user"` } func WebhookToDiploma(body io.ReadCloser) (diplomas.Diploma, error) { @@ -35,7 +36,7 @@ func WebhookToDiploma(body io.ReadCloser) (diplomas.Diploma, error) { newDiploma.AlumniDate = time.Now().Format("2006-01-02") newDiploma.Level = level newDiploma.Skills = skills - tools.LogsDev(newDiploma.String()) - tools.LogsDev("Webhook -> Diploma: ok") + newDiploma.Counter = 0 + log.WithFields(newDiploma.LogFields()).Debug("Webhook to Diploma success") return newDiploma, nil } diff --git a/src/dao/contracts/FtDiploma.go b/src/dao/contracts/FtDiploma.go index e60b0ed..20780a5 100644 --- a/src/dao/contracts/FtDiploma.go +++ b/src/dao/contracts/FtDiploma.go @@ -26,10 +26,10 @@ var ( _ = event.NewSubscription ) -// FtDiplomaDiploma is an auto generated low-level Go binding around an user-defined struct. -type FtDiplomaDiploma struct { +// FtDiplomaDiplomas is an auto generated low-level Go binding around an user-defined struct. +type FtDiplomaDiplomas struct { Level uint64 - Skills [30]uint64 + Skills [30]FtDiplomaSkill Hash [32]byte Signature FtDiplomaSign } @@ -41,11 +41,17 @@ type FtDiplomaSign struct { S [32]byte } +// FtDiplomaSkill is an auto generated low-level Go binding around an user-defined struct. +type FtDiplomaSkill struct { + Name string + Level uint64 +} + // DiplomaABI is the input ABI used to generate the binding from. -const DiplomaABI = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"student\",\"type\":\"bytes32\"}],\"name\":\"CreateDiploma\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ftPubAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_link\",\"type\":\"string\"}],\"name\":\"Publish42Diploma\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_level\",\"type\":\"uint64\"},{\"internalType\":\"uint64[30]\",\"name\":\"_skills\",\"type\":\"uint64[30]\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_studentHash\",\"type\":\"bytes32\"}],\"name\":\"createDiploma\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ftPubAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllDiploma\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"level\",\"type\":\"uint64\"},{\"internalType\":\"uint64[30]\",\"name\":\"skills\",\"type\":\"uint64[30]\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structFtDiploma.Sign\",\"name\":\"signature\",\"type\":\"tuple\"}],\"internalType\":\"structFtDiploma.Diploma[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_studentHash\",\"type\":\"bytes32\"}],\"name\":\"getDiploma\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"level\",\"type\":\"uint64\"},{\"internalType\":\"uint64[30]\",\"name\":\"skills\",\"type\":\"uint64[30]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkOfRepo\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" +const DiplomaABI = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"student\",\"type\":\"bytes32\"}],\"name\":\"CreateDiploma\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ftPubAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_link\",\"type\":\"string\"}],\"name\":\"Publish42Diploma\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_level\",\"type\":\"uint64\"},{\"internalType\":\"uint64[30]\",\"name\":\"_skillLevel\",\"type\":\"uint64[30]\"},{\"internalType\":\"string[30]\",\"name\":\"_skillSlug\",\"type\":\"string[30]\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_studentHash\",\"type\":\"bytes32\"}],\"name\":\"createDiploma\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ftPubAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllDiploma\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"level\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"level\",\"type\":\"uint64\"}],\"internalType\":\"structFtDiploma.Skill[30]\",\"name\":\"skills\",\"type\":\"tuple[30]\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structFtDiploma.Sign\",\"name\":\"signature\",\"type\":\"tuple\"}],\"internalType\":\"structFtDiploma.Diplomas[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_studentHash\",\"type\":\"bytes32\"}],\"name\":\"getDiploma\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"level\",\"type\":\"uint64\"}],\"internalType\":\"structFtDiploma.Skill[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkOfRepo\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" // DiplomaBin is the compiled bytecode used for deploying new contracts. -var DiplomaBin = "0x6080604052348015620000125760006000fd5b505b7f88f959f217ca7512aff2b6020e52875bfe620c8115d803d8d6dec6e0fd952ecc737e12234e994384a757e2689addb2a463ccd3b47d604051806060016040528060268152602001620016756026913960405162000074929190620000dc565b60405180910390a15b620001b056620001af565b62000093816200012f565b82525b5050565b6000620000a78262000111565b620000b381856200011d565b9350620000c581856020860162000165565b620000d0816200019d565b84019150505b92915050565b6000604082019050620000f3600083018562000088565b81810360208301526200010781846200009a565b90505b9392505050565b6000815190505b919050565b60008282526020820190505b92915050565b60006200013c8262000144565b90505b919050565b600073ffffffffffffffffffffffffffffffffffffffff821690505b919050565b60005b83811015620001865780820151818401525b60208101905062000168565b8381111562000196576000848401525b505b505050565b6000601f19601f83011690505b919050565b5b6114b580620001c06000396000f3fe60806040523480156100115760006000fd5b50600436106100825760003560e01c80638ebc72c11161005c5780638ebc72c1146100f557806395d89b4114610113578063be55a55614610131578063fbbb6e401461014f57610082565b806306fdde03146100885780632b04cb77146100a65780635679a859146100d757610082565b60006000fd5b61009061016b565b60405161009d9190611105565b60405180910390f35b6100c060048036038101906100bb9190610c0c565b6101a7565b6040516100ce92919061118b565b60405180910390f35b6100df610330565b6040516100ec9190611064565b60405180910390f35b6100fd610348565b60405161010a9190611105565b60405180910390f35b61011b610364565b6040516101289190611105565b60405180910390f35b6101396103a0565b6040516101469190611080565b60405180910390f35b61016960048036038101906101649190610c37565b6106cc565b005b6040518060400160405280600981526020017f343220416c756d6e69000000000000000000000000000000000000000000000081526020015081565b60006101b16109ca565b60006000600050600085600019166000191681526020019081526020016000206000506040518060800160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600050601e806020026040519081016040528092919082601e8015610284576020028201916000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001906008019060208260070104928301926001038202915080841161023f5790505b50505050508152602001600982016000505460001916600019168152602001600a82016000506040518060600160405290816000820160009054906101000a900460ff1660ff1660ff168152602001600182016000505460001916600019168152602001600282016000505460001916600019168152602001505081526020015050905060008160000151905060008260200151905081819450945050505061032b565050505b915091565b737e12234e994384a757e2689addb2a463ccd3b47d81565b60405180606001604052806026815260200161145a6026913981565b6040518060400160405280600381526020017f343241000000000000000000000000000000000000000000000000000000000081526020015081565b6060737e12234e994384a757e2689addb2a463ccd3b47d73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041d9061116a565b60405180910390fd5b600060016000508054905067ffffffffffffffff811115610470577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156104a957816020015b6104966109ed565b81526020019060019003908161048e5790505b5090506000600090505b6001600050805490508110156106be5760006000506000600160005083815481101515610509577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020900160005b5054600019166000191681526020019081526020016000206000506040518060800160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600050601e806020026040519081016040528092919082601e80156105e2576020028201916000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001906008019060208260070104928301926001038202915080841161059d5790505b50505050508152602001600982016000505460001916600019168152602001600a82016000506040518060600160405290816000820160009054906101000a900460ff1660ff1660ff168152602001600182016000505460001916600019168152602001600282016000505460001916600019168152602001505081526020015050828281518110151561069f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b80806106b690611349565b9150506104b3565b50809150506106c956505b90565b737e12234e994384a757e2689addb2a463ccd3b47d73ffffffffffffffffffffffffffffffffffffffff166001828686866040516000815260200160405260405161071a94939291906110bf565b6020604051602081039080840390855afa15801561073d573d600060003e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1614151561079f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079690611128565b60405180910390fd5b600060006000506000836000191660001916815260200190815260200160002060005060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16141515610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081d90611149565b60405180910390fd5b60405180608001604052808767ffffffffffffffff1681526020018681526020018260001916815260200160405180606001604052808760ff16815260200186600019168152602001856000191681526020015081526020015060006000506000836000191660001916815260200190815260200160002060005060008201518160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060208201518160010160005090601e6108ea929190610a32565b5060408201518160090160005090600019169055606082015181600a0160005060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160010160005090600019169055604082015181600201600050906000191690555050905050600160005081908060018154018082558091505060019003906000526020600020900160005b90919091909150906000191690557f0b638557d56f5cb5f2923ac2d36850a0c1c0a1944c628abb24fd73fabeeee600816040516109b991906110a3565b60405180910390a15b505050505050565b604051806103c00160405280601e90602082028036833780820191505090505090565b6040518060800160405280600067ffffffffffffffff168152602001610a116109ca565b81526020016000600019168152602001610a29610ae3565b81526020015090565b82601e9090600301600490048101928215610ad25791602002820160005b83821115610a9c57835183826101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055509260200192600801602081600701049283019260010302610a50565b8015610ad05782816101000a81549067ffffffffffffffff0219169055600801602081600701049283019260010302610a9c565b505b509050610adf9190610b12565b5090565b6040518060600160405280600060ff168152602001600060001916815260200160006000191681526020015090565b610b17565b80821115610b315760008181506000905550600101610b17565b509056611458565b6000610b4c610b47846111e8565b6111b6565b90508082856020860282011115610b635760006000fd5b60005b85811015610b945781610b798882610be0565b8452602084019350602083019250505b600181019050610b66565b5050505b9392505050565b600082601f8301121515610bb35760006000fd5b601e610bc0848285610b39565b9150505b92915050565b600081359050610bd981611407565b5b92915050565b600081359050610bef81611422565b5b92915050565b600081359050610c058161143d565b5b92915050565b600060208284031215610c1f5760006000fd5b6000610c2d84828501610bca565b9150505b92915050565b6000600060006000600060006104608789031215610c555760006000fd5b6000610c6389828a01610be0565b9650506020610c7489828a01610b9f565b9550506103e0610c8689828a01610bf6565b945050610400610c9889828a01610bca565b935050610420610caa89828a01610bca565b925050610440610cbc89828a01610bca565b9150505b9295509295509295565b6000610cd68383610f88565b610460830190505b92915050565b6000610cf08383611024565b6020830190505b92915050565b610d06816112a7565b82525b5050565b6000610d188261122b565b610d22818561126b565b9350610d2d8361120f565b8060005b83811015610d5f578151610d458882610cca565b9750610d508361124f565b9250505b600181019050610d31565b508593505050505b92915050565b610d7681611237565b610d80818461127d565b9250610d8b82611220565b8060005b83811015610dbd578151610da38782610ce4565b9650610dae8361125d565b9250505b600181019050610d8f565b505050505b5050565b610dcf81611237565b610dd98184611289565b9250610de482611220565b8060005b83811015610e16578151610dfc8782610ce4565b9650610e078361125d565b9250505b600181019050610de8565b505050505b5050565b610e28816112ba565b82525b5050565b610e38816112ba565b82525b5050565b6000610e4a82611243565b610e548185611295565b9350610e64818560208601611314565b610e6d816113f5565b84019150505b92915050565b6000610e86602783611295565b91507f46744469706c6f6d613a204973206e6f74203432207369676e2074686973206460008301527f69706c6f6d612e0000000000000000000000000000000000000000000000000060208301526040820190505b919050565b6000610eed602683611295565b91507f46744469706c6f6d613a20546865206469706c6f6d6120616c7265616479206560008301527f78697374732e000000000000000000000000000000000000000000000000000060208301526040820190505b919050565b6000610f54601583611295565b91507f46744469706c6f6d613a204973206e6f742034322e000000000000000000000060008301526020820190505b919050565b61046082016000820151610f9f6000850182611024565b506020820151610fb26020850182610d6d565b506040820151610fc66103e0850182610e1f565b506060820151610fda610400850182610fe1565b50505b5050565b606082016000820151610ff76000850182611044565b50602082015161100a6020850182610e1f565b50604082015161101d6040850182610e1f565b50505b5050565b61102d816112f1565b82525b5050565b61103d816112f1565b82525b5050565b61104d81611306565b82525b5050565b61105d81611306565b82525b5050565b60006020820190506110796000830184610cfd565b5b92915050565b6000602082019050818103600083015261109a8184610d0d565b90505b92915050565b60006020820190506110b86000830184610e2f565b5b92915050565b60006080820190506110d46000830187610e2f565b6110e16020830186611054565b6110ee6040830185610e2f565b6110fb6060830184610e2f565b5b95945050505050565b6000602082019050818103600083015261111f8184610e3f565b90505b92915050565b6000602082019050818103600083015261114181610e79565b90505b919050565b6000602082019050818103600083015261116281610ee0565b90505b919050565b6000602082019050818103600083015261118381610f47565b90505b919050565b60006103e0820190506111a16000830185611034565b6111ae6020830184610dc6565b5b9392505050565b6000604051905081810181811067ffffffffffffffff821117156111dd576111dc6113c4565b5b80604052505b919050565b600067ffffffffffffffff821115611203576112026113c4565b5b6020820290505b919050565b60008190506020820190505b919050565b60008190505b919050565b6000815190505b919050565b6000601e90505b919050565b6000815190505b919050565b60006020820190505b919050565b60006020820190505b919050565b60008282526020820190505b92915050565b60008190505b92915050565b60008190505b92915050565b60008282526020820190505b92915050565b60006112b2826112c5565b90505b919050565b60008190505b919050565b600073ffffffffffffffffffffffffffffffffffffffff821690505b919050565b60008190505b919050565b600067ffffffffffffffff821690505b919050565b600060ff821690505b919050565b60005b838110156113335780820151818401525b602081019050611317565b83811115611342576000848401525b505b505050565b6000611354826112e6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561138757611386611393565b5b6001820190505b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b565b6000601f19601f83011690505b919050565b611410816112ba565b8114151561141e5760006000fd5b5b50565b61142b816112f1565b811415156114395760006000fd5b5b50565b61144681611306565b811415156114545760006000fd5b5b50565bfe6769746875622e636f6d2f34325363686f6f6c2f626c6f636b636861696e2d73657276696365a2646970667358221220a1bcc9eaab056a73365221e4563cac5e7513fdae69d632bd2985c50bf6d8a15164736f6c634300080000336769746875622e636f6d2f34325363686f6f6c2f626c6f636b636861696e2d73657276696365" +var DiplomaBin = "0x6080604052348015620000125760006000fd5b505b7f88f959f217ca7512aff2b6020e52875bfe620c8115d803d8d6dec6e0fd952ecc737e12234e994384a757e2689addb2a463ccd3b47d60405180606001604052806026815260200162001d726026913960405162000074929190620000dc565b60405180910390a15b620001b056620001af565b62000093816200012f565b82525b5050565b6000620000a78262000111565b620000b381856200011d565b9350620000c581856020860162000165565b620000d0816200019d565b84019150505b92915050565b6000604082019050620000f3600083018562000088565b81810360208301526200010781846200009a565b90505b9392505050565b6000815190505b919050565b60008282526020820190505b92915050565b60006200013c8262000144565b90505b919050565b600073ffffffffffffffffffffffffffffffffffffffff821690505b919050565b60005b83811015620001865780820151818401525b60208101905062000168565b8381111562000196576000848401525b505b505050565b6000601f19601f83011690505b919050565b5b611bb280620001c06000396000f3fe60806040523480156100115760006000fd5b50600436106100825760003560e01c80635679a8591161005c5780635679a859146100f35780638ebc72c11461011157806395d89b411461012f578063be55a5561461014d57610082565b806306fdde03146100885780632b04cb77146100a65780633a59ea31146100d757610082565b60006000fd5b61009061016b565b60405161009d91906116b9565b60405180910390f35b6100c060048036038101906100bb91906110c4565b6101a7565b6040516100ce92919061173f565b60405180910390f35b6100f160048036038101906100ec91906110ef565b610405565b005b6100fb610815565b6040516101089190611618565b60405180910390f35b61011961082d565b60405161012691906116b9565b60405180910390f35b610137610849565b60405161014491906116b9565b60405180910390f35b610155610885565b6040516101629190611634565b60405180910390f35b6040518060400160405280600981526020017f343220416c756d6e69000000000000000000000000000000000000000000000081526020015081565b600060606000600060005060008560001916600019168152602001908152602001600020600050905060008160000160009054906101000a900467ffffffffffffffff1690506000601e67ffffffffffffffff811115610230577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561026957816020015b610256610d87565b81526020019060019003908161024e5790505b5090506000600090505b601e8167ffffffffffffffff1610156103ee578360010160005060008267ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000506040518060400160405290816000820160005080546102d3906119ae565b80601f01602080910402602001604051908101604052809291908181526020018280546102ff906119ae565b801561034c5780601f106103215761010080835404028352916020019161034c565b820191906000526020600020905b81548152906001019060200180831161032f57829003601f168201915b505050505081526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020015050828267ffffffffffffffff168151811015156103cf577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101819052505b80806103e690611a2d565b915050610273565b50818194509450505050610400565050505b915091565b737e12234e994384a757e2689addb2a463ccd3b47d73ffffffffffffffffffffffffffffffffffffffff16600182868686604051600081526020016040526040516104539493929190611673565b6020604051602081039080840390855afa158015610476573d600060003e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff161415156104d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104cf906116dc565b60405180910390fd5b600060006000506000836000191660001916815260200190815260200160002060005060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614151561055f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610556906116fd565b60405180910390fd5b60006000600050600083600019166000191681526020019081526020016000206000509050878160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081816002016000508190906000191690555060405180606001604052808660ff1681526020018560001916815260200184600019168152602001508160030160005060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160010160005090600019169055604082015181600201600050906000191690559050506000600090505b601e8167ffffffffffffffff16101561079e576040518060400160405280888367ffffffffffffffff16601e811015156106a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518152602001898367ffffffffffffffff16601e811015156106f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015167ffffffffffffffff168152602001508260010160005060008367ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000506000820151816000016000509080519060200190610757929190610dae565b5060208201518160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055509050505b808061079690611a2d565b915050610642565b50600160005082908060018154018082558091505060019003906000526020600020900160005b90919091909150906000191690557f0b638557d56f5cb5f2923ac2d36850a0c1c0a1944c628abb24fd73fabeeee600826040516108029190611657565b60405180910390a1505b50505050505050565b737e12234e994384a757e2689addb2a463ccd3b47d81565b604051806060016040528060268152602001611b576026913981565b6040518060400160405280600381526020017f343241000000000000000000000000000000000000000000000000000000000081526020015081565b6060737e12234e994384a757e2689addb2a463ccd3b47d73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561090b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109029061171e565b60405180910390fd5b600060016000508054905067ffffffffffffffff811115610955577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561098e57816020015b61097b610e39565b8152602001906001900390816109735790505b5090506000600090505b600160005080549050811015610d79576000600060005060006001600050848154811015156109f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020900160005b50546000191660001916815260200190815260200160002060005090508060000160009054906101000a900467ffffffffffffffff168383815181101515610a6f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101516000019067ffffffffffffffff16908167ffffffffffffffff16815260200150506000600090505b601e8167ffffffffffffffff161015610c5d578160010160005060008267ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600050604051806040016040529081600082016000508054610aff906119ae565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2b906119ae565b8015610b785780601f10610b4d57610100808354040283529160200191610b78565b820191906000526020600020905b815481529060010190602001808311610b5b57829003601f168201915b505050505081526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200150508484815181101515610bf1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151602001518267ffffffffffffffff16601e81101515610c41577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201819052505b8080610c5590611a2d565b915050610a9f565b5080600201600050548383815181101515610ca1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151604001906000191690816000191681526020015050806003016000506040518060600160405290816000820160009054906101000a900460ff1660ff1660ff16815260200160018201600050546000191660001916815260200160028201600050546000191660001916815260200150508383815181101515610d55577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001015160600181905250505b8080610d71906119e3565b915050610998565b5080915050610d8456505b90565b604051806040016040528060608152602001600067ffffffffffffffff1681526020015090565b828054610dba906119ae565b90600052602060002090601f016020900481019282610ddc5760008555610e28565b82601f10610df557805160ff1916838001178555610e28565b82800160010185558215610e28579182015b82811115610e275782518260005090905591602001919060010190610e07565b5b509050610e359190610e7e565b5090565b6040518060800160405280600067ffffffffffffffff168152602001610e5d610ea1565b81526020016000600019168152602001610e75610ecf565b81526020015090565b610e83565b80821115610e9d5760008181506000905550600101610e83565b5090565b604051806103c00160405280601e905b610eb9610d87565b815260200190600190039081610eb15790505090565b6040518060600160405280600060ff16815260200160006000191681526020016000600019168152602001509056611b55565b6000610f15610f10846117a2565b611770565b9050808260005b85811015610f4d5781358501610f32888261106a565b8452602084019350602083019250505b600181019050610f1c565b5050505b9392505050565b6000610f6b610f66846117c9565b611770565b90508082856020860282011115610f825760006000fd5b60005b85811015610fb35781610f988882611098565b8452602084019350602083019250505b600181019050610f85565b5050505b9392505050565b6000610fd1610fcc846117f0565b611770565b905082815260208101848484011115610fea5760006000fd5b610ff5848285611969565b505b9392505050565b600082601f83011215156110125760006000fd5b601e61101f848285610f02565b9150505b92915050565b600082601f830112151561103d5760006000fd5b601e61104a848285610f58565b9150505b92915050565b60008135905061106381611b04565b5b92915050565b600082601f830112151561107e5760006000fd5b813561108e848260208601610fbe565b9150505b92915050565b6000813590506110a781611b1f565b5b92915050565b6000813590506110bd81611b3a565b5b92915050565b6000602082840312156110d75760006000fd5b60006110e584828501611054565b9150505b92915050565b6000600060006000600060006000610480888a03121561110f5760006000fd5b600061111d8a828b01611098565b975050602061112e8a828b01611029565b9650506103e088013567ffffffffffffffff81111561114d5760006000fd5b6111598a828b01610ffe565b95505061040061116b8a828b016110ae565b94505061042061117d8a828b01611054565b93505061044061118f8a828b01611054565b9250506104606111a18a828b01611054565b9150505b92959891949750929550565b60006111bd83836114f3565b90505b92915050565b60006111d2838361159a565b90505b92915050565b6111e4816118fc565b82525b5050565b60006111f68261184e565b61120081856118a8565b93508360208202850161121285611821565b8060005b8581101561124f578484038952815161122f85826111b1565b945061123a8361187e565b925060208a019950505b600181019050611216565b5082975087955050505050505b92915050565b600061126d8261185a565b61127781856118ba565b93508360208202850161128985611832565b8060005b858110156112c657848403895281516112a685826111c6565b94506112b18361188c565b925060208a019950505b60018101905061128d565b5082975087955050505050505b92915050565b60006112e482611866565b6112ee81856118c6565b9350836020820285016113008561183d565b8060005b8581101561133d578484038952815161131d85826111c6565b94506113288361189a565b925060208a019950505b600181019050611304565b5082975087955050505050505b92915050565b6113598161190f565b82525b5050565b6113698161190f565b82525b5050565b600061137b82611872565b61138581856118d8565b9350611395818560208601611979565b61139e81611af2565b84019150505b92915050565b60006113b582611872565b6113bf81856118ea565b93506113cf818560208601611979565b6113d881611af2565b84019150505b92915050565b60006113f16027836118ea565b91507f46744469706c6f6d613a204973206e6f74203432207369676e2074686973206460008301527f69706c6f6d612e0000000000000000000000000000000000000000000000000060208301526040820190505b919050565b60006114586026836118ea565b91507f46744469706c6f6d613a20546865206469706c6f6d6120616c7265616479206560008301527f78697374732e000000000000000000000000000000000000000000000000000060208301526040820190505b919050565b60006114bf6015836118ea565b91507f46744469706c6f6d613a204973206e6f742034322e000000000000000000000060008301526020820190505b919050565b600060c08301600083015161150b60008601826115d8565b50602083015184820360208601526115238282611262565b91505060408301516115386040860182611350565b50606083015161154b6060860182611557565b50809150505b92915050565b60608201600082015161156d60008501826115f8565b5060208201516115806020850182611350565b5060408201516115936040850182611350565b50505b5050565b600060408301600083015184820360008601526115b78282611370565b91505060208301516115cc60208601826115d8565b50809150505b92915050565b6115e181611946565b82525b5050565b6115f181611946565b82525b5050565b6116018161195b565b82525b5050565b6116118161195b565b82525b5050565b600060208201905061162d60008301846111db565b5b92915050565b6000602082019050818103600083015261164e81846111eb565b90505b92915050565b600060208201905061166c6000830184611360565b5b92915050565b60006080820190506116886000830187611360565b6116956020830186611608565b6116a26040830185611360565b6116af6060830184611360565b5b95945050505050565b600060208201905081810360008301526116d381846113aa565b90505b92915050565b600060208201905081810360008301526116f5816113e4565b90505b919050565b600060208201905081810360008301526117168161144b565b90505b919050565b60006020820190508181036000830152611737816114b2565b90505b919050565b600060408201905061175460008301856115e8565b818103602083015261176681846112d9565b90505b9392505050565b6000604051905081810181811067ffffffffffffffff8211171561179757611796611ac1565b5b80604052505b919050565b600067ffffffffffffffff8211156117bd576117bc611ac1565b5b6020820290505b919050565b600067ffffffffffffffff8211156117e4576117e3611ac1565b5b6020820290505b919050565b600067ffffffffffffffff82111561180b5761180a611ac1565b5b601f19601f83011690506020810190505b919050565b60008190506020820190505b919050565b60008190505b919050565b60008190506020820190505b919050565b6000815190505b919050565b6000601e90505b919050565b6000815190505b919050565b6000815190505b919050565b60006020820190505b919050565b60006020820190505b919050565b60006020820190505b919050565b60008282526020820190505b92915050565b60008190505b92915050565b60008282526020820190505b92915050565b60008282526020820190505b92915050565b60008282526020820190505b92915050565b60006119078261191a565b90505b919050565b60008190505b919050565b600073ffffffffffffffffffffffffffffffffffffffff821690505b919050565b60008190505b919050565b600067ffffffffffffffff821690505b919050565b600060ff821690505b919050565b828183376000838301525b505050565b60005b838110156119985780820151818401525b60208101905061197c565b838111156119a7576000848401525b505b505050565b6000600282049050600182168015156119c857607f821691505b602082108114156119dc576119db611a90565b5b505b919050565b60006119ee8261193b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611a2157611a20611a5f565b5b6001820190505b919050565b6000611a3882611946565b915067ffffffffffffffff821415611a5357611a52611a5f565b5b6001820190505b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b565b6000601f19601f83011690505b919050565b611b0d8161190f565b81141515611b1b5760006000fd5b5b50565b611b2881611946565b81141515611b365760006000fd5b5b50565b611b438161195b565b81141515611b515760006000fd5b5b50565bfe6769746875622e636f6d2f34325363686f6f6c2f626c6f636b636861696e2d73657276696365a2646970667358221220e6abbda4ab8f1cf627775ae8abcb70f99d74fdb5171ea8f42eff19c6720afa5264736f6c634300080000336769746875622e636f6d2f34325363686f6f6c2f626c6f636b636861696e2d73657276696365" // DeployDiploma deploys a new Ethereum contract, binding an instance of Diploma to it. func DeployDiploma(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Diploma, error) { @@ -236,16 +242,16 @@ func (_Diploma *DiplomaCallerSession) FtPubAddress() (common.Address, error) { // GetAllDiploma is a free data retrieval call binding the contract method 0xbe55a556. // -// Solidity: function getAllDiploma() view returns((uint64,uint64[30],bytes32,(uint8,bytes32,bytes32))[]) -func (_Diploma *DiplomaCaller) GetAllDiploma(opts *bind.CallOpts) ([]FtDiplomaDiploma, error) { +// Solidity: function getAllDiploma() view returns((uint64,(string,uint64)[30],bytes32,(uint8,bytes32,bytes32))[]) +func (_Diploma *DiplomaCaller) GetAllDiploma(opts *bind.CallOpts) ([]FtDiplomaDiplomas, error) { var out []interface{} err := _Diploma.contract.Call(opts, &out, "getAllDiploma") if err != nil { - return *new([]FtDiplomaDiploma), err + return *new([]FtDiplomaDiplomas), err } - out0 := *abi.ConvertType(out[0], new([]FtDiplomaDiploma)).(*[]FtDiplomaDiploma) + out0 := *abi.ConvertType(out[0], new([]FtDiplomaDiplomas)).(*[]FtDiplomaDiplomas) return out0, err @@ -253,57 +259,47 @@ func (_Diploma *DiplomaCaller) GetAllDiploma(opts *bind.CallOpts) ([]FtDiplomaDi // GetAllDiploma is a free data retrieval call binding the contract method 0xbe55a556. // -// Solidity: function getAllDiploma() view returns((uint64,uint64[30],bytes32,(uint8,bytes32,bytes32))[]) -func (_Diploma *DiplomaSession) GetAllDiploma() ([]FtDiplomaDiploma, error) { +// Solidity: function getAllDiploma() view returns((uint64,(string,uint64)[30],bytes32,(uint8,bytes32,bytes32))[]) +func (_Diploma *DiplomaSession) GetAllDiploma() ([]FtDiplomaDiplomas, error) { return _Diploma.Contract.GetAllDiploma(&_Diploma.CallOpts) } // GetAllDiploma is a free data retrieval call binding the contract method 0xbe55a556. // -// Solidity: function getAllDiploma() view returns((uint64,uint64[30],bytes32,(uint8,bytes32,bytes32))[]) -func (_Diploma *DiplomaCallerSession) GetAllDiploma() ([]FtDiplomaDiploma, error) { +// Solidity: function getAllDiploma() view returns((uint64,(string,uint64)[30],bytes32,(uint8,bytes32,bytes32))[]) +func (_Diploma *DiplomaCallerSession) GetAllDiploma() ([]FtDiplomaDiplomas, error) { return _Diploma.Contract.GetAllDiploma(&_Diploma.CallOpts) } // GetDiploma is a free data retrieval call binding the contract method 0x2b04cb77. // -// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64 level, uint64[30] skills) -func (_Diploma *DiplomaCaller) GetDiploma(opts *bind.CallOpts, _studentHash [32]byte) (struct { - Level uint64 - Skills [30]uint64 -}, error) { +// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64, (string,uint64)[]) +func (_Diploma *DiplomaCaller) GetDiploma(opts *bind.CallOpts, _studentHash [32]byte) (uint64, []FtDiplomaSkill, error) { var out []interface{} err := _Diploma.contract.Call(opts, &out, "getDiploma", _studentHash) - outstruct := new(struct { - Level uint64 - Skills [30]uint64 - }) + if err != nil { + return *new(uint64), *new([]FtDiplomaSkill), err + } - outstruct.Level = out[0].(uint64) - outstruct.Skills = out[1].([30]uint64) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + out1 := *abi.ConvertType(out[1], new([]FtDiplomaSkill)).(*[]FtDiplomaSkill) - return *outstruct, err + return out0, out1, err } // GetDiploma is a free data retrieval call binding the contract method 0x2b04cb77. // -// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64 level, uint64[30] skills) -func (_Diploma *DiplomaSession) GetDiploma(_studentHash [32]byte) (struct { - Level uint64 - Skills [30]uint64 -}, error) { +// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64, (string,uint64)[]) +func (_Diploma *DiplomaSession) GetDiploma(_studentHash [32]byte) (uint64, []FtDiplomaSkill, error) { return _Diploma.Contract.GetDiploma(&_Diploma.CallOpts, _studentHash) } // GetDiploma is a free data retrieval call binding the contract method 0x2b04cb77. // -// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64 level, uint64[30] skills) -func (_Diploma *DiplomaCallerSession) GetDiploma(_studentHash [32]byte) (struct { - Level uint64 - Skills [30]uint64 -}, error) { +// Solidity: function getDiploma(bytes32 _studentHash) view returns(uint64, (string,uint64)[]) +func (_Diploma *DiplomaCallerSession) GetDiploma(_studentHash [32]byte) (uint64, []FtDiplomaSkill, error) { return _Diploma.Contract.GetDiploma(&_Diploma.CallOpts, _studentHash) } @@ -400,25 +396,25 @@ func (_Diploma *DiplomaCallerSession) Symbol() (string, error) { return _Diploma.Contract.Symbol(&_Diploma.CallOpts) } -// CreateDiploma is a paid mutator transaction binding the contract method 0xfbbb6e40. +// CreateDiploma is a paid mutator transaction binding the contract method 0x3a59ea31. // -// Solidity: function createDiploma(uint64 _level, uint64[30] _skills, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() -func (_Diploma *DiplomaTransactor) CreateDiploma(opts *bind.TransactOpts, _level uint64, _skills [30]uint64, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { - return _Diploma.contract.Transact(opts, "createDiploma", _level, _skills, _v, _r, _s, _studentHash) +// Solidity: function createDiploma(uint64 _level, uint64[30] _skillLevel, string[30] _skillSlug, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() +func (_Diploma *DiplomaTransactor) CreateDiploma(opts *bind.TransactOpts, _level uint64, _skillLevel [30]uint64, _skillSlug [30]string, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { + return _Diploma.contract.Transact(opts, "createDiploma", _level, _skillLevel, _skillSlug, _v, _r, _s, _studentHash) } -// CreateDiploma is a paid mutator transaction binding the contract method 0xfbbb6e40. +// CreateDiploma is a paid mutator transaction binding the contract method 0x3a59ea31. // -// Solidity: function createDiploma(uint64 _level, uint64[30] _skills, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() -func (_Diploma *DiplomaSession) CreateDiploma(_level uint64, _skills [30]uint64, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { - return _Diploma.Contract.CreateDiploma(&_Diploma.TransactOpts, _level, _skills, _v, _r, _s, _studentHash) +// Solidity: function createDiploma(uint64 _level, uint64[30] _skillLevel, string[30] _skillSlug, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() +func (_Diploma *DiplomaSession) CreateDiploma(_level uint64, _skillLevel [30]uint64, _skillSlug [30]string, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { + return _Diploma.Contract.CreateDiploma(&_Diploma.TransactOpts, _level, _skillLevel, _skillSlug, _v, _r, _s, _studentHash) } -// CreateDiploma is a paid mutator transaction binding the contract method 0xfbbb6e40. +// CreateDiploma is a paid mutator transaction binding the contract method 0x3a59ea31. // -// Solidity: function createDiploma(uint64 _level, uint64[30] _skills, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() -func (_Diploma *DiplomaTransactorSession) CreateDiploma(_level uint64, _skills [30]uint64, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { - return _Diploma.Contract.CreateDiploma(&_Diploma.TransactOpts, _level, _skills, _v, _r, _s, _studentHash) +// Solidity: function createDiploma(uint64 _level, uint64[30] _skillLevel, string[30] _skillSlug, uint8 _v, bytes32 _r, bytes32 _s, bytes32 _studentHash) returns() +func (_Diploma *DiplomaTransactorSession) CreateDiploma(_level uint64, _skillLevel [30]uint64, _skillSlug [30]string, _v uint8, _r [32]byte, _s [32]byte, _studentHash [32]byte) (*types.Transaction, error) { + return _Diploma.Contract.CreateDiploma(&_Diploma.TransactOpts, _level, _skillLevel, _skillSlug, _v, _r, _s, _studentHash) } // DiplomaCreateDiplomaIterator is returned from FilterCreateDiploma and is used to iterate over the raw logs and unpacked data for CreateDiploma events raised by the Diploma contract. diff --git a/src/dao/contracts/interfaceContract.go b/src/dao/contracts/interfaceContract.go index d04c9e2..ac8dd2c 100644 --- a/src/dao/contracts/interfaceContract.go +++ b/src/dao/contracts/interfaceContract.go @@ -12,12 +12,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "log" + log "github.com/sirupsen/logrus" "strings" "math/big" ) +// connectEthGetInstance connect the client Ethereum and get the instance of the smart-contract. func connectEthGetInstance() (*Diploma, *ethclient.Client, error) { client, err := ethclient.Dial(tools.NetworkLink) if err != nil { @@ -32,26 +33,40 @@ func connectEthGetInstance() (*Diploma, *ethclient.Client, error) { } func getAuth() (*bind.TransactOpts, error) { + //ethclient.NewClient(rpc.Dial(rpc.DialIPC())) client, err := ethclient.Dial(tools.NetworkLink) if err != nil { + log.Debug("Dial") return nil, err } address, privateKey, err := account.GetWriterAccount() if err != nil { + log.Debug("GetWriterAccount") + return nil, err + } + chainID, err := client.ChainID(context.Background()) + if err != nil { + log.Debug("ChainID") return nil, err } nonce, err := client.PendingNonceAt(context.Background(), address) - if err != nil { + if err != nil { + log.Debug("PendingNonceAt") return nil, err } gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { + log.Debug("SuggestGasPrice") + return nil, err + } + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + if err != nil { + log.Debug("NewKeyedTransactorWithChainID") return nil, err } - auth := bind.NewKeyedTransactor(privateKey) auth.Nonce = big.NewInt(int64(nonce)) auth.Value = big.NewInt(0) - auth.GasLimit = uint64(604758) + auth.GasLimit = uint64(2424242) auth.GasPrice = gasPrice return auth, nil } @@ -71,6 +86,18 @@ func getLogs(client *ethclient.Client) ([]types.Log, abi.ABI, error) { return logs, contractAbi, nil } +func GetBalance(address common.Address) (int64, error) { + client, err := ethclient.Dial(tools.NetworkLink) + if err != nil { + return 0, err + } + balance, err := client.PendingBalanceAt(context.Background(), address) + if err != nil { + return 0, err + } + return balance.Int64(), err +} + func GetRevert(client *ethclient.Client, tx *types.Transaction, receipt *types.Receipt) string { address, _, _ := account.GetWriterAccount() msg := ethereum.CallMsg{ @@ -87,8 +114,8 @@ func GetRevert(client *ethclient.Client, tx *types.Transaction, receipt *types.R return "" } var ( - errorSig = []byte{0x08, 0xc3, 0x79, 0xa0} - abiString, _ = abi.NewType("string", "", nil) + errorSig = []byte{0x08, 0xc3, 0x79, 0xa0} + abiString, _ = abi.NewType("string", "", nil) ) if len(res) < 4 || !bytes.Equal(res[:4], errorSig) { tools.LogsError(err) @@ -118,9 +145,7 @@ func CheckSecurity(client *ethclient.Client, tx *types.Transaction, hash []byte) return true } if common.Bytes2Hex(hash[:]) != common.Bytes2Hex(eventHash[:]) { - tools.LogsMsg("Error: The hash writing in blockchain is not the same of this student !") - tools.SendMail("Security Alert", "") - tools.SecuritySystem = true + log.Panic("Error: The hash writing in blockchain is not the same of this student !") return false } } @@ -128,47 +153,50 @@ func CheckSecurity(client *ethclient.Client, tx *types.Transaction, hash []byte) return true } -func CallCreateDiploma(level uint64, skills [30]uint64, v uint8, r [32]byte, s [32]byte, hash [32]byte) (*types.Transaction, bool) { +func CallCreateDiploma(level uint64, skills [30]uint64, skillsSlugs [30]string, v uint8, r [32]byte, s [32]byte, hash [32]byte) (*types.Transaction, bool) { instance, _, err := connectEthGetInstance() if err != nil { + log.Debug("Instance") tools.LogsError(err) return nil, false } auth, err := getAuth() if err != nil { + log.Debug("Auth") tools.LogsError(err) return nil, false } - tx, err := instance.CreateDiploma(auth, level, skills, v, r, s, hash) + tx, err := instance.CreateDiploma(auth, level, skills, skillsSlugs, v, r, s, hash) if err != nil { + log.Debug("Write") tools.LogsError(err) if strings.Contains(err.Error(), "insufficient funds for gas * price + value") { account.ChangeAccount() } return nil, false } - tools.LogsDev("Transation Hash: " + tx.Hash().Hex()) + log.WithFields(log.Fields{"tx_hash": tx.Hash().Hex()}).Debug("Transaction Hash") return tx, true } -func CallGetDiploma(hash []byte) (uint64, [30]uint64, error) { +func CallGetDiploma(hash []byte) (uint64, []FtDiplomaSkill, error) { instance, _, err := connectEthGetInstance() if err != nil { - return 0, [30]uint64{}, err + return 0, []FtDiplomaSkill{}, err } hash32 := [32]byte{} copy(hash32[:], hash) - result, err := instance.GetDiploma(&bind.CallOpts{}, hash32) + level, skills, err := instance.GetDiploma(&bind.CallOpts{}, hash32) if err != nil { - return 0, [30]uint64{}, err + return 0, []FtDiplomaSkill{}, err } - if result.Level == 0 { - return 0, [30]uint64{}, fmt.Errorf("the diploma doesnt exist") + if level == 0 { + return 0, []FtDiplomaSkill{}, fmt.Errorf("the diploma doesnt exist") } - return result.Level, result.Skills, nil + return level, skills, nil } -func CallGetAllDiploma() ([]FtDiplomaDiploma, error) { +func CallGetAllDiploma() ([]FtDiplomaDiplomas, error) { instance, _, err := connectEthGetInstance() if err != nil { return nil, err @@ -179,4 +207,4 @@ func CallGetAllDiploma() ([]FtDiplomaDiploma, error) { } log.Print(result) return result, nil -} \ No newline at end of file +} diff --git a/src/dao/diplomas/blockchainFunctions.go b/src/dao/diplomas/blockchainFunctions.go new file mode 100644 index 0000000..7ae84ae --- /dev/null +++ b/src/dao/diplomas/blockchainFunctions.go @@ -0,0 +1,83 @@ +package diplomas + +import ( + "github.com/42School/blockchain-service/src/account" + "github.com/42School/blockchain-service/src/dao/contracts" + "github.com/42School/blockchain-service/src/metrics" + "github.com/42School/blockchain-service/src/tools" + "github.com/ethereum/go-ethereum/common" + crypgo "github.com/ethereum/go-ethereum/crypto" + log "github.com/sirupsen/logrus" + "time" +) + +func (_dp Diploma) convertDpToData(_sign []byte, _hash common.Hash) (uint64, [30]uint64, [30]string, uint8, [32]byte, [32]byte, [32]byte) { + level := uint64(_dp.Level * 100) + skillsLevels := [30]uint64{} + skillsSlugs := [30]string{} + for i := 0; i < 30; i++ { + if i > len(_dp.Skills)-1 { + skillsLevels[i] = uint64(0) + skillsSlugs[i] = "" + } else { + skillsLevels[i] = uint64(_dp.Skills[i].Level * 100) + skillsSlugs[i] = _dp.Skills[i].Name + } + } + v := uint8(int(_sign[64])) + 27 + r := [32]byte{} + s := [32]byte{} + hash := [32]byte{} + copy(r[:], _sign[:32]) + copy(s[:], _sign[32:64]) + copy(hash[:], _hash.Bytes()) + return level, skillsLevels, skillsSlugs, v, r, s, hash +} + +func (_dp Diploma) EthWriting() (string, bool) { + dataToHash := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate + newHash := crypgo.Keccak256Hash([]byte(dataToHash)) + sign, err := account.KeyStore.SignHashWithPassphrase(account.GetSignAccount(), tools.PasswordAccount, newHash.Bytes()) + log.WithFields(log.Fields{"hash": newHash.String(), "sign": common.Bytes2Hex(sign)}).Debug("The hash & signature of the diploma") + if err != nil { + tools.LogsError(err) + return "", false + } + tx, success := contracts.CallCreateDiploma(_dp.convertDpToData(sign, newHash)) + if success == false { + _dp.AddToRetry() + return "", false + } + metrics.NumberOfRetryDiploma.Observe(float64(_dp.Counter)) + metrics.NumberOfRetryPerDiploma.WithLabelValues(_dp.String()).Add(float64(_dp.Counter)) + log.WithFields(log.Fields{"hash": newHash.String(), "tx": tx.Hash().String()}).Info("Diploma submit in transaction.") + addToCheck(VerificationHash{Tx: tx, StudentHash: newHash.Bytes(), SendTime: time.Now()}) + return newHash.Hex(), true +} + +func (_dp Diploma) EthGetter() (float64, [30]Skill, error) { + dataToHash := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate + hash := crypgo.Keccak256Hash([]byte(dataToHash)) + levelInt, skillsEth, err := contracts.CallGetDiploma(hash.Bytes()) + if err != nil { + tools.LogsError(err) + return 0, [30]Skill{}, err + } + level := float64(levelInt) / 100 + skills := [30]Skill{} + for i := 0; i < 30; i++ { + skills[i].Level = float64(skillsEth[i].Level) / 100 + skills[i].Name = skillsEth[i].Name + } + log.Print(level, skills) + return level, skills, nil +} + +func EthAllGetter() []contracts.FtDiplomaDiplomas { + diplomas, err := contracts.CallGetAllDiploma() + if err != nil { + tools.LogsError(err) + return nil + } + return diplomas +} diff --git a/src/dao/diplomas/diploma.go b/src/dao/diplomas/diploma.go deleted file mode 100644 index 582973e..0000000 --- a/src/dao/diplomas/diploma.go +++ /dev/null @@ -1,175 +0,0 @@ -package diplomas - -import ( - "context" - account "github.com/42School/blockchain-service/src/account" - "github.com/42School/blockchain-service/src/dao/contracts" - "github.com/42School/blockchain-service/src/tools" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - crypgo "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" - "go.mongodb.org/mongo-driver/bson" - "log" -) - -type Diploma struct { - Id uuid.UUID `bson:"_id"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - BirthDate string `json:"birth_date"` - AlumniDate string `json:"alumni_date"` - Level float64 `json:"level"` - Skills []float64 `json:"skills"` -} - -type VerificationHash struct { - Id uuid.UUID `bson:"_id"` - Tx *types.Transaction - StudentHash []byte -} - -func convertSkillToInt(skills []float64) [30]uint64 { - newSkills := [30]uint64{} - for i := 0; i < 30; i++ { - if i > len(skills) - 1 { - newSkills[i] = uint64(0) - } else { - newSkills[i] = uint64(skills[i] * 100) - } - } - return newSkills -} - -func convertSkillToFloat(skills [30]uint64) [30]float64 { - newSkills := [30]float64{} - for i := 0; i < 30; i++ { - if i > len(skills) - 1 { - newSkills[i] = float64(0) - } else { - newSkills[i] = float64(skills[i]) / 100 - } - } - return newSkills -} - -func addToCheck(toAdd VerificationHash) { - var checkDB VerificationHash - result := tools.ToCheckDB.FindOne(context.TODO(), bson.M{"studenthash": toAdd.StudentHash}) - err := result.Decode(&checkDB) - if hexutil.Encode(checkDB.StudentHash) == hexutil.Encode(toAdd.StudentHash) || err == nil { - tools.LogsDev("Verification Hash already in DB Queue: " + hexutil.Encode(toAdd.StudentHash)) - return - } - tools.ToCheckHash.PushBack(toAdd) - txJson, _ := toAdd.Tx.MarshalJSON() - tools.ToCheckDB.InsertOne(context.Background(), bson.M{"tx": txJson, "studenthash": toAdd.StudentHash}) -} - -func (_dp Diploma) CheckDiploma() bool { - if _dp.FirstName == "" || _dp.LastName == "" || _dp.Level <= 6 || _dp.AlumniDate == "" || _dp.BirthDate == "" { - return false - } - for i := 0; i < len(_dp.Skills); i++ { - if _dp.Skills[i] <= 0.0 { - return false - } - } - return true -} - -func (_dp Diploma) PrintDiploma() { - log.Println("First Name:", _dp.FirstName) - log.Println("Last Name:", _dp.LastName) - log.Println("Birth Date:", _dp.BirthDate) - log.Println("Alumni Date:", _dp.AlumniDate) - log.Println("Level:", _dp.Level) - log.Println("Skills:", _dp.Skills) -} - -func (_dp Diploma) String() string { - str := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate - return str -} - -func (_dp Diploma) AddToRetry() { - copyList := tools.RetryQueue - for e := copyList.Front(); e != nil; e = e.Next() { - if e != nil { - diploma, _ := e.Value.(Diploma) - tools.LogsDev("Diploma in list: " + diploma.String()) - tools.LogsDev("Diploma to find: " + _dp.String()) - if diploma.String() == _dp.String() { - tools.LogsDev("Match diploma in list & to find") - return - } - } - } - var DpDB Diploma - result := tools.RetryDB.FindOne(context.TODO(), bson.M{"firstname": _dp.FirstName, "lastname": _dp.LastName, "birthdate": _dp.BirthDate, "alumnidate": _dp.AlumniDate}) - err := result.Decode(&DpDB) - if DpDB.String() == _dp.String() || err == nil { - tools.LogsDev("Diploma already in DB Queue: " + _dp.String()) - return - } - tools.LogsDev("Adding diploma in Queue: " + _dp.String()) - _dp.Id = uuid.New() - tools.RetryDB.InsertOne(context.TODO(), _dp) - tools.RetryQueue.PushBack(_dp) -} - -func (_dp Diploma) convertDpToData(_sign []byte, _hash common.Hash) (uint64, [30]uint64, uint8, [32]byte, [32]byte, [32]byte) { - level := uint64(_dp.Level * 100) - skills := convertSkillToInt(_dp.Skills) - v := uint8(int(_sign[64])) + 27 - r := [32]byte{} - s := [32]byte{} - hash := [32]byte{} - copy(r[:], _sign[:32]) - copy(s[:], _sign[32:64]) - copy(hash[:], _hash.Bytes()) - return level, skills, v, r, s, hash -} - -func (_dp Diploma) EthWriting() (string, bool) { - dataToHash := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate - newHash := crypgo.Keccak256Hash([]byte(dataToHash)) - sign, err := account.KeyStore.SignHashWithPassphrase(account.GetSignAccount(), tools.PasswordAccount, newHash.Bytes()) - tools.LogsDev("The hash of the diploma is " + newHash.String()) - tools.LogsDev("The signature on the diploma is " + common.Bytes2Hex(sign)) - if err != nil { - tools.LogsError(err) - return "", false - } - tx, success := contracts.CallCreateDiploma(_dp.convertDpToData(sign, newHash)) - if success == false { - _dp.AddToRetry() - return "", false - } - addToCheck(VerificationHash{Tx: tx, StudentHash: newHash.Bytes()}) - return newHash.Hex(), true -} - -func (_dp Diploma) EthGetter() (float64, [30]float64, error) { - dataToHash := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate - hash := crypgo.Keccak256Hash([]byte(dataToHash)) - levelInt, skillsInt, err := contracts.CallGetDiploma(hash.Bytes()) - if err != nil { - tools.LogsError(err) - return 0, [30]float64{}, err - } - level := float64(levelInt) / 100 - skills := convertSkillToFloat(skillsInt) - log.Print(levelInt, skillsInt) - return level, skills, nil -} - -func EthAllGetter() []contracts.FtDiplomaDiploma { - diplomas, err := contracts.CallGetAllDiploma() - if err != nil { - tools.LogsError(err) - return nil - } - return diplomas -} \ No newline at end of file diff --git a/src/dao/diplomas/othersFunctions.go b/src/dao/diplomas/othersFunctions.go new file mode 100644 index 0000000..0daba90 --- /dev/null +++ b/src/dao/diplomas/othersFunctions.go @@ -0,0 +1,78 @@ +package diplomas + +import ( + "context" + "github.com/42School/blockchain-service/src/metrics" + "github.com/42School/blockchain-service/src/tools" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" + "go.mongodb.org/mongo-driver/bson" +) + +func (_dp Diploma) CheckDiploma() bool { + if _dp.FirstName == "" || _dp.LastName == "" || _dp.Level <= 6 || _dp.AlumniDate == "" || _dp.BirthDate == "" || len(_dp.Skills) == 0 { + return false + } + for i := 0; i < len(_dp.Skills); i++ { + if _dp.Skills[i].Level <= 0.0 { + return false + } + } + return true +} + +func (_dp Diploma) String() string { + str := _dp.FirstName + ", " + _dp.LastName + ", " + _dp.BirthDate + ", " + _dp.AlumniDate + return str +} + +func (_dp Diploma) LogFields() log.Fields { + return log.Fields{"first_name": _dp.FirstName, "last_name": _dp.LastName, "birth_date": _dp.BirthDate, "alumni_date": _dp.AlumniDate} +} + +func addToCheck(toAdd VerificationHash) { + var checkDB VerificationHash + result := tools.ToCheckDB.FindOne(context.TODO(), bson.M{"studenthash": toAdd.StudentHash}) + err := result.Decode(&checkDB) + if hexutil.Encode(checkDB.StudentHash) == hexutil.Encode(toAdd.StudentHash) || err == nil { + log.WithFields(log.Fields{"hash": hexutil.Encode(toAdd.StudentHash)}).Debug("The verification hash already exist in the CheckDB") + return + } + tools.ToCheckHash.PushBack(toAdd) + txJson, _ := toAdd.Tx.MarshalJSON() + metrics.GaugeCheckQueue.Inc() + metrics.CounterCheckQueue.Inc() + tools.ToCheckDB.InsertOne(context.Background(), bson.M{"tx": txJson, "studenthash": toAdd.StudentHash, "time": toAdd.SendTime}) +} + +func (_dp Diploma) AddToRetry() { + copyList := tools.RetryQueue + for e := copyList.Front(); e != nil; e = e.Next() { + if e != nil { + diploma, _ := e.Value.(Diploma) + log.WithFields(diploma.LogFields()).Debug("Diploma in the retry queue") + log.WithFields(_dp.LogFields()).Debug("Diploma to find in the retry queue") + if diploma.String() == _dp.String() { + log.Debug("Matching diploma in the queue & to find") + return + } + } + } + var DpDB Diploma + result := tools.RetryDB.FindOne(context.TODO(), bson.M{"firstname": _dp.FirstName, "lastname": _dp.LastName, "birthdate": _dp.BirthDate, "alumnidate": _dp.AlumniDate}) + err := result.Decode(&DpDB) + if DpDB.String() == _dp.String() || err == nil { + log.WithFields(_dp.LogFields()).Debug("Diploma already exist in Retry DB Queue") + return + } + _dp.Id = uuid.New() + if _dp.Counter == 0 { + _dp.Counter = 1 + } + tools.RetryDB.InsertOne(context.TODO(), _dp) + tools.RetryQueue.PushBack(_dp) + metrics.GaugeRetryQueue.Inc() + metrics.CounterRetryQueue.Inc() + log.WithFields(_dp.LogFields()).Debug("Adding diploma in the retry queue & retry db") +} diff --git a/src/dao/diplomas/othersFunctions_test.go b/src/dao/diplomas/othersFunctions_test.go new file mode 100644 index 0000000..502f319 --- /dev/null +++ b/src/dao/diplomas/othersFunctions_test.go @@ -0,0 +1,71 @@ +package diplomas + +import ( + "github.com/google/uuid" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "testing" +) + +var diploma = Diploma{uuid.UUID{0}, "Louise", "Pieri", "27-12-1998", "01-01-2021", 21.42, + []Skill{{"Security", 16.42}, + {"Unix", 13.87}, + {"Adaptation & creativity", 12.7}, + {"Company experience", 11.22}, + {"Algorithms & AI", 10.38}, + {"Group & interpersonal", 10.13}, + {"Graphics", 7.49}, + {"Rigor", 6.6}, + {"Imperative programming", 5.34}, + {"Technology integration", 5.26}, + {"Web", 5.2}, + {"Organization", 5.04}, + {"Network & system administration", 4.5}, + {"DB & Data", 4.28}, + {"Object-oriented programming", 4.2}}, +0} + +func TestDiploma_String(t *testing.T) { + a := assert.New(t) + str := "Louise, Pieri, 27-12-1998, 01-01-2021" + a.Equal(str, diploma.String(), "Function Diploma.String are not valid.") +} + +func TestDiploma_CheckDiploma(t *testing.T) { + a := assert.New(t) + // Check a 100% valid diploma + a.Equal(true, diploma.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with valid diploma.") + // Check a invalid diploma (first_name = "") + diplomaNotValid := diploma + diplomaNotValid.FirstName = "" + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (first_name = '').") + // Check a invalid diploma (last_name = "") + diplomaNotValid.FirstName = diploma.FirstName + diplomaNotValid.LastName = "" + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (last_name = '').") + // Check a invalid diploma (birth_date = "") + diplomaNotValid.LastName = diploma.LastName + diplomaNotValid.BirthDate = "" + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (birth_date = '').") + // Check a invalid diploma (alumni_date = "") + diplomaNotValid.BirthDate = diploma.BirthDate + diplomaNotValid.AlumniDate = "" + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (alumni_date = '').") + // Check a invalid diploma (level = 0.0) + diplomaNotValid.AlumniDate = diploma.AlumniDate + diplomaNotValid.Level = 0.0 + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (level = 0.0).") + // Check a invalid diploma (no skills) + diplomaNotValid.Level = diploma.Level + diplomaNotValid.Skills = []Skill{} + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (no skills).") + // Check a invalid diploma ([1]skills{level = 0.0}) + diplomaNotValid.Skills = []Skill{{"Web", 0.0}} + a.Equal(false, diplomaNotValid.CheckDiploma(), "Function Diploma.CheckDiploma are not valid with not valid diploma (no skills).") +} + +func TestDiploma_LogFields(t *testing.T) { + a := assert.New(t) + field := log.Fields{"first_name": "Louise", "last_name": "Pieri", "birth_date": "27-12-1998", "alumni_date": "01-01-2021"} + a.Equal(field, diploma.LogFields(), "Function Diploma.LogFields are not valid.") +} diff --git a/src/dao/diplomas/struct.go b/src/dao/diplomas/struct.go new file mode 100644 index 0000000..67ee7a5 --- /dev/null +++ b/src/dao/diplomas/struct.go @@ -0,0 +1,30 @@ +package diplomas + +import ( + "github.com/ethereum/go-ethereum/core/types" + "github.com/google/uuid" + "time" +) + +type Skill struct { + Name string `json:"name"` + Level float64 `json:"level"` +} + +type Diploma struct { + Id uuid.UUID `bson:"_id"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + BirthDate string `json:"birth_date"` + AlumniDate string `json:"alumni_date"` + Level float64 `json:"level"` + Skills []Skill `json:"skills"` + Counter int `json:"counter"` +} + +type VerificationHash struct { + Id uuid.UUID `bson:"_id"` + Tx *types.Transaction + StudentHash []byte + SendTime time.Time +} diff --git a/src/metrics/functions.go b/src/metrics/functions.go new file mode 100644 index 0000000..647fed3 --- /dev/null +++ b/src/metrics/functions.go @@ -0,0 +1,76 @@ +package metrics + +import ( + "context" + "github.com/42School/blockchain-service/src/account" + "github.com/42School/blockchain-service/src/dao/contracts" + "github.com/42School/blockchain-service/src/tools" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/gorilla/mux" + "github.com/prometheus/client_golang/prometheus" + log "github.com/sirupsen/logrus" + "io/ioutil" + "net/http" + "strconv" + "time" +) + +func NewResponseWriter(w http.ResponseWriter) *responseWriter { + return &responseWriter{w, http.StatusOK} +} + +func (rw *responseWriter) WriteHeader(code int) { + rw.statusCode = code + rw.ResponseWriter.WriteHeader(code) +} + +func PrometheusMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + route := mux.CurrentRoute(r) + path, _ := route.GetPathTemplate() + rw := NewResponseWriter(w) + next.ServeHTTP(rw, r) + timer := prometheus.NewTimer(httpDuration.WithLabelValues(path, r.Method, strconv.Itoa(rw.statusCode))) + timer.ObserveDuration() + }) +} + +func prometheusGaugeWallets() { + for { + for i := 0; i < len(account.Accounts); i++ { + keyjson, err := ioutil.ReadFile(tools.PathKeyStore + "/" + account.Accounts[i].KeyStoreFile) + if err != nil { + log.WithFields(log.Fields{"error": err}).Error("Metrics Records failed - prometheusGaugeWallets.ReadFile (keystore)") + continue + } + key, err := keystore.DecryptKey(keyjson, account.Accounts[i].Password) + if err != nil { + log.WithFields(log.Fields{"error": err}).Error("Metrics Records failed - prometheusGaugeWallets.DecryptKey") + continue + } + balance, err := contracts.GetBalance(key.Address) + if err != nil { + log.WithFields(log.Fields{"address": key.Address.String(), "error": err}).Error("Metrics Records failed - prometheusGaugeWallets.getBalance") + continue + } + GaugeBalanceWallet.WithLabelValues(key.Address.String()).Set(float64(balance)) + } + time.Sleep(10 * time.Minute) + } +} + +func PrometheusBlockDuration(blockHash common.Hash, txSendTime time.Time) { + client, _ := ethclient.Dial(tools.NetworkLink) + block, err := client.BlockByHash(context.TODO(), blockHash) + if err != nil { + return + } + metricsTime := block.ReceivedAt.Minute() - txSendTime.Minute() + validationBlockDuration.Observe(float64(metricsTime)) +} + +func RecordMetrics() { + go prometheusGaugeWallets() +} diff --git a/src/metrics/vars.go b/src/metrics/vars.go new file mode 100644 index 0000000..f7cebdd --- /dev/null +++ b/src/metrics/vars.go @@ -0,0 +1,86 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "net/http" +) + +type responseWriter struct { + http.ResponseWriter + statusCode int +} + +var ( + /* + *** Metrics for middleware + */ + httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: "blockchain_service", + Name: "http_duration_seconds", + Help: "Duration of HTTP requests.", + Buckets: prometheus.ExponentialBuckets(1, 2, 10), + }, []string{"url", "methods", "code"}) + + validationBlockDuration = promauto.NewHistogram(prometheus.HistogramOpts{ + Namespace: "blockchain_service", + Name: "block_eth_duration_validation_minutes", + Help: "Duration of the validation block Ethereum (in minutes).", + Buckets: prometheus.ExponentialBuckets(1, 2, 7), + }) + + NumberOfRetryDiploma = promauto.NewHistogram(prometheus.HistogramOpts{ + Namespace: "blockchain_service", + Name: "number_of_retry_diploma", + Help: "Histogram with number of retry diploma.", + Buckets: prometheus.LinearBuckets(0, 1, 10), + }) + + /* + *** Gauge metrics + */ + GaugeBalanceWallet = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: "blockchain_service", + Name: "gauge_balance_of_wallet", + Help: "The level of each wallets", + }, []string{"address"}) + + GaugeRetryQueue = promauto.NewGauge(prometheus.GaugeOpts{ + Namespace: "blockchain_service", + Name: "gauge_of_retry_queue", + Help: "The level of the retry queue.", + }) + + GaugeCheckQueue = promauto.NewGauge(prometheus.GaugeOpts{ + Namespace: "blockchain_service", + Name: "gauge_of_check_queue", + Help: "The level of the check queue.", + }) + + /* + *** Counter metrics + */ + CounterDiplomaSuccess = promauto.NewCounter(prometheus.CounterOpts{ + Namespace: "blockchain_service", + Name: "number_of_diploma_success", + Help: "The total number of diploma completely written on Ethereum.", + }) + + CounterRetryQueue = promauto.NewCounter(prometheus.CounterOpts{ + Namespace: "blockchain_service", + Name: "number_of_diploma_in_retry_queue", + Help: "The total number of diploma in the retry queue.", + }) + + CounterCheckQueue = promauto.NewCounter(prometheus.CounterOpts{ + Namespace: "blockchain_service", + Name: "number_of_diploma_in_check_queue", + Help: "The total number of diploma in the check queue.", + }) + + NumberOfRetryPerDiploma = promauto.NewCounterVec(prometheus.CounterOpts{ + Namespace: "blockchain_service", + Name: "number_of_retry_per_diploma", + Help: "Histogram with number of retry per diploma.", + }, []string{"diploma"}) +) diff --git a/src/rest/handlers/check-router.go b/src/rest/handlers/check-router.go index 4dba9d5..ac4c901 100644 --- a/src/rest/handlers/check-router.go +++ b/src/rest/handlers/check-router.go @@ -6,7 +6,7 @@ import ( "net/http" ) -func CheckRouter (w http.ResponseWriter, r *http.Request) { +func CheckRouter(w http.ResponseWriter, r *http.Request) { jsonData, _ := ioutil.ReadAll(r.Body) log.Println("r.body", string(jsonData)) } diff --git a/src/rest/handlers/diplomas-post.go b/src/rest/handlers/diplomas-post.go index 760494b..30312e0 100644 --- a/src/rest/handlers/diplomas-post.go +++ b/src/rest/handlers/diplomas-post.go @@ -3,7 +3,9 @@ package handlers import ( "encoding/json" "github.com/42School/blockchain-service/src/dao/api" + "github.com/42School/blockchain-service/src/dao/diplomas" "github.com/42School/blockchain-service/src/tools" + log "github.com/sirupsen/logrus" "net/http" ) @@ -22,20 +24,15 @@ func CreateDiploma(w http.ResponseWriter, r *http.Request) { http.Error(w, "The data sent are not valid, to be written in blockchain please try again !", http.StatusBadRequest) return } - if tools.SecuritySystem { - newDiploma.AddToRetry() - http.Error(w, "The security system is activated, the request has just been queued.", http.StatusInternalServerError) - return - } - tools.LogsDev("Received request to write the " + newDiploma.FirstName + " " + newDiploma.LastName + " diploma.") + log.WithFields(newDiploma.LogFields()).Debug("Received new request to write diploma.") hash, bool := newDiploma.EthWriting() if bool == false { http.Error(w, "Blockchain writing had a problem, the diploma is saved in the queue.", http.StatusBadRequest) return } else { - res, _ := json.Marshal(ResponseJson{true, "The writing in blockchain has been done, it will be confirmed in 10 min.", ResponseData{hash, 0, []float64{}}}) + res, _ := json.Marshal(ResponseJson{true, "The writing in blockchain has been done, it will be confirmed in 10 min.", ResponseData{hash, 0, []diplomas.Skill{}}}) w.WriteHeader(http.StatusOK) w.Write(res) } return -} \ No newline at end of file +} diff --git a/src/rest/handlers/struct-response.go b/src/rest/handlers/struct-response.go index ca75355..f34700e 100644 --- a/src/rest/handlers/struct-response.go +++ b/src/rest/handlers/struct-response.go @@ -1,13 +1,15 @@ package handlers +import "github.com/42School/blockchain-service/src/dao/diplomas" + type ResponseData struct { - Hash string - Level float64 - Skills []float64 + Hash string + Level float64 + Skills []diplomas.Skill } type ResponseJson struct { - Status bool - Message string - Data ResponseData + Status bool + Message string + Data ResponseData } diff --git a/src/rest/server.go b/src/rest/server.go index a2618c5..488780f 100644 --- a/src/rest/server.go +++ b/src/rest/server.go @@ -1,13 +1,17 @@ package rest import ( - handlers "github.com/42School/blockchain-service/src/rest/handlers" + "github.com/42School/blockchain-service/src/metrics" + "github.com/42School/blockchain-service/src/rest/handlers" "github.com/42School/blockchain-service/src/tools" "github.com/gorilla/mux" + "github.com/prometheus/client_golang/prometheus/promhttp" ) func InitRouter() *mux.Router { router := mux.NewRouter().StrictSlash(true) + router.Use(metrics.PrometheusMiddleware) + router.Handle("/metrics", promhttp.Handler()) router.Methods("POST").Path("/create-diploma").Name("Create").HandlerFunc(handlers.CreateDiploma) router.Methods("POST").Path("/get-diploma").Name("Get").HandlerFunc(handlers.GetDiploma) router.Methods("GET").Path("/get-all-diploma").Name("GetAll").HandlerFunc(handlers.GetAllDiplomas) diff --git a/src/tools/global.go b/src/tools/global.go index 3c3d742..1d6dfed 100644 --- a/src/tools/global.go +++ b/src/tools/global.go @@ -7,40 +7,38 @@ import ( ) // Keystore File -var PathKeyStoreSign string = os.Getenv("KEYSTORE_PATH_SIGN") -var PasswordAccount string = os.Getenv("KEY_PASSWD") -var PathKeyStore string = os.Getenv("KEYSTORE_PATH") -var AccountsFile string = os.Getenv("ACCOUNTS_FILE") +var PathKeyStoreSign = os.Getenv("KEYSTORE_PATH_SIGN") +var PasswordAccount = os.Getenv("KEY_PASSWD") +var PathKeyStore = os.Getenv("KEYSTORE_PATH") +var AccountsFile = os.Getenv("ACCOUNTS_FILE") // Blockchain Variable -var NetworkLink string = os.Getenv("NETWORK_LINK") -var AddressOfContract string = os.Getenv("CONTRACT_ADDRESS") +var NetworkLink = os.Getenv("NETWORK_LINK") +var AddressOfContract = os.Getenv("CONTRACT_ADDRESS") // Endpoint of 42 intra -var FtEndPoint string = os.Getenv("FT_END_POINT") -var RetryPath string = os.Getenv("RETRY_PATH") -var ValidationPath string = os.Getenv("VALIDATION_PATH") -var Token string = os.Getenv("TOKEN") +var FtEndPoint = os.Getenv("FT_END_POINT") +var RetryPath = os.Getenv("RETRY_PATH") +var ValidationPath = os.Getenv("VALIDATION_PATH") +var Token = os.Getenv("TOKEN") // Mailer Variable -var EmailSender string = os.Getenv("SENDER_EMAIL") -var PasswordEmail string = os.Getenv("PASSWD_EMAIL") -var EmailHost string = os.Getenv("EMAIL_HOST") -var ToEmail string = os.Getenv("TO_EMAIL") +var EmailSender = os.Getenv("SENDER_EMAIL") +var PasswordEmail = os.Getenv("PASSWD_EMAIL") +var EmailHost = os.Getenv("EMAIL_HOST") +var ToEmail = os.Getenv("TO_EMAIL") // Mongo Variable -var MongoIp string = os.Getenv("MONGO_IP") -var MongoPort string = os.Getenv("MONGO_PORT") -var MongoUser string = os.Getenv("MONGO_USER") -var MongoPasswd string = os.Getenv("MONGO_PASSWD") +var MongoIp = os.Getenv("MONGO_IP") +var MongoPort = os.Getenv("MONGO_PORT") +var MongoUser = os.Getenv("MONGO_USER") +var MongoPasswd = os.Getenv("MONGO_PASSWD") // Other Variable -var Env string = os.Getenv("RUN_ENV") +var Env = os.Getenv("RUN_ENV") -var SecuritySystem bool = false +var RetryQueue = list.New() +var ToCheckHash = list.New() -var RetryQueue *list.List = list.New() -var ToCheckHash *list.List = list.New() - -var RetryDB *mongo.Collection -var ToCheckDB *mongo.Collection \ No newline at end of file +var RetryDB *mongo.Collection +var ToCheckDB *mongo.Collection diff --git a/src/tools/logs.go b/src/tools/logs.go index 7dc4f6d..b3ad5f4 100644 --- a/src/tools/logs.go +++ b/src/tools/logs.go @@ -1,7 +1,7 @@ package tools import ( - "log" + log "github.com/sirupsen/logrus" "runtime" ) @@ -23,18 +23,8 @@ func getFrame(skipFrames int) runtime.Frame { return frame } -func LogsDev(msg string) { - if Env == "dev" || Env == "DEV" || Env == "Dev" { - log.Println("Developper mode:", msg) - } -} - func LogsError(_err error) { caller := getFrame(2).Function[39:] - string := "Error - " + caller + ":" - log.Println(string, _err) -} - -func LogsMsg(msg string) { - log.Println(msg) + string := "In the function: " + caller + log.WithError(_err).Error(string) } diff --git a/src/tools/mailer.go b/src/tools/mailer.go index 39e80fe..7f871ae 100644 --- a/src/tools/mailer.go +++ b/src/tools/mailer.go @@ -16,13 +16,8 @@ func getAuth() smtp.Auth { func SendMail(msg string, address string) bool { auth := getAuth() - if msg == "Security Alert" { - body := "A different hash than the request has just been written in the smart-contract. \nThis is a serious error that compromises the security of the service. \nA security mode has just been activated, all future requests are automatically queued, until the problem is solved and this mode is manually deactivated." - msg = "From: Blockchain-Service <" + EmailSender + ">\n" + "To: " + ToEmail + "\n" + "Subject: [Blockchain-Service]: Security Alert\n\n" + body - } else if msg == "Empty Account" { - body := "This Ethereum account " + address + ", no longer has sufficient funds to be able to write other diplomas on the blockchain.\nPlease add more Ethereum to the account.\nAnother account has just taken over writing on the blockchain, if this is not the case the diplomas are put in queue." - msg = "From: Blockchain-Service <" + EmailSender + ">\n" + "To: " + ToEmail + "\n" + "Subject: [Blockchain-Service]: Empty Account\n\n" + body - } + body := "This Ethereum account " + address + ", no longer has sufficient funds to be able to write other diplomas on the blockchain.\nPlease add more Ethereum to the account.\nAnother account has just taken over writing on the blockchain, if this is not the case the diplomas are put in queue." + msg = "From: Blockchain-Service <" + EmailSender + ">\n" + "To: " + ToEmail + "\n" + "Subject: [Blockchain-Service]: Empty Account\n\n" + body err := smtp.SendMail("smtp.gmail.com:587", auth, EmailSender, []string{ToEmail}, []byte(msg)) if err != nil { LogsError(err) diff --git a/test/ft_diploma_test.js b/test/ft_diploma_test.js index c2e2f60..8d06237 100644 --- a/test/ft_diploma_test.js +++ b/test/ft_diploma_test.js @@ -2,12 +2,21 @@ const truffleConfig = require("../truffle-config"); const FtDiploma = artifacts.require("FtDiploma"); -let skills = [ +let skillsLevel = [ 857, 542, 62, 942, 661, 416, 902, 902, 902, 36, 222, 55, 145, 435, 267, 1122, 73, 206, 103, 817, 116, 2828, 920, 157, 1112, 2126, 328, 423, 203, 416 ] +let skillsSlug = [ + "Written Communication", "Web", "Unix", "Technology integration", "Shell", + "Security", "Ruby", "Rigor", "Python", "Parallel computing", "Organization", + "Object-oriented programming", "Network & system administration", "Motion Design", + "Imperative programming", "Group & interpersonal", "Graphics", "Functional programming", + "DB & Data", "Company experience", "Basics", "Algorithms & AI", "Adaptation & creativity", + "157", "1112", "2126", "328", "423", "203", "416" +] + const keystore = `{"address":"7e12234e994384a757e2689addb2a463ccd3b47d","crypto":{"cipher":"aes-128-ctr","ciphertext":"6d9f85fc277cbbd66f01f15358a62fff3a1cef9c7a96a8024043d8b3c9adeaf6","cipherparams":{"iv":"39516f9f12fe7cccfbdaa11dab569cb9"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"56bb6dac014acbb558e2cb6c533d73d25dc3fe7fa2b1653e664ce32fa72347d5"},"mac":"7d69e74114b8529df420adb173d62a97ef12f631272253c8ce69416c2234245d"},"id":"3ae16ea0-ef89-4b2c-b527-ad1259a53b4d","version":3}`; const account = web3.eth.accounts.decrypt(keystore, 'password'); @@ -18,7 +27,7 @@ contract("FtDiploma", async (accounts) => { let dataToHash = "Louise, Pieri, 1998-12-27, 2020-06-25"; let hash = web3.utils.sha3(dataToHash); let sign = account.sign(hash); - const tx = await instance.createDiploma(1517, skills, sign.v, sign.r, sign.s, sign.messageHash); + const tx = await instance.createDiploma(1517, skillsLevel, skillsSlug, sign.v, sign.r, sign.s, sign.messageHash); txStudent = tx.logs[0].args.student; assert.equal(txStudent, sign.messageHash, 'Error: The writing is not valid!'); }) @@ -29,7 +38,7 @@ contract("FtDiploma", async (accounts) => { let hash = web3.utils.sha3(dataToHash); let sign = account.sign(hash); const tx = await instance.getDiploma(sign.messageHash); - level = web3.utils.BN(tx.level).toNumber(); + level = web3.utils.BN(tx[0]).toNumber(); assert.equal(level, 1517, `Error: The diploma couldn't be gotten, or doesn't exist.`); }) @@ -39,7 +48,7 @@ contract("FtDiploma", async (accounts) => { let hash = web3.utils.sha3(dataToHash); let sign = account.sign(hash); try { - await instance.createDiploma(1517, skills, sign.v, sign.r, sign.s, hash); + await instance.createDiploma(1517, skillsLevel, skillsSlug, sign.v, sign.r, sign.s, hash); } catch (error) { assert.equal(error.reason, 'FtDiploma: Is not 42 sign this diploma.', `Error: It is possible to write a diploma not signed by 42.`); } @@ -50,9 +59,9 @@ contract("FtDiploma", async (accounts) => { let dataToHash = "Prenom, Nom, AAAA-MM-JJ, AAAA-MM-JJ"; let hash = web3.utils.sha3(dataToHash); let sign = account.sign(hash); - const firstTx = await instance.createDiploma(1517, skills, sign.v, sign.r, sign.s, sign.messageHash); + const firstTx = await instance.createDiploma(1517, skillsLevel, skillsSlug, sign.v, sign.r, sign.s, sign.messageHash); try { - await instance.createDiploma(1517, skills, sign.v, sign.r, sign.s, sign.messageHash); + await instance.createDiploma(1517, skillsLevel, skillsSlug, sign.v, sign.r, sign.s, sign.messageHash); } catch (error) { assert.equal(error.reason, "FtDiploma: The diploma already exists.", `Error: The double insertion of a diploma is possible.`); } @@ -69,7 +78,7 @@ contract("FtDiploma", async (accounts) => { it("Testing the gets all data", async () => { let instance = await FtDiploma.deployed(); - let datas = await instance.getAllDiploma({from: "0x7e12234e994384a757e2689addb2a463ccd3b47d"}) + let datas = await instance.getAllDiploma({from: account.address}) assert.isNotEmpty(datas); }) }) \ No newline at end of file diff --git a/truffle-config.js b/truffle-config.js index 59f761f..ad01eac 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -18,11 +18,10 @@ * */ -// const HDWalletProvider = require('@truffle/hdwallet-provider'); -// const infuraKey = "fj4jll3k....."; -// -// const fs = require('fs'); -// const mnemonic = fs.readFileSync(".secret").toString().trim(); +const HDWalletProvider = require("/usr/local/lib/node_modules/truffle-hdwallet-provider"); + +const fs = require('fs'); +const mnemonic = fs.readFileSync("./config-dev/.secret").toString().trim(); module.exports = { /** @@ -66,14 +65,11 @@ module.exports = { // Useful for deploying to a public network. // NB: It's important to wrap the provider as a function. - // ropsten: { - // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), - // network_id: 3, // Ropsten's id - // gas: 5500000, // Ropsten has a lower block limit than mainnet - // confirmations: 2, // # of confs to wait between deployments. (default: 0) - // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) - // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) - // }, + ropsten: { + provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/c752dcd7173947b6bc2cef7c5bf8234e`), + network_id: 3, // Ropsten's id + confirmations: 2, // # of confs to wait between deployments. (default: 0) + }, // Useful for private networks // private: {