-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
Java mock & multi node chainspace
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Chainspace | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
################################################################################## | ||
# Chainspace Mock | ||
# bank_transfer_checker.py | ||
# | ||
# version: 0.0.1 | ||
################################################################################## | ||
from __future__ import print_function # In python 2.7 | ||
import sys | ||
from json import loads, dumps | ||
from flask import Flask, request | ||
|
||
|
||
|
||
################################################################################## | ||
# checker | ||
################################################################################## | ||
|
||
# ------------------------------------------------------------------------------- | ||
# helper | ||
# ------------------------------------------------------------------------------- | ||
def ccheck(V, msg): | ||
if not V: | ||
raise Exception(msg) | ||
|
||
# ------------------------------------------------------------------------------- | ||
# checker | ||
# ------------------------------------------------------------------------------- | ||
def checker_function(T): | ||
|
||
print(T) | ||
|
||
# check transfer's format | ||
ccheck(T["contractMethod"] == r"http://127.0.0.1:5001/bank/transfer", "Wrong Method") | ||
ccheck(len(T["referenceInputs"]) == 0, "Expect no references") | ||
|
||
# retrieve inputs | ||
from_account, to_account = T[u"inputs"] | ||
amount = T[u"parameters"]["amount"] | ||
from_account_new, to_account_new = T[u"outputs"] | ||
|
||
# check positive amount | ||
ccheck(0 < amount, "Transfer should be positive") | ||
|
||
# check sender and receiver account | ||
ccheck(from_account["accountId"] == from_account_new["accountId"], "Old and new account do not match") | ||
ccheck(to_account["accountId"] == to_account_new["accountId"], "Old and new account do not match") | ||
|
||
# check that the sender has enough fundings | ||
ccheck(amount <= from_account["amount"], "No funds available") | ||
|
||
# check inntegrity of the operation | ||
ccheck(from_account["amount"] - amount == from_account_new["amount"], "Incorrect new balance") | ||
ccheck(to_account["amount"] + amount == to_account_new["amount"], "Incorrect new balance") | ||
|
||
# return | ||
return {"status": "OK"} | ||
|
||
|
||
|
||
################################################################################## | ||
# webapp | ||
################################################################################## | ||
# the state of the infrastructure | ||
app = Flask(__name__) | ||
|
||
# ------------------------------------------------------------------------------- | ||
# /bank/transfer | ||
# checker the correctness of a bank transfer | ||
# ------------------------------------------------------------------------------- | ||
@app.route("/bank/transfer", methods=["GET", "POST"]) | ||
def check(): | ||
if request.method == "POST": | ||
try: | ||
return dumps(checker_function(loads(request.data))) | ||
except KeyError as e: | ||
return dumps({"status": "Error", "message": e.args}) | ||
except Exception as e: | ||
return dumps({"status": "Error", "message": e.args}) | ||
else: | ||
return dumps({"status": "Error", "message":"Use POST method."}) | ||
|
||
|
||
################################################################################## | ||
# execute | ||
################################################################################## | ||
if __name__ == "__main__": | ||
app.run(host="127.0.0.1", port="5001") | ||
|
||
|
||
################################################################################## |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,18 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module type="JAVA_MODULE" version="4"> | ||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true"> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
<orderEntry type="library" name="gson-2.6.2" level="project" /> | ||
<orderEntry type="library" name="httpcore-4.4.6" level="project" /> | ||
<orderEntry type="library" name="httpclient-4.5.3" level="project" /> | ||
<orderEntry type="library" name="commons-logging-1.2" level="project" /> | ||
<orderEntry type="library" name="json-20140107" level="project" /> | ||
<orderEntry type="library" name="json-simple-1.1.1" level="project" /> | ||
<orderEntry type="library" name="sqlite-jdbc-3.18.0" level="project" /> | ||
</component> | ||
</module> | ||
|
||
</module> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package uk.ac.ucl.cs.sec.chainspace; | ||
|
||
|
||
/** | ||
* Custom exception. Thrown when a chainspace transaction aborts. | ||
*/ | ||
class AbortTransactionException extends Exception { | ||
|
||
/** | ||
* Message constructor. | ||
* | ||
* @param message the error message. | ||
*/ | ||
AbortTransactionException(String message) { | ||
|
||
super(message); | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,145 @@ | ||
package uk.ac.ucl.cs.sec.chainspace; | ||
|
||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import uk.ac.ucl.cs.sec.chainspace.examples.BankAccount; | ||
|
||
import java.io.IOException; | ||
import java.sql.SQLException; | ||
|
||
|
||
/** | ||
* Main class. | ||
* This class run two tests ( test1() and test2() ) testing chainspace. They rely on the example client BankTransaction, | ||
* and the python checker bank_transfer_checker.py should be running. | ||
*/ | ||
public class Main { | ||
|
||
|
||
/* | ||
This list keeps all the node instances that are used for test2(). See below. | ||
*/ | ||
static Node[] nodeList; | ||
|
||
/** | ||
* Main method. | ||
* | ||
* @param args args. | ||
*/ | ||
public static void main(String[] args) { | ||
// write your code here | ||
|
||
try { | ||
|
||
/* | ||
This first test execute a transaction in the case where the system is composed of a single node. Therefore, | ||
all input objects are kept by the same database. | ||
*/ | ||
test1(); | ||
|
||
/* | ||
This second test suppose six nodes, grouped into two shards. The transaction is submitted to all the nodes. | ||
Each node process the transaction and ask to the other nodes if they are missing some inputs. | ||
(We suppose that all nodes included in the same shard are sharing the same database). | ||
*/ | ||
test2(); | ||
|
||
} catch (SQLException | ClassNotFoundException | IOException | AbortTransactionException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Test1. all objects are in the same node. | ||
* | ||
* @throws SQLException SQLException. | ||
* @throws ClassNotFoundException ClassNotFoundException. | ||
* @throws IOException IOException. | ||
* @throws AbortTransactionException ChainspaceException. | ||
*/ | ||
private static void test1() throws SQLException, ClassNotFoundException, IOException, AbortTransactionException { | ||
// init | ||
Gson gson = new GsonBuilder().create(); | ||
|
||
// checker url | ||
String checkerURL = "http://127.0.0.1:5001/bank/transfer"; | ||
|
||
// create Alice's account | ||
BankAccount aliceAccount = new BankAccount("Alice", 10); | ||
BankAccount sallyAccount = new BankAccount("Sally", 0); | ||
String aliceAccountJson = gson.toJson(aliceAccount); | ||
String sallyAccountJson = gson.toJson(sallyAccount); | ||
|
||
// create transfer | ||
Transaction transfer = aliceAccount.sendMoney(sallyAccount, 8, checkerURL); | ||
|
||
// instantiate the node | ||
Node node = new Node(1); | ||
|
||
// register objects | ||
node.registerObject(aliceAccountJson); | ||
node.registerObject(sallyAccountJson); | ||
|
||
// apply transaction | ||
// Note that the transaction is first changed to JSON: nodes accept only transaction in JSON format. | ||
node.applyTransaction(gson.toJson(transfer)); | ||
|
||
// shut down the node | ||
node.shutdown(); | ||
} | ||
|
||
|
||
|
||
/** | ||
* Test2. the transaction requires an input from each node. | ||
* | ||
* @throws SQLException SQLException. | ||
* @throws ClassNotFoundException ClassNotFoundException. | ||
* @throws IOException IOException. | ||
* @throws AbortTransactionException ChainspaceException. | ||
*/ | ||
private static void test2() throws SQLException, ClassNotFoundException, IOException, AbortTransactionException { | ||
|
||
// run nodes | ||
// Nodes should not run like this: each node should be an independent webservice. | ||
nodeList = new Node[]{ | ||
new Node(10), | ||
new Node(10), | ||
new Node(10), | ||
new Node(20), | ||
new Node(20), | ||
new Node(20), | ||
}; | ||
|
||
// init | ||
Gson gson = new GsonBuilder().create(); | ||
|
||
// checker url | ||
String checkerURL = "http://127.0.0.1:5001/bank/transfer"; | ||
|
||
// create Alice's account | ||
BankAccount aliceAccount = new BankAccount("Alice", 10); | ||
BankAccount sallyAccount = new BankAccount("Sally", 0); | ||
String aliceAccountJson = gson.toJson(aliceAccount); | ||
String sallyAccountJson = gson.toJson(sallyAccount); | ||
|
||
// create transfer | ||
Transaction transfer = aliceAccount.sendMoney(sallyAccount, 5, checkerURL); | ||
|
||
// register objects | ||
nodeList[0].registerObject(aliceAccountJson); | ||
nodeList[3].registerObject(sallyAccountJson); | ||
|
||
// apply transaction | ||
|
||
for (Node node: nodeList) { | ||
node.applyTransaction(gson.toJson(transfer)); | ||
} | ||
|
||
// shut down the node | ||
for (Node node: nodeList) { | ||
node.shutdown(); | ||
} | ||
} | ||
} |