# SYD - TP Blockchain - Build Your Blockchain
[Github](https://github.com/dreimert/BuildYourBlockChain/tree/etape-3)
###### tags: `SYD` `TP`
## Lancement
Pour lancer un noeud, il faut au préalable créer un wallet à l'aide du CLI.
```bash
node cli.js create
```
On rentre ensuite le nom du wallet
```
Nom du wallet ? (default) NomDuWallet
Nom du wallet : NomDuWallet
```
On peut alors lancer un noeud et l'associer au wallet qui va le contrôler. On peut éventuellement préciser le numéro de port si un autre noeud est ouvert sur la même machine sur le port 3000.
```bash
node noeud.js -w NomDuWallet
```
## A deux (ou plus), c'est mieux !
Pour synchroniser les noeuds, il faut les lancer en leur donnant le même timestamp. On lance aussi le minage
```bash
node noeud.js -w NomDuWallet -b 1 -m
```
Avec le CLI, on les ajoute mutuellement comme peers avec la commande addPeers
```bash
node cli.js addPeer http://localhost:3001
```
Le noeuds sont alors synchronisés.
*NB: Les noeuds doivent être contrôlés par le même wallet*
Modifications de ```noeud.js``` pour que la commande ```node cli.js mine <state>``` fonctionne.
```javascript=
// # gestion des commandes authentifiées
network.on('cmd', function (socket, cmd, callback) {
cmd = Command.fromObject(cmd)
if (cmd.user !== publicKey || !cmd.verify()) {
const error = new Error('cmd error : vous n\'avez pas les droits')
log.info(error)
callback(error.message)
} else if (cmd.type === 'set') {
log.info('cmd::set', cmd.params.key, cmd.params.value)
const transaction = Transaction.fromCommand(cmd)
if (blockchain.addTransaction(transaction)) {
network.notifyNeighbors('transaction', transaction)
callback()
} else {
const error = new Error('cmd error : cette transaction existe déjà')
log.info(error)
callback(error.message)
}
} else if (cmd.type === 'addPeer') {
log.info('cmd::addPeer', cmd.params.url, cmd.params.port)
const s = network.addPeer(cmd.params.url, cmd.params.port, callback)
if (s) {
s.emit('last', (error, last) => {
if (error) {
log.error('addPeer::last fail:', error)
}
setBlock(Block.fromObject(last), s, callback)
})
}
/***** Début modifications *****/
} else if (cmd.type === 'mine'){
log.info('cmd::mine', cmd.params.state)
if(cmd.params.state == "start"){
log.info('Minage activé')
miner.findPow(blockchain.buildNextBlock())
argv.mine = true
callback()
} else if (cmd.params.state == "stop") {
log.info('Minage désactivé')
argv.mine = false
callback()
} else {
const error = new Error(`State ${state} n'existe pas`)
}
/***** Fin modifications *****/
} else {
const error = new Error('cmd error : type inconnue')
log.info(error)
callback(error.message)
}
})
```
## Connectons-nous !
Pour être synchronisés, il faut que notre noeud ait le même timestamp que celui qui tourne sur https://syd.reimert.fr
Pour cela, on récupère le timestamp du bloc 0 grâce à la commande ```blockByIndex```
```bash
node cli.js -u https://syd.reimert.fr -p 443 blockByIndex 0
```
On lance ensuite notre noeud avec le timestamp obtenu
```bash
node noeud.js -b timestamp
```
On ajoute ensuite le noeud public comme peer de notre noeud
```bash
node cli.js addPeer https://syd.reimert.fr:443
```
Notre noeud est alors synchronisé au noeud public.
## Laisser une trace dans ce monde
Modification de ```noeud.js``` pour que la commande ```node cli.js identity <name>``` fonctionne.
```javascript=
// # gestion des commandes authentifiées
network.on('cmd', function (socket, cmd, callback) {
cmd = Command.fromObject(cmd)
if (cmd.user !== publicKey || !cmd.verify()) {
const error = new Error('cmd error : vous n\'avez pas les droits')
log.info(error)
callback(error.message)
} else if (cmd.type === 'set') {
log.info('cmd::set', cmd.params.key, cmd.params.value)
const transaction = Transaction.fromCommand(cmd)
if (blockchain.addTransaction(transaction)) {
network.notifyNeighbors('transaction', transaction)
callback()
} else {
const error = new Error('cmd error : cette transaction existe déjà')
log.info(error)
callback(error.message)
}
} else if (cmd.type === 'addPeer') {
log.info('cmd::addPeer', cmd.params.url, cmd.params.port)
const s = network.addPeer(cmd.params.url, cmd.params.port, callback)
if (s) {
s.emit('last', (error, last) => {
if (error) {
log.error('addPeer::last fail:', error)
}
setBlock(Block.fromObject(last), s, callback)
})
}
} else if (cmd.type === 'mine'){
log.info('cmd::mine', cmd.params.state)
if(cmd.params.state == "start"){
log.info('Minage activé')
miner.findPow(blockchain.buildNextBlock())
argv.mine = true
callback()
} else if (cmd.params.state == "stop") {
log.info('Minage désactivé')
argv.mine = false
callback()
} else {
const error = new Error(`State ${state} n'existe pas`)
}
/***** Début modifications *****/
} else if (cmd.type === 'identity') {
log.info('cmd::identity', cmd.params.name)
const transaction = Transaction.fromCommand(cmd)
if (blockchain.addTransaction(transaction)) {
network.notifyNeighbors('transaction', transaction)
callback()
} else {
const error = new Error('cmd error : cette transaction existe déjà')
log.info(error)
callback(error.message)
}
/***** Fin modifications *****/
} else {
const error = new Error('cmd error : type inconnue')
log.info(error)
callback(error.message)
}
})
```
## Contribuer au réseau
Modification de ```noeud.js``` pour ajouter une transaction de type ```reward``` aux blocs minés
```javascript=
async function setBlock (block, socket, callback = () => {}) {
if (!block.isValid()) {
const error = new Error('block error : block invalid')
log.warn(error, block)
callback(error.message)
} else {
if (await blockchain.addBlock(block, socket)) {
network.notifyNeighbors('block', block)
if (argv.mine) {
const nextBlock = blockchain.buildNextBlock()
/***** Ajout d'une transaction reward *****/
const publicKey = fs.readFileSync(`./wallets/${argv.wallet}/pub`, 'utf8')
const privateKey = fs.readFileSync(`./wallets/${argv.wallet}/priv`, 'utf8')
const params = null
const transaction = new Transaction('reward', params, publicKey)
transaction.sign(privateKey)
nextBlock.transactions.unshift(transaction)
/******************************************/
// reward here ;)
// indice : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
// indice : pour créer une transaction, vous pouvez regarder comment cli.js crée une command
log.info(`Search for the hash of block ${nextBlock.index}`)
miner.findPow(nextBlock)
}
}
callback()
}
}
```