Skip to content
Snippets Groups Projects
Commit f4017c23 authored by saintdi25u's avatar saintdi25u
Browse files

ajout des prints

parent ade1fde2
No related branches found
No related tags found
No related merge requests found
Showing
with 402 additions and 143 deletions
{
"java.configuration.updateBuildConfiguration": "automatic"
}
\ No newline at end of file
File deleted
......@@ -7,19 +7,40 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import fr.miage.threads.Mineur;
import fr.miage.threads.TransactionCreator;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) throws NoSuchAlgorithmException, InterruptedException {
public static synchronized void main(String[] args) throws NoSuchAlgorithmException, InterruptedException {
System.out.println("Début de la blockchain");
// Création de 2 wallets
Wallet bobWallet = new Wallet("bob");
Wallet aliceWallet = new Wallet("alice");
Wallet charlieWallet = new Wallet("charlie");
Wallet daveWallet = new Wallet("dave");
Wallet eveWallet = new Wallet("eve");
List<Wallet> wallets = new ArrayList<Wallet>();
wallets.add(bobWallet);
wallets.add(aliceWallet);
wallets.add(charlieWallet);
wallets.add(daveWallet);
wallets.add(eveWallet);
Blockchain blockchain = new Blockchain("Blockchain de Jérémy BRODIER et Corentin SAINT-DIZIER", wallets);
List<Wallet> wallets = Arrays.asList(bobWallet, aliceWallet);
Blockchain blockchain = new Blockchain("BloBlockchain", wallets);
// wallets.add(mineur.getWallet());
System.out.println("Liste des wallets de la blockchain : \n");
// Thread du créateur de transaction
TransactionCreator transactionCreator = new TransactionCreator(blockchain);
Mineur mineur = new Mineur(blockchain);
transactionCreator.start();
mineur.start();
// System.out.println("Wallet de bob : " + bobWallet.getUtxos());
// System.out.println("Wallet de alice : " + aliceWallet.getUtxos());
......@@ -32,14 +53,14 @@ public class App {
// System.out.println("Alice reçoit : " + transaction.getOutputs());
// System.out.println(transaction);
int i = 1;
while (blockchain.transactionsPool.size() < 20) {
System.out.println("Transaction n°" + i);
blockchain.createTrasaction();
i++;
}
System.out.println("Transactions pool count : " +
blockchain.transactionsPool.size());
// int i = 1;
// while (blockchain.transactionsPool.size() < 20) {
// System.out.println("Transaction n°" + i);
// blockchain.createTrasaction();
// i++;
// }
// System.out.println("Transactions pool count : " +
// blockchain.transactionsPool.size());
// // print all utxo in the utxo set
// for (UTxO utxo : Blockchain.utxos) {
......
package fr.miage;
public class BlocHeader {
private String previousHash;
private long time;
private long nonce;
// private long size;
// public static final int DIFFICULTY = 27;
public BlocHeader(String previousHash, long time, long nonce) {
// this.hash = hash;
this.previousHash = previousHash;
this.time = time;
this.nonce = nonce;
// this.size = size;
}
// public String getHash() {
// return hash;
// }
// public void setHash(String hash) {
// this.hash = hash;
// }
public String getPreviousHash() {
return previousHash;
}
// public void setPreviousHash(String previousHash) {
// this.previousHash = previousHash;
// }
public long getTime() {
return time;
}
// public void setTime(long time) {
// this.time = time;
// }
public long getNonce() {
return nonce;
}
// public void setNonce(long nonce) {
// this.nonce = nonce;
// }
// public long getSize() {
// return size;
// }
// public void setSize(long size) {
// this.size = size;
// }
}
......@@ -14,12 +14,14 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import fr.miage.blocs.Bloc;
public class Blockchain {
private String name;
private LinkedList<Bloc> blocs;
private List<Wallet> wallets;
public static Set<UTxO> utxos = new HashSet<>();
public Set<Transaction> transactionsPool = new HashSet<>();
public static Set<Transaction> transactionsPool = new HashSet<>();
public Blockchain(String name, List<Wallet> wallets) {
this.name = name;
......@@ -31,6 +33,7 @@ public class Blockchain {
}
};
;
System.out.println("[BLOC] --- Hash du genesis bloc : " + this.blocs.getFirst().getHash());
}
// Permet de créer une transaction avec deux wallets aléatoire et de l'ajouter
......@@ -39,15 +42,13 @@ public class Blockchain {
// Random wallet selection
List<Wallet> walletsCopy = new ArrayList<>();
walletsCopy.addAll(wallets);
Wallet walletSender = selectWallet(walletsCopy);
walletsCopy.remove(walletSender);
Wallet walletReceiver = selectWallet(walletsCopy);
walletsCopy.remove(walletReceiver);
double amountWalletSender = walletSender.getUtxos().stream().mapToDouble(utxo -> utxo.getMontant()).sum();
double randomAmountToSend = new Random().nextDouble(amountWalletSender);
// System.out.println("Amount to send : " + randomAmountToSend);
// System.out.println("Envoie de " + walletSender.getName() + " à " +
// walletReceiver.getName());
......@@ -61,21 +62,28 @@ public class Blockchain {
System.out.println("Wallets vides");
return;
}
System.out.println("[TRANSACTION] --- Création d'une transaction =========================================");
System.out.println(" " + walletSender.getName() + " envoie " + randomAmountToSend + " à "
+ walletReceiver.getName() + "\n");
Transaction tx = new Transaction(walletSender, walletReceiver, randomAmountToSend, EnumTypeTransaction.NORMAL);
String transactionData = getTransactionData(tx);
try {
byte[] signature = sign(transactionData, walletSender.getKeyPair().getPrivate());
System.out.println("[SIGNATURE] --- Signature de la transaction : " + signature);
tx.setSignature(signature);
if (verifySignature(transactionData, signature, walletSender.getKeyPair().getPublic())) {
System.out.println("Signature vérifiée");
System.out.println("[SIGNATURE] --- Signature vérifiée");
Blockchain.transactionsPool.add(tx);
} else {
System.out.println("Signature non vérifiée");
System.out.println("[SIGNATURE] --- Signature non valide : TRANSACTION REJETEE");
}
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
this.transactionsPool.add(tx);
}
public String getTransactionData(Transaction tx) {
......@@ -95,6 +103,7 @@ public class Blockchain {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(publicKey);
sign.update(data.getBytes());
System.out.println("[SIGNATURE] --- Vérification de la signature : " + signature.toString());
return sign.verify(signature);
}
......@@ -140,10 +149,11 @@ public class Blockchain {
@Override
public String toString() {
return "{" +
" name='" + getName() + "'" +
", blocs='" + getBlocs() + "'" +
", wallets='" + getWallets() + "'" +
"}";
StringBuilder sb = new StringBuilder();
for (int i = 1; i < this.blocs.size(); i++) {
sb.append("Bloc n° : " + i + this.blocs.get(i).getHash() + "\n");
}
return sb.toString();
}
}
......@@ -12,4 +12,8 @@ public class Coinbase extends Transaction {
public Coinbase(List<UTxO> outputs, PublicKey signature, EnumTypeTransaction typeTransaction) {
super(new ArrayList<UTxO>(), outputs, signature, EnumTypeTransaction.COINBASE);
}
public Coinbase() {
super(new ArrayList<UTxO>(), new ArrayList<UTxO>(), null, EnumTypeTransaction.COINBASE);
}
}
package fr.miage;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.UUID;
import java.util.stream.DoubleStream;
import org.apache.commons.codec.digest.DigestUtils;
import fr.miage.blocs.Bloc;
import fr.miage.blocs.BlocHeader;
import fr.miage.threads.Mineur;
public class MinageManager {
private static final int DIFFICULTY = 27;
private static final int DIFFICULTY = 21;
private static double MAX_NONCE = Math.pow(2, 32);
private Blockchain blockchain;
public MinageManager(Blockchain blockchain) {
this.blockchain = blockchain;
}
public Bloc mineABloc() {
Bloc previousBloc = blockchain.getLastBloc();
return mineABloc(previousBloc);
// public Bloc mineABloc() {
// Bloc previousBloc = blockchain.getLastBloc();
// return mineABloc(previousBloc);
// }
public static Bloc mineABloc(Bloc previousBloc, List<Transaction> transactions) {
Bloc bloc = new Bloc();
String hashGenerate = "";
bloc.setCoinbase(addCoinbaseTransaction());
BlocHeader blocHeader = new BlocHeader(transactions.toString(), previousBloc.getHash(),
Instant.now().toEpochMilli());
String header = blocHeader.toString();
double target = MinageManager.computeTarget(header);
OptionalDouble result = MinageManager.findNonce(header, target); // Difficulty
if (result.isPresent()) {
NumberFormat formatter = new DecimalFormat("#0");
System.out.println("Nonce trouvé : " + formatter.format(result.getAsDouble()));
hashGenerate = generateHash(header, result.getAsDouble());
bloc.setHash(hashGenerate);
bloc.setTransactions(transactions);
} else {
System.out.println("Aucun nonce trouvé");
hashGenerate = generateHash("", MAX_NONCE);
bloc.setHash(hashGenerate);
bloc.setTransactions(transactions);
}
return bloc;
}
public static Coinbase addCoinbaseTransaction() {
Coinbase coinbase = new Coinbase();
List<UTxO> outputs = Arrays.asList(new UTxO(coinbase.getId(), null, 5.0));
return new Coinbase(outputs, null, EnumTypeTransaction.COINBASE);
}
public Bloc mineABloc(Bloc previousBloc) {
String header = previousBloc.getHeader();
double target = computeTarget(header);
int nonce = findNonce(header, target);
String hash = DigestUtils.sha256Hex(header + nonce + previousBloc.getTransactionsString());
return new Bloc(hash, previousBloc.getTransactions());
public static double computeTarget(String header) {
return Math.pow(2, (256 - DIFFICULTY));
}
private static double computeTarget(String header) {
return new BigInteger(header, 16).doubleValue() / Math.pow(2, DIFFICULTY);
public static String generateHash(String header, Double nonce) {
return DigestUtils.sha256Hex(header + nonce);
}
private static int findNonce(String header, double target) {
return (int) DoubleStream.iterate(0, i -> i + 1).limit((long) Math.pow(2, DIFFICULTY))
public static OptionalDouble findNonce(String header, double target) {
return (OptionalDouble) DoubleStream.iterate(0, i -> i + 1).limit((long) Math.pow(2, DIFFICULTY))
.filter(nonce -> new BigInteger(DigestUtils.sha256Hex(header + nonce), 16).doubleValue() < target)
.findFirst().orElseThrow();
.findFirst();
}
record Result(String hash, double nonce) {
......
......@@ -28,24 +28,26 @@ public class Transaction {
public Transaction(Wallet sender, Wallet receiver, double amount, EnumTypeTransaction typeTransaction) {
this.inputs = sender.getUTxOsForTransaction(amount);
System.out.println("Inputs : " + this.inputs);
System.out.println("Set UTxO : " + Blockchain.utxos);
// System.out.println("Inputs : " + this.inputs);
// System.out.println("Set UTxO : " + Blockchain.utxos);
if (inputs != null) {
if (isValidTransaction(inputs)) {
this.sender = sender;
this.receiver = receiver;
this.typeTransaction = typeTransaction.NORMAL;
this.id = UUID.randomUUID();
UTxO utxoAmount = new UTxO(this.id, receiver.getKeyPair().getPublic(), amount); // peut
// etre
// changr par
// amout
UTxO utxoAmount = new UTxO(this.id, receiver.getKeyPair().getPublic(), amount);
this.receiver.addUTxO(utxoAmount);
UTxO utxoRest = new UTxO(this.id, sender.getKeyPair().getPublic(),
getTotalAmountUtxoInput(inputs) - amount);
this.sender.addUTxO(utxoRest);
this.outputs = Arrays.asList(utxoAmount, utxoRest);
for (UTxO utxo : this.inputs) {
Blockchain.utxos.add(utxo);
}
Blockchain.utxos.addAll(this.outputs);
printUtxoDetails(inputs, outputs);
} else {
System.err.println("Transaction invalide, utxo absent");
}
......@@ -55,6 +57,17 @@ public class Transaction {
Blockchain.utxos.removeAll(this.inputs);
}
public void printUtxoDetails(List<UTxO> inputs, List<UTxO> outputs) {
System.out.println(" UTxO inputs : \n");
for (UTxO utxo : inputs) {
System.out.println(" " + utxo.getUuid() + " : " + utxo.getMontant());
}
System.out.println(" UTxO outputs : ");
for (UTxO utxo : outputs) {
System.out.println(" " + utxo.getUuid() + " : " + utxo.getMontant());
}
}
// public void signTransaction() throws NoSuchAlgorithmException{
// Signature signature = Signature.getInstance("SHA256withRSA");
// signature.initSign(sender.getPrivateKey());
......@@ -94,33 +107,11 @@ public class Transaction {
return this.outputs;
}
public EnumTypeTransaction getTypeTransaction() {
return this.typeTransaction;
}
public Wallet getReceiver() {
return receiver;
}
public Wallet getSender() {
return sender;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
@Override
public String toString() {
return "{" +
" id='" + getId() + "'" +
", inputs='" + getInputs() + "'" +
", outputs='" + getOutputs() + "'" +
", typeTransaction='" + getTypeTransaction() + "'" +
"}";
public byte[] getSignature() {
return signature;
}
}
}
\ No newline at end of file
......@@ -29,7 +29,7 @@ public class UTxO implements Comparable {
@Override
public String toString() {
return "UTxO [uuid=" + uuid + ", ownerAdress=" + ownerAdresss + ", montant=" + montant + "]";
return "UTxO [uuid=" + uuid + ", montant=" + montant + "]";
}
@Override
......
......@@ -114,13 +114,16 @@ public class Wallet {
}
public void loadPrivateKey() throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, FileNotFoundException, IOException {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("keystore.jks"), null); // replace null by privateKey
PrivateKey privateKey = (PrivateKey) keyStore.getKey("wallet_" + this.name, null); // replace null by //
// privateKey// // (password)
}
// public void loadPrivateKey() throws UnrecoverableKeyException,
// KeyStoreException, NoSuchAlgorithmException,
// CertificateException, FileNotFoundException, IOException {
// KeyStore keyStore = KeyStore.getInstance("JKS");
// keyStore.load(new FileInputStream("keystore.jks"), null); // replace null by
// privateKey
// PrivateKey privateKey = (PrivateKey) keyStore.getKey("wallet_" + this.name,
// null); // replace null by //
// // privateKey// // (password)
// }
// public void publishPublicKey() {
// String command = "keytool -exportcert -alias wallet_" + name
......
package fr.miage;
package fr.miage.blocs;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.codec.digest.DigestUtils;
import fr.miage.Blockchain;
import fr.miage.Coinbase;
import fr.miage.EnumTypeTransaction;
import fr.miage.MinageManager;
import fr.miage.Transaction;
import fr.miage.UTxO;
import fr.miage.Wallet;
import fr.miage.Blockchain;
import fr.miage.Coinbase;
import fr.miage.EnumTypeTransaction;
import fr.miage.Transaction;
import fr.miage.UTxO;
public class Bloc {
private String hash;
private List<Transaction> transactions;
private List<Transaction> transactions; // transaction à insérer dans le bloc
private String header; // Contient le nonce et le hash du bloc précédent
private Coinbase coinbase;
public Bloc(String hash, List<Transaction> transactions) {
this.hash = hash;
this.transactions = transactions;
}
public Bloc() {
}
public String getHash() {
return hash;
}
......@@ -48,6 +70,7 @@ public class Bloc {
}
public static Bloc createGenuineBloc(List<Wallet> wallets) {
System.out.println("Création du Genuine Bloc...");
List<Transaction> transactions = new ArrayList<Transaction>();
for (Wallet wallet : wallets) {
int amount = RandomNumberGenerator.getRandomNumber(1, 20);
......@@ -64,13 +87,26 @@ public class Bloc {
transactions.add(coinbase);
}
// System.out.println("Set UTxO INITIAL " + Blockchain.utxos);
BlocHeader blocHeader = new BlocHeader("", Instant.now().toEpochMilli(), 0);
BlocHeader blocHeader = new BlocHeader("", "", Instant.now().toEpochMilli());
String header = blocHeader.toString();
String hash = generateHash(header, transactions);
String hash = MinageManager.generateHash(header, 0.0);
return new Bloc(hash, transactions);
}
// BlocHeader blocHeader = new BlocHeader("", Instant.now().toEpochMilli(), 0);
// String header = blocHeader.toString();
// String hash = generateHash(header, transactions);return new
// Bloc(hash,transactions);
// public static Bloc createBloc(List<Transaction> transactions, String
// previousHash) {
// BlocHeader blocHeader = new BlocHeader(previousHash,
// Instant.now().toEpochMilli(), 0);
// String header = blocHeader.toString();
// String hash = generateHash(header, transactions);
// return new Bloc(hash, transactions);
// }
private static String generateHash(String header, List<Transaction> transactions) {
return DigestUtils.sha256Hex(header + transactions.toString());
}
......@@ -90,6 +126,18 @@ public class Bloc {
}
}
public Coinbase getCoinbaseTransaction() {
return coinbase;
}
public void setCoinbase(Coinbase coinbase) {
this.coinbase = coinbase;
}
public Coinbase getCoinbase() {
return coinbase;
}
@Override
public String toString() {
return "{" +
......
package fr.miage.blocs;
public class BlocHeader {
private String previousHash;
private long time;
private String transactions;
// private long nonce;
// private long size;
// public static final int DIFFICULTY = 27;
public BlocHeader(String transactions, String previousHash, long time) {
// this.hash = hash;
this.previousHash = previousHash;
this.time = time;
this.transactions = transactions;
// this.nonce = nonce;
// this.size = size;
}
// public String getHash() {
// return hash;
// }
// public void setHash(String hash) {
// this.hash = hash;
// }
public String getPreviousHash() {
return previousHash;
}
// public void setPreviousHash(String previousHash) {
// this.previousHash = previousHash;
// }
public long getTime() {
return time;
}
@Override
public String toString() {
return "BlocHeader [previousHash=" + previousHash + ", time=" + time + ", transactions=" + transactions + "]";
}
// public void setTime(long time) {
// this.time = time;
// }
// public long getNonce() {
// return nonce;
// }
// public void setNonce(long nonce) {
// this.nonce = nonce;
// }
// public long getSize() {
// return size;
// }
// public void setSize(long size) {
// this.size = size;
// }
}
package fr.miage.threads;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import fr.miage.Blockchain;
import fr.miage.MinageManager;
import fr.miage.Transaction;
import fr.miage.Wallet;
import fr.miage.blocs.Bloc;
public class Mineur extends Thread {
private Blockchain blockchain;
private MinageManager minageManager = new MinageManager(blockchain);
private Wallet wallet;
List<Transaction> transactions = new ArrayList<>();
public Mineur(Blockchain blockchain) throws NoSuchAlgorithmException, InterruptedException {
this.blockchain = blockchain;
this.wallet = new Wallet("Mineur");
}
public void run() {
System.out.println("Attente de transactions pour minage....");
while (true) {
try {
if (Blockchain.transactionsPool.size() >= 20) {
System.out.println(" [MINAGE] -- Récupération du dernier bloc de la blockchain....");
Bloc previousBloc = blockchain.getLastBloc();
System.out.println("[MINAGE] -- Dernier bloc de la blockchain : " + previousBloc.getHash());
this.transactions = getLastTransactions();
System.out.println("[MINAGE] -- Minage du bloc....");
Bloc bloc = MinageManager.mineABloc(previousBloc, transactions);
Blockchain.transactionsPool.removeAll(transactions);
transactions.clear();
if (bloc != null) {
blockchain.addBloc(bloc);
System.out.println("[MINAGE] --- Bloc miné : " + bloc.getHash());
System.out.println("[MINAGE] --- Gain du mineur : "
+ bloc.getCoinbase().getOutputs().getFirst().getMontant());
this.wallet.addUTxO(bloc.getCoinbase().getOutputs().getFirst());
}
// remove the transactions from the pool
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized List<Transaction> getLastTransactions() {
System.out.println("[MINAGE] -- Récupération des dernières transactions....");
Iterator<Transaction> it = Blockchain.transactionsPool.iterator();
while (transactions.size() < 20) {
Transaction tx = it.next();
transactions.add(tx);
}
System.out.println(transactions.size());
System.out.println("[COINBAE] --- Ajout de la coinbase transaction dans la liste de transaction");
return transactions;
}
public Wallet getWallet() {
return wallet;
}
public void setWallet(Wallet wallet) {
this.wallet = wallet;
}
}
package fr.miage.threads;
import java.util.List;
import fr.miage.Blockchain;
import fr.miage.Transaction;
import fr.miage.blocs.Bloc;
public class TransactionCreator extends Thread {
private Blockchain blockchain;
public TransactionCreator(Blockchain blockchain) {
this.blockchain = blockchain;
}
public void run() {
while (true) {
blockchain.createTrasaction();
System.out.println("[POOL] Nombre de transaction dans la pool : " + Blockchain.transactionsPool.size());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package fr.miage.transactions;
public enum EnumTypeTransaction {
NORMAL, COINBASE;
}
File added
File added
#Created by Apache Maven 3.9.6
artifactId=blockchain-project
groupId=fr.miage
version=1.0-SNAPSHOT
fr/miage/Transaction.class
fr/miage/Bloc.class
fr/miage/UTxO.class
fr/miage/App.class
fr/miage/Blockchain.class
fr/miage/EnumTypeTransaction.class
fr/miage/MinageManager.class
fr/miage/Wallet.class
fr/miage/BlocHeader.class
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/EnumTypeTransaction.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/Bloc.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/Blockchain.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/App.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/MinageManager.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/Transaction.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/Wallet.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/BlocHeader.java
/Users/corentinstd/Library/CloudStorage/OneDrive-Personnel/Cours/M2_S1/Blockchain/blockchain-project/src/main/java/fr/miage/UTxO.java
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment