import [Link];import [Link].
PublicKey;public class Wallet { public PrivateKey
privateKey; public PublicKey publicKey;
}
public void generateKeyPair() { try { KeyPairGenerator keyGen =
[Link]("ECDSA", "BC"); SecureRandom random =
[Link]("SHA1PRNG"); ECGenParameterSpec ecSpec = new
ECGenParameterSpec("prime192v1"); [Link](ecSpec, random); KeyPair keyPair =
[Link](); // on récupère les clés générées pour notre Wallet privateKey =
[Link](); publicKey = [Link](); } catch (Exception e) { throw new
RuntimeException(e); }
}
import [Link];import [Link];import [Link];public class
Transaction { public String transactionId; public PublicKey sender; public PublicKey recipient;
public float value; public byte[] signature; public ArrayList<TransactionInput> inputs = new
ArrayList<TransactionInput>(); public ArrayList<TransactionOutput> outputs = new
ArrayList<TransactionOutput>(); // Nombre de transactions générées private static int sequence = 0;
public Transaction(PublicKey from, PublicKey to, float value, ArrayList<TransactionInput> inputs) {
[Link] = from; [Link] = to; [Link] = value; [Link] = inputs; } // ...
}
import [Link];import [Link];import [Link];public
class Utils { // Application d'une signature avec les courbes elliptiques (ECDSA) public static byte[]
applyECDSASig(PrivateKey privateKey, String input) { Signature dsa; byte[] output = new byte[0];
try { dsa = [Link]("ECDSA", "BC"); [Link](privateKey); byte[] strByte =
[Link](); [Link](strByte); byte[] realSig = [Link](); output = realSig; } catch
(Exception e) { throw new RuntimeException(e); } return output; } // Vérification de la signature
pour les données d'entrée public static boolean verifyECDSASig(PublicKey publicKey, String data,
byte[] signature) { try { Signature ecdsaVerify = [Link]("ECDSA", "BC");
[Link](publicKey); [Link]([Link]()); return
[Link](signature); } catch (Exception e) { throw new RuntimeException(e); } } // ...
}
public class Transaction { // ... private String calculateHash() { sequence++; return
Utils.applySha256([Link](sender) + [Link](recipient) +
[Link](value) + sequence); } public void generateSignature(PrivateKey privateKey) {
String data = [Link](sender) + [Link](recipient)
+ [Link](value); signature = [Link](privateKey, data); } public
boolean verifiySignature() { String data = [Link](sender) +
[Link](recipient) + [Link](value); return
[Link](sender, data, signature); } // ...
}
public class TransactionInput { public String transactionOutputId; public TransactionOutput UTXO;
public TransactionInput(String transactionOutputId) { [Link] = transactionOutputId;
}
}
import [Link];public class TransactionOutput { public String id; public PublicKey
recipient; public float value; public String parentTransactionId; public TransactionOutput(PublicKey
recipient, float value, String parentTransactionId) { [Link] = recipient; [Link] = value;
[Link] = parentTransactionId; [Link] =
Utils.applySha256([Link](recipient) + [Link](value) +
parentTransactionId); } public boolean isMine(PublicKey publicKey) { return (publicKey ==
recipient); }
}
public class Transaction { // ... public boolean processTransaction() { if (verifiySignature() == false) {
[Link]("Echec de vérification de la signature de la Transaction"); return false; } // On
associe les données des transactions entrantes for (TransactionInput i : inputs) { [Link] =
[Link]([Link]); } // On vérifie que la transaction est valide if
(getInputsValue() < [Link]) { [Link]("Somme montant des
transactions entrantes trop faible : " + getInputsValue()); [Link]("Le montant doit être
plus grand que : " + [Link]); return false; } // Génération des
transactions sortantes // Calcul montant restant float leftOver = getInputsValue() - value;
transactionId = calulateHash(); // prise en compte envoi du montant au destinataire [Link](new
TransactionOutput([Link], value, transactionId)); // prise en compte montant restant pour
l'expéditeur [Link](new TransactionOutput([Link], leftOver, transactionId)); // Ajout aux
transactions non dépensées de la Blockchain for (TransactionOutput o : outputs) {
[Link]([Link], o); } // Suppression de ces transactions de la liste UTXOs de la
Blockchain for (TransactionInput i : inputs) { if ([Link] == null) continue;
[Link]([Link]); } return true; } public float getInputsValue() { float total =
0; for (TransactionInput i : inputs) { if ([Link] == null) continue; total += [Link];
} return total; } // ...
}
public class Wallet { // ... // Retourne le montant disponible dans le Wallet public float getBalance() {
float total = 0; for ([Link]<String, TransactionOutput> item : [Link]()) {
TransactionOutput UTXO = [Link](); if ([Link](publicKey)) { // on ajoute
uniquement le montant des transactions appartenant à ce wallet [Link]([Link], UTXO);
total += [Link]; } } return total; } public Transaction sendFunds(PublicKey recipient, float
value) { if (getBalance() < value) { [Link]("Manque de fonds pour créer la
transaction"); return null; } ArrayList<TransactionInput> inputs = new
ArrayList<TransactionInput>(); float total = 0; for ([Link]<String, TransactionOutput> item :
[Link]()) { TransactionOutput UTXO = [Link](); total += [Link];
[Link](new TransactionInput([Link])); if (total > value) break; } Transaction
newTransaction = new Transaction(publicKey, recipient, value, inputs);
[Link](privateKey); for (TransactionInput input : inputs) {
[Link]([Link]); } return newTransaction; }
}
public static String getMerkleRoot(ArrayList<Transaction> transactions) { int count =
[Link](); ArrayList<String> previousTreeLayer = new ArrayList<String>(); for (Transaction
transaction : transactions) { [Link]([Link]); } ArrayList<String>
treeLayer = previousTreeLayer; while (count > 1) { treeLayer = new ArrayList<String>(); for (int i
= 1; i < [Link](); i++) { [Link](applySha256([Link](i - 1) +
[Link](i))); } count = [Link](); previousTreeLayer = treeLayer; } String
merkleRoot = ([Link]() == 1) ? [Link](0) : ""; return merkleRoot;
}
public class Block { // ... public ArrayList<Transaction> transactions = new ArrayList<Transaction>();
// ... public void mineBlock(int difficulty) { String merkleRoot = [Link](transactions);
data = (!"".equals(merkleRoot)) ? merkleRoot : data; nonce = 0; while (!getHash().substring(0,
difficulty).equals([Link](difficulty))) { nonce++; hash = [Link](this); } }
public boolean addTransaction(Transaction transaction) { if (transaction == null) return false; if
(previousHash != null) { if (![Link]()) { [Link]("Transaction
non valide. Ajout annulé"); return false; } } [Link](transaction);
[Link]("Transaction ajoutée avec succès au bloc"); return true; }
}
import [Link];import [Link];import [Link];import
[Link];public class Blockchain { public static float minimumTransaction = 0.1f; private int
difficulty; private List<Block> blocks;
public static HashMap<String, TransactionOutput> UTXOs = new HashMap<String,
TransactionOutput>();
public Wallet walletA; public Wallet walletB; public Transaction genesisTransaction; public
Blockchain(int difficulty) { [Link](new
[Link]()); // Création des Wallets walletA = new
Wallet(); walletB = new Wallet(); Wallet baseWallet = new Wallet(); // Transaction genèse
genesisTransaction = new Transaction([Link], [Link], 100f, null); //
Signature de de la transaction [Link]([Link]);
[Link] = "0";
[Link](new TransactionOutput([Link],
[Link], [Link]));
// Ajout à la liste UTXOs des transactions non dépensées
[Link]([Link](0).id, [Link](0)); [Link] =
difficulty; blocks = new ArrayList<>(); // Création du bloc genèse Block b = new Block(0,
[Link](), null, "Genesis Block"); [Link](genesisTransaction);
[Link](difficulty); // Ajout du Bloc addBlock(b); } // ...
}
public static void main(String[] args) { Blockchain blockchain = new Blockchain(4);
[Link]("\nWallet A montant : " + [Link]());
[Link]("Wallet A essaie d'envoyer 40 au Wallet B ..."); Block b =
[Link]("Block 2");
[Link]([Link]([Link], 40f));
[Link](b); [Link]("Wallet A montant : " + [Link]());
[Link]("Wallet B montant : " + [Link]());
[Link]("\nWallet A essaie d'envoyer plus (100) que ce qu'il possède ..."); b =
[Link]("Block 3");
[Link]([Link]([Link], 1000f));
[Link](b); [Link]("Wallet A montant : " + [Link]());
[Link]("Wallet B montant : " + [Link]());
[Link]("\nWallet B essaie d'envoyer 20 au Wallet A ..."); [Link]("Wallet A essaie
d'envoyer 10 au Wallet B ..."); b = [Link]("Block 4");
[Link]([Link]([Link], 20f));
[Link]([Link]([Link], 10f));
[Link](b); [Link]("Wallet A montant : " + [Link]());
[Link]("Wallet B montant : " + [Link]()); [Link]();
[Link](blockchain); [Link]("Blockchain valide : " +
([Link]() ? "Oui" : "Non"));
}