From 72de8f1a7896aa0f901601f0a05585ee4d523c0a Mon Sep 17 00:00:00 2001 From: corentinstd <corentinstd@gmail.com> Date: Thu, 22 Feb 2024 17:41:38 +0100 Subject: [PATCH] avancement transaction --- .DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 6148 bytes src/main/java/fr/miage/App.java | 51 +++++++++++++++--- src/main/java/fr/miage/Bloc.java | 3 +- src/main/java/fr/miage/Blockchain.java | 36 +++++++++++++ src/main/java/fr/miage/Transaction.java | 66 ++++++++++++++++++++--- src/main/java/fr/miage/UTxO.java | 33 ++++++++---- src/main/java/fr/miage/Wallet.java | 67 ++++++++++++++++++++++-- target/classes/fr/miage/App.class | Bin 894 -> 1208 bytes 9 files changed, 227 insertions(+), 29 deletions(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store mode change 100644 => 100755 src/main/java/fr/miage/App.java mode change 100644 => 100755 src/main/java/fr/miage/Blockchain.java mode change 100644 => 100755 src/main/java/fr/miage/Transaction.java mode change 100644 => 100755 src/main/java/fr/miage/UTxO.java diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9c80ff7151c0c744b384abb047561d4d60cce3f8 GIT binary patch literal 6148 zcmZQzU|@7AO)+F(5MW?n;9!8zEL;p&0Z1N%F(jFwA|OK;L1yHn8wMxm=N3T4N2$>e z7!85J9Ri@d%fg_?kj{|FP=b<w8P!3V9xj)g@8Xh_lb-}BFdF8V?mX(qz`%ecpMqDu zAOopv;0XYQ3Oj=yLm5LcLo!1?LkdGGitP*xP7DkTXev<Mz;GpdHP{Ups*qiROBITH zz~vwVGea>$5koSnJ3PKKFu-I`?Qckf+7H#2n~!WSx-6=F3qby7V<=%rWGG@tXGld0 zdxqsk3=9k?^2m1kG0fk|z5(oaG&Kkp;8KI)4#o)}cZ}kZ83K$DZ*y=%=uvVs1V%$( zGz8!w04g68Kz#)U1_lQx-2kCMQVfg?4B##RBd8ew)dlVcK-7S=g4BStf@qLd21XDI zEDzSoz{tP?*2xI&hA=QNLaJg0Mh38U21c;WAaSsE21c;W3=E7A?F@_%?F@{d#tO(> zP=f|UL$ot6f^7#|F-nYvz-R~{g#a^zEdZ+jT^Sf~_5UHNM#<3-7!84883K$fF2OFK z?l!b;#qcDkt_9Vn2~Zi3I#6}Y2&$Jsl`XU(0Fq{c3@A!~*dWZv0IA6tA#Dgy^$*fI Q+7JK*&L|!YfdL8u0MMs<rT_o{ literal 0 HcmV?d00001 diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fbb6cd10b24a60f472c9b06770d7b373e8fec9d2 GIT binary patch literal 6148 zcmZQzU|@7AO)+F(5MW?n;9!8zj35RBCIAV8Fop~hR0Jf+2r?rl-7q*gKeqrXJ`^aB z+gTWL84?*X8S+rw@9~|1fdMX;oA2V1l#`zX39yE=?A1pdQRP$c$`@oHhs^>|*sw5^ zFr+dRGnAm(3zA}h%i**asy8<uhrLjFRC~c@j}oIHFd71*Aut*OBRd2bA>QZUhR~zr zXb6mkz-S1-LjY7hD1iD33=9koP`Uv^gQOT385qD_07g(V8LA814}hovX$7ePX$8?B ztqhDH7FZsvm4T6g1+0@1+znx1U<7wbKr~o810&dG5Ff0afe~yo0|O&OI|Cy`I|Hoq z!U*cofXs(zXJ7=|4z^;H7!85Z5I_n6W(ZpVRR6m&z_SoUbd($ofzc2c5h1|H;u7rQ z1gbP~co$UHg6h)*s640+hE&I(iW#*Lzyujklz=J)RresRAR1g1GcquMwT?CfU?DV0 KkA?vKLjV9UHbIX7 literal 0 HcmV?d00001 diff --git a/src/main/java/fr/miage/App.java b/src/main/java/fr/miage/App.java old mode 100644 new mode 100755 index 831f4f3..e0cad8e --- a/src/main/java/fr/miage/App.java +++ b/src/main/java/fr/miage/App.java @@ -1,5 +1,6 @@ package fr.miage; +import java.security.NoSuchAlgorithmException; import java.util.HashSet; import java.util.Set; @@ -9,23 +10,57 @@ import java.util.Set; */ public class App { - public static void main( String[] args ) + public static void main( String[] args ) throws NoSuchAlgorithmException, InterruptedException { 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"); + Wallet bobWallet = new Wallet("jesuislacleprivedebob", "bob"); + //Wallet aliceWallet = new Wallet("je suis la clé privé de alice", "alice"); + Set<Wallet> wallets = new HashSet<Wallet>() { { add(bobWallet); - add(aliceWallet); + //add(aliceWallet); } }; - // Création de la blockchain Blockchain blockchain = new Blockchain("BloBlockchain", wallets); - System.out.println(blockchain); - // MinageManager minageManager = new MinageManager(blockchain); - // minageManager.mineABloc(); + + // System.out.println("Utxos du wallet de bob : " + bobWallet.getUtxos()); + // System.out.println("Utxos du wallet de alice : " + aliceWallet.getUtxos()); + // Transaction transaction = new Transaction(bobWallet, aliceWallet, 2, EnumTypeTransaction.NORMAL); + // System.out.println("Transaction : "); + // System.out.println("Bob envoie : " + transaction.getInputs()); + // 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++; + // } + + // // print all utxo in the utxo set + // for (UTxO utxo : Blockchain.utxos) { + // System.out.println("UTXO ID: " + utxo); + // } + + //TODO : S'asurer de créer une bonne transaction avec les UTxO etc... + //TODO : Faire la signature de la transaction + // + + // Set<Wallet> wallets = new HashSet<Wallet>() { + // { + // add(bobWallet); + // add(aliceWallet); + // } + // }; + // // Création de la blockchain + + + // // MinageManager minageManager = new MinageManager(blockchain); + // // minageManager.mineABloc(); } } diff --git a/src/main/java/fr/miage/Bloc.java b/src/main/java/fr/miage/Bloc.java index 2e47b1b..00e64ee 100644 --- a/src/main/java/fr/miage/Bloc.java +++ b/src/main/java/fr/miage/Bloc.java @@ -50,8 +50,9 @@ public class Bloc { List<Transaction> transactions = new ArrayList<Transaction>(); for (Wallet wallet : wallets) { int amount = RandomNumberGenerator.getRandomNumber(1, 20); - UTxO utxo = new UTxO(null, amount); + UTxO utxo = new UTxO(null, amount); wallet.addUTxO(utxo); + Blockchain.utxos.add(utxo); List<UTxO> utxos = new ArrayList<UTxO>() { { add(utxo); diff --git a/src/main/java/fr/miage/Blockchain.java b/src/main/java/fr/miage/Blockchain.java old mode 100644 new mode 100755 index 180bf59..8accd91 --- a/src/main/java/fr/miage/Blockchain.java +++ b/src/main/java/fr/miage/Blockchain.java @@ -1,12 +1,17 @@ package fr.miage; +import java.util.HashSet; import java.util.LinkedList; +import java.util.List; +import java.util.Random; import java.util.Set; public class Blockchain { private String name; private LinkedList<Bloc> blocs; private Set<Wallet> wallets; + public static Set<UTxO> utxos = new HashSet<>(); + public Set<Transaction> transactionsPool = new HashSet<>(); public Blockchain(String name, Set<Wallet> wallets) { this.name = name; @@ -17,6 +22,37 @@ public class Blockchain { add(Bloc.createGenuineBloc(wallets)); } }; + ; + } + + //Permet de créer une transaction avec deux wallets aléatoire et de l'ajouter dans la transaction pool; + public void createTrasaction(){ + //Random wallet selection + Set<Wallet> walletsCopy = new HashSet<>(wallets); + + int walletIndexSender = new Random().nextInt(walletsCopy.size()); + Wallet walletSender = selectWallet(walletIndexSender); + walletsCopy.remove(walletSender); + + int walletIndexReceiver = new Random().nextInt(walletsCopy.size()); + Wallet walletReceiver = selectWallet(walletIndexReceiver); + + double amountWalletSender = walletSender.getUtxos().stream().mapToDouble(utxo -> utxo.getMontant()).sum(); + double randomAmountToSend = new Random().nextInt((int) amountWalletSender); + Transaction tx = new Transaction(walletSender, walletReceiver, randomAmountToSend, EnumTypeTransaction.NORMAL); + this.transactionsPool.add(tx); + } + + public Wallet selectWallet(int index){ + int i = 0; + for (Wallet wallet : wallets) { + if(i == index){ + return wallet; + } + i++; + } + return null; + } public void addBloc(Bloc bloc) { diff --git a/src/main/java/fr/miage/Transaction.java b/src/main/java/fr/miage/Transaction.java old mode 100644 new mode 100755 index 6c6e7b5..e52ca8e --- a/src/main/java/fr/miage/Transaction.java +++ b/src/main/java/fr/miage/Transaction.java @@ -1,25 +1,83 @@ package fr.miage; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Signature; +import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.UUID; public class Transaction { private UUID id; + private Wallet sender; + private Wallet receiver; private List<UTxO> inputs; private List<UTxO> outputs; - private String signature; private EnumTypeTransaction typeTransaction; public Transaction(List<UTxO> inputs, List<UTxO> outputs, String signature, EnumTypeTransaction typeTransaction) { this.inputs = inputs; this.outputs = outputs; - this.signature = signature; + this.typeTransaction = typeTransaction; + this.id = UUID.randomUUID(); + } + + public Transaction(Wallet sender, Wallet receiver ,double amount, EnumTypeTransaction typeTransaction) { + this.inputs = sender.getUTxOsForTransaction(amount); + if (inputs != null ) { + if(isValidTransaction(inputs)){ + this.sender = sender; + this.receiver = receiver; + this.typeTransaction = typeTransaction.NORMAL; + this.id = UUID.randomUUID(); + UTxO utxoAmount = new UTxO(receiver.getPublicKey(), getTotalAmountUtxoInput(inputs)); // peut etre changr par amout + this.receiver.addUTxO(utxoAmount); + UTxO utxoRest = new UTxO(sender.getPublicKey(), getTotalAmountUtxoInput(inputs) - amount); + this.sender.addUTxO(utxoRest); + this.outputs = Arrays.asList(utxoAmount, utxoRest); + updateSetUtxo(); + } else { + System.err.println("Transaction invalide, utxo absent"); + } + } else { + System.out.println("Solde insuffisant"); + } + } + + public void updateSetUtxo(){ + Blockchain.utxos.clear(); + Blockchain.utxos.addAll(this.outputs); + } + + // public void signTransaction() throws NoSuchAlgorithmException{ + // Signature signature = Signature.getInstance("SHA256withRSA"); + // signature.initSign(sender.getPrivateKey()); + // } + + public double getTotalAmountUtxoInput(List<UTxO> inputs) { + double total = 0; + for (UTxO utxo : inputs) { + total += utxo.getMontant(); + } + return total; + } + + public boolean isValidTransaction( List<UTxO> inputs) { + boolean isValid = true; + for (UTxO utxo : inputs) { + if (!Blockchain.utxos.contains(utxo)) { + isValid = false; + } + } + return isValid; } public UUID getId() { return this.id; } + public void setId(UUID id) { this.id = id; } @@ -32,9 +90,6 @@ public class Transaction { return this.outputs; } - public String getSignature() { - return this.signature; - } public EnumTypeTransaction getTypeTransaction() { return this.typeTransaction; @@ -46,7 +101,6 @@ public class Transaction { " id='" + getId() + "'" + ", inputs='" + getInputs() + "'" + ", outputs='" + getOutputs() + "'" + - ", signature='" + getSignature() + "'" + ", typeTransaction='" + getTypeTransaction() + "'" + "}"; } diff --git a/src/main/java/fr/miage/UTxO.java b/src/main/java/fr/miage/UTxO.java old mode 100644 new mode 100755 index d151088..fbdf1e6 --- a/src/main/java/fr/miage/UTxO.java +++ b/src/main/java/fr/miage/UTxO.java @@ -2,30 +2,41 @@ package fr.miage; import java.util.UUID; -public class UTxO { +public class UTxO implements Comparable { //UTXO : Hash qui renvoie a la transaction d'avant - private UUID uuid; - private Transaction transaction; // transaction précédente (provenance de l'argent) --> peut etre meme que le hash de la transaction + private UUID uuid; // identifiant + private String transactionHash; // transaction de provenance de l'Utxo (provenance de l'argent) --> peut etre meme que le hash de la transaction private double montant; - public UTxO(Transaction transaction, double montant) { - this.transaction = transaction; + public UTxO(String transactionHash, double montant) { + this.transactionHash = transactionHash; this.montant = montant; } - public Transaction getTransaction() { - return this.transaction; + public String getTransaction() { + return this.transactionHash; } public double getMontant() { return this.montant; } + + @Override public String toString() { - return "{" + - "transaction='" + getTransaction() + "'" + - ", montant='" + getMontant() + "'" + - "}"; + return "UTxO [uuid=" + uuid + ", transactionHash=" + transactionHash + ", montant=" + montant + "]"; + } + + @Override + public int compareTo(Object o) { + UTxO utxo = (UTxO) o; + if (this.montant > utxo.getMontant()) { + return 1; + } else if (this.montant < utxo.getMontant()) { + return -1; + } else { + return 0; + } } } diff --git a/src/main/java/fr/miage/Wallet.java b/src/main/java/fr/miage/Wallet.java index cf65318..9beca0f 100644 --- a/src/main/java/fr/miage/Wallet.java +++ b/src/main/java/fr/miage/Wallet.java @@ -1,9 +1,13 @@ package fr.miage; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Wallet { @@ -12,14 +16,50 @@ public class Wallet { private double solde; private List<UTxO> utxos; - public Wallet(String publicKey, String privateKey) { - this.publicKey = publicKey; + public Wallet(String privateKey, String name) throws NoSuchAlgorithmException, InterruptedException { this.privateKey = privateKey; + initWallet(); + createKeyPair(privateKey, name); + } + + public void initWallet() throws NoSuchAlgorithmException { + this.publicKey = hashSha256(this.privateKey); this.utxos = new ArrayList<>(); } - public void initWallet(byte[] data) throws NoSuchAlgorithmException { + public void createKeyPair(String privateKey, String name) throws InterruptedException{ + + String command = "keytool -genkeypair -alias wallet_"+name+" -keyalg RSA -keysize 2048 -dname \"CN=" + name + "\" -validity 365 -storetype JKS -keystore keystore.jks -storepass \"" + privateKey + "\""; + + System.out.println(command); + ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+")); + processBuilder.redirectErrorStream(true); + try { + Process process = processBuilder.start(); + OutputStream outputStream = process.getOutputStream(); + outputStream.write("\n".getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + + InputStream inputStream = process.getInputStream(); + InputStream errorStream = process.getErrorStream(); + byte[] buffer = new byte[1024]; + int bytesRead; + + while ((bytesRead = inputStream.read(buffer)) != -1) { + System.out.write(buffer, 0, bytesRead); + } + + while ((bytesRead = errorStream.read(buffer)) != -1) { + System.err.write(buffer, 0, bytesRead); + + } + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Erreur lors de la création du keypair"); + } + System.out.println("Le wallet de " + name + " a été créé avec succès"); } private String hashSha256(String privateKey) throws NoSuchAlgorithmException { @@ -28,6 +68,27 @@ public class Wallet { return new String(hash, StandardCharsets.UTF_8); } + public List<UTxO> getUTxOsForTransaction(double amount) { + List<UTxO> result = new ArrayList<>(); + int res = 0; + boolean stop = false; + Collections.sort(this.utxos); + for (UTxO utxo : this.utxos) { + if(res >= amount) { + stop = true; + } + if (res < amount && !stop) { + result.add(utxo); + res += utxo.getMontant(); + } + } + if (res < amount) { + return null; + } else { + return result; + } + } + public String getPublicKey() { return this.publicKey; } diff --git a/target/classes/fr/miage/App.class b/target/classes/fr/miage/App.class index e101c779abed4e7b739e1fa70d480be8175b415c..e1089d23ed730878e852d327dc5414686a9f68fc 100644 GIT binary patch delta 838 zcmeyzwu6)F)W2Q(7#J8F8QdmvEw5)};Bu`<PAw?O%+D)kXAoj!P|HdzOVlq;O)f3U zEUDD@%MUJ1&T!00&o9a>$;gE(W@iv#WRL@^%}LBl*Z0gTNi8ZWEhtG%fve$U5Mz*F zXAoy(5I`slt}HG|&E;W`WRPNHn0Q&vPKJ>|+~x4fq|y?FlvIVBM1`cB{N(K9jKs`5 zE(SRU1$G8`Mh0Q90h#&w0Y#a4CBY>{sfoEf42ld&ll2)@990+@_|uB?b2AguQ}x3W zb8=EkI2hCz8AP*Ei%T<$a}twtQVWVQ%TiNPlk$@|7&I6en3M98xEPcfw0Ia;8MG%K zXVj`^XV7J2;DejvSWuv1$i<+;pbt`Fz{nt?;RBb1SYoXi#?D~G$RG?CcY?c}gTaK6 zf!8S~A0foWV8~zwGR&NjK}Ev{>?LsE1(y_M=IN(fLxf68GIR8UQ%kHh!x$M@5{uG{ z85xA5A#w=i>63$*lqK2A!M-hKWZ;J=fN7qr$D~m&=98bCm=l&*l$n^6lNwT4kQxGF zFfu5iDz?G!n4L8v16Oc<X;E^jTV_rwBLjzHL4h8~#f%I*o_TqxMb0^i#l@+`j11g< zsl_F}skuq1Ma2w?42%rS3?RV7z&LpYlLjOA<cmy_^-K%`3=9lx3``7y48jcT3=9mD z8CV!t7#J8dH!+9`NpEA2-OZpJDWoc-zMVnSXE%dRr1o|OJ>T67hLJ+XI@=jc{WdZ% zFfcQ4F)%QQF|aZ)Fz_>QFbFb;Fo-b7GDtCKFgP-BGcYh{K@4TEV6bFhU=U#tWw2tf zX7FZYkY(Uuuwk%eU}Df<U}UgkuxDUqaA06y;9-EtIWjOYFf%wYFfcGNI5W5~Ffed2 UFf!<XJj1}i;L5<jzyjg}0MA>>bN~PV delta 449 zcmdnN`Hzk3)W2Q(7#J8F8LTF9Emz=V5M&T$XAoj!5Xed_OVrOv%uCk~t}HG|&E;Vb zVGy0H$Ed(4KG~m9hE0+|nw>#vav`GxvkZgm<Q_&9b9qJv;j|+C+|0!ERDGwM{N(K9 zjKs`54hBU=241I}e1s4egB*i04+ATMEIWhh<c*9Xn(B-UTm_{`Iho1csg;Ht44RA# z+yzCMWr-!JAOS806$WjP2A#<t8MPES81#_U8*wlgpr|*Ryp~CRG6%Ej<TFePD%^=V znaQc)i8(o`C5#MQ!TF^{$*FFcIjM{c9F7GAdLXY(p2uuf&(6Tjz`(%6z{tSBz{<eG zz{|kEz{$YJz|X+Qz|O$H(9FQXz{0@5puLGfKuByGgT!tIxkw>}?F>pjyBSm>h17&J zwliq?g4w!4`r8?_{5CQ$FfcK2F)%QQF|aZ)FmN+)Fz_-6G4M0UF$gedF$jUJ)B+o; xugze{V8p<{AjBZaV9a2`z{nuSz{_CDV8+12pvAz*V9sF1z|6qNU;#GN5&$OhRxtno -- GitLab