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