Solution Mid Term 2017 Advanced Programming Giuseppe Attardi

  • Slides: 19
Download presentation
Solution Mid. Term 2017 Advanced Programming Giuseppe Attardi Università di Pisa

Solution Mid. Term 2017 Advanced Programming Giuseppe Attardi Università di Pisa

General Remarks l Follow good programming guidelines – eg: – https: //github. com/twitter/commons/blob/mast er/src/java/com/twitter/common/styleguide.

General Remarks l Follow good programming guidelines – eg: – https: //github. com/twitter/commons/blob/mast er/src/java/com/twitter/common/styleguide. md l In particular: –NEVER, EVER USE global variables: they hinder parallelism l Use exceptions sparingly (and handle them) l Use strings sparingly (String. Buffer)

Use Object Oriented Programming l USE Polymorphism, USE Polymorphism makes your code more modular,

Use Object Oriented Programming l USE Polymorphism, USE Polymorphism makes your code more modular, more readable, more extensible l Avoid using Reflection (instanceof) l Avoid static methods, aka functions, in OOP l Avoid functions for similar tasks: use polymorphic method in each of the classes where the operation is needed

Bad Example class Utils { static String bytes. To. String(); static String inputsto. String();

Bad Example class Utils { static String bytes. To. String(); static String inputsto. String(); static String outputs. To. String(); … { l Alternative: – Use method serialize() in each class

Exercise 1

Exercise 1

Hash class Hash { private static final Message. Digest md = Message. Digest. get.

Hash class Hash { private static final Message. Digest md = Message. Digest. get. Instance(“SHA-256”); public byte[] code; public Hash(byte[] bytes) { code = md. digest(bytes); } boolean is. Valid() { return code[0] == 0 && … code[2] == 0; } } boolean equals(Hash other) { return Arrays. equals(code, other. code); }

Input class Input extends Pair<Hash, Integer> { // Hash for transaction, Integer for index

Input class Input extends Pair<Hash, Integer> { // Hash for transaction, Integer for index in outputs public Input(Transaction t, int idx) { super(new Hash(t. serialize()), idx); } public byte[] serialize() { byte[] hash = get. Key(). code; byte bb = Byte. Buffer. allocate(hash. length + 4); bb. put(hash). put. Int(get. Value()); return bb. array(); } } class Output extends Pair<Integer, Public. Key> { public Output(int v, Public. Key key) { { … public byte[] serialize() { { … {

Transaction class Transaction implements Serializable { private List<Input> inputs; private List<Output> outputs; private byte[]

Transaction class Transaction implements Serializable { private List<Input> inputs; private List<Output> outputs; private byte[] signature; public Transaction() { inputs = new Array. List<>(); outputs = new Array. List<>(); } public add(Input i) { inputs. add(i); } public add(Output o) { outputs. add(o); }

Transaction public void sign(Private. Key key) { Signature s = new Signature(”SHA 256 with.

Transaction public void sign(Private. Key key) { Signature s = new Signature(”SHA 256 with. RSA”); s. init(key); for (Input i : inputs) s. update(i. serialize()); for (Output o : outputs) s. update(o. serialize()); signature = s. sign(); } public byte[] serialize() { byte bs = Byte. Array. Output. Stream(); for (Input i : inputs) bs. write(i. serialize()); for (Output o : outputs) bs. write(o. serialize()); bs. write(signature); return bs. to. Byte. Array(); }

Block class Block implements Serializable { private int seq; private int nonce = -1;

Block class Block implements Serializable { private int seq; private int nonce = -1; private Hash previous; private Transaction t; public Block(int seq, Hash previous, Transaction t) { { … public hash() { return new Hash(serialize()); } public int mine() { Hash hash; do { nonce++; hash = this. hash(); } while (!hash. is. Valid()) return nonce; }

Block public byte[] serialize() { byte bs = Byte. Array. Output. Stream(); bs. write(Byte.

Block public byte[] serialize() { byte bs = Byte. Array. Output. Stream(); bs. write(Byte. Buffer. allocate(4). put. Int( seq). array()); bs. write(Byte. Buffer. allocate(4). put. Int( nonce). array()); bs. write(previous. hash()); bs. write(t. serialize()); return bs. to. Byte. Array(); }

Exercise 2

Exercise 2

Block. Chain class Block. Chain { private List<Block> chain = new Linked. List<>();

Block. Chain class Block. Chain { private List<Block> chain = new Linked. List<>();

 boolean is. Valid. Block. Chain() { Map<Hash, Bit. Set> spent. Outputs = new

boolean is. Valid. Block. Chain() { Map<Hash, Bit. Set> spent. Outputs = new Hash. Map<>(); Hash current = null; // current block in chain for (Block next : chain) { // next block in chain Transaction tx = next. transaction; if (current == null) { spent. Outputs. put(new Hash(tx. serialize()), new Bit. Set(tx. get. Outputs(). size())); current = next; continue; } Hash previous = current. previous(); Hash hash = next. hash(); if (!hash. is. Valid() || !hash. equals(previous)) // current block must refer to next one return false; for (Input input : tx. get. Inputs()) { if (spent. Outputs. compute. If. Present(input. get. Key(), // update spent. Outputs (k, v) -> { if (v. get(input. get. Value())) // already spent output at index input. get. Value() return null; v. set(input. get. Value()); // update return v; // put back into Map }) == null) return false; } spent. Outputs. put(new Hash(tx. serialize()), new Bit. Set(tx. get. Outputs(). size())); current = next; } return true;

public int get. Balance(Public. Key user) { Map<Hash, Bit. Set> spent. Outputs = new

public int get. Balance(Public. Key user) { Map<Hash, Bit. Set> spent. Outputs = new Hash. Map<>(); Iterator <Block> it = chain. descending. Iterator(); // from last to first while (it. has. Next()) { Block b = it. next(); Transaction tx = b. transaction(); Hash hash = new Hash(tx); List<Output> outputs = tx. get. Outputs(); for (int i = 0; i < outputs. size(); i++) { Output o = outputs. get(i); if (user. equals(o. get. Value()) && (spent. Outputs. get(hash) == null || !spent. Outputs. get(hash). get(i))) balance += o. get. Key(); } // now add the outputs to the map spent. Outputs for (Input in : tx. get. Inputs()) spent. Outputs. compute. If. Absent(in. get. Key(), v -> new Bit. Set()). set(in. get. Value())); } return balance; }

Exercise 3

Exercise 3

 public static void main(String args[]) { String input; String[] tokens; Scanner reader =

public static void main(String args[]) { String input; String[] tokens; Scanner reader = new Scanner(System. in); init(); do { System. out. print("> "); input = reader. next. Line(). trim(); } while (input. equals("")); tokens = input. split("\s+"); switch (tokens[0]) { case "status": print. Block. Chain(); break; case "check": if (chain. is. Valid. Block. Chain()) System. out. println("The block chain is valid!"); else System. out. println("The block chain is not valid. "); break;

Exercise 4

Exercise 4

A closure is a functional object that consists of a function and the lexical

A closure is a functional object that consists of a function and the lexical environment at the time of its creation. The environment contains the bindings for the non local variables visible in the scope of the function. l In C#, a delegate type is a type that represents functions with a given signature. l A delegate instance is created on an object and a method on that object compatible with its signature. l A delegate instance can be used as a function by invoking it with arguments, and this corresponds to invoking the delegate method on the delegate target with the given arguments. l