Skip to content
Snippets Groups Projects
Commit db42a627 authored by BRODIER Jeremy's avatar BRODIER Jeremy
Browse files

Create coinbase and genuine bloc

parent 30a09594
No related branches found
No related tags found
1 merge request!1Create coinbase and genuine bloc
target/
.vscode
\ No newline at end of file
.vscode
.idea
\ No newline at end of file
......@@ -20,6 +20,11 @@
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
......
package fr.miage;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;
/**
* Hello world!
......@@ -8,14 +9,23 @@ import java.security.NoSuchAlgorithmException;
*/
public class App
{
public static void main( String[] args ) throws NoSuchAlgorithmException
public static void main( String[] args )
{
System.out.println("Début de la blockchain");
// Création de 2 wallets
Wallet bobWallet = new Wallet("publicKey1", "privateKey1");
Wallet aliceWallet = new Wallet("publicKey2", "privateKey2");
Set<Wallet> wallets = new HashSet<Wallet>() {
{
add(bobWallet);
add(aliceWallet);
}
};
// Création de la blockchain
Blockchain blockchain = new Blockchain("BloBlockchain");
//Création de 2 wallets
Wallet bobWallet = new Wallet("Ceci est la clé privé de bob");
///System.out.println(bobWallet.getPublicKey());
//System.out.println(bobWallet.getPrivateKey());
Blockchain blockchain = new Blockchain("BloBlockchain", wallets);
System.out.println(blockchain);
// MinageManager minageManager = new MinageManager(blockchain);
// minageManager.mineABloc();
}
}
package fr.miage;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.apache.commons.codec.digest.DigestUtils;
public class Bloc {
private String hash;
private List<Transaction> transactions;
private String header;
private String header; // Contient le nonce et le hash du bloc précédent
public Bloc(String hash, List<Transaction> transactions) {
this.hash = hash;
this.transactions = transactions;
}
public String getHash() {
return hash;
}
public String getHeader() {
return header;
}
public Bloc(String hash,List<Transaction> transactions) {
public void setHash(String hash) {
this.hash = hash;
this.transactions = transactions;
}
public String getHash() {
return hash;
}
public String getHeader() {
return header;
}
public void setHash(String hash) {
this.hash = hash;
}
public void setHeader(String header) {
this.header = header;
}
}
public void setHeader(String header) {
this.header = header;
}
public Bloc(List<Transaction> transactions) {
this.transactions = transactions;
......@@ -34,7 +41,59 @@ public class Bloc {
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
public static Bloc createGenuineBloc(Set<Wallet> wallets) {
List<Transaction> transactions = new ArrayList<Transaction>();
for (Wallet wallet : wallets) {
int amount = RandomNumberGenerator.getRandomNumber(1, 20);
UTxO utxo = new UTxO(null, amount);
wallet.addUTxO(utxo);
List<UTxO> utxos = new ArrayList<UTxO>() {
{
add(utxo);
}
};
Coinbase coinbase = new Coinbase(utxos, wallet.getPublicKey(), EnumTypeTransaction.COINBASE);
transactions.add(coinbase);
}
BlocHeader blocHeader = new BlocHeader("", 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());
}
public String getTransactionsString() {
StringBuilder sb = new StringBuilder();
for (Transaction transaction : this.transactions) {
sb.append(transaction.toString());
}
return sb.toString();
}
public class RandomNumberGenerator {
public static int getRandomNumber(int min, int max) {
Random random = new Random();
return random.nextInt(max) + min;
}
}
@Override
public String toString() {
return "{" +
" hash='" + getHash() + "'" +
", transactions='" + getTransactions() + "'" +
", header='" + getHeader() + "'" +
"}";
}
}
// package fr.miage;
package fr.miage;
// public class BlocHeader {
// private String previousHash;
// private long time;
// private long nonce;
public class BlocHeader {
private String previousHash;
private long time;
private long nonce;
// private long size;
// public static final int DIFFICULTY = 27;
// public BlocHeader(String hash, String previousHash, long time, long nonce, long size) {
public BlocHeader(String previousHash, long time, long nonce) {
// this.hash = hash;
// this.previousHash = previousHash;
// this.time = time;
// this.nonce = nonce;
this.previousHash = previousHash;
this.time = time;
this.nonce = nonce;
// this.size = size;
// }
}
// public String getHash() {
// return hash;
......@@ -23,25 +23,25 @@
// this.hash = hash;
// }
// public String getPreviousHash() {
// return previousHash;
// }
public String getPreviousHash() {
return previousHash;
}
// public void setPreviousHash(String previousHash) {
// this.previousHash = previousHash;
// }
// public long getTime() {
// return time;
// }
public long getTime() {
return time;
}
// public void setTime(long time) {
// this.time = time;
// }
// public long getNonce() {
// return nonce;
// }
public long getNonce() {
return nonce;
}
// public void setNonce(long nonce) {
// this.nonce = nonce;
......@@ -57,4 +57,4 @@
// }
}
package fr.miage;
import java.util.LinkedList;
import java.util.Set;
public class Blockchain {
private String name;
private LinkedList<Bloc> blocs;
private Set<Wallet> wallets;
public Blockchain(String name) {
public Blockchain(String name, Set<Wallet> wallets) {
this.name = name;
this.blocs = new LinkedList<Bloc>();
this.wallets = wallets;
// Création du premier bloc contenant les transactions de coinbase
this.blocs = new LinkedList<>() {
{
add(Bloc.createGenuineBloc(wallets));
}
};
}
public void addBloc(Bloc bloc) {
this.blocs.add(bloc);
}
public Bloc getLastBloc() {
return this.blocs.getLast();
}
public String getName() {
return this.name;
}
private LinkedList<Bloc> getBlocs() {
return this.blocs;
}
public Set<Wallet> getWallets() {
return this.wallets;
}
@Override
public String toString() {
return "{" +
" name='" + getName() + "'" +
", blocs='" + getBlocs() + "'" +
", wallets='" + getWallets() + "'" +
"}";
}
}
package fr.miage;
import java.util.ArrayList;
import java.util.List;
public class Coinbase extends Transaction {
public Coinbase(List<UTxO> inputs, List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) {
super(inputs, outputs, signature, EnumTypeTransaction.COINBASE);
}
public Coinbase(List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) {
super(new ArrayList<UTxO>(), outputs, signature, EnumTypeTransaction.COINBASE);
}
}
package fr.miage;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Optional;
import java.util.stream.DoubleStream;
import javax.swing.text.html.Option;
import org.apache.commons.codec.digest.DigestUtils;
public class MinageManager {
private static final int DIFFICULTY = 27;
private Blockchain blockchain;
public MinageManager() {
public MinageManager(Blockchain blockchain) {
this.blockchain = blockchain;
}
public Bloc mineABloc() {
Bloc previousBloc = blockchain.getLastBloc();
return mineABloc(previousBloc);
}
public Bloc mineABloc(Bloc previousBloc) {
double target = Math.pow(2, 256 - DIFFICULTY);
//DoubleStream doubleStream = DoubleStream.iterate(0, i -> i + 1).limit((long) Math.pow(2, DIFFICULTY));
Compute result = new Compute(new BigInteger(DigestUtils.sha256Hex(previousBloc.getHeader() + Math.pow(2,DIFFICULTY)), 16).doubleValue(), Math.pow(2,DIFFICULTY));
if(result.hash < target){
System.out.println("Bloc miné avec succès : " + result.nonce);
System.out.println("Hash : " + DigestUtils.sha256Hex(previousBloc.getHeader() + result.nonce));
Bloc bloc = new Bloc(transactions, new BlocHeader(DigestUtils.sha256Hex(previousBloc.getHeader() + result.nonce), previousBloc.getHeader(), System.currentTimeMillis(), result.nonce, transactions.size()));
}
System.out.println("Failed after " + BlocHeader.DIFFICULTY + " tries");
return new Result("", BlocHeader.DIFFICULTY);
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());
}
private static double computeTarget(String header) {
return new BigInteger(header, 16).doubleValue() / Math.pow(2, DIFFICULTY);
}
record Result(String hash, double nonce){}
record Compute(double hash, double nonce){}
private static int findNonce(String header, double target) {
return (int) 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();
}
record Result(String hash, double nonce) {
}
record Compute(double hash, double nonce) {
}
}
package fr.miage;
import java.util.List;
import java.util.UUID;
public class Transaction {
private String id;
private UUID id;
private List<UTxO> inputs;
private List<UTxO> outputs;
private String signature;
private String typeTransaction;
private Bloc bloc;
private EnumTypeTransaction typeTransaction;
public Transaction(String id, List<UTxO> inputs, List<UTxO> outputs, String signature, String typeTransaction) {
this.id = id;
public Transaction(List<UTxO> inputs, List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) {
this.inputs = inputs;
this.outputs = outputs;
this.signature = signature;
}
public void createTransaction(Wallet fromWallet, String toWallet, double amount, List<UTxO> utxoInput, List<UTxO> utxoOutput){
//créer transaction normale
this.signature = fromWallet.getPrivateKey();
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
public void createFirstTranscation(Wallet fromWallet, String toWallet, double amount, List<UTxO> utxoInput, List<UTxO> utxoOutput){
//créer transaction normale
this.signature = fromWallet.getPrivateKey();
utxoInput.add(new UTxO(fromWallet, null, amount))
public List<UTxO> getInputs() {
return this.inputs;
}
//créer transaction coinbase
public List<UTxO> getOutputs() {
return this.outputs;
}
//un bloc avec que des coinbase avec un seul utxo de sortie
public String getSignature() {
return this.signature;
}
public EnumTypeTransaction getTypeTransaction() {
return this.typeTransaction;
}
@Override
public String toString() {
return "{" +
" id='" + getId() + "'" +
", inputs='" + getInputs() + "'" +
", outputs='" + getOutputs() + "'" +
", signature='" + getSignature() + "'" +
", typeTransaction='" + getTypeTransaction() + "'" +
"}";
}
}
package fr.miage;
import java.util.UUID;
public class UTxO {
//UTXO : Hash qui renvoie a la transaction d'avant
private Wallet hashWallet; // hash du wallet
private UUID uuid;
private Transaction transaction; // transaction précédente (provenance de l'argent) --> peut etre meme que le hash de la transaction
private double montant;
public UTxO(Wallet hashWallet, Transaction transaction, double montant) {
this.hashWallet = hashWallet;
public UTxO(Transaction transaction, double montant) {
this.transaction = transaction;
this.montant = montant;
}
public Transaction getTransaction() {
return this.transaction;
}
public double getMontant() {
return this.montant;
}
@Override
public String toString() {
return "{" +
"transaction='" + getTransaction() + "'" +
", montant='" + getMontant() + "'" +
"}";
}
}
......@@ -3,39 +3,53 @@ package fr.miage;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
public class Wallet {
private String publicKey;
private String privateKey; // pour la signature
private double solde;
private List<UTxO> utxos;
public Wallet(String privateKey) throws NoSuchAlgorithmException {
this.init(privateKey);
public Wallet(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
this.utxos = new ArrayList<>();
}
public void initWallet(byte[] data) throws NoSuchAlgorithmException {
private void init(String privateKey) throws NoSuchAlgorithmException{
}
private String hashSha256(String privateKey) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(privateKey.getBytes(StandardCharsets.UTF_8));
StringBuilder hashedByte = new StringBuilder();
for(byte b : hash){
hashedByte.append(String.format("%02x", b));
}
this.publicKey = hashedByte.toString();
this.privateKey = privateKey;
this.solde = 20;
this.utxos.add(new UTxO(this, null, solde))
return new String(hash, StandardCharsets.UTF_8);
}
public String getPublicKey() {
return this.publicKey;
}
public String getPrivateKey() {
return privateKey;
return this.privateKey;
}
public String getPublicKey() {
return publicKey;
public List<UTxO> getUtxos() {
return this.utxos;
}
public void addUTxO(UTxO utxo) {
this.utxos.add(utxo);
}
@Override
public String toString() {
return "{" +
" publicKey='" + getPublicKey() + "'" +
", privateKey='" + getPrivateKey() + "'" +
", utxos='" + getUtxos() + "'" +
"}";
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment