Skip to content

Commit

Permalink
Merge pull request #3 from 42School/dev/go/eth
Browse files Browse the repository at this point in the history
[Version]: v2 - beta
  • Loading branch information
lpieri authored Jul 24, 2020
2 parents 4fcfa13 + 046ef80 commit 5db3259
Show file tree
Hide file tree
Showing 18 changed files with 429 additions and 110 deletions.
18 changes: 10 additions & 8 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@ RUN cd /blockchain-service && go mod download

ENV KEYPASSWD="password"

ENV KEYSTOREFILE="UTC--2020-07-16T13-52-10.535505000Z--7e12234e994384a757e2689addb2a463ccd3b47d"

ENV OFFICIALADDRESS="0x7e12234E994384A757E2689aDdB2A463ccD3B47d"
ENV KEYSTOREPATHSIGN="./keystore-sign"

ENV KEYSTOREPATH="./keystore"

ENV FTENDPOINT="http://[ip-42]/confirmed-alumni"
ENV FTENDPOINT="http://127.0.0.1:8080"

ENV NETWORKLINK="http://172.17.0.1:9545"
ENV VALIDATIONPATH="/check-request"

ENV RUNENV="Dev"
ENV RETRYPATH="/check-request"

ENV EMAILSENDER="emailSender"

ENV DEVADDRESS="0x8718F961628D97f8d20e23Ec0e264Fd51bfD6451"
ENV PASSWDEMAIL="password"

ENV DEVPRIVATEKEY="2a5c20b8657e52644b994b71d451b1a5f40188cec559e288475750710d1c54a7"
ENV NETWORKLINK="http://172.17.0.1:9545"

ENV RUNENV="Dev"

EXPOSE 8080:8080

Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.server
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:buster
FROM debian:buster-backports

RUN apt-get update -y && apt-get upgrade -y

Expand All @@ -12,4 +12,4 @@ COPY ./truffle-config.js /.

EXPOSE 9545:9545

CMD ganache-cli --account "0x2a5c20b8657e52644b994b71d451b1a5f40188cec559e288475750710d1c54a7,500000000000000000000" -h 0.0.0.0 -p 9545 -k muirGlacier
CMD ganache-cli --account "0xd4ecb28d0bbfdc6e12c9245d42e2ca58bc13e2fe434d0b547de3356124ce9bc2,134439500000000000" --account "0xd634b7172b296da0b018a52582a0d41add6acc3289d361df2c984df27958fa1b,13443950000" --account "0x5b273f2fd8aaf42c31aa995a3cd2b6ce298cbcd6f8cba2785f4e5d46ba5ef147,500000000000000000000" -h 0.0.0.0 -p 9545 -k muirGlacier
77 changes: 71 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,34 @@ Blockchain-service est un project blockchain de 42.

La stack choisi pour ce projet est `go`, la blockchain `ethereum` et `solidity` pour le smartcontract.

La branche dev en cours est [dev/go/eth](https://github.com/lpieri/42-Alumni/tree/dev/go/eth).
La branche dev en cours est [dev/go/eth](https://github.com/42School/blockchain-service/tree/dev/go/eth).

La précédente version stable est la [v1.3.1](https://github.com/42School/blockchain-service/tree/v1.3.1), si vous trouvez des bugs sur cette version n'hésitez pas à faire une `issue`

## Sommaire

- [Installation](#installation)
- [Lancement en mode dev](#lancement-en-mode-dev)
- [Route de l'api](#route-de-lapi)
- [Makefile](#makefile)
- [Nouvelle Feature](#nouvelle-feature)
- [Configuration](#configuration)
- [Création d'un fichier keystore](#création-dun-fichier-keystore)

## Installation

**Petite modification importante** - Avant de lancer `make install` veuillez modifier dans le Dockerfile `Dockerfile.dev` la variable `FTENDPOINT` avec l'ip du service d'alumnisation:

```dockerfile
ENV FTENDPOINT="http://[ip-42]/confirmed-alumni"
ENV FTENDPOINT="http://[ip-42]" # By default "http://127.0.0.1:8080"
ENV VALIDATIONPATH="/[Path for validation]" # By default "/check-request"
ENV RETRYPATH="/[Path for retry]" # By default "/check-request"
```

L'API enverra toutes les 10 minutes des requêtes confirmant les diplômes en blockchain à cette adresse.
L'API enverra:

- Toutes les 10 minutes des requêtes confirmant les diplômes en blockchain à l'adresse `EndPoint + ValidationPath`
- Toutes les 30 minutes des requêtes validant l'inscription d'un diplôme ayant échouer sont écriture à cette adresse `EndPoint + RetryPath`

Pour lancé le projet il faut intaller `docker`

Expand Down Expand Up @@ -74,11 +91,59 @@ dev: Lance le projet en mode dev dans un container docker (commande un peu lente
compile: Compile le smart-contract, convertie le smart-contract solidity en golang et compile la partie golang
clean: Supprime le binaire go et tous autres fichiers utiles à la compilation
docker-stop: Stop les containers docker et les supprimes
docker-clean: Appel la règle docker-stop et supprime les images docker
fclean: Supprime l'image docker
re: Appelle les règles clean et all
docker-rm: Supprime les images docker des dockerfiles
docker-clean: Appelle les règles docker-stop et docker-rm
re: Appelle les règles docker-clean et all
```

## Nouvelle Feature

Voici les nouvelles features pour la v2:

- Une meilleure vérification lors de l'écriture d'un diplôme. Check du hash demandé lors de l'écriture et celui écrit emit par un événement blockchain.
- Une queue de retry qui ré-essaye l'écriture d'un diplôme 30 minutes après, si il avait échouer une première fois.
- Un système de roulement de compte Ethereum qui va envoyer les transactions pour écrire un diplôme en blockchain.
- Un sytème d'envoye de mail:
- Si le seuil d'Eth est trop faible sur un compte
- Si le système de sécurité s'active
- Un sytème de sécurité, si l'écriture d'un diplôme en blockchain est différent que celui demandé alors il s'active et envoie toutes les prochaines demande en queue de retry. Sa désactivation se fait manuellement via un mode de commande sur STDIN.
- Un système de commande, il lis des commandes sur STDIN lors de l'éxecution du programme.
- Pour l'activer il faut écrire `cmd` dans STDIN
- Commandes prise en charge:
- `disable security system` pour désactiver le système de sécurité
- `exit` pour quitté le mode de commande

## Configuration

### Roulement de compte ETH

Pour configurer le roulement des comptes Ethereum qui vont écrire sur la blockchain, vous devez créer un fichier csv tel quel:

```csv
#file name, password
UTC--2020-07-24T08-19-17.983576000Z--cac03bac6965e6d8ca96537a0344cc506b32c2c7, password
UTC--2020-07-24T08-24-31.985849000Z--fe5ac6a7bb66da6916becb74a4a3e00074cd2599, password
UTC--2020-07-24T08-25-31.194883000Z--aec7bdfb241e56c04acf5e1a2a49f147867b85b7, password
```

Puis ajouté dans l'env le path du dossier contenant les fichiers keystore:

```dockerfile
ENV KEYSTOREPATH="./keystore"
```

Pour les tests un fichier est fournis `accounts.csv` ainsi qu'un dossier `./keystore`.

### Compte Officiel de 42

Pour configurer le compte qui va signer les diplômes vous devez créer un fichier `keystore` qui sera stocker un dossier à part du dossier pour le roulement, puis enregistrer son `path` dans l`env:

```dockerfile
ENV KEYSTOREPATHSIGN="./keystore-sign"
```

Pour les tests un dossier ainsi qu'un fichier keystore sont fournis

## Création d'un fichier Keystore

Le fichier keystore est un fichier contenant votre compte eth chiffré.
Expand Down
4 changes: 4 additions & 0 deletions accounts.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#file name, password
UTC--2020-07-24T08-19-17.983576000Z--cac03bac6965e6d8ca96537a0344cc506b32c2c7, password
UTC--2020-07-24T08-24-31.985849000Z--fe5ac6a7bb66da6916becb74a4a3e00074cd2599, password
UTC--2020-07-24T08-25-31.194883000Z--aec7bdfb241e56c04acf5e1a2a49f147867b85b7, password
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"address":"cac03bac6965e6d8ca96537a0344cc506b32c2c7","crypto":{"cipher":"aes-128-ctr","ciphertext":"b0f7933ddae70555ec5e9be4eeaf69bf54b97af2339cb31c7ea8b84906ad6ca7","cipherparams":{"iv":"ebfb836718296ff3b9659500d17e5b69"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"def9f196f7f993e06b9cbf51c2c851f179d662598fad54e28689aebc844d0042"},"mac":"d7ad37f3eb085a20ce9e63f6a60c3074c7868c1d21fe903ac255fffc235fc6a1"},"id":"1264d556-0a3a-4500-b0bd-1caf4b52ae8d","version":3}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"address":"fe5ac6a7bb66da6916becb74a4a3e00074cd2599","crypto":{"cipher":"aes-128-ctr","ciphertext":"63e3dcea141801c206eb576eff5447ef73d66b918887d3a15e876eb5de8b435d","cipherparams":{"iv":"e4f94f97b28d2fde10a50d46456c13cf"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"9670a93a59bf542a3cdc2719a68c7fb48e07f4e90d6bcb9a4187889e9230bc8a"},"mac":"f9ab926a2097eb2b13afc8bb9cc796909900c2da33e487c110a770af0094e37b"},"id":"cefadaf8-d5d4-4613-a299-09c263f4e3f6","version":3}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"address":"aec7bdfb241e56c04acf5e1a2a49f147867b85b7","crypto":{"cipher":"aes-128-ctr","ciphertext":"0adfabd931884c06624972f353d76d555a57e234df3e292cb725de7a1cebad60","cipherparams":{"iv":"7688c51e8e753e55e21557b7deb80370"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"ac0947910cfd927c15072225ab6e3d91d4b89c34144384081e1b742b535d2153"},"mac":"8491060883404e8fc9dd6d7c12761fe6eb6a69c85b6928e2a684baa35025a170"},"id":"5bfeda77-4edb-4c3c-9329-ffa8eadf7d8c","version":3}
33 changes: 7 additions & 26 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,21 @@
package main

import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/42School/blockchain-service/src/account"
"github.com/42School/blockchain-service/src/api"
"github.com/42School/blockchain-service/src/contracts"
"github.com/42School/blockchain-service/src/global"
"github.com/42School/blockchain-service/src/async"
"github.com/42School/blockchain-service/src/tools"
"log"
"net/http"
"strings"
"time"
)

func ValidedHash() {
for {
time.Sleep(6000/*00*/ * time.Millisecond)
copyList := global.ToCheckHash
for e := copyList.Front(); e != nil; e = copyList.Front() {
if e != nil {
hash, _ := e.Value.([]byte)
_, _, err := contracts.CallGetDiploma(hash)
if err == nil {
strHash := hexutil.Encode(hash)
data := "{'Status': true, 'Message': 'The " + strHash + " diploma is definitely inscribed on Ethereum.', 'Data': {" + strHash + "}}"
_, err := http.Post(global.FtEndPoint, "Content-Type: application/json", strings.NewReader(data))
if err == nil {
global.ToCheckHash.Remove(e)
}
}
}
}
}
}


func main() {
go ValidedHash()
go async.ValideHash()
go async.RetryDiploma()
go async.ReadStdin()
tools.LogsMsg("Blockchain Service is running !")
account.CreateAccountsManager()
router := api.InitRouter()
log.Fatal(http.ListenAndServe(":8080", router))
Expand Down
65 changes: 51 additions & 14 deletions src/account/account.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,73 @@
package account

import (
"fmt"
"crypto/ecdsa"
"github.com/42School/blockchain-service/src/global"
"github.com/42School/blockchain-service/src/tools"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/42School/blockchain-service/src/global"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"io/ioutil"
"log"
"strings"
)

var AccountsManager *accounts.Manager
type Account struct {
KeyStoreFile string
Password string
}

var KeyStore *keystore.KeyStore
var CurrentAccount int = 0
var Accounts []Account

func ParseAccounts() {
bits, err := ioutil.ReadFile("./accounts.csv")
if err == nil {
data := string(bits)
lines := strings.Split(data, "\n")
for i := 0; i < len(lines); i++ {
line := lines[i]
if line[0] != '#' {
accountData := strings.Split(line, ", ")
account := Account{accountData[0], accountData[1]}
Accounts = append(Accounts, account)
}
}
}
}

func CreateAccountsManager() {
KeyStore = keystore.NewKeyStore(global.PathKeyStore, keystore.StandardScryptN, keystore.StandardScryptP)
AccountsManager = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, KeyStore)
KeyStore = keystore.NewKeyStore(global.PathKeyStoreSign, keystore.StandardScryptN, keystore.StandardScryptP)
ParseAccounts()
}

func GetAccount() accounts.Account {
func GetSignAccount() accounts.Account {
return KeyStore.Accounts()[0]
}

func GetKey() (*keystore.Key, error) {
keyjson, errRead := ioutil.ReadFile(global.PathKeyStore + "/" + global.FileKeyStore)
func GetWriterAccount() (common.Address, *ecdsa.PrivateKey, error) {
keyjson, errRead := ioutil.ReadFile(global.PathKeyStore + "/" + Accounts[CurrentAccount].KeyStoreFile)
if errRead != nil {
return nil, errRead
return common.Address{}, nil, errRead
}
key, errDecrypt := keystore.DecryptKey(keyjson, global.PasswordAccount)
key, errDecrypt := keystore.DecryptKey(keyjson, Accounts[CurrentAccount].Password)
if errDecrypt != nil {
return nil, errDecrypt
return common.Address{}, nil, errDecrypt
}
if key.Address != global.OfficialAddress {
return nil, fmt.Errorf("key content mismatch: have account %x, want %x", key.Address, global.OfficialAddress)
log.Println("pk:", hexutil.Encode(crypto.FromECDSA(key.PrivateKey)))
return key.Address, key.PrivateKey, nil
}

func ChangeAccount() {
// Send Mail of Current Account
address, _, _ := GetWriterAccount()
tools.SendMail("Empty Account", address.Hex())
if CurrentAccount + 1 == len(Accounts) {
CurrentAccount = 0
} else {
CurrentAccount = CurrentAccount + 1
}
return key, nil
}
22 changes: 19 additions & 3 deletions src/api/controllers/diplomas.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package controllers
import (
"encoding/json"
"github.com/42School/blockchain-service/src/api/models"
"github.com/42School/blockchain-service/src/global"
"github.com/42School/blockchain-service/src/tools"
"io/ioutil"
"log"
"net/http"
)

Expand All @@ -30,10 +33,18 @@ func CreateDiploma(w http.ResponseWriter, r *http.Request) {
w.Write(res)
return
}
if global.SecuritySystem {
newDiploma.AddToRetry()
res, _ := json.Marshal(ResponseJson{false, "The security system is activated, the request has just been queued.", ResponseData{}})
w.WriteHeader(http.StatusInternalServerError)
w.Write(res)
return
}
tools.LogsDev("Received request to write the " + newDiploma.FirstName + " " + newDiploma.LastName + " diploma.")
var res []byte
hash, bool := models.NewDiploma(newDiploma)
hash, bool := newDiploma.EthWriting()
if bool == false {
res, _ = json.Marshal(ResponseJson{false, "Blockchain writing had a problem, please try again.", ResponseData{"", 0, []float64{}}})
res, _ = json.Marshal(ResponseJson{false, "Blockchain writing had a problem, the diploma is saved in the queue.", ResponseData{"", 0, []float64{}}})
w.WriteHeader(http.StatusBadRequest)
} else {
res, _ = json.Marshal(ResponseJson{true, "The writing in blockchain has been done, it will be confirmed in 10 min.", ResponseData{hash, 0, []float64{}}})
Expand All @@ -49,7 +60,7 @@ func GetDiploma(w http.ResponseWriter, r *http.Request) {
var res []byte
jsonData, readErr := ioutil.ReadAll(r.Body)
jsonErr := json.Unmarshal(jsonData, &diploma)
level, skills, errGet := models.GetDiploma(diploma)
level, skills, errGet := diploma.EthGetter()
if r.ContentLength == 0 || readErr != nil || jsonErr != nil || errGet != nil {
res, _ = json.Marshal(ResponseJson{false, "The request is fail, please retry & check the data", ResponseData{}})
w.WriteHeader(http.StatusBadRequest)
Expand All @@ -60,3 +71,8 @@ func GetDiploma(w http.ResponseWriter, r *http.Request) {
w.Write(res)
return
}

func CheckRouter (w http.ResponseWriter, r *http.Request) {
jsonData, _ := ioutil.ReadAll(r.Body)
log.Println("r.body", string(jsonData))
}
Loading

0 comments on commit 5db3259

Please sign in to comment.