diff --git a/.gitignore b/.gitignore index 4cdc72a..3652ccd 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ testem.log .DS_Store Thumbs.db *.iml + +local-maven-repo/blockchain-access-layer-api*.jar \ No newline at end of file diff --git a/README.md b/README.md index 24e288f..c6f57de 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,35 @@ # Blockchain Access Layer (BAL) - SCIP Gateway -BAL is an extensible abstraction layer that allows client applications to access permissioned and permissionless blockchains using a uniform interface. -BAL is designed to support business process management systems to access blockchains using the [Blockchain Modeling and Execution (BlockME) method](https://link.springer.com/article/10.1007/s00450-019-00399-5). +BAL is an extensible abstraction layer that allows client applications to access permissioned and permissionless +blockchains using a uniform interface. BAL is designed to support business process management systems to access +blockchains using +the [Blockchain Modeling and Execution (BlockME) method](https://link.springer.com/article/10.1007/s00450-019-00399-5). It also implements the [Smart Contract Invocation Protocol (SCIP)](https://github.com/lampajr/scip) as a gateway. -BAL is a Java 8 web application that uses Jersey to expose a [RESTful API](#restful-api) and a [JSON-RPC API](#json-rpc-api). +BAL is a Java 8 web application that uses Jersey to expose a [RESTful API](#restful-api) and +a [JSON-RPC API](#json-rpc-api). ## Configuration -BAL allows simultaneous access to multiple blockchain systems. -Currently, [Ethereum](https://ethereum.org/), [Bitcoin](https://bitcoin.org/), and [Hyperledger Fabric](https://www.hyperledger.org/projects/fabric) are supported. -- To access the Ethereum blockchain, BAL needs to be able to communicate with a [geth node](https://github.com/ethereum/go-ethereum) -which has RPC connections enabled. Furthermore, BAL directly accesses the keystore file holding the private key of an Ethereum account used for sending and receiving transactions. -- To access the Bitcoin blockchain, BAL needs to be able to communicate with a [bitcoind node](https://bitcoin.org/en/bitcoin-core/) -which has RPC connections enabled. -- To access a given Hyperledger Fabric network, it needs to have access to a wallet file with authorized users, and an appropriate [connection profile](https://hyperledger-fabric.readthedocs.io/en/latest/developapps/connectionprofile.html). +BAL allows simultaneous access to multiple blockchain systems. Currently, [Ethereum](https://ethereum.org/) +, [Bitcoin](https://bitcoin.org/), and [Hyperledger Fabric](https://www.hyperledger.org/projects/fabric) are supported. + +- To access the Ethereum blockchain, BAL needs to be able to communicate with + a [geth node](https://github.com/ethereum/go-ethereum) + which has RPC connections enabled. Furthermore, BAL directly accesses the keystore file holding the private key of an + Ethereum account used for sending and receiving transactions. +- To access the Bitcoin blockchain, BAL needs to be able to communicate with + a [bitcoind node](https://bitcoin.org/en/bitcoin-core/) + which has RPC connections enabled. +- To access a given Hyperledger Fabric network, it needs to have access to a wallet file with authorized users, and an + appropriate [connection profile](https://hyperledger-fabric.readthedocs.io/en/latest/developapps/connectionprofile.html) + . ### Configuring Access to Multiple Blockchains -BAL expectes a configuration file with the name `connectionProfiles.json` inside the path `[User Folder]/.bal/`. -An example for this file that accesses a geth node, a bitcoind node and a Hyperledger Fabric network is: + +BAL expectes a configuration file with the name `connectionProfiles.json` inside the path `[User Folder]/.bal/`. An +example for this file that accesses a geth node, a bitcoind node and a Hyperledger Fabric network is: + ```[json] { "eth-0": { @@ -26,7 +37,7 @@ An example for this file that accesses a geth node, a bitcoind node and a Hyperl "nodeUrl":"http://localhost:7545", "keystorePath":"C:\\Ethereum\\keystore\\UTC--2019-05-30T11-21-08.970000000Z--90645dc507225d61cb81cf83e7470f5a6aa1215a.json", "keystorePassword":"123456789", - "adversaryVotingRatio": "0.2", + "adversaryVotingRatio": 0.2, "pollingTimeSeconds": 2 }, "btc-0" : { @@ -53,25 +64,55 @@ An example for this file that accesses a geth node, a bitcoind node and a Hyperl ## Building and Deployment -After cloning, you can build the project and package it into a WAR -file using the following command: +After cloning, you can build the project and package it into a WAR file using the following command: + ``` mvn install ``` -Then, the WAR file (which can be found in the folder 'target' generated after -a successful build) can be deployed on an Apache Tomcat server. -**Notice:** the build requires a library (btcd-cli4j) to communicate with the Bitcoin Core node. [The used library](https://github.com/pythonmax/btcd-cli4j) is forked from an [unmaintained library](http://btcd-cli4j.neemre.com) to fix some issues resulting from changes in the recent versions of the Bitcoin Core node. However, the used library is not available in a public Maven repository, so we had to provide a local Maven repository which includes the required binaries. This repository is found [here](local-maven-repo). +Then, the WAR file (which can be found in the folder 'target' generated after a successful build) can be deployed on an +Apache Tomcat server. + +Required VM options while running + +- `pf4j.pluginsDir` path where the plugins will be stored + +## Plugin management + +The project uses pf4j framework for managing the plugins. The application exposes RESTful APIs to: + +- Upload the plugins as jar +- Remove plugins +- Get list of plugins with status +- Start plugin +- Disable plugin + +### Supported plugins + +- [Ethereum](https://github.com/TIHBS/blockchain-access-layer-ethereum-plugin) +- [Bitcoin](https://github.com/TIHBS/blockchain-access-layer-bitcoin-plugin) +- [Fabric](https://github.com/TIHBS/blockchain-access-layer-fabric-plugin) + +One can create their own plugin. A plugin should: + +- Use the core [api](https://github.com/TIHBS/blockchain-access-layer-api). +- +Implement [IAdapterExtension](https://github.com/TIHBS/blockchain-access-layer-api/blob/main/src/main/java/blockchains/iaas/uni/stuttgart/de/api/IAdapterExtenstion.java) +interface. +- Define a [Plugin](https://pf4j.org/doc/plugins.html). +- Provide a class that + extends [AbstractConnectionProfile](https://github.com/TIHBS/blockchain-access-layer-api/blob/main/src/main/java/blockchains/iaas/uni/stuttgart/de/api/connectionprofiles/AbstractConnectionProfile.java) ## Accessing the APIs ### RESTful API + The application exposes an asynchronous RESTful API to subscribe and unsubscribe from the provided operations. **To summarize:** -The RESTful api provides the following resources/methods: -* A POST method is provided for each of the following -paths to create the corresponding subscription: +The RESTful api provides the following resources/methods: + +* A POST method is provided for each of the following paths to create the corresponding subscription: ``` {application-URL}/webapi/submit-transaction @@ -84,8 +125,7 @@ paths to create the corresponding subscription: * A GET method is also provided for the aforementioned URLs that lists the currently active subscriptions. -* A DELETE method is provided in each of the following -paths to manually delete the corresponding subscription: +* A DELETE method is provided in each of the following paths to manually delete the corresponding subscription: ``` {application-URL}/webapi/submit-transaction/{subscription-id} @@ -96,130 +136,141 @@ paths to manually delete the corresponding subscription: {application-URL}/webapi/invoke-smart-contract-function ``` -### JSON-RPC API -BAL implements the [JSON-RPC binding](https://github.com/lampajr/scip#json-rpc-binding) described in the SCIP specifications. -It can be accessed with any standard [JSON-RPC client](https://www.jsonrpc.org/archive_json-rpc.org/implementations.html). +#### Plugin management RESTful apis: -## Setting Up Various Blockchains for Testing +In the current implementation, the plugin management apis do not require authentication. + +##### **POST** `/webapi/plugins/` + +- Example + +```bash +curl --location --request POST '{application-URL}/webapi/plugins/' \ +--form 'file=@"/blockchain-access-layer-ethereum-plugin-1.0.0.jar"' +``` -BAL needs to have access to a node for each blockchain instance it needs to communicate with. -These nodes can be already running nodes that you have access to. -Otherwise, you need to setup and manage your own nodes. -Below, are basic instructions how to setup Ethereum, Bitcoin, and Hyperledger Fabric nodes. - -### Running a Local geth Node -A geth node is used to access the Ethereum network. For development purposes, it is advised -not to connect to the main Ethereum network, but rather to one of the testnets. -(another, more difficult option would be to run a local private Ethereum network). -In order to connect a geth node to [Rinkeby](https://www.rinkeby.io) (one of Ethereum testnets), you can follow these steps: - -1. [Install geth](https://github.com/ethereum/go-ethereum/wiki/Installing-Geth): - this differs depending on your operating system. -2. Run geth in the fast-sync mode: This option downlaoads the whole blockchain but does not re-execute all transactions. Syncing -the whole testnet blockchain (which is done once only) takes about 1-4 hours (depending on the hardware, the speed of the network -connection, and the availability of peers). -To start a geth node in the fast-sync mode, execute the following command: - ``` - geth --rpcapi personal,db,eth,net,web3 --rpc --rinkeby --cache=2048 --rpcport "8545" - --bootnodes= - enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303, - enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303, - enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303 - ``` - If you want your node to be accessible remotely, apart from configuring your firewall, you also need to use the following extra option, - when running the node: ```--rpcaddr "0.0.0.0"``` -3. Test connection: you can test your connection to a running geth node using the following command -(make sure to install geth on the computer where you run this command):```geth attach http://localhost:8545``` -please replace _localhost_ with the ip address of the computer running the node. - -### Running a Local Bitcoin Core Node -A Bitcoin Core node (or _bitcoind_ node) is used to access the Bitcoin network. For development purposes, it is advised -not to connect to the main Bitcoin network, but rather to one of the testnets. -(another, more difficult option would be to run a local private Bitcoin network). -In order to connect a _bitcoind_ node to [testnet3](https://en.bitcoin.it/wiki/Testnet) (one of Bitcoin's testnets), you can follow these steps: - -1. [Install bitcoind](https://bitcoin.org/en/download): - this differs depending on your operating system. For the installation instructions on Ubuntu you can follow [these steps](https://gist.github.com/rjmacarthy/b56497a81a6497bfabb1). -2. Configure _bitcoind_: This can be done by editing and using the [`bitcoin.conf`](src/main/resources/bitcoin.conf) file when starting the bicoind daemon. -The configuration allows external rpc-based communication with the node, and instructs it to communicate with the testnet rather than -the mainnet. Furthermore, it orders the node to build an index on the blockchain that allows querying even historic transactions. Finally, it instructs the node -to send notifications to the BAL when it detects a new block or a transaction addressed to one of the Bitcoin wallet's addresses. -Syncing the whole testnet blockchain (which is done once only) takes about 1-4 hours (depending on the hardware, the speed of the network -connection, and the availability of peers). -3. Start the pre-configured _bitcoind_ node with the following command:```bitcoind -daemon``` -4. Test connection: you can test your connection to a running _bitcoind_ node using the following command -(make sure to install bitcoin-cli (shipped with _bitcoind_) on the computer where you run this command): +##### **GET** `/webapi/plugins/` + +- Example + +```bash +curl --location --request GET '{application-URL}/webapi/plugins/' ``` -bitcoin-cli -getinfo -rpcconnect= -rpcport= -rpcuser= -rpcpassword= + +##### **DELETE** `/webapi/plugins/{plugin-id}` + +- Example + +```bash +curl --location --request DELETE '{application-URL}/webapi/plugins/ethereum-plugin' ``` -### Setting-up a Basic Hyperledger Fabric Network -Please follow these steps [Fabric Setup](https://hyperledger-fabric.readthedocs.io/en/latest/getting_started.html) +##### **POST** `/webapi/plugins/{plugin-id}/start` + +- Example -#### Note -The included Fabric unit test depends on the [FabCar official example](https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html), so in order to run it -ensure the following: +```bash +curl --location --request POST '{application-URL}/webapi/plugins/ethereum-plugin/start' +``` -1. follow the steps of running the first Fabric tutorial at: https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html (use the javascript smart contract). -2. execute the enrollAdmin.js and the registerUser.js node programs. -3. alter the local hosts file by adding the following entries: - * 127.0.0.1 orderer.example.com - * 127.0.0.1 peer0.org1.example.com - * 127.0.0.1 peer0.org2.example.com - * 127.0.0.1 peer1.org1.example.com - * 127.0.0.1 peer1.org2.example.com - - This ensures that the SDK is able to find the orderer and network peers. +##### **POST** `/webapi/plugin-manager/{plugin-id}/disable` + +- Example + +```bash +curl --location --request POST '{application-URL}/webapi/plugins/ethereum-plugin/disable' +``` + +##### **POST** `/webapi/plugin-manager/{plugin-id}/unload` + +- Example + +```bash +curl --location --request POST '{application-URL}/webapi/plugins/ethereum-plugin/unload' +``` + +##### **POST** `/webapi/plugin-manager/{plugin-id}/enable` + +- Example + +```bash +curl --location --request POST '{application-URL}/webapi/plugins/ethereum-plugin/enable' +``` + +### JSON-RPC API + +BAL implements the [JSON-RPC binding](https://github.com/lampajr/scip#json-rpc-binding) described in the SCIP +specifications. It can be accessed with any +standard [JSON-RPC client](https://www.jsonrpc.org/archive_json-rpc.org/implementations.html). + +## Setting Up Various Blockchains for Testing + +BAL needs to have access to a node for each blockchain instance it needs to communicate with. These nodes can be already +running nodes that you have access to. Otherwise, you need to setup and manage your own nodes. The basic instructions +how to setup Ethereum, Bitcoin, and Hyperledger Fabric nodes are provided in the README.md of the respective plugin +source code. ## Case Studies ### BlockME Case Study -[Blockchain Modeling Extension (BlockME)](https://link.springer.com/article/10.1007/s00450-019-00399-5) is an extension to BPMN 2.0 that allows business processes to communicate with heterogeneous blockchains. -The case study invloves a cryptocurrency exchange service utilitzing the blockchain access layer. -The exchange uses the following simplified BlockME-model: + +[Blockchain Modeling Extension (BlockME)](https://link.springer.com/article/10.1007/s00450-019-00399-5) is an extension +to BPMN 2.0 that allows business processes to communicate with heterogeneous blockchains. The case study invloves a +cryptocurrency exchange service utilitzing the blockchain access layer. The exchange uses the following simplified +BlockME-model: ![](src/main/resources/images/original-model.png) Please follow these instructions: + 1. Configure and run a local geth node (see above). 2. Configure and run a local bitcoind node (see above). -3. Configure the blockchain access layer to communicate with these nodes (see the file [gatewayConfiguration.json](src/main/resources/gatewayConfiguration.json)). +3. Configure the blockchain access layer to communicate with these nodes (see the + file [gatewayConfiguration.json](src/main/resources/gatewayConfiguration.json)). 4. Build and deploy the blockchain access layer (see above). -5. Configure, build, deploy and initiate the process model ([see this Github repository for instructions](https://github.com/ghareeb-falazi/BlockME-UseCase)) -6. Send ethers to the address maintained by the blockchain access layer (the first address of the keyfile mentioned in step 3). -7. Monitor the Tomcat server logs for both applications to see the progress. You can also use the -Camunda Cockpit application (installed as part of step 4) to monitor the current state of instances of deployed process models. +5. Configure, build, deploy and initiate the process + model ([see this Github repository for instructions](https://github.com/ghareeb-falazi/BlockME-UseCase)) +6. Send ethers to the address maintained by the blockchain access layer (the first address of the keyfile mentioned in + step 3). +7. Monitor the Tomcat server logs for both applications to see the progress. You can also use the Camunda Cockpit + application (installed as part of step 4) to monitor the current state of instances of deployed process models. The following series of screenshots show a sample execution of the case study: - 1. Initiating the process instance: - ![](src/main/resources/images/start.png) - - 2. Setting the source, and target addresses (exchange request parameters): - ![](src/main/resources/images/input-params.png) - - 3. Sending a transaction to the address of the crypto-exchange using the Ethereum Wallet application: - ![](src/main/resources/images/send-transaction-form.png) - - 4. While waiting for the resulting Bitcoin transaction sent to the client to receive 1 confirmation, the business process instance looks - as follows: - ![](src/main/resources/images/waiting-for-bitcoin-tx.png) - - 5. The log records produced by the process instance. The final message in the log shows the id of the transaction - the exchange sent to the client. - ![](src/main/resources/images/log.png) - - 6. [BlockCypher](https://live.blockcypher.com/btc-testnet/) can be used to explore Bitcoin testnet3 (and other) blockchains. - The following screenshot represents the result of querying the transaction id reported in the previous step: - ![](src/main/resources/images/blockcypher.png) -You can find the details about the resulting testnet3 Bitcoin transaction [here](https://live.blockcypher.com/btc-testnet/tx/347d8f2bc8dbc7cf62d8313f66d2ae930c9e92632fb5a2cfb2507caaaffa7f71/). - - When we performed this sample execution, the setup was as follows: - +1. Initiating the process instance: + ![](src/main/resources/images/start.png) + +2. Setting the source, and target addresses (exchange request parameters): + ![](src/main/resources/images/input-params.png) + +3. Sending a transaction to the address of the crypto-exchange using the Ethereum Wallet application: + ![](src/main/resources/images/send-transaction-form.png) + +4. While waiting for the resulting Bitcoin transaction sent to the client to receive 1 confirmation, the business + process instance looks as follows: + ![](src/main/resources/images/waiting-for-bitcoin-tx.png) + +5. The log records produced by the process instance. The final message in the log shows the id of the transaction the + exchange sent to the client. + ![](src/main/resources/images/log.png) + +6. [BlockCypher](https://live.blockcypher.com/btc-testnet/) can be used to explore Bitcoin testnet3 (and other) + blockchains. The following screenshot represents the result of querying the transaction id reported in the previous + step: + ![](src/main/resources/images/blockcypher.png) + You can find the details about the resulting testnet3 Bitcoin + transaction [here](https://live.blockcypher.com/btc-testnet/tx/347d8f2bc8dbc7cf62d8313f66d2ae930c9e92632fb5a2cfb2507caaaffa7f71/) + . + +When we performed this sample execution, the setup was as follows: + * a _geth_ node is running on a virtual machine in a VSphere accessible from the local network. * a _bitcoind_ (Bitcoin Core) node is running on a virtual machine in a VSphere accessible from the local network. * The blockchain access layer is running in a local Tomcat server listening to port 8081 * The camunda engine is running in a local Tomcat server listening to port 8080 ### SCIP Case Studies -Two case studies that demonstrate the usage of the BAL as a SCIP gateway can be found [here](https://github.com/ghareeb-falazi/SCIP-CaseStudy) and [here](https://github.com/ghareeb-falazi/SCIP-CaseStudy-2). + +Two case studies that demonstrate the usage of the BAL as a SCIP gateway can be +found [here](https://github.com/ghareeb-falazi/SCIP-CaseStudy) +and [here](https://github.com/ghareeb-falazi/SCIP-CaseStudy-2). diff --git a/local-maven-repo/add-local-dependencies-btcd-cli4j-core.bat b/local-maven-repo/add-local-dependencies-btcd-cli4j-core.bat deleted file mode 100644 index c1ced0c..0000000 --- a/local-maven-repo/add-local-dependencies-btcd-cli4j-core.bat +++ /dev/null @@ -1 +0,0 @@ -mvn deploy:deploy-file -DgroupId=com.neemre.btcd-cli4j -DartifactId=btcd-cli4j-core -Dversion=0.5.10 -Durl=file:./ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile="..\..\btcd-cli4j\core\target\btcd-cli4j-core-0.5.10-SNAPSHOT.jar" \ No newline at end of file diff --git a/local-maven-repo/add-local-dependencies-btcd-cli4j-daemon.bat b/local-maven-repo/add-local-dependencies-btcd-cli4j-daemon.bat deleted file mode 100644 index 5478cee..0000000 --- a/local-maven-repo/add-local-dependencies-btcd-cli4j-daemon.bat +++ /dev/null @@ -1 +0,0 @@ -mvn deploy:deploy-file -DgroupId=com.neemre.btcd-cli4j -DartifactId=btcd-cli4j-daemon -Dversion=0.5.10 -Durl=file:./ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile="..\..\btcd-cli4j\daemon\target\btcd-cli4j-daemon-0.5.10-SNAPSHOT.jar" \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar deleted file mode 100644 index 31b57d7..0000000 Binary files a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar and /dev/null differ diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.md5 deleted file mode 100644 index 40e8368..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -01eda02a666159b64e824fa45b28a28a \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.sha1 deleted file mode 100644 index 3e2d2a6..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -21ca979bbe858907d720347b7bdd12dc58bb3430 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom deleted file mode 100644 index d724c07..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.neemre.btcd-cli4j - btcd-cli4j-core - 0.5.10 - diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.md5 deleted file mode 100644 index 6175980..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -a1a3268508753cb2f901c85152079676 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.sha1 deleted file mode 100644 index abec9c7..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/0.5.10/btcd-cli4j-core-0.5.10.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -655db29089591b5ec39c2240903027569cc74658 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml deleted file mode 100644 index e42dc20..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.neemre.btcd-cli4j - btcd-cli4j-core - - 0.5.10 - - 0.5.10 - - 20180412113438 - - diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.md5 deleted file mode 100644 index e62f50e..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -df7eed869c05681ba1d166d5325a4e8e \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.sha1 deleted file mode 100644 index 451c125..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-core/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -04a21c19198b015ba28bc94a4e1941a19bb796f7 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar deleted file mode 100644 index 4d9c16c..0000000 Binary files a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar and /dev/null differ diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.md5 deleted file mode 100644 index 39c596c..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -12fa01c30237ac77da62bcf4beabb64f \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.sha1 deleted file mode 100644 index a8eaa0e..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -689ef46cdfc6d2a9bf992c262f947e189582c0c8 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom deleted file mode 100644 index ce4698a..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.neemre.btcd-cli4j - btcd-cli4j-daemon - 0.5.10 - diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.md5 deleted file mode 100644 index b78691e..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -0a556a18163e1f8147dcc2e61702c2cf \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.sha1 deleted file mode 100644 index ec59fde..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/0.5.10/btcd-cli4j-daemon-0.5.10.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -7b9c567e215f705ee65db33e7f7911481ee81462 \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml deleted file mode 100644 index 5152e31..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.neemre.btcd-cli4j - btcd-cli4j-daemon - - 0.5.10 - - 0.5.10 - - 20180412113548 - - diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.md5 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.md5 deleted file mode 100644 index 96cbc62..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -5d5ad69f5bcd83e59b7573901455878b \ No newline at end of file diff --git a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.sha1 b/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.sha1 deleted file mode 100644 index 248f4eb..0000000 --- a/local-maven-repo/com/neemre/btcd-cli4j/btcd-cli4j-daemon/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -b46c1d4af8dc062526f088109cd4018119faddeb \ No newline at end of file diff --git a/pom.xml b/pom.xml index a18c02a..2c734fc 100644 --- a/pom.xml +++ b/pom.xml @@ -5,8 +5,8 @@ blockchains.iaas.uni.stuttgart.de blockchain-access-layer - war 1.0-SNAPSHOT + war Blockchain Access Layer @@ -30,6 +30,10 @@ local-maven-repo file:///${project.basedir}/local-maven-repo + + jitpack.io + https://jitpack.io + @@ -46,12 +50,6 @@ - - org.hyperledger.fabric - fabric-gateway-java - 1.4.0 - - org.glassfish.jersey.containers jersey-container-servlet-core @@ -59,92 +57,57 @@ - org.glassfish.jersey.media - jersey-media-json-jackson + jersey-media-multipart ${jersey.version} - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} + org.web3j + core + 4.5.6 - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} + com.github.TIHBS + blockchain-access-layer-api + 1.0.7 + + + org.projectlombok + lombok + 1.18.8 + provided - com.fasterxml.jackson.core - jackson-databind + jackson-core ${jackson.version} - - org.web3j - core - 4.5.6 + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey.version} - - org.projectlombok - lombok - 1.18.8 - provided + org.apache.httpcomponents + httpclient + 4.5.2 - - com.neemre.btcd-cli4j - btcd-cli4j-core - 0.5.10 - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - com.fasterxml.jackson.core - jackson-databind - - - org.slf4j - slf4j-api - - - + org.apache.commons + commons-lang3 + 3.7 - com.neemre.btcd-cli4j - btcd-cli4j-daemon - 0.5.10 - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - com.fasterxml.jackson.core - jackson-databind - - - org.slf4j - slf4j-api - - + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} - ch.qos.logback @@ -165,54 +128,28 @@ ${org.slf4j} compile - - - org.apache.httpcomponents - httpclient - 4.5.2 - - - - org.apache.commons - commons-lang3 - 3.7 - org.junit.jupiter - junit-jupiter-api + junit-jupiter RELEASE test - - com.github.arteam - simple-json-rpc-server - ${jsonrpc.version} - - - org.slf4j - slf4j-api - - - com.google.guava - guava - - + org.pf4j + pf4j + 3.6.0 com.github.arteam - simple-json-rpc-client - ${jsonrpc.version} - - - org.slf4j - slf4j-api - - + simple-json-rpc-server + 0.10 - + + 8 + 8 + true 2.9.1 [2.9.9.2,) 0.10 diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/Constants.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/Constants.java new file mode 100644 index 0000000..57e9d75 --- /dev/null +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/Constants.java @@ -0,0 +1,9 @@ +package blockchains.iaas.uni.stuttgart.de; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Constants { + + public final static Path PLUGINS_DIRECTORY = Paths.get(System.getProperty( "pf4j.pluginsDir")); +} diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/contracts/Permissions.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/Permissions.java similarity index 97% rename from src/test/java/blockchains/iaas/uni/stuttgart/de/contracts/Permissions.java rename to src/main/java/blockchains/iaas/uni/stuttgart/de/Permissions.java index cdd0118..74d901f 100644 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/contracts/Permissions.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/Permissions.java @@ -9,19 +9,10 @@ * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.contracts; +package blockchains.iaas.uni.stuttgart.de; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.DynamicArray; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.*; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.RemoteCall; @@ -30,6 +21,12 @@ import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; + /** *

Auto generated code. *

Do not modify! diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManager.java index 90b1456..0eac455 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManager.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManager.java @@ -1,8 +1,8 @@ /******************************************************************************** - * Copyright (c) 2019 Institute for the Architecture of Application System - + * Copyright (c) 2019-2022 Institute for the Architecture of Application System - * University of Stuttgart * Author: Ghareeb Falazi - * + * Co-author: Akshay Patel * This program and the accompanying materials are made available under the * terms the Apache Software License 2.0 * which is available at https://www.apache.org/licenses/LICENSE-2.0. @@ -11,16 +11,13 @@ ********************************************************************************/ package blockchains.iaas.uni.stuttgart.de.adaptation; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; +import blockchains.iaas.uni.stuttgart.de.api.connectionprofiles.AbstractConnectionProfile; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainIdNotFoundException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.BlockchainIdNotFoundException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.BlockchainNodeUnreachableException; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; @@ -63,12 +60,12 @@ public BlockchainAdapter getAdapter(String blockchainId) throws BlockchainIdNotF } try { - final BlockchainAdapter adapter = factory.createBlockchainAdapter(connectionProfile, blockchainId); + final BlockchainAdapter adapter = factory.createBlockchainAdapter(connectionProfile); map.put(blockchainId, ImmutablePair.of(adapter, connectionProfile)); return Objects.requireNonNull(adapter); } catch (Exception e) { throw new BlockchainNodeUnreachableException("Failed to create a blockchain adapter. Reason: " + e.getMessage()); } } + } -; \ No newline at end of file diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/BlockchainAdapterFactory.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/BlockchainAdapterFactory.java index b97d9c3..4c232c7 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/BlockchainAdapterFactory.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/BlockchainAdapterFactory.java @@ -1,7 +1,8 @@ /******************************************************************************** - * Copyright (c) 2019 Institute for the Architecture of Application System - + * Copyright (c) 2019-2022 Institute for the Architecture of Application System - * University of Stuttgart * Author: Ghareeb Falazi + * Co-author: Akshay Patel * * This program and the accompanying materials are made available under the * terms the Apache Software License 2.0 @@ -11,46 +12,28 @@ ********************************************************************************/ package blockchains.iaas.uni.stuttgart.de.adaptation; -import java.io.IOException; - -import blockchains.iaas.uni.stuttgart.de.adaptation.adapters.bitcoin.BitcoinAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum.EthereumAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.adapters.fabric.FabricAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.PoWConfidenceCalculator; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.BitcoinConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.EthereumConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.FabricConnectionProfile; -import com.neemre.btcdcli4j.core.BitcoindException; -import com.neemre.btcdcli4j.core.CommunicationException; -import com.neemre.btcdcli4j.core.client.BtcdClient; -import com.neemre.btcdcli4j.core.client.BtcdClientImpl; -import com.neemre.btcdcli4j.daemon.BtcdDaemon; -import com.neemre.btcdcli4j.daemon.BtcdDaemonImpl; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import blockchains.iaas.uni.stuttgart.de.api.IAdapterExtension; +import blockchains.iaas.uni.stuttgart.de.api.connectionprofiles.AbstractConnectionProfile; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; +import blockchains.iaas.uni.stuttgart.de.management.BlockchainPluginManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.web3j.crypto.CipherException; + +import java.util.List; public class BlockchainAdapterFactory { + + public BlockchainAdapterFactory() { + + } + private static final Logger log = LoggerFactory.getLogger(BlockchainAdapterFactory.class); - public BlockchainAdapter createBlockchainAdapter(AbstractConnectionProfile connectionProfile, String blockchainId) throws Exception { + public BlockchainAdapter createBlockchainAdapter(AbstractConnectionProfile connectionProfile) throws Exception { + try { - if (connectionProfile instanceof EthereumConnectionProfile) { - return createEthereumAdapter((EthereumConnectionProfile) connectionProfile); - } else if (connectionProfile instanceof BitcoinConnectionProfile) { - return createBitcoinAdapter((BitcoinConnectionProfile) connectionProfile); - } else if (connectionProfile instanceof FabricConnectionProfile) { - return createFabricAdapter((FabricConnectionProfile) connectionProfile, blockchainId); - } else { - log.error("Invalid connectionProfile type!"); - return null; - } + return createAdapter(connectionProfile); } catch (Exception e) { final String msg = String.format("Error while creating a blockchain adapter for. Details: %s", e.getMessage()); log.error(msg); @@ -58,32 +41,15 @@ public BlockchainAdapter createBlockchainAdapter(AbstractConnectionProfile conne } } - private EthereumAdapter createEthereumAdapter(EthereumConnectionProfile gateway) throws IOException, CipherException { - final EthereumAdapter result = new EthereumAdapter(gateway.getNodeUrl(), gateway.getPollingTimeSeconds()); - result.setCredentials(gateway.getKeystorePassword(), gateway.getKeystorePath()); - final PoWConfidenceCalculator cCalc = new PoWConfidenceCalculator(); - cCalc.setAdversaryRatio(gateway.getAdversaryVotingRatio()); - result.setConfidenceCalculator(cCalc); - - return result; - } - - private BitcoinAdapter createBitcoinAdapter(BitcoinConnectionProfile gateway) throws BitcoindException, CommunicationException { - final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); - final CloseableHttpClient httpProvider = HttpClients.custom().setConnectionManager(connManager).build(); - final BtcdClient client = new BtcdClientImpl(httpProvider, gateway.getAsProperties()); - final BtcdDaemon daemon = new BtcdDaemonImpl(client); - final BitcoinAdapter result = new BitcoinAdapter(client, daemon); - final PoWConfidenceCalculator cCalc = new PoWConfidenceCalculator(); - cCalc.setAdversaryRatio(gateway.getAdversaryVotingRatio()); - result.setConfidenceCalculator(cCalc); - - return result; + private BlockchainAdapter createAdapter(AbstractConnectionProfile connectionProfile) { + List adapterExtensions = BlockchainPluginManager.getInstance().getExtensions(); + for (IAdapterExtension adapterExtension : adapterExtensions) { + if (connectionProfile.getClass() == adapterExtension.getConnectionProfileClass()) { + return adapterExtension.getAdapter(connectionProfile); + } + } + System.err.println("No extension for blockchain-id: " + connectionProfile); + return null; } - private FabricAdapter createFabricAdapter(FabricConnectionProfile gateway, String blockchainId) { - return FabricAdapter.builder() - .blockchainId(blockchainId) - .build(); - } } diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/AbstractAdapter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/AbstractAdapter.java deleted file mode 100644 index eeb1123..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/AbstractAdapter.java +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters; - -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.FinalityConfidenceCalculator; - -public abstract class AbstractAdapter implements BlockchainAdapter { - protected FinalityConfidenceCalculator confidenceCalculator; - - public FinalityConfidenceCalculator getConfidenceCalculator() { - return confidenceCalculator; - } - - public void setConfidenceCalculator(FinalityConfidenceCalculator confidenceCalculator) { - this.confidenceCalculator = confidenceCalculator; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinAdapter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinAdapter.java deleted file mode 100644 index 6e14088..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinAdapter.java +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.bitcoin; - -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import blockchains.iaas.uni.stuttgart.de.adaptation.BlockchainAdapterFactory; -import blockchains.iaas.uni.stuttgart.de.adaptation.adapters.AbstractAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.PoWConfidenceCalculator; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidTransactionException; -import blockchains.iaas.uni.stuttgart.de.exceptions.NotSupportedException; -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import blockchains.iaas.uni.stuttgart.de.model.Block; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; -import blockchains.iaas.uni.stuttgart.de.model.Occurrence; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; -import com.google.common.base.Strings; -import com.neemre.btcdcli4j.core.BitcoindException; -import com.neemre.btcdcli4j.core.CommunicationException; -import com.neemre.btcdcli4j.core.client.BtcdClient; -import com.neemre.btcdcli4j.core.domain.PaymentOverview; -import com.neemre.btcdcli4j.core.domain.RawInput; -import com.neemre.btcdcli4j.core.domain.RawTransactionOverview; -import com.neemre.btcdcli4j.daemon.BtcdDaemon; -import com.neemre.btcdcli4j.daemon.event.BlockListener; -import com.neemre.btcdcli4j.daemon.event.WalletListener; -import io.reactivex.Observable; -import io.reactivex.subjects.PublishSubject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BitcoinAdapter extends AbstractAdapter { - private static final Logger log = LoggerFactory.getLogger(BlockchainAdapterFactory.class); - private BtcdClient client; - private BtcdDaemon daemon; - - public BitcoinAdapter(BtcdClient client, - BtcdDaemon daemon) { - this.client = client; - this.daemon = daemon; - } - - /** - * Finds the sending address of the first input of a given transaction (requires an indexed bitcoin core) - * - * @param transactionId the id of the transaction to inspect - * @return the Bitcoin address that owned the output used to fund the first input of the given transaction - */ - private String findTransactionFirstSender(String transactionId) throws BitcoindException, CommunicationException { - String address = ""; - final RawTransactionOverview rawTx = client.decodeRawTransaction(client.getRawTransaction(transactionId)); - final List vIn = rawTx.getVIn(); - - if (vIn.size() > 0) { - RawInput input = vIn.get(0); - RawTransactionOverview inputRawTx = client.decodeRawTransaction(client.getRawTransaction(input.getTxId())); - address = inputRawTx.getVOut().get(input.getVOut()).getScriptPubKey().getAddresses().get(0); - } - - return address; - } - - private static Block generateBlockObject(com.neemre.btcdcli4j.core.domain.Block block) { - final Block result = new Block(); - result.setHash(block.getHash()); - result.setNumberAsLong(block.getHeight().longValue()); - - return result; - } - - private LinearChainTransaction generateTransactionObject(com.neemre.btcdcli4j.core.domain.Transaction transaction, Block block, boolean detectSender) { - LinearChainTransaction result = null; - // there might be multi-inputs and/or multi-outputs for a transactions, we only consider the first input/output affecting the wallet - if (transaction.getDetails().size() > 0) { - final PaymentOverview overview = transaction.getDetails().get(0); - result = new LinearChainTransaction(); - result.setTo(overview.getAddress()); - result.setBlock(block); - result.setTransactionHash(transaction.getTxId()); - result.setValue(BitcoinUtils.bitcoinsToSatoshi(transaction.getAmount().abs()).toBigInteger());// always a positive value! - - if (detectSender) { - try { - result.setFrom(findTransactionFirstSender(result.getTransactionHash())); - } catch (BitcoindException | CommunicationException e) { - final String msg = String.format("Could not detect the sender of the transaction: %s. Reason: %s", - result.getTransactionHash(), e.getMessage()); - log.error(msg); - } - } - } - - return result; - } - - /** - * Subscribes for the event of detecting a transition of the state of a given transaction which is assumed to having been - * MINED before. The method supports detecting - * (i) a transaction being not found anymore or being in contradiction with another transaction(invalidated), - * or (ii) not having a containing block (orphaned), or (iii) having received enough block-confirmations(durably committed). - * - * @param txHash the hash of the transaction to monitor - * @param waitFor the number of block-confirmations to wait until the transaction is considered persisted (-1 if the - * transaction is never to be considered persisted) - * @param observedStates the set of states that will be reported to the calling method - * @return a future which is used to handle the subscription and receive the callback - */ - private CompletableFuture subscribeForTxEvent(String txHash, long waitFor, TransactionState... observedStates) { - final CompletableFuture result = new CompletableFuture<>(); - final BlockListener listener = new BlockListener() { - void handleDetectedState(final com.neemre.btcdcli4j.core.domain.Transaction transactionDetails, - final com.neemre.btcdcli4j.core.domain.Block block, - final TransactionState detectedState, final TransactionState[] interesting, - CompletableFuture future) { - // Only complete the future if we are interested in this event - if (Arrays.asList(interesting).contains(detectedState)) { - LinearChainTransaction result; - - if (transactionDetails != null) { - final Block myBlock = generateBlockObject(block); - result = generateTransactionObject(transactionDetails, myBlock, true); - } else { - result = new LinearChainTransaction(); - } - - result.setState(detectedState); - future.complete(result); - } - } - - @Override - public void blockDetected(com.neemre.btcdcli4j.core.domain.Block block) { - try { - final com.neemre.btcdcli4j.core.domain.Transaction tx = client.getTransaction(txHash); - - if (tx == null || tx.getConfirmations() == -1) {// transaction is dropped or specifically found to be in contradiction with another transaction - final String msg = String.format("The transaction of the hash %s is not found!", txHash); - log.info(msg); - handleDetectedState(tx, block, TransactionState.NOT_FOUND, observedStates, result); - - return; - } - - if (tx.getConfirmations() == 0) {// Not contained in a block anymore - final String msg = String.format("The transaction of the hash %s has no block (orphaned?)", - txHash); - log.info(msg); - handleDetectedState(tx, block, TransactionState.PENDING, observedStates, result); - return; - } - - // check if enough block-confirmations have occurred. - if (waitFor >= 0 && tx.getConfirmations() >= waitFor) { - final String msg = String.format("The transaction of the hash %s has been confirmed", - txHash); - log.info(msg); - - handleDetectedState(tx, block, TransactionState.CONFIRMED, observedStates, result); - } - } catch (BitcoindException e) { - result.completeExceptionally(new InvalidTransactionException(e.getMessage())); - } catch (CommunicationException e) { - result.completeExceptionally(new BlockchainNodeUnreachableException(e.getMessage())); - } - } - }; - - // unsubscribe the observable when the CompletableFuture completes (either when detecting an event, or manually) - result.whenComplete((v, e) -> daemon.removeBlockListener(listener)); - daemon.addBlockListener(listener); - - return result; - } - - @Override - public CompletableFuture submitTransaction(String receiverAddress, BigDecimal value, double requiredConfidence) throws InvalidTransactionException { - try { - final BigDecimal valueBitcoins = BitcoinUtils.satoshiToBitcoin(value); - final String transactionId = client.sendToAddress(receiverAddress, valueBitcoins); - CompletableFuture result; - long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - - if (waitFor > 0) { - result = subscribeForTxEvent(transactionId, waitFor, TransactionState.NOT_FOUND, TransactionState.CONFIRMED); - } else { - result = new CompletableFuture<>(); - final com.neemre.btcdcli4j.core.domain.Transaction tx = client.getTransaction(transactionId); - final LinearChainTransaction resultTx = generateTransactionObject(tx, null, true); - resultTx.setState(TransactionState.CONFIRMED); - result.complete(resultTx); - } - - return result; - } catch (BitcoindException e) { - throw new InvalidTransactionException(e.getMessage()); - } catch (CommunicationException e) { - throw new BlockchainNodeUnreachableException(e.getMessage()); - } - } - - @Override - public Observable receiveTransactions(String senderId, double requiredConfidence) { - - final PublishSubject subject = PublishSubject.create(); - long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - final WalletListener listener = new WalletListener() { - @Override - public void walletChanged(com.neemre.btcdcli4j.core.domain.Transaction transaction) { - // All transactions here are relevant to me as this is a wallet-based event - // But we need to make sure that the transaction is actually increasing the balance and that this is the - // first time we see this transaction (we receive multiple notifications for the same transaction) - - if (transaction.getAmount().compareTo(BigDecimal.ZERO) >= 0 && transaction.getConfirmations() == 0) { // a new receive-, or self-transaction - try { - if (senderId == null || senderId.trim().length() == 0 || - findTransactionFirstSender(transaction.getTxId()).equals(senderId)) { - log.info("New transaction received with id " + transaction.getTxId()); - - if (waitFor > 0) { - subscribeForTxEvent(transaction.getTxId(), waitFor, TransactionState.CONFIRMED) - .thenAccept(subject::onNext) - .exceptionally(error -> { - subject.onError(error); - return null; - }); - } else { - final LinearChainTransaction resultTx = generateTransactionObject(transaction, null, true); - resultTx.setState(TransactionState.CONFIRMED); - subject.onNext(resultTx); - } - } - } catch (BitcoindException | CommunicationException e) { - log.error("Failed to receive a Bitcoin transaction. Reason: " + e.getMessage()); - } - } - } - }; - - final Observable result = subject.doFinally(() -> daemon.removeWalletListener(listener)); - daemon.addWalletListener(listener); - - return result; - } - - @Override - public CompletableFuture ensureTransactionState(String transactionId, double requiredConfidence) { - long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - return subscribeForTxEvent(transactionId, waitFor, TransactionState.NOT_FOUND, TransactionState.CONFIRMED) - .thenApply(Transaction::getState); - } - - @Override - public CompletableFuture detectOrphanedTransaction(String transactionId) { - return subscribeForTxEvent(transactionId, -1, TransactionState.PENDING, TransactionState.NOT_FOUND) - .thenApply(Transaction::getState); - } - - @Override - public CompletableFuture invokeSmartContract(String smartContractPath, String functionIdentifier, List inputs, List outputs, double requiredConfidence, long timeoutMillis) throws NotSupportedException, ParameterException { - throw new NotSupportedException("Bitcoin does not support smart contract function invocations!"); - } - - @Override - public Observable subscribeToEvent(String smartContractAddress, String eventIdentifier, List outputParameters, double degreeOfConfidence, String filter) throws BalException { - return null; - } - - @Override - public CompletableFuture queryEvents(String smartContractAddress, String eventIdentifier, List outputParameters, String filter, TimeFrame timeFrame) throws BalException { - return null; - } - - @Override - public String testConnection() { - try { - return String.valueOf(!Strings.isNullOrEmpty(client.getNodeVersion())); - } catch (Exception e) { - return e.getMessage(); - } - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinUtils.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinUtils.java deleted file mode 100644 index d68e53c..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/bitcoin/BitcoinUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.bitcoin; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; - -public class BitcoinUtils { - private static final long SATOSHIS_PER_BITCCOIN = 100000000L; - private static final int LARGEST_SCALE = 8; - - public static BigDecimal satoshiToBitcoin(BigDecimal satoshis){ - return satoshis.divide(new BigDecimal(SATOSHIS_PER_BITCCOIN), LARGEST_SCALE, RoundingMode.UNNECESSARY); - } - - public static BigDecimal bitcoinsToSatoshi(BigDecimal bitcoins){ - return bitcoins.multiply(new BigDecimal(SATOSHIS_PER_BITCCOIN)); - } - -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapter.java deleted file mode 100644 index f6acc97..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapter.java +++ /dev/null @@ -1,719 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import javax.naming.OperationNotSupportedException; - -import blockchains.iaas.uni.stuttgart.de.adaptation.adapters.AbstractAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.BooleanExpressionEvaluator; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.PoWConfidenceCalculator; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.SmartContractPathParser; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidScipParameterException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidTransactionException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvokeSmartContractFunctionFailure; -import blockchains.iaas.uni.stuttgart.de.exceptions.NotSupportedException; -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import blockchains.iaas.uni.stuttgart.de.exceptions.SmartContractNotFoundException; -import blockchains.iaas.uni.stuttgart.de.exceptions.TimeoutException; -import blockchains.iaas.uni.stuttgart.de.model.Block; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; -import blockchains.iaas.uni.stuttgart.de.model.Occurrence; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; -import com.google.common.base.Strings; -import io.reactivex.Observable; -import io.reactivex.disposables.Disposable; -import io.reactivex.subjects.PublishSubject; -import okhttp3.OkHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.abi.EventEncoder; -import org.web3j.abi.EventValues; -import org.web3j.abi.FunctionEncoder; -import org.web3j.abi.FunctionReturnDecoder; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Event; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.crypto.CipherException; -import org.web3j.crypto.Credentials; -import org.web3j.crypto.WalletUtils; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.DefaultBlockParameter; -import org.web3j.protocol.core.DefaultBlockParameterName; -import org.web3j.protocol.core.DefaultBlockParameterNumber; -import org.web3j.protocol.core.JsonRpc2_0Web3j; -import org.web3j.protocol.core.methods.request.EthFilter; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.protocol.core.methods.response.EthGetTransactionCount; -import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt; -import org.web3j.protocol.core.methods.response.EthLog; -import org.web3j.protocol.core.methods.response.EthTransaction; -import org.web3j.protocol.core.methods.response.Log; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.protocol.http.HttpService; -import org.web3j.tx.Contract; -import org.web3j.tx.Transfer; -import org.web3j.tx.gas.DefaultGasProvider; -import org.web3j.utils.Async; -import org.web3j.utils.Convert; - -public class EthereumAdapter extends AbstractAdapter { - private Credentials credentials; - private final String nodeUrl; - private final Web3j web3j; - private final DateTimeFormatter formatter; - private static final Logger log = LoggerFactory.getLogger(EthereumAdapter.class); - private final int averageBlockTimeSeconds; - - public EthereumAdapter(final String nodeUrl, final int averageBlockTimeSeconds) { - this.nodeUrl = nodeUrl; - this.averageBlockTimeSeconds = averageBlockTimeSeconds; - // We use a specific implementation so we can change the polling period (useful for prototypes). - this.web3j = new JsonRpc2_0Web3j(createWeb3HttpService(this.nodeUrl), this.averageBlockTimeSeconds, Async.defaultExecutorService()); - this.formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; - } - - public Web3j getWeb3j() { - return web3j; - } - - Credentials getCredentials() { - return credentials; - } - - void setCredentials(Credentials credentials) { - this.credentials = credentials; - } - - public void setCredentials(String password, String fileSource) throws IOException, CipherException { - try { - this.credentials = WalletUtils.loadCredentials(password, fileSource); - } catch (IOException | CipherException e) { - log.error("Error occurred while setting the user credentials for Ethereum. Reason {}", e.getMessage()); - throw e; - } - } - - String testConnectionToNode() { - try { - log.info("Connected to Ethereum client: URL: {}, Version: {}", this.nodeUrl, this.web3j.web3ClientVersion().send().getWeb3ClientVersion()); - return "true"; - } catch (IOException e) { - log.error("Failed to connect to Ethereum client at URL: {}. Reason: {}", this.nodeUrl, e.getMessage()); - - return e.getMessage(); - } - } - - /** - * Subscribes for the event of detecting a transition of the state of a given transaction, which is assumed to having been - * MINED before. The method supports detecting: - * (i) a transaction being not found anymore (invalidated): NOT_FOUND, - * (ii) not having a containing block (orphaned): PENDING: , - * (iii) reporting an error although mined into a block (e.g., SC function threw an error): ERRORED - * (iii) having received enough block-confirmations (durably committed): CONFIRMED. - * - * @param txHash the hash of the transaction to monitor - * @param waitFor the number of block-confirmations to wait until the transaction is considered persisted (-1 if the - * transaction is never to be considered persisted) - * @param observedStates the set of states that will be reported to the calling method - * @return a future which is used to handle the subscription and receive the callback - */ - private CompletableFuture subscribeForTxEvent(String txHash, long waitFor, TransactionState... observedStates) { - final CompletableFuture result = new CompletableFuture<>(); - final Disposable subscription = web3j.blockFlowable(false).subscribe(ethBlock -> { - try { - // make sure the transaction exists - final EthTransaction transaction = web3j.ethGetTransactionByHash(txHash).send(); - // if not, then it is either invalidated or did not exist in the first place - if (!transaction.getTransaction().isPresent()) { - final String msg = String.format("The transaction of the hash %s is not found!", txHash); - log.info(msg); - handleDetectedState(transaction.getTransaction(), TransactionState.NOT_FOUND, observedStates, result); - - return; - } - - // determine if the transaction reported an error - EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(txHash).send(); - - if (!receipt.getResult().isStatusOK()) { - if (handleDetectedState(transaction.getTransaction(), TransactionState.ERRORED, observedStates, result)) - return; - } - - // make sure the transaction is still contained in a block, i.e., it was not orphaned - final String retrievedBlockHash = transaction.getTransaction().get().getBlockHash(); - - if (retrievedBlockHash == null || retrievedBlockHash.isEmpty()) { - final String msg = String.format("The transaction of the hash %s has no block (orphaned?)", txHash); - log.info(msg); - - handleDetectedState(transaction.getTransaction(), TransactionState.PENDING, observedStates, result); - return; - } - // check if enough block-confirmations have occurred. - if (waitFor >= 0 && ethBlock.getBlock() != null) { - if (ethBlock.getBlock().getNumber() - .subtract(transaction.getTransaction().get().getBlockNumber()) - .intValue() >= waitFor) { - final String msg = String.format("The transaction of the hash %s has been confirmed", - txHash); - log.info(msg); - - handleDetectedState(transaction.getTransaction(), TransactionState.CONFIRMED, observedStates, result); - } - } - } catch (IOException e) { - result.completeExceptionally(e); - } - }); - - //dispose the flowable when the CompletableFuture completes (either when detecting an event, or manually) - result.whenComplete((v, e) -> subscription.dispose()); - - return result; - } - - private static CompletionException wrapEthereumExceptions(Throwable e) { - return new CompletionException(mapEthereumException(e)); - } - - private static BalException mapEthereumException(Throwable e) { - BalException result; - - if (e instanceof BalException) - result = (BalException) e; - else if (e.getCause() instanceof BalException) - result = (BalException) e.getCause(); - else if (e.getCause() instanceof IOException) - result = new BlockchainNodeUnreachableException(e.getMessage()); - else if (e instanceof IllegalArgumentException || e instanceof OperationNotSupportedException) - result = new InvokeSmartContractFunctionFailure(e.getMessage()); - else if (e.getCause() instanceof RuntimeException) - result = new InvalidTransactionException(e.getMessage()); - else { - log.error("Unexpected exception was thrown!"); - result = new InvalidTransactionException(e.getMessage()); - } - - return result; - } - - @Override - public CompletableFuture submitTransaction(String receiverAddress, BigDecimal value, double requiredConfidence) - throws InvalidTransactionException { - if (credentials == null) { - log.error("Credentials are not set for the Ethereum user"); - throw new NullPointerException("Credentials are not set for the Ethereum user"); - } - - try { - final long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - return Transfer.sendFunds(web3j, credentials, receiverAddress, value, Convert.Unit.WEI) // 1 wei = 10^-18 Ether - .sendAsync() - // when an exception (e.g., ConnectException happens), the following is skipped - .thenCompose(tx -> subscribeForTxEvent(tx.getTransactionHash(), waitFor, TransactionState.CONFIRMED, TransactionState.NOT_FOUND)) - .exceptionally((e) -> { - throw wrapEthereumExceptions(e); - } - ); - } catch (Exception e) {// this seems to never get invoked - final String msg = "An error occurred while trying to submit a new transaction to ethereum. Reason: " + e.getMessage(); - log.error(msg); - - throw new InvalidTransactionException(msg); - } - } - - @Override - public Observable receiveTransactions(String senderId, double requiredConfidence) { - if (credentials == null) { - log.error("Credentials are not set for the Ethereum user"); - throw new NullPointerException("Credentials are not set for the Ethereum user"); - } - - final long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - final String myAddress = credentials.getAddress(); - final PublishSubject result = PublishSubject.create(); - final Disposable newTransactionObservable = web3j.transactionFlowable().subscribe(tx -> { - if (myAddress.equalsIgnoreCase(tx.getTo())) { - if (senderId == null || senderId.trim().length() == 0 || senderId.equalsIgnoreCase(tx.getFrom())) { - log.info("New transaction received from:" + tx.getFrom()); - subscribeForTxEvent(tx.getHash(), waitFor, TransactionState.CONFIRMED) - .thenAccept(result::onNext) - .exceptionally(error -> { - result.onError(wrapEthereumExceptions(error)); - return null; - }); - } - } - }, e -> result.onError(wrapEthereumExceptions(e))); - - return result.doFinally(newTransactionObservable::dispose); - } - - @Override - public CompletableFuture ensureTransactionState(String transactionId, double requiredConfidence) { - final long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - // only monitor the transition into the CONFIRMED state or the NOT_FOUND state - return subscribeForTxEvent(transactionId, waitFor, TransactionState.CONFIRMED, TransactionState.NOT_FOUND) - .thenApply(Transaction::getState) - .exceptionally((e) -> { - throw wrapEthereumExceptions(e); - }); - } - - @Override - public CompletableFuture detectOrphanedTransaction(String transactionId) { - // only monitor the transition into the PENDING state - return subscribeForTxEvent(transactionId, -1, TransactionState.PENDING, TransactionState.NOT_FOUND) - .thenApply(Transaction::getState) - .exceptionally((e) -> { - throw wrapEthereumExceptions(e); - }); - } - - @Override - public CompletableFuture invokeSmartContract( - String smartContractPath, - String functionIdentifier, - List inputs, - List outputs, - double requiredConfidence, - long timeoutMillis - ) throws NotSupportedException, ParameterException { - if (credentials == null) { - log.error("Credentials are not set for the Ethereum user"); - throw new NullPointerException("Credentials are not set for the Ethereum user"); - } - - Objects.requireNonNull(smartContractPath); - Objects.requireNonNull(functionIdentifier); - Objects.requireNonNull(inputs); - Objects.requireNonNull(outputs); - - try { - long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(requiredConfidence); - final String[] pathSegments = SmartContractPathParser.parse(smartContractPath).getSmartContractPathSegments(); - - if (pathSegments.length != 1) { - throw new SmartContractNotFoundException("Malformed Ethereum path!"); - } - - if (!pathSegments[0].matches("^0x[a-fA-F0-9]{40}$")) { - throw new SmartContractNotFoundException("Malformed Ethereum address!"); - } - - final String smartContractAddress = pathSegments[0]; - List> outputParameters = new ArrayList<>(); - Class currentReturnType; - - for (Parameter output : outputs) { - currentReturnType = EthereumTypeMapper.getEthereumType(output.getType()); - outputParameters.add(TypeReference.create(currentReturnType)); - } - - final Function function = new Function( - functionIdentifier, // function we're calling - this.convertToSolidityTypes(inputs), // Parameters to pass as Solidity Types - outputParameters); //Type of returned value - - final String encodedFunction = FunctionEncoder.encode(function); - - // if we are expecting a return value, we try to invoke as a method call, otherwise, we try a transaction - if (outputParameters.size() > 0) { - return this.invokeFunctionByMethodCall( - encodedFunction, - smartContractAddress, - outputs, - function.getOutputParameters()); - } else { - return this.invokeFunctionByTransaction( - waitFor, - encodedFunction, - smartContractAddress, - timeoutMillis); - } - } catch (Exception e) { - log.error("Decoding smart contract function call failed. Reason: {}", e.getMessage()); - throw mapEthereumException(e); - } - } - - @Override - public Observable subscribeToEvent(String smartContractAddress, String eventIdentifier, - List outputParameters, double degreeOfConfidence, String filter) throws BalException { - long waitFor = ((PoWConfidenceCalculator) this.confidenceCalculator).getEquivalentBlockDepth(degreeOfConfidence); - List> types = this.convertTypes(outputParameters); - final Event event = new Event(eventIdentifier, types); - final EthFilter ethFilter = this.generateSubscriptionFilter(smartContractAddress, event, types.size()); - final PublishSubject result = PublishSubject.create(); - - Disposable newEventObservable = web3j.ethLogFlowable(ethFilter).subscribe(log -> { - Occurrence occurrence = this.handleLog(log, event, outputParameters, filter); - - // if the result is null, then the filter has evaluated to false. - if (occurrence != null) { - this.subscribeForTxEvent(log.getTransactionHash(), waitFor, TransactionState.CONFIRMED) - .thenAccept(tx -> result.onNext(occurrence)) - .exceptionally(error -> { - result.onError(wrapEthereumExceptions(error)); - return null; - }); - } - }, e -> result.onError(wrapEthereumExceptions(e))); - - return result.doFinally(newEventObservable::dispose); - } - - @Override - public CompletableFuture queryEvents(String smartContractAddress, String eventIdentifier, - List outputParameters, String filter, TimeFrame timeFrame) throws BalException { - List> types = this.convertTypes(outputParameters); - final Event event = new Event(eventIdentifier, types); - try { - final EthFilter ethFilter = this.generateQueryFilter(smartContractAddress, event, types.size(), timeFrame); - return web3j.ethGetLogs(ethFilter) - .sendAsync() - .thenApply(result -> { - try { - List finalResult = new ArrayList<>(); - - for (EthLog.LogResult logResult : result.getLogs()) { - Log log = (Log) logResult.get(); - Occurrence occurrence = this.handleLog(log, event, outputParameters, filter); - - if (occurrence != null) { - finalResult.add(occurrence); - } - } - - return QueryResult.builder().occurrences(finalResult).build(); - } catch (Exception e) { - throw new CompletionException(new InvalidScipParameterException("The filter script is invalid: " + e.getMessage())); - } - }); - } catch (IOException e) { - throw new BlockchainNodeUnreachableException(e.getMessage()); - } - } - - @Override - public String testConnection() { - return this.testConnectionToNode(); - } - - private List> convertTypes(List parameters) { - return parameters - .stream() - .map(param -> (EthereumTypeMapper.getEthereumType(param.getType()))) - .map(TypeReference::create) - .collect(Collectors.toList()); - } - - private Occurrence handleLog(Log log, Event event, List outputParameters, String filter) throws Exception { - final EventValues values = Contract.staticExtractEventParameters(event, log); - List parameters = new ArrayList<>(); - - for (int i = 0; i < outputParameters.size(); i++) { - parameters.add(Parameter.builder() - .name(outputParameters.get(i).getName()) - .type(outputParameters.get(i).getType()) - .value(ParameterDecoder.decode(values.getNonIndexedValues().get(i))) - .build()); - } - - if (BooleanExpressionEvaluator.evaluate(filter, parameters)) { - EthBlock block = this.web3j.ethGetBlockByHash(log.getBlockHash(), false).send(); - LocalDateTime timestamp = LocalDateTime.ofEpochSecond(block.getBlock().getTimestamp().longValue(), 0, ZoneOffset.UTC); - String timestampS = formatter.format(timestamp); - - return Occurrence.builder().parameters(parameters).isoTimestamp(timestampS).build(); - } - - return null; - } - - private EthFilter generateSubscriptionFilter(String smartContractAddress, Event event, int parameterCount) { - return this.generateFilter(smartContractAddress, event, parameterCount, DefaultBlockParameterName.LATEST, DefaultBlockParameterName.LATEST); - } - - private EthFilter generateQueryFilter(String smartContractAddress, Event event, int parameterCount, TimeFrame timeFrame) throws IOException { - DefaultBlockParameter from; - DefaultBlockParameter to; - - if (timeFrame == null) { - from = DefaultBlockParameterName.EARLIEST; - to = DefaultBlockParameterName.LATEST; - } else { - - if (Strings.isNullOrEmpty(timeFrame.getFrom())) { - from = DefaultBlockParameterName.EARLIEST; - } else { - LocalDateTime fromDateTime = LocalDateTime.parse(timeFrame.getFrom(), DateTimeFormatter.ISO_LOCAL_DATE_TIME); - long fromBlockNumber = this.getBlockAfterIsoDate(fromDateTime); - from = new DefaultBlockParameterNumber(fromBlockNumber); - } - - if (Strings.isNullOrEmpty(timeFrame.getTo())) { - to = DefaultBlockParameterName.LATEST; - } else { - LocalDateTime toDateTime = LocalDateTime.parse(timeFrame.getTo(), DateTimeFormatter.ISO_LOCAL_DATE_TIME); - long toBlockNumber = this.getBlockAfterIsoDate(toDateTime); - - // this indicates the specified date is after the last block - if (toBlockNumber == Long.MAX_VALUE) { - to = DefaultBlockParameterName.LATEST; - } else { - if (toBlockNumber > 0) - toBlockNumber--; - else - throw new InvalidScipParameterException(); - - to = new DefaultBlockParameterNumber(toBlockNumber); - } - } - } - - return this.generateFilter(smartContractAddress, event, parameterCount, from, to); - } - - long getBlockAfterIsoDate(final LocalDateTime dateTime) throws IOException { - final long seconds = Duration.between(dateTime, LocalDateTime.now()).getSeconds(); - long estimatedBlockLag = seconds / averageBlockTimeSeconds; - - // if the block is in the future - if (estimatedBlockLag < 0) { - estimatedBlockLag = 0; - } - - final long latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber().longValue(); - long blockNumber = latestBlockNumber - estimatedBlockLag; - - // if the estimated block is before the genesis - if (blockNumber < 0) { - blockNumber = 0; - } - - BigInteger blockTimeStamp = web3j.ethGetBlockByNumber(new DefaultBlockParameterNumber(blockNumber), false).send().getBlock().getTimestamp(); - LocalDateTime blockDateTime = LocalDateTime.ofEpochSecond(blockTimeStamp.longValue(), 0, ZoneOffset.UTC); - - // decide on direction - if (blockDateTime.isAfter(dateTime)) { - while (--blockNumber >= 0) { - blockTimeStamp = web3j.ethGetBlockByNumber(new DefaultBlockParameterNumber(blockNumber), false).send().getBlock().getTimestamp(); - blockDateTime = LocalDateTime.ofEpochSecond(blockTimeStamp.longValue(), 0, ZoneOffset.UTC); - - if (blockDateTime.isBefore(dateTime)) { - return blockNumber + 1; - } - } - - return 0; - } - - while (++blockNumber <= latestBlockNumber) { - blockTimeStamp = web3j.ethGetBlockByNumber(new DefaultBlockParameterNumber(blockNumber), false).send().getBlock().getTimestamp(); - blockDateTime = LocalDateTime.ofEpochSecond(blockTimeStamp.longValue(), 0, ZoneOffset.UTC); - - if (blockDateTime.isAfter(dateTime)) { - return blockNumber; - } - } - - return Long.MAX_VALUE; - } - - private EthFilter generateFilter(String smartContractAddress, Event event, int parameterCount, DefaultBlockParameter from, DefaultBlockParameter to) { - EthFilter filter = new EthFilter( - from, - to, - smartContractAddress). - addSingleTopic(EventEncoder.encode(event)); - // for each parameter, we add a null topic - for (int i = 0; i < parameterCount; i++) { - filter = filter.addNullTopic(); - } - - return filter; - } - - private CompletableFuture invokeFunctionByMethodCall(String encodedFunction, String scAddress, List outputs, - List> returnTypes) { - org.web3j.protocol.core.methods.request.Transaction transaction = org.web3j.protocol.core.methods.request.Transaction - .createEthCallTransaction(credentials.getAddress(), scAddress, encodedFunction); - - return web3j.ethCall(transaction, DefaultBlockParameterName.LATEST) - .sendAsync() - .thenApply(ethCall -> FunctionReturnDecoder.decode(ethCall.getValue(), returnTypes)) - .thenApply(decoded -> { - if (returnTypes.size() != decoded.size()) - throw new InvokeSmartContractFunctionFailure("Failed to invoke read-only Ethereum smart contract function"); - - Transaction tx = new LinearChainTransaction(); - tx.setState(TransactionState.RETURN_VALUE); - List returnedValues = new ArrayList<>(); - - for (int i = 0; i < decoded.size(); i++) { - returnedValues.add(Parameter - .builder() - .name(outputs.get(i).getName()) - .value(ParameterDecoder.decode(decoded.get(i))) - .build()); - } - - tx.setReturnValues(returnedValues); - - return tx; - }); - } - - private CompletableFuture invokeFunctionByTransaction(long waitFor, String encodedFunction, String scAddress, long timeoutMillis) { - return this - .retrieveNewNonce() - .thenApply(nonce -> { - try { - return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction( - credentials.getAddress(), - nonce, - DefaultGasProvider.GAS_PRICE, - DefaultGasProvider.GAS_LIMIT, - scAddress, - encodedFunction); - } catch (Exception e) { - log.error("An error occurred while trying to create a function signature!. Reason: {}", e.getMessage()); - throw new CompletionException(wrapEthereumExceptions(e)); - } - }) - .thenCompose(transaction -> web3j.ethSendTransaction(transaction).sendAsync()) - .thenCompose(tx -> { - final String txHash = tx.getTransactionHash(); - log.info("transaction hash is {}", txHash); - return CompletableFuture.completedFuture(txHash); - }) - .thenCompose(txHash -> waitUntilTransactionIsMined(txHash, timeoutMillis)) - .thenCompose(txReceipt -> subscribeForTxEvent(txReceipt.getTransactionHash(), waitFor, - TransactionState.CONFIRMED, TransactionState.NOT_FOUND, TransactionState.ERRORED)) - .exceptionally((e) -> { - throw wrapEthereumExceptions(e); - }); - } - - private CompletableFuture waitUntilTransactionIsMined(final String txHash, final long timeOutMillis) - throws CompletionException { - final CompletableFuture result = new CompletableFuture<>(); - final long START_TIME_MILLIS = (new Date()).getTime(); - - final Disposable subscription = web3j.blockFlowable(false).subscribe(ethBlock -> { - try { - long currentTimeMillis = (new Date()).getTime(); - - // if the time passed since we started is longer than the timeout - if (currentTimeMillis - START_TIME_MILLIS >= timeOutMillis) { - TimeoutException exception = - new TimeoutException("Timeout is reached before transaction is mined!", txHash, 0.0); - result.completeExceptionally(exception); - } else { - EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(txHash).send(); - if (receipt != null && receipt.getTransactionReceipt().isPresent()) { - result.complete(receipt.getResult()); - } - } - } catch (IOException e) { - result.completeExceptionally(e); - } - }); - - //dispose the flowable when the CompletableFuture completes (either when detecting an event, or manually) - result.whenComplete((v, e) -> subscription.dispose()); - - return result; - } - - // based on https://github.com/web3j/web3j/blob/master/abi/src/test/java/org/web3j/abi/FunctionEncoderTest.java - private List convertToSolidityTypes(List params) throws ParameterException { - List result = new ArrayList<>(); - - for (Parameter param : params) { - result.add(ParameterEncoder.encode(param)); - } - - return result; - } - - private CompletableFuture retrieveNewNonce() { - return web3j.ethGetTransactionCount( - credentials.getAddress(), DefaultBlockParameterName.LATEST) - .sendAsync() - .thenApply(EthGetTransactionCount::getTransactionCount); - } - - private static boolean handleDetectedState(final Optional transactionDetails, - final TransactionState detectedState, final TransactionState[] interesting, - CompletableFuture future) { - // Only complete the future if we are interested in this event - if (Arrays.asList(interesting).contains(detectedState)) { - final LinearChainTransaction result = new LinearChainTransaction(); - result.setState(detectedState); - // it is important that this list is not null - result.setReturnValues(new ArrayList<>()); - - if (transactionDetails.isPresent()) { - result.setBlock(new Block(transactionDetails.get().getBlockNumber(), transactionDetails.get().getBlockHash())); - result.setFrom(transactionDetails.get().getFrom()); - result.setTo(transactionDetails.get().getTo()); - result.setTransactionHash(transactionDetails.get().getHash()); - result.setValue(transactionDetails.get().getValue()); - } - - future.complete(result); - - return true; - } - - return false; - } - - private static HttpService createWeb3HttpService(String url) { - OkHttpClient.Builder builder = new OkHttpClient.Builder(); - OkHttpClient client = builder - .connectTimeout(0, TimeUnit.SECONDS) - .readTimeout(0, TimeUnit.SECONDS) - .writeTimeout(0, TimeUnit.SECONDS) - .build(); - return new HttpService(url, client, false); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapper.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapper.java deleted file mode 100644 index aa673ee..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapper.java +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import java.io.ByteArrayInputStream; -import java.math.BigInteger; - -import javax.json.Json; -import javax.json.JsonObject; - -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.MathUtils; -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import org.web3j.abi.datatypes.AbiTypes; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Bool; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Utf8String; - -public class EthereumTypeMapper { - public static Class getEthereumType(String typeAsJsonSchema) throws ParameterException { - JsonObject jsonObject = null; - try { - jsonObject = Json.createReader(new ByteArrayInputStream(typeAsJsonSchema.getBytes())).readObject(); - - String type = jsonObject.getString("type"); - - if (type.equals("boolean")) { - return Bool.class; - } - - if (type.equals("string")) { - return handleStringType(jsonObject); - } - - if (type.equals("integer")) { - return handleIntegerType(jsonObject); - } - - if (type.equals("array")) { - return handleArrayType(jsonObject); - } - - throw new ParameterException("Unrecognized type " + type); - } catch (Exception e) { - throw new ParameterException(e.getMessage()); - } - } - - private static Class handleStringType(JsonObject jsonObject) { - if (jsonObject.containsKey("pattern")) { - if (jsonObject.getString("pattern").equals("^0x[a-fA-F0-9]{40}$")) { - return Address.class; - } else { - throw new ParameterException("Unrecognized string type"); - } - } - - return Utf8String.class; - } - - private static Class handleIntegerType(JsonObject jsonObject) throws ArithmeticException { - if (jsonObject.containsKey("minimum") && jsonObject.containsKey("maximum")) { - BigInteger minimum = jsonObject.getJsonNumber("minimum").bigIntegerValue(); - BigInteger maximum = jsonObject.getJsonNumber("maximum").bigIntegerValue(); - - if (minimum.equals(BigInteger.ZERO)) { - // this might be a uint. Let's try to find M - if (maximum.compareTo(BigInteger.ZERO) > 0) { - // will throw an exception if not exact! - int m = MathUtils.log2(maximum.add(BigInteger.ONE)); - - if (m % 8 == 0) { - return AbiTypes.getType("uint" + m); - } - } - } else { - if (minimum.compareTo(BigInteger.ZERO) < 0 && minimum.abs().equals(maximum.add(BigInteger.ONE))) { - // this might be an int. Let's try to find M - // will throw an exception if not exact! - int m = MathUtils.log2(maximum.add(BigInteger.ONE)); - - if ((m + 1) % 8 == 0) { - return AbiTypes.getType("int" + (m + 1)); - } - } - } - } - - throw new ParameterException("Unrecognized integer type!"); - } - - /** - * only bytes and byte are supported at the moment - */ - private static Class handleArrayType(JsonObject outerJsonObject) { - if (outerJsonObject.containsKey("items")) { - // get the "items" schema, tuples are not yet supported! - JsonObject jsonObject = outerJsonObject.getJsonObject("items"); - - if (jsonObject.containsKey("type") && jsonObject.getString("type").equals("string")) { - if (jsonObject.containsKey("pattern") && jsonObject.getString("pattern").equals("^[a-fA-F0-9]{2}$")) { - if (outerJsonObject.containsKey("maxItems")) { - int maxSize = outerJsonObject.getInt("maxItems"); - if (maxSize > 0 && maxSize <= 32) { - return AbiTypes.getType("bytes" + maxSize); - } - } else { - return DynamicBytes.class; - } - } - } - } - - throw new ParameterException("Unrecognized array type!"); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterDecoder.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterDecoder.java deleted file mode 100644 index 19f8435..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterDecoder.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import java.math.BigInteger; - -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Bool; -import org.web3j.abi.datatypes.Bytes; -import org.web3j.abi.datatypes.BytesType; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Int; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Uint; -import org.web3j.abi.datatypes.Utf8String; - -//todo support array types e.g., address[] -public class ParameterDecoder { - public static String decode(Type value) throws ParameterException { - try { - if (value instanceof Utf8String || value instanceof Address) - return value.getValue().toString(); - - if (value instanceof Bool) - return String.valueOf(((Bool) value).getValue()); - - if (value instanceof Uint || value instanceof Int) - return ((BigInteger) value.getValue()).toString(10); - - if (value instanceof DynamicBytes || value instanceof Bytes) { - if (((BytesType) value).getValue().length > 0) { - return (new BigInteger(((BytesType) value).getValue())).toString(16); - } - return "empty"; - } - } catch (Exception e) { - throw new ParameterException("An error occurred while encoding return value. Reason: " - + e.getMessage()); - } - - throw new ParameterException("The passed type is not supported! " + value.getTypeAsString()); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoder.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoder.java deleted file mode 100644 index be9800f..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoder.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import java.math.BigInteger; - -import javax.xml.bind.DatatypeConverter; - -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Bool; -import org.web3j.abi.datatypes.Bytes; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Int; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Uint; -import org.web3j.abi.datatypes.Utf8String; - -public class ParameterEncoder { - public static Type encode(Parameter parameter) throws ParameterException { - Class typeClass = EthereumTypeMapper.getEthereumType(parameter.getType()); - try { - if (typeClass == Bool.class) { - return new Bool(Boolean.parseBoolean(parameter.getValue())); - } - - if (typeClass == Address.class) { - return new Address(parameter.getValue()); - } - - if (typeClass == Utf8String.class) { - return new Utf8String(parameter.getValue()); - } - - if (typeClass == DynamicBytes.class) { - return new DynamicBytes(DatatypeConverter.parseHexBinary(parameter.getValue())); - } - - if (typeClass.getSuperclass() == Int.class) { - return typeClass.getDeclaredConstructor(BigInteger.class) - .newInstance(new BigInteger(parameter.getValue(), 10)); - } - - if (typeClass.getSuperclass() == Uint.class) { - return typeClass.getDeclaredConstructor(BigInteger.class) - .newInstance(new BigInteger(parameter.getValue(), 10)); - } - - if (typeClass.getSuperclass() == Bytes.class) { - byte[] value = DatatypeConverter.parseHexBinary(parameter.getValue()); - return typeClass.getDeclaredConstructor(value.getClass()) - .newInstance((Object) value); - } - - throw new ParameterException("Unrecognized parameter type!"); - } catch (Exception e) { - if (e instanceof ParameterException) - throw (ParameterException) e; - - throw new ParameterException(e.getMessage()); - } - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapter.java deleted file mode 100644 index 7fb340a..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapter.java +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.fabric; - -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.BooleanExpressionEvaluator; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.SmartContractPathParser; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidScipParameterException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidTransactionException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvokeSmartContractFunctionFailure; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvokeSmartContractFunctionRevoke; -import blockchains.iaas.uni.stuttgart.de.exceptions.NotSupportedException; -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import blockchains.iaas.uni.stuttgart.de.model.Occurrence; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; -import io.reactivex.Observable; -import io.reactivex.subjects.PublishSubject; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hyperledger.fabric.gateway.Contract; -import org.hyperledger.fabric.gateway.ContractEvent; -import org.hyperledger.fabric.gateway.Gateway; -import org.hyperledger.fabric.gateway.Network; -import org.hyperledger.fabric.gateway.impl.event.ContractEventImpl; -import org.hyperledger.fabric.sdk.BlockEvent; -import org.hyperledger.fabric.sdk.ChaincodeEvent; -import org.hyperledger.fabric.sdk.exception.InvalidArgumentException; -import org.hyperledger.fabric.sdk.exception.ProposalException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Builder -public class FabricAdapter implements BlockchainAdapter { - private String blockchainId; - private static final Logger log = LoggerFactory.getLogger(FabricAdapter.class); - - @Override - public CompletableFuture submitTransaction(String receiverAddress, BigDecimal value, double requiredConfidence - - ) throws InvalidTransactionException, NotSupportedException { - throw new NotSupportedException("Fabric does not support submitting monetary transactions!"); - } - - @Override - public Observable receiveTransactions(String senderId, double requiredConfidence) throws NotSupportedException { - throw new NotSupportedException("Fabric does not support receiving monetary transactions!"); - } - - @Override - public CompletableFuture ensureTransactionState(String transactionId, double requiredConfidence) throws NotSupportedException { - throw new NotSupportedException("Fabric does not support monetary transactions!"); - } - - @Override - public CompletableFuture detectOrphanedTransaction(String transactionId) throws NotSupportedException { - throw new NotSupportedException("Fabric does not support monetary transactions!"); - } - - @Override - public CompletableFuture invokeSmartContract( - String smartContractPath, - String functionIdentifier, - List inputs, - List outputs, - double requiredConfidence, - long timeoutMillis) throws BalException { - if (outputs.size() > 1) { - throw new ParameterException("Hyperledger Fabric supports only at most a single return value."); - } - CompletableFuture result = new CompletableFuture<>(); - SmartContractPathElements path = this.parsePathElements(smartContractPath); - - try { - Contract contract = GatewayManager.getInstance().getContract(blockchainId, path.channel, path.chaincode); - String[] params = inputs.stream().map(Parameter::getValue).toArray(String[]::new); - - try { - byte[] resultAsBytes = contract.submitTransaction(functionIdentifier, params); - Transaction resultT = new Transaction(); - - if (outputs.size() == 1) { - Parameter resultP = Parameter - .builder() - .name(outputs.get(0).getName()) - .value(new String(resultAsBytes, StandardCharsets.UTF_8)) - .build(); - resultT.setReturnValues(Collections.singletonList(resultP)); - log.info(resultP.getValue()); - } else if (outputs.size() == 0) { - log.info("Fabric transaction without a return value executed!"); - resultT.setReturnValues(Collections.emptyList()); - } - - resultT.setState(TransactionState.RETURN_VALUE); - result.complete(resultT); - } catch (Exception e) { - // exceptions at this level are invocation exceptions. They should be sent asynchronously to the client app. - result.completeExceptionally(new InvokeSmartContractFunctionFailure(e.getMessage())); - } - } catch (Exception e) { - // this is a synchronous exception. - throw new BlockchainNodeUnreachableException(e.getMessage()); - } - - return result; - } - - @Override - public Observable subscribeToEvent( - String smartContractAddress, - String eventIdentifier, - List outputParameters, - double degreeOfConfidence, - String filter) throws BalException { - SmartContractPathElements path = this.parsePathElements(smartContractAddress); - Contract contract = GatewayManager.getInstance().getContract(blockchainId, path.channel, path.chaincode); - final PublishSubject result = PublishSubject.create(); - - Consumer consumer = contract.addContractListener(event -> { - log.info(event.toString()); - - try { - Occurrence occurrence = this.handleEvent(event, outputParameters, filter); - - if (occurrence != null) { - result.onNext(occurrence); - } - } catch (InvalidScipParameterException e) { - result.onError(e); - } - }, eventIdentifier); - - return result.doFinally(() -> contract.removeContractListener(consumer)); - } - - @Override - public CompletableFuture queryEvents(String smartContractAddress, String eventIdentifier, List outputParameters, String filter, TimeFrame timeFrame) throws BalException { - try { - final SmartContractPathElements path = this.parsePathElements(smartContractAddress); - final LocalDateTime fromDateTime = timeFrame != null ? timeFrame.getFromLocalDateTime() : null; - final LocalDateTime toDateTime = timeFrame != null ? timeFrame.getToLocalDateTime() : null; - final Network network = GatewayManager.getInstance().getChannel(blockchainId, path.channel); - final long latestBlockNumber = network - .getChannel() - .queryBlockchainInfo() - .getHeight() - 1; - final CompletableFuture result = new CompletableFuture<>(); - final QueryResult queryResult = QueryResult.builder().occurrences(new ArrayList<>()).build(); - log.info("latest Fabric block number: {}", latestBlockNumber); - - // the listening is over either when the block number is past the latest block number at the time of invocation, - // or when the "to" timestamp is exceeded by the transaction timestamp. - // using the provided ContractListener does not work since we cannot tell when past events are done in the replay! - final Consumer consumer = network.addBlockListener(0, blockEvent -> { - log.info("handling block no. {}", blockEvent.getBlockNumber()); - - blockEvent.getTransactionEvents().forEach(tE -> { - log.info("handling transaction hash: {}", tE.getTransactionID()); - final LocalDateTime transactionDateTime = tE.getTimestamp().toInstant() - .atZone(ZoneId.systemDefault()) - .toLocalDateTime(); - // we could be already done! - if (toDateTime != null && toDateTime.isBefore(transactionDateTime)) { - log.info("transaction after last allowed time. Completing!"); - result.complete(queryResult); - } else { - // ensure we are not before the first permitted timestamp - if (fromDateTime == null || fromDateTime.isBefore(transactionDateTime)) { - // iterate over events of this transaction - tE.getTransactionActionInfos().forEach(tAI -> { - ChaincodeEvent cE = tAI.getEvent(); - // check if name matches - if (cE != null && cE.getEventName() != null && cE.getEventName().equals(eventIdentifier)) { - // check if filter evaluates to true - Occurrence occurrence = this.handleEvent(new ContractEventImpl(tE, cE), outputParameters, filter); - - if (occurrence != null) { - // we found a matching occurrence - queryResult.getOccurrences().add(occurrence); - } - } - }); - } - } - }); - - if (blockEvent.getBlockNumber() >= latestBlockNumber) { - log.info("currentBlock >= latestBlock so completing!"); - result.complete(queryResult); - } - }); - - return result.whenComplete((res, error) -> network.removeBlockListener(consumer)); - } catch (ProposalException | InvalidArgumentException e) { - throw new BlockchainNodeUnreachableException(e.getMessage()); - } - } - - private Occurrence handleEvent(ContractEvent event, List outputParameters, String filter) throws InvalidScipParameterException { - // todo try to parse the returned value according to the outputParameters - List parameters = new ArrayList<>(); - - if (event.getPayload().isPresent() && outputParameters.size() > 0) { - Parameter parameter = Parameter - .builder() - .name(outputParameters.get(0).getName()) - .type(outputParameters.get(0).getType()) - .value(new String(event.getPayload().get(), StandardCharsets.UTF_8)) - .build(); - parameters.add(parameter); - } - - try { - if (BooleanExpressionEvaluator.evaluate(filter, parameters)) { - return Occurrence - .builder() - .parameters(parameters) - .isoTimestamp(DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.of("UTC")).format(event.getTransactionEvent().getTimestamp().toInstant())) - .build(); - } - - return null; - } catch (Exception e) { - throw new InvalidScipParameterException(e.getMessage()); - } - } - - @Override - public String testConnection() { - try { - Gateway gateway = GatewayManager.getInstance().getGateway(blockchainId); - if (gateway.getIdentity() != null) - return "true"; - else - return "Cannot get gateway identity!"; - } catch (Exception e) { - return e.getMessage(); - } - } - - private SmartContractPathElements parsePathElements(String smartContractPath) throws InvokeSmartContractFunctionFailure { - SmartContractPathParser parser = SmartContractPathParser.parse(smartContractPath); - String[] pathSegments = parser.getSmartContractPathSegments(); - - if (pathSegments.length != 3 && pathSegments.length != 2) { - String message = String.format("Unable to identify the path to the requested function. Expected path segments: 3 or 2. Found path segments: %s", pathSegments.length); - log.error(message); - throw new InvalidScipParameterException(message); - } - - SmartContractPathElements.SmartContractPathElementsBuilder builder = SmartContractPathElements - .builder() - .channel(pathSegments[0]) - .chaincode(pathSegments[1]); - - if (pathSegments.length == 3) { - builder = builder.smartContract(pathSegments[2]); - } - - return builder.build(); - } - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - private static class SmartContractPathElements { - private String channel; - private String chaincode; - private String smartContract; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/GatewayManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/GatewayManager.java deleted file mode 100644 index b0b42fc..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/GatewayManager.java +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.fabric; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.FabricConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidScipParameterException; -import org.hyperledger.fabric.gateway.Contract; -import org.hyperledger.fabric.gateway.Gateway; -import org.hyperledger.fabric.gateway.Network; -import org.hyperledger.fabric.gateway.Wallet; - -// todo make thread-safe -public class GatewayManager { - private static GatewayManager instance; - private Map gateways; - // todo make the key include blockchain-id as well - private Map channels; - // todo make the key include blockchaon-id and channel name as well - private Map contracts; - - private GatewayManager() { - gateways = new HashMap<>(); - channels = new HashMap<>(); - contracts = new HashMap<>(); - - ConnectionProfilesManager.getInstance().setListener(() -> { - gateways.values().forEach(Gateway::close); - gateways.clear(); - channels.clear(); - contracts.clear(); - }); - } - - public Gateway getGateway(String blockchainId) throws BlockchainNodeUnreachableException { - if (gateways.containsKey(blockchainId)) { - return gateways.get(blockchainId); - } - - AbstractConnectionProfile profile = ConnectionProfilesManager.getInstance().getConnectionProfiles().get(blockchainId); - - if (!(profile instanceof FabricConnectionProfile)) { - throw new InvalidScipParameterException(); - } - final String walletPath = ((FabricConnectionProfile) profile).getWalletPath(); - final String networkConfigPath = ((FabricConnectionProfile) profile).getConnectionProfilePath(); - final String user = ((FabricConnectionProfile) profile).getUserName(); - // Load an existing wallet holding identities used to access the network. - Path walletDirectory = Paths.get(walletPath); - - Wallet wallet = null; - try { - wallet = Wallet.createFileSystemWallet(walletDirectory); - - // Path to a connection profile describing the network. - Path networkConfigFile = Paths.get(networkConfigPath); - - // Configure the gateway connection used to access the network. - Gateway result = Gateway.createBuilder() - .identity(wallet, user) - .networkConfig(networkConfigFile) - .connect(); - gateways.put(blockchainId, result); - - return result; - } catch (IOException e) { - throw new BlockchainNodeUnreachableException("Cannot create Fabric gateway. Reason: " + e.getMessage()); - } - } - - public Network getChannel(String blockchainId, String channelName) { - if (channels.containsKey(channelName)) { - return channels.get(channelName); - } - - Network channel = this.getGateway(blockchainId).getNetwork(channelName); - channels.put(channelName, channel); - - return channel; - } - - public Contract getContract(String blockchainId, String channelName, String chaincodeName) { - if (contracts.containsKey(chaincodeName)) { - return contracts.get(chaincodeName); - } - - Contract contract = this.getChannel(blockchainId, channelName).getContract(chaincodeName); - contracts.put(chaincodeName, contract); - - return contract; - } - - public static GatewayManager getInstance() { - if (instance == null) { - instance = new GatewayManager(); - } - - return instance; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/BlockchainAdapter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/BlockchainAdapter.java deleted file mode 100644 index beffec6..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/BlockchainAdapter.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2022 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.interfaces; - -import java.math.BigDecimal; -import java.time.Period; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidTransactionException; -import blockchains.iaas.uni.stuttgart.de.exceptions.NotSupportedException; -import blockchains.iaas.uni.stuttgart.de.model.Occurrence; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; -import io.reactivex.Observable; - -public interface BlockchainAdapter { - /** - * submits a transaction to the blockchain that transfers an amount of the native crypto-currency to some address. - * - * @param requiredConfidence the degree-of-confidence required to be achieved before sending a callback message to the invoker. - * @param receiverAddress the address of the receiver - * @param value the value to transfer measured in the most granular unit, e.g., wei, satoshi - * @return a completable future that emits a summary of the submitted transaction. - * The future should normally complete with a transaction of the state CONFIRMED if the desired number of block-confirmations were received, - * and with a transaction of the state NOT_FOUND if the transaction was committed to a block and then orphaned and invalidated. - * The future should exceptionally complete with an exception of type BlockchainNodeUnreachableException if the blockchain node is not reachable, - * and with an exception of type InvalidTransactionException if the transaction is initially invalid (e.g., malformed) - * @throws InvalidTransactionException if the submitted transaction causes an immediate validation error, e.g., - * insufficient funds, or incorrect receiverAddress (this seems to never be thrown) - */ - CompletableFuture submitTransaction(String receiverAddress, BigDecimal value, double requiredConfidence) throws InvalidTransactionException, NotSupportedException; - - /** - * receives transactions addressed to us (potentially from a specific sender) - * - * @param requiredConfidence the degree-of-confidence required to be achieved before sending a callback message to the invoker. - * @param senderId an optional address of the sender. If specified, only transactions from this sender are considered - * @return an observable that emits a summary of the received transaction whenever one is detected - */ - Observable receiveTransactions(String senderId, double requiredConfidence) throws NotSupportedException; - - /** - * ensures that a transaction receives enough block-confirmations - * - * @param requiredConfidence the degree-of-confidence required to be achieved before sending a callback message to the invoker. - * @param transactionId the hash of the transaction we want to monitor - * @return a completable future that emits the new state of the transaction (either COFIRMED in case the desired - * number of block-confirmations got received, or NOT_FOUND if the transaction got invalidated). - * The future should exceptionally complete with an exception of type BlockchainNodeUnreachableException if the blockchain node is not reachable - */ - CompletableFuture ensureTransactionState(String transactionId, double requiredConfidence) throws NotSupportedException; - - /** - * detects that the given transaction got orphaned - * - * @param transactionId the hash of the transaction we want to monitor - * @return a completable future that emits the new state of the transaction (PENDING meaning that it no longer has a - * block, i.e., it is orphaned) - * The future should exceptionally complete with an exception of type BlockchainNodeUnreachableException if the blockchain node is not reachable - */ - CompletableFuture detectOrphanedTransaction(String transactionId) throws NotSupportedException; - - /** - * invokes a smart contract function - * - * @param smartContractPath the path to the smart contract - * @param functionIdentifier the function name - * @param inputs the input parameters of the function to be invoked - * @param outputs the output parameters of the function to be invoked - * @param requiredConfidence the degree-of-confidence required to be achieved before sending a callback message to the invoker. - * @return a completable future that emits a new transaction object holding the result of the invocation, or finishes exceptionally - * indicating a failed invocation. - * @throws NotSupportedException if the underlying blockchain system does not support smart contracts. - */ - CompletableFuture invokeSmartContract( - String smartContractPath, - String functionIdentifier, - List inputs, - List outputs, - double requiredConfidence, - long timeoutMillis - ) throws BalException; - - /** - * Monitors the occurrences of a given blockchain event. - * - * @param smartContractAddress the address of the smart contract that contains the event. - * @param eventIdentifier the name of the event to be monitored. - * @param outputParameters the list of output parameter names and types of the event to be monitored. - * @param degreeOfConfidence the degree of confidence required for the transactions triggering the events. - * @param filter C-style filter for the events that uses the output parameters. - * @return An observable that emits matching occurrences. - */ - Observable subscribeToEvent(String smartContractAddress, String eventIdentifier, - List outputParameters, - double degreeOfConfidence, - String filter) throws BalException; - - /** - * Queries previous occurrences of a given blockchain event - * - * @param smartContractAddress the address of the smart contract that contains the event. - * @param eventIdentifier the name of the event to be monitored. - * @param outputParameters the list of output parameter names and types of the event to be monitored. - * @param filter C-style filter for the events that uses the output parameters. - * @param timeFrame The timeFrame in which to consider event occurrences. - * @return A completable future containing a list of matching occurrences. - */ - CompletableFuture queryEvents(String smartContractAddress, String eventIdentifier, List outputParameters, - String filter, TimeFrame timeFrame) throws BalException; - /** - * Tests the connection settings with the underlying blockchain - * - * @return true if the connection is successful, an error message otherwise. - */ - String testConnection(); -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/FinalityConfidenceCalculator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/FinalityConfidenceCalculator.java deleted file mode 100644 index 59a69b8..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/interfaces/FinalityConfidenceCalculator.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.interfaces; - -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; - -/** - * Calculates the DoC of a transaction - */ -public interface FinalityConfidenceCalculator { - double getCurrentConfidence(LinearChainTransaction transaction); -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BFTConfidenceCalculator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BFTConfidenceCalculator.java deleted file mode 100644 index 12c8196..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BFTConfidenceCalculator.java +++ /dev/null @@ -1,22 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.FinalityConfidenceCalculator; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; - -public class BFTConfidenceCalculator implements FinalityConfidenceCalculator { - @Override - public double getCurrentConfidence(LinearChainTransaction transaction) { - // always return 1.0 since when BFT consensus succeeds, we are sure that the included tx are durably committed. - return 1.0; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluator.java deleted file mode 100644 index dfbd283..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluator.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.util.List; - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; - -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import com.google.common.base.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BooleanExpressionEvaluator { - private static final Logger log = LoggerFactory.getLogger(BooleanExpressionEvaluator.class); - - public static boolean evaluate(String expression, List parameters) throws Exception { - if (Strings.isNullOrEmpty(expression)) { - return true; - } - - ScriptEngineManager mgr = new ScriptEngineManager(); - ScriptEngine jsEngine = mgr.getEngineByName("JavaScript"); - - for (Parameter param : parameters) { - jsEngine.put(param.getName(), JsonSchemaToJavaTypeMapper.map(param)); - } - - log.info("Executing in script environment..."); - - try { - Object result = jsEngine.eval(expression); - if (result instanceof Boolean) { - return (Boolean) result; - } else { - throw new RuntimeException(String.format("The expression evaluated to type: %s, but a boolean value was expected!", result.getClass().getName())); - } - } catch (ScriptException ex) { - log.error("Failed to execute boolean expression {}. Reason: {}.", expression, ex.getMessage()); - throw ex; - } - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapper.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapper.java deleted file mode 100644 index 9e33653..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapper.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.io.ByteArrayInputStream; -import java.util.Arrays; - -import javax.json.Json; -import javax.json.JsonObject; -import javax.xml.bind.DatatypeConverter; - -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.ParameterException; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; - -public class JsonSchemaToJavaTypeMapper { - - public static Object map(Parameter parameter) throws BalException { - try { - JsonObject jsonObject = Json.createReader(new ByteArrayInputStream(parameter.getType().getBytes())).readObject(); - - return map(jsonObject, parameter.getValue()); - } catch (Exception e) { - if (!(e instanceof BalException)) - throw new ParameterException(e.getMessage()); - - throw (BalException) e; - } - } - - private static Object map(JsonObject jsonObject, String value) { - - String type = jsonObject.getString("type"); - - if (type.equals("boolean")) { - return Boolean.parseBoolean(value); - } - - if (type.equals("string")) { - if (jsonObject.containsKey("pattern") && jsonObject.getString("pattern").equals("^[a-fA-F0-9]{2}$")) { - byte[] bytes = DatatypeConverter.parseHexBinary(value); - - if (bytes.length == 1) { - return bytes[0]; - } - - throw new ParameterException("Invalid byte array: " + value); - } - - return value; - } - - if (type.equals("integer")) { - return Long.parseLong(value); - } - - if (type.equals("number")) { - return Double.parseDouble(value); - } - - if (type.equals("array")) { - return handleArrayType(jsonObject, value); - } - - throw new ParameterException("Unrecognized type!"); - } - - // todo this will not work with ethereum byte array types! - private static Object handleArrayType(JsonObject outerJsonObject, String value) { - if (outerJsonObject.containsKey("items")) { - // get the "items" schema, tuples are not yet supported! - JsonObject jsonObject = outerJsonObject.getJsonObject("items"); - - // not an empty array! - if (value.length() > 2) { - String[] values = value.substring(1, value.length() - 1).split(","); - - return Arrays.stream(values).map(current -> map(jsonObject, current)).toArray(); - } - } - - throw new ParameterException("Unrecognized array type!"); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/MathUtils.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/MathUtils.java deleted file mode 100644 index 1621a5e..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/MathUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.math.BigInteger; -import java.math.RoundingMode; - -import com.google.common.math.BigIntegerMath; -import com.google.common.math.LongMath; - -public class MathUtils { - public static final double ACCEPTED_DOUBLE_ERROR = 0.000001; - public static long factorial(int n) { - return LongMath.factorial(n); - } - public static int log2(BigInteger n) throws ArithmeticException { - return BigIntegerMath.log2(n, RoundingMode.UNNECESSARY); - } - - public static int doubleCompare(double lhs, double rhs) { - if (Math.abs(lhs-rhs) < ACCEPTED_DOUBLE_ERROR) - return 0; - if(lhs-rhs > ACCEPTED_DOUBLE_ERROR) - return 1; - return -1; - } - - -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculator.java deleted file mode 100644 index f6df29f..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculator.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.FinalityConfidenceCalculator; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; - -public class PoWConfidenceCalculator implements FinalityConfidenceCalculator { - private long currentBlockchainHeight; - private double adversaryRatio; - - public double getAdversaryRatio() { - return adversaryRatio; - } - - public void setAdversaryRatio(double adversaryRatio) { - if (adversaryRatio >= 0.0 && adversaryRatio <= 1.0) { - this.adversaryRatio = adversaryRatio; - } else { - throw new IllegalArgumentException("Adversary ratio must be between 0.0 and 1.0!"); - } - } - - public long getCurrentBlockchainHeight() { - return currentBlockchainHeight; - } - - public void setCurrentBlockchainHeight(long currentBlockchainHeight) { - this.currentBlockchainHeight = currentBlockchainHeight; - } - - /** - * Uses the equation from the Bitcoin whitepaper to calculate the degree-of-confidence - * - * @param transaction the transaction to calculate the current confidence for. - * @return the current DoC measured between 0.0 and 1.0 - */ - @Override - public double getCurrentConfidence(LinearChainTransaction transaction) { - final long z = this.currentBlockchainHeight - transaction.getBlock().getNumberAsLong(); - return this.getConfidence(z); - } - - public long getEquivalentBlockDepth(double requiredConfidence) { - long z = 0; - double currentConfidence = 0.0; - - while (currentConfidence < requiredConfidence) { - currentConfidence = getConfidence(z); - ++z; - } - - return z; - } - - private double getConfidence(long z) { - final double q = this.adversaryRatio; - - if (z < 0.0) { - throw new RuntimeException("currentBlockchainHeight is smaller than the block height of the transaction!"); - } - - final double lambda = z * (q / (1 - q)); - double accumulator = 0.0; - double part1; - double part2; - - for (int k = 0; k < z; k++) { - part1 = (Math.pow(lambda, k) * Math.exp(-lambda)) / MathUtils.factorial(k); - part2 = 1 - Math.pow(q / (1 - q), z - k); - accumulator += part1 * part2; - } - - return accumulator; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/SmartContractPathParser.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/SmartContractPathParser.java deleted file mode 100644 index 901e491..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/SmartContractPathParser.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import lombok.Data; - -@Data -public class SmartContractPathParser { - private final String path; - private String[] smartContractPathSegments; - - private SmartContractPathParser(String path) { - this.path = path; - } - - private void parse() { - this.smartContractPathSegments = path.split("/"); - } - - public static SmartContractPathParser parse(String smartContractPath) { - final SmartContractPathParser result = new SmartContractPathParser(smartContractPath); - result.parse(); - - return result; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/TimeUtils.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/TimeUtils.java deleted file mode 100644 index f09d17e..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/TimeUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; - -import com.google.common.base.Strings; - -public class TimeUtils { - - public static LocalDateTime getTimestampObject(String isoTimestamp) { - if (!Strings.isNullOrEmpty(isoTimestamp)) { - return LocalDateTime.parse(isoTimestamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME); - } - - return null; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/config/Application.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/config/Application.java index 1de500d..fbadf48 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/config/Application.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/config/Application.java @@ -1,6 +1,8 @@ package blockchains.iaas.uni.stuttgart.de.config; - +import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; +import blockchains.iaas.uni.stuttgart.de.management.BlockchainPluginManager; import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.server.ResourceConfig; @@ -20,9 +22,12 @@ @ApplicationPath("") public class Application extends ResourceConfig { public Application() { + // Required to load the plugins at startup + BlockchainPluginManager.getInstance(); + packages("blockchains.iaas.uni.stuttgart.de"); register(ObjectMapperProvider.class); - register( JacksonFeature.class ); + register(JacksonFeature.class); } } diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/AbstractConnectionProfile.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/AbstractConnectionProfile.java deleted file mode 100644 index 0d3471c..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/AbstractConnectionProfile.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.connectionprofiles; - -import java.util.Properties; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.BitcoinConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.EthereumConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.FabricConnectionProfile; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME) -@JsonSubTypes( { - @JsonSubTypes.Type(value = EthereumConnectionProfile.class, name = "ethereum"), - @JsonSubTypes.Type(value = BitcoinConnectionProfile.class, name = "bitcoin"), - @JsonSubTypes.Type(value = FabricConnectionProfile.class, name = "fabric")} -) -public abstract class AbstractConnectionProfile { - private static final String PREFIX = "common."; - private static final String ADVERSARY_VOTING_RATIO = PREFIX + "adversaryVotingRatio"; - private double adversaryVotingRatio; - - public double getAdversaryVotingRatio() { - return adversaryVotingRatio; - } - - public void setAdversaryVotingRatio(double adversaryVotingRatio) { - if (adversaryVotingRatio < 0 || adversaryVotingRatio > 1.0) { - throw new IllegalArgumentException("Voting power of adversary should be between 0.0 and 1.0, but (" + - adversaryVotingRatio + ") is passed!"); - } - - this.adversaryVotingRatio = adversaryVotingRatio; - } - - public Properties getAsProperties() { - Properties result = new Properties(); - result.put(ADVERSARY_VOTING_RATIO, String.valueOf(adversaryVotingRatio)); - - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AbstractConnectionProfile that = (AbstractConnectionProfile) o; - return this.getAsProperties().equals(that.getAsProperties()); - } - - @Override - public int hashCode() { - return this.getAsProperties().hashCode(); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfilesManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfilesManager.java index 88a618e..ef8c3e8 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfilesManager.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfilesManager.java @@ -2,6 +2,7 @@ * Copyright (c) 2019 Institute for the Architecture of Application System * - University of Stuttgart * Author: Ghareeb Falazi + * Co-author: Akshay Patel * * This program and the accompanying materials are made available under the * terms the Apache Software License 2.0 @@ -18,6 +19,7 @@ import java.util.HashMap; import java.util.Map; +import blockchains.iaas.uni.stuttgart.de.api.connectionprofiles.AbstractConnectionProfile; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -52,6 +54,7 @@ public Map getConnectionProfiles() { return this.connectionProfilesMap; } + public String getConnectionProfilesAsJson() throws JsonProcessingException { return this.writer.writeValueAsString(this.connectionProfilesMap); } diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/BitcoinConnectionProfile.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/BitcoinConnectionProfile.java deleted file mode 100644 index f17e71b..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/BitcoinConnectionProfile.java +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles; - -import java.util.Properties; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; - -public class BitcoinConnectionProfile extends AbstractConnectionProfile { - private static final String PREFIX = "node.bitcoind."; - // Configuration parameters for the 'bitcoind' JSON-RPC client ('BtcdClient') - public static final String RPC_PROTOCOL = "rpc.protocol"; - public static final String RPC_HOST = PREFIX + "rpc.host"; - public static final String RPC_PORT = PREFIX + "rpc.port"; - public static final String RPC_USER = PREFIX + "rpc.user"; - public static final String RPC_PASSWORD = PREFIX + "rpc.password"; - public static final String HTTP_AUTHENTICATION_SCHEME = PREFIX + "http.auth_scheme"; - // Configuration parameters for the 'bitcoind' notification daemon ('BtcdDaemon') - public static final String NOTIFICATION_ALERT_PORT = PREFIX + "notification.alert.port"; - public static final String NOTIFICATION_BLOCK_PORT = PREFIX + "notification.block.port"; - public static final String NOTIFICATION_WALLET_PORT = PREFIX + "notification.wallet.port"; - - private String rpcProtocol; - private String rpcHost; - private String rpcPort; - private String rpcUser; - private String rpcPassword; - private String httpAuthScheme; - private String notificationAlertPort; - private String notificationBlockPort; - private String notificationWalletPort; - - public BitcoinConnectionProfile() { - } - - public BitcoinConnectionProfile(String rpcProtocol, String rpcHost, String rpcPort, String rpcUser, String rpcPassword, String httpAuthScheme, String notificationAlertPort, String notificationBlockPort, String notificationWalletPort) { - this.rpcProtocol = rpcProtocol; - this.rpcHost = rpcHost; - this.rpcPort = rpcPort; - this.rpcUser = rpcUser; - this.rpcPassword = rpcPassword; - this.httpAuthScheme = httpAuthScheme; - this.notificationAlertPort = notificationAlertPort; - this.notificationBlockPort = notificationBlockPort; - this.notificationWalletPort = notificationWalletPort; - } - - public String getRpcProtocol() { - return rpcProtocol; - } - - public void setRpcProtocol(String rpcProtocol) { - this.rpcProtocol = rpcProtocol; - } - - public String getRpcHost() { - return rpcHost; - } - - public void setRpcHost(String rpcHost) { - this.rpcHost = rpcHost; - } - - public String getRpcPort() { - return rpcPort; - } - - public void setRpcPort(String rpcPort) { - this.rpcPort = rpcPort; - } - - public String getRpcUser() { - return rpcUser; - } - - public void setRpcUser(String rpcUser) { - this.rpcUser = rpcUser; - } - - public String getRpcPassword() { - return rpcPassword; - } - - public void setRpcPassword(String rpcPassword) { - this.rpcPassword = rpcPassword; - } - - public String getHttpAuthScheme() { - return httpAuthScheme; - } - - public void setHttpAuthScheme(String httpAuthScheme) { - this.httpAuthScheme = httpAuthScheme; - } - - public String getNotificationAlertPort() { - return notificationAlertPort; - } - - public void setNotificationAlertPort(String notificationAlertPort) { - this.notificationAlertPort = notificationAlertPort; - } - - public String getNotificationBlockPort() { - return notificationBlockPort; - } - - public void setNotificationBlockPort(String notificationBlockPort) { - this.notificationBlockPort = notificationBlockPort; - } - - public String getNotificationWalletPort() { - return notificationWalletPort; - } - - public void setNotificationWalletPort(String notificationWalletPort) { - this.notificationWalletPort = notificationWalletPort; - } - - @Override - public Properties getAsProperties() { - final Properties result = super.getAsProperties(); - result.setProperty(HTTP_AUTHENTICATION_SCHEME, this.httpAuthScheme); - result.setProperty(NOTIFICATION_ALERT_PORT, this.notificationAlertPort); - result.setProperty(NOTIFICATION_BLOCK_PORT, this.notificationBlockPort); - result.setProperty(NOTIFICATION_WALLET_PORT, this.notificationWalletPort); - result.setProperty(RPC_HOST, this.rpcHost); - result.setProperty(RPC_PASSWORD, this.rpcPassword); - result.setProperty(RPC_PORT, this.rpcPort); - result.setProperty(RPC_USER, this.rpcUser); - result.setProperty(RPC_PROTOCOL, this.rpcProtocol); - return result; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/EthereumConnectionProfile.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/EthereumConnectionProfile.java deleted file mode 100644 index a9c6592..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/EthereumConnectionProfile.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles; - -import java.util.Properties; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; - -public class EthereumConnectionProfile extends AbstractConnectionProfile { - private static final String PREFIX = "ethereum."; - public static final String NODE_URL = PREFIX + "nodeUrl"; - public static final String KEYSTORE_PATH = PREFIX + "keystorePath"; - public static final String KEYSTORE_PASSWORD = PREFIX + "keystorePassword"; - public static final String BLOCK_TIME = PREFIX + "blockTimeSeconds"; - private String nodeUrl; - private String keystorePath; - private String keystorePassword; - private int pollingTimeSeconds; - - public EthereumConnectionProfile() { - } - - public EthereumConnectionProfile(String nodeUrl, String keystorePath, String keystorePassword, int pollingTimeSeconds) { - this.nodeUrl = nodeUrl; - this.keystorePath = keystorePath; - this.keystorePassword = keystorePassword; - this.pollingTimeSeconds = pollingTimeSeconds; - } - - public String getNodeUrl() { - return nodeUrl; - } - - public void setNodeUrl(String nodeUrl) { - this.nodeUrl = nodeUrl; - } - - public String getKeystorePath() { - return keystorePath; - } - - public void setKeystorePath(String keystorePath) { - this.keystorePath = keystorePath; - } - - public String getKeystorePassword() { - return keystorePassword; - } - - public void setKeystorePassword(String keystorePassword) { - this.keystorePassword = keystorePassword; - } - - public int getPollingTimeSeconds() { - return pollingTimeSeconds; - } - - public void setPollingTimeSeconds(int pollingTimeSeconds) { - this.pollingTimeSeconds = pollingTimeSeconds; - } - - @Override - public Properties getAsProperties() { - final Properties result = super.getAsProperties(); - result.setProperty(NODE_URL, this.nodeUrl); - result.setProperty(KEYSTORE_PASSWORD, this.keystorePassword); - result.setProperty(KEYSTORE_PATH, this.keystorePath); - result.setProperty(BLOCK_TIME, String.valueOf(this.pollingTimeSeconds)); - - return result; - } - - -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/FabricConnectionProfile.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/FabricConnectionProfile.java deleted file mode 100644 index 4dc3e90..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/profiles/FabricConnectionProfile.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles; - -import java.util.Properties; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; - -public class FabricConnectionProfile extends AbstractConnectionProfile { - private static final String PREFIX = "hyperledger.fabric."; - private static final String WALLET_PATH = PREFIX + "walletPath"; - private static final String USER_NAME = PREFIX + "userName"; - private static final String CONNECTION_PROFILE_PATH = PREFIX + "connectionProfilePath"; - private String walletPath; - private String userName; - private String connectionProfilePath; - - public FabricConnectionProfile() { - } - - public FabricConnectionProfile(String walletPath, String userName, String connectionProfilePath) { - this.walletPath = walletPath; - this.userName = userName; - this.connectionProfilePath = connectionProfilePath; - } - - public String getWalletPath() { - return walletPath; - } - - public void setWalletPath(String walletPath) { - this.walletPath = walletPath; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getConnectionProfilePath() { - return connectionProfilePath; - } - - public void setConnectionProfilePath(String connectionProfilePath) { - this.connectionProfilePath = connectionProfilePath; - } - - @Override - public Properties getAsProperties() { - final Properties result = super.getAsProperties(); - result.setProperty(WALLET_PATH, this.walletPath); - result.setProperty(USER_NAME, this.userName); - result.setProperty(CONNECTION_PROFILE_PATH, this.connectionProfilePath); - - return result; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BalException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BalException.java deleted file mode 100644 index a3b4e77..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BalException.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -public abstract class BalException extends RuntimeException { - - public BalException() { - } - - public BalException(String message) { - super(message); - } - - public BalException(String message, Throwable cause) { - super(message, cause); - } - - public BalException(Throwable cause) { - super(cause); - } - - public abstract int getCode(); -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainIdNotFoundException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainIdNotFoundException.java deleted file mode 100644 index 0a9b626..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainIdNotFoundException.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.NotFound, message = "The specified blockchain-id cannot be found") -public class BlockchainIdNotFoundException extends BalException { - - public BlockchainIdNotFoundException() { - super(); - } - - public BlockchainIdNotFoundException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.NotFound; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainNodeUnreachableException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainNodeUnreachableException.java deleted file mode 100644 index b6b1807..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/BlockchainNodeUnreachableException.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.ConnectionException, message = "The blockchain node cannot be reached.") -public class BlockchainNodeUnreachableException extends BalException { - - public BlockchainNodeUnreachableException() { - } - - public BlockchainNodeUnreachableException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.ConnectionException; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ExceptionCode.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ExceptionCode.java deleted file mode 100644 index 7bd99e0..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ExceptionCode.java +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -public class ExceptionCode { - public static final int UnknownError = 0; - - /** - * The blockchain instance, smart contract, event or function are not found - */ - public static final int NotFound = -32000; - /** - * Input parameter types, names, or order mismatch the designated function or event. - * This also indicates inability to map a parameter's abstract type to a native type. - */ - public static final int InvalidParameters = -32001; - /** - * Client certificate is missing - */ - public static final int MissingCertificate = -32002; - /** - * The client application is not authorized to perform the requested task. - * Gateway-side authorization. - */ - public static final int NotAuthorized = -32003; - /** - * The specified blockchain instance does not support the requested operation. - */ - public static final int NotSupported = -32004; - /** - * Connection to the underlying blockchain node is not possible. - */ - public static final int ConnectionException = -32005; - /** - * The transaction associated with an function invocation is invalidated after it was mined. - */ - public static final int TransactionInvalidatedException = -32006; - - /** - * A scip method parameter has an invalid value - */ - public static final int InvalidScipParam = -32007; - - /** - * A general error occurred when trying to invoke a smart contract function - * This error is used when the specific cause of the error cannot be deteremined. - */ - public static final int InvocationError = -32100; - /** - * The smart contract function threw an exception - */ - public static final int ExecutionError = -32101; - /** - * Not enough funds to invoke the state-changing smart contract funciton. - */ - public static final int InsufficientFunds = -32102; - /** - * The BAL instance is not authorized to performed the requested operation on the underlying blockchain. - */ - public static final int BalNotAuthorized = -32103; - - /** - * Timeout is reached before fulfilling the desired degree of confidence. - * This is an asynchronous error. - */ - public static final int Timeout = -32201; -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidScipParameterException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidScipParameterException.java deleted file mode 100644 index 51714ba..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidScipParameterException.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.InvalidScipParam, message = "A scip method parameter has an invalid value.") -public class InvalidScipParameterException extends BalException { - @Override - public int getCode() { - return ExceptionCode.InvalidScipParam; - } - - public InvalidScipParameterException() { - } - - public InvalidScipParameterException(String message) { - super(message); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidTransactionException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidTransactionException.java deleted file mode 100644 index fb0ffb1..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvalidTransactionException.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.InvocationError, message = "An error occurred while trying to invoke the smart contract function.") -public class InvalidTransactionException extends BalException { - - public InvalidTransactionException() { - } - - public InvalidTransactionException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.InvocationError; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionFailure.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionFailure.java deleted file mode 100644 index d9edca5..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionFailure.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.InvocationError, message = "The smart contract function invocation failed.") -public class InvokeSmartContractFunctionFailure extends BalException { - public InvokeSmartContractFunctionFailure() { - } - - public InvokeSmartContractFunctionFailure(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.InvocationError; - } -} \ No newline at end of file diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionRevoke.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionRevoke.java deleted file mode 100644 index 6d5d522..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/InvokeSmartContractFunctionRevoke.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.ExecutionError, message = "The execution of the smart contract function resulted in an error.") -public class InvokeSmartContractFunctionRevoke extends BalException{ - public InvokeSmartContractFunctionRevoke() { - } - - public InvokeSmartContractFunctionRevoke(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.ExecutionError; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ManualUnsubscriptionException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ManualUnsubscriptionException.java deleted file mode 100644 index 1c632ed..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ManualUnsubscriptionException.java +++ /dev/null @@ -1,22 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -public class ManualUnsubscriptionException extends RuntimeException { - public ManualUnsubscriptionException() { - super(); - } - - public ManualUnsubscriptionException(String message) { - super(message); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/NotSupportedException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/NotSupportedException.java deleted file mode 100644 index a1fcde6..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/NotSupportedException.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.NotSupported, message = "The requested operation is not supported by the underlying blockchain instance.") -public class NotSupportedException extends BalException { - public NotSupportedException() { - } - - public NotSupportedException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.NotSupported; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ParameterException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ParameterException.java deleted file mode 100644 index c12a544..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/ParameterException.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.InvalidParameters, message = "The passed function/event parameter names, order, or types are invalid.") -public class ParameterException extends BalException { - public ParameterException() { - } - - public ParameterException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.InvalidParameters; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/SmartContractNotFoundException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/SmartContractNotFoundException.java deleted file mode 100644 index 895a6ea..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/SmartContractNotFoundException.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.NotFound, message = "The specified smart contract is not found.") -public class SmartContractNotFoundException extends BalException { - public SmartContractNotFoundException() { - } - - public SmartContractNotFoundException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.NotFound; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TimeoutException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TimeoutException.java deleted file mode 100644 index 12182c5..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TimeoutException.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; -import lombok.Getter; -import lombok.Setter; - -@JsonRpcError(code = ExceptionCode.Timeout, message = "Timeout was reached before the desired DoC was fulfilled.") -@Setter -@Getter -public class TimeoutException extends BalException { - private String transactionHash; - private double doc; - - public TimeoutException() { - } - - public TimeoutException(String message, String transactionHash, double doc) { - super(message); - this.transactionHash = transactionHash; - this.doc = doc; - } - - @Override - public int getCode() { - return ExceptionCode.Timeout; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TransactionNotFoundException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TransactionNotFoundException.java deleted file mode 100644 index 48319bd..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/TransactionNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018-2019 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.TransactionInvalidatedException, message = "The transaction associated with an function invocation is invalidated after it was mined.") -public class TransactionNotFoundException extends BalException { - - public TransactionNotFoundException() { - } - - public TransactionNotFoundException(String message) { - super(message); - } - - @Override - public int getCode() { - return ExceptionCode.TransactionInvalidatedException; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/UnknownException.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/UnknownException.java deleted file mode 100644 index 50bff97..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/exceptions/UnknownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.exceptions; - -import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcError; - -@JsonRpcError(code = ExceptionCode.UnknownError, message = "Unknown server error occurred.") -public class UnknownException extends BalException { - @Override - public int getCode() { - return ExceptionCode.UnknownError; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/BalService.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/BalService.java index 889cd6b..9a80360 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/BalService.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/BalService.java @@ -13,11 +13,11 @@ import java.util.List; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidScipParameterException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.InvalidScipParameterException; import blockchains.iaas.uni.stuttgart.de.management.BlockchainManager; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.QueryResult; +import blockchains.iaas.uni.stuttgart.de.api.model.TimeFrame; import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcMethod; import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcOptional; import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcParam; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/Occurrence.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/Occurrence.java index 12b83ba..012e362 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/Occurrence.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/Occurrence.java @@ -13,7 +13,7 @@ import java.util.List; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; import lombok.Data; @Data diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/ScipResponse.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/ScipResponse.java index 303c7d9..0873b07 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/ScipResponse.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/jsonrpc/model/ScipResponse.java @@ -13,9 +13,9 @@ import java.util.List; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.BalException; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CallbackMessage; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; import lombok.Builder; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainManager.java index bfd0834..d213729 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainManager.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainManager.java @@ -19,31 +19,23 @@ import java.util.concurrent.CompletionException; import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.MathUtils; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainIdNotFoundException; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainNodeUnreachableException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidScipParameterException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvalidTransactionException; -import blockchains.iaas.uni.stuttgart.de.exceptions.InvokeSmartContractFunctionFailure; -import blockchains.iaas.uni.stuttgart.de.exceptions.NotSupportedException; -import blockchains.iaas.uni.stuttgart.de.exceptions.TransactionNotFoundException; -import blockchains.iaas.uni.stuttgart.de.exceptions.UnknownException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.*; import blockchains.iaas.uni.stuttgart.de.management.callback.CallbackManager; import blockchains.iaas.uni.stuttgart.de.management.callback.CamundaMessageTranslator; import blockchains.iaas.uni.stuttgart.de.management.callback.ScipMessageTranslator; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; +import blockchains.iaas.uni.stuttgart.de.api.utils.MathUtils; import blockchains.iaas.uni.stuttgart.de.management.model.CompletableFutureSubscription; import blockchains.iaas.uni.stuttgart.de.management.model.MonitorOccurrencesSubscription; import blockchains.iaas.uni.stuttgart.de.management.model.ObservableSubscription; import blockchains.iaas.uni.stuttgart.de.management.model.Subscription; import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionKey; import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionType; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.QueryResult; -import blockchains.iaas.uni.stuttgart.de.model.TimeFrame; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.QueryResult; +import blockchains.iaas.uni.stuttgart.de.api.model.TimeFrame; +import blockchains.iaas.uni.stuttgart.de.api.model.Transaction; +import blockchains.iaas.uni.stuttgart.de.api.model.TransactionState; import com.google.common.base.Strings; import io.reactivex.disposables.Disposable; import org.slf4j.Logger; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainPluginManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainPluginManager.java new file mode 100644 index 0000000..35e675a --- /dev/null +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainPluginManager.java @@ -0,0 +1,104 @@ +/******************************************************************************** + * Copyright (c) 2022 Institute for the Architecture of Application System - + * University of Stuttgart + * Author: Akshay Patel + * + * This program and the accompanying materials are made available under the + * terms the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package blockchains.iaas.uni.stuttgart.de.management; + +import blockchains.iaas.uni.stuttgart.de.Constants; +import blockchains.iaas.uni.stuttgart.de.api.IAdapterExtension; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.NamedType; +import org.pf4j.*; + +import java.nio.file.Path; +import java.util.List; + +public class BlockchainPluginManager { + + private PluginManager pluginManager = null; + private static BlockchainPluginManager instance = null; + + private BlockchainPluginManager() { + this.pluginManager = new DefaultPluginManager(Constants.PLUGINS_DIRECTORY) { + // + @Override + protected PluginLoader createPluginLoader() { + // load only jar plugins + return new JarPluginLoader(this); + } + + @Override + protected PluginDescriptorFinder createPluginDescriptorFinder() { + // read plugin descriptor from jar's manifest + return new ManifestPluginDescriptorFinder(); + } + }; + pluginManager.loadPlugins(); + + } + + public static BlockchainPluginManager getInstance() { + if (instance == null) { + instance = new BlockchainPluginManager(); + } + return instance; + } + + public List getExtensions() { + return this.pluginManager.getExtensions(IAdapterExtension.class); + } + + public void loadJar(Path path) { + pluginManager.loadPlugin(path); + } + + public Path getPluginsPath() { + return Constants.PLUGINS_DIRECTORY; + } + + public List getPlugins() { + return pluginManager.getPlugins(); + } + + public void unloadPlugin(String pluginId) { + pluginManager.unloadPlugin(pluginId); + } + + public void startPlugin(String pluginId) { + pluginManager.startPlugin(pluginId); + + + } + + public void disablePlugin(String pluginId) { + pluginManager.disablePlugin(pluginId); + } + + public void deletePlugin(String pluginId) { + pluginManager.deletePlugin(pluginId); + } + + public void enablePlugin(String pluginId) { + pluginManager.enablePlugin(pluginId); + } + + public PluginState getPluginState(String pluginId) { + return pluginManager.getPlugin(pluginId).getPluginState(); + } + + public void registerConnectionProfileSubtypeClass(ObjectMapper objectMapper, String pluginId) { + List adapterExtensions = this.pluginManager.getExtensions(IAdapterExtension.class, pluginId); + for (IAdapterExtension adapterExtension : adapterExtensions) { + String namedType = adapterExtension.getConnectionProfileNamedType(); + objectMapper.registerSubtypes(new NamedType(adapterExtension.getConnectionProfileClass(), namedType)); + } + } +} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManager.java index 4e76433..9ce0a8d 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManager.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManager.java @@ -23,7 +23,7 @@ import blockchains.iaas.uni.stuttgart.de.management.model.Subscription; import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionKey; import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionType; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CallbackManager.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CallbackManager.java index 5fc4145..e16f5a2 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CallbackManager.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CallbackManager.java @@ -24,7 +24,7 @@ import blockchains.iaas.uni.stuttgart.de.adaptation.BlockchainAdapterFactory; import blockchains.iaas.uni.stuttgart.de.config.ObjectMapperProvider; -import blockchains.iaas.uni.stuttgart.de.exceptions.TimeoutException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.TimeoutException; import blockchains.iaas.uni.stuttgart.de.jsonrpc.model.ScipResponse; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CallbackMessage; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CamundaMessage; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CamundaMessageTranslator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CamundaMessageTranslator.java index 206652e..9bf0c0e 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CamundaMessageTranslator.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/CamundaMessageTranslator.java @@ -13,9 +13,9 @@ import java.util.Map; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import blockchains.iaas.uni.stuttgart.de.model.TransactionState; +import blockchains.iaas.uni.stuttgart.de.api.model.LinearChainTransaction; +import blockchains.iaas.uni.stuttgart.de.api.model.Transaction; +import blockchains.iaas.uni.stuttgart.de.api.model.TransactionState; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CallbackMessage; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CamundaMessage; import blockchains.iaas.uni.stuttgart.de.restapi.model.response.CamundaVariable; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/ScipMessageTranslator.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/ScipMessageTranslator.java index 32c655a..adf014f 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/ScipMessageTranslator.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/callback/ScipMessageTranslator.java @@ -13,10 +13,10 @@ import java.util.List; -import blockchains.iaas.uni.stuttgart.de.exceptions.BalException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.BalException; import blockchains.iaas.uni.stuttgart.de.jsonrpc.model.Occurrence; import blockchains.iaas.uni.stuttgart.de.jsonrpc.model.ScipResponse; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; public class ScipMessageTranslator { public static ScipResponse getInvocationResponseMessage(String correlationId, List outputs) { diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/CompletableFutureSubscription.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/CompletableFutureSubscription.java index 4ffbc9a..fd97808 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/CompletableFutureSubscription.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/CompletableFutureSubscription.java @@ -13,7 +13,7 @@ import java.util.concurrent.CompletableFuture; -import blockchains.iaas.uni.stuttgart.de.exceptions.ManualUnsubscriptionException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.ManualUnsubscriptionException; public class CompletableFutureSubscription extends Subscription { private CompletableFuture future; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/MonitorOccurrencesSubscription.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/MonitorOccurrencesSubscription.java index 3cc72d2..b77048d 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/MonitorOccurrencesSubscription.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/management/model/MonitorOccurrencesSubscription.java @@ -13,7 +13,7 @@ import java.util.List; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; import io.reactivex.disposables.Disposable; import lombok.Data; diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Block.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Block.java deleted file mode 100644 index 93628d0..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Block.java +++ /dev/null @@ -1,60 +0,0 @@ -package blockchains.iaas.uni.stuttgart.de.model; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.math.BigInteger; - -/******************************************************************************** - * Copyright (c) 2018 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -@XmlRootElement(name="Block") -@XmlAccessorType(XmlAccessType.NONE) -public class Block { - private BigInteger number; - private String hash; - - public Block(){ - - } - - public Block(BigInteger number, String hash) { - this.number = number; - this.hash = hash; - } - - public BigInteger getNumber() { - return number; - } - - public void setNumber(BigInteger number) { - this.number = number; - } - - @XmlElement(name="BlockNumber") - public long getNumberAsLong(){ - return this.number.longValue(); - } - - public void setNumberAsLong(long value){ - this.number = BigInteger.valueOf(value); - } - - @XmlElement(name="BlockHash") - public String getHash() { - return hash; - } - - public void setHash(String hash) { - this.hash = hash; - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/LinearChainTransaction.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/LinearChainTransaction.java deleted file mode 100644 index 2b6c0cb..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/LinearChainTransaction.java +++ /dev/null @@ -1,107 +0,0 @@ -package blockchains.iaas.uni.stuttgart.de.model; - - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.math.BigInteger; -import java.util.List; - -import lombok.Builder; - -/******************************************************************************** - * Copyright (c) 2018 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -@XmlRootElement(name="Transaction") -@XmlAccessorType(XmlAccessType.NONE) -public class LinearChainTransaction extends Transaction { - - @XmlElement(name="TransactionHash") - private String transactionHash; - - @XmlElement - private Block block; - - @XmlElement(name="From") - private String from; - - @XmlElement(name="To") - private String to; - - private BigInteger value; - - public LinearChainTransaction() { - super(); - } - - public LinearChainTransaction(String transactionHash, - Block block, - String from, String to, BigInteger value, TransactionState state, List returnValues) { - this.setReturnValues(returnValues); - this.setState(state); - this.transactionHash = transactionHash; - this.block = block; - this.from = from; - this.to = to; - this.value = value; - } - - public String getTransactionHash() { - return transactionHash; - } - - public void setTransactionHash(String transactionHash) { - this.transactionHash = transactionHash; - } - - public Block getBlock() { - return block; - } - - public void setBlock(Block block) { - this.block = block; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public BigInteger getValue() { - return value; - } - - public void setValue(BigInteger value) { - this.value = value; - } - - @XmlElement(name="Value") - public String getValueAsString(){ - return value.toString(); - } - - public void setValueAsString(String value){ - this.value = new BigInteger(value); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Occurrence.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Occurrence.java deleted file mode 100644 index ea933ac..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Occurrence.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.model; - -import java.time.LocalDateTime; -import java.util.List; - -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.TimeUtils; -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class Occurrence { - List parameters; - String isoTimestamp; - - @JsonIgnore - public LocalDateTime getTimestampObject() { - return TimeUtils.getTimestampObject(isoTimestamp); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Parameter.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Parameter.java deleted file mode 100644 index 38ae7c6..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Parameter.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.model; - -import java.util.Objects; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Setter -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Parameter { - private String name; - private String type; - private String value; -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/QueryResult.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/QueryResult.java deleted file mode 100644 index d787d50..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/QueryResult.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.model; - -import java.util.List; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class QueryResult { - private List occurrences; -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TimeFrame.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TimeFrame.java deleted file mode 100644 index ce9dae2..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TimeFrame.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.model; - -import java.time.LocalDateTime; - -import blockchains.iaas.uni.stuttgart.de.adaptation.utils.TimeUtils; -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Builder -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class TimeFrame { - private String from; - private String to; - - @JsonIgnore - public LocalDateTime getFromLocalDateTime() { - return TimeUtils.getTimestampObject(from); - } - - @JsonIgnore - public LocalDateTime getToLocalDateTime() { - return TimeUtils.getTimestampObject(to); - } -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Transaction.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Transaction.java deleted file mode 100644 index 8cc9064..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/Transaction.java +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.model; - -import java.util.List; - -import javax.xml.bind.annotation.XmlElement; - -import lombok.Data; - -@Data -public class Transaction { - @XmlElement(name = "TransactionState") - private TransactionState state; - - @XmlElement(name = "ReturnValues") - private List returnValues; -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TransactionState.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TransactionState.java deleted file mode 100644 index 9a00a0d..0000000 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/model/TransactionState.java +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - - * University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package blockchains.iaas.uni.stuttgart.de.model; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "State") -public enum TransactionState { - UNKNOWN, - PENDING, - CONFIRMED, - NOT_FOUND, - INVALID, - // When a smart contract function fails although a transaction is recorded (relevant for Ethereum-like BCs) - ERRORED, - // indicates that a successful read-only function invocation occurred - RETURN_VALUE -} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/ConnectionProfilesController.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/ConnectionProfilesController.java index 6957e63..a218155 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/ConnectionProfilesController.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/ConnectionProfilesController.java @@ -1,6 +1,7 @@ /******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart + * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart * Author: Ghareeb Falazi + * Co-author: Akdhay Patel * * This program and the accompanying materials are made available under the * terms the Apache Software License 2.0 @@ -8,7 +9,6 @@ * * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ - package blockchains.iaas.uni.stuttgart.de.restapi.Controllers; import java.util.Map; @@ -21,15 +21,21 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.AbstractConnectionProfile; +import blockchains.iaas.uni.stuttgart.de.api.connectionprofiles.AbstractConnectionProfile; import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; import blockchains.iaas.uni.stuttgart.de.management.BlockchainManager; import com.fasterxml.jackson.core.JsonProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Path("configure") public class ConnectionProfilesController { + + private static final Logger log = LoggerFactory.getLogger(ConnectionProfilesController.class); + @Context protected UriInfo uriInfo; @@ -40,14 +46,16 @@ public void acceptConfiguration(Map profiles) } @DELETE - public void resetConfigurations() { + public Response resetConfigurations() { ConnectionProfilesManager.getInstance().resetConnectionProfiles(); + return Response.ok().build(); } @GET @Produces(MediaType.APPLICATION_JSON) public String getConfigurations() throws JsonProcessingException { return ConnectionProfilesManager.getInstance().getConnectionProfilesAsJson(); + } @Path("test") diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/PluginManagerController.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/PluginManagerController.java new file mode 100644 index 0000000..6b58514 --- /dev/null +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/Controllers/PluginManagerController.java @@ -0,0 +1,137 @@ +package blockchains.iaas.uni.stuttgart.de.restapi.Controllers; + +import blockchains.iaas.uni.stuttgart.de.management.BlockchainPluginManager; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; +import org.pf4j.PluginWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Providers; + +@Path("plugins") +public class PluginManagerController { + private static final Logger log = LoggerFactory.getLogger(PluginManagerController.class); + + @Context + Providers providers; + + @Context + protected UriInfo uriInfo; + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response uploadJar(@FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetails) { + + BlockchainPluginManager blockchainPluginManager = BlockchainPluginManager.getInstance(); + String fileName = fileDetails.getFileName(); + log.info("Received file {}", fileName); + String uploadedFileLocation = blockchainPluginManager.getPluginsPath() + "/" + fileDetails.getFileName(); + java.nio.file.Path filePath = Paths.get(uploadedFileLocation); + if (Files.exists(filePath)) { + log.error("Received file {} already exists in plugins directory.", fileName); + return Response.status(Response.Status.BAD_REQUEST).entity("File already exists with same name.").build(); + } + writeToFile(uploadedInputStream, uploadedFileLocation); + + blockchainPluginManager.loadJar(filePath); + + return Response.ok().build(); + } + + @POST + @Path("{plugin-id}/enable") + public Response enablePlugin(@PathParam("plugin-id") final String pluginId) { + BlockchainPluginManager.getInstance().enablePlugin(pluginId); + return Response.ok().build(); + } + + @POST + @Path("{plugin-id}/start") + public Response startPlugin(@PathParam("plugin-id") final String pluginId) { + BlockchainPluginManager blockchainPluginManager = BlockchainPluginManager.getInstance(); + blockchainPluginManager.startPlugin(pluginId); + + ContextResolver resolver = providers.getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE); + ObjectMapper objectMapper = resolver.getContext(ObjectMapper.class); + + blockchainPluginManager.registerConnectionProfileSubtypeClass(objectMapper, pluginId); + return Response.ok().build(); + } + + @POST + @Path("{plugin-id}/disable") + public Response disablePlugin(@PathParam("plugin-id") final String pluginId) { + BlockchainPluginManager.getInstance().disablePlugin(pluginId); + return Response.ok().build(); + } + + @POST + @Path("{plugin-id}/unload") + public Response unloadPlugin(@PathParam("plugin-id") final String pluginId) { + BlockchainPluginManager.getInstance().unloadPlugin(pluginId); + return Response.ok().build(); + } + + @DELETE + @Path("{plugin-id}") + public Response deletePlugin(@PathParam("plugin-id") final String pluginId) { + BlockchainPluginManager blockchainPluginManager = BlockchainPluginManager.getInstance(); + blockchainPluginManager.deletePlugin(pluginId); + return Response.ok().build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getPlugins() { + BlockchainPluginManager blockchainPluginManager = BlockchainPluginManager.getInstance(); + List plugins = blockchainPluginManager.getPlugins(); + + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode parentArray = objectMapper.createArrayNode(); + for (PluginWrapper p : plugins) { + ObjectNode pluginInfo = objectMapper.createObjectNode(); + pluginInfo.put("plugin-id", p.getPluginId()); + pluginInfo.put("status", String.valueOf(p.getPluginState())); + parentArray.add(pluginInfo); + } + return Response.ok().entity(parentArray).build(); + } + + private void writeToFile(InputStream uploadedInputStream, + String uploadedFileLocation) { + + try { + OutputStream out = new FileOutputStream(new File( + uploadedFileLocation)); + try { + int read = 0; + byte[] bytes = new byte[1024]; + + out = new FileOutputStream(new File(uploadedFileLocation)); + while ((read = uploadedInputStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + } finally { + out.flush(); + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/ParameterList.java b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/ParameterList.java index b6db970..a9f0b76 100644 --- a/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/ParameterList.java +++ b/src/main/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/ParameterList.java @@ -17,7 +17,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; // todo rethink type @XmlRootElement(name = "Parameters") @XmlAccessorType(XmlAccessType.PROPERTY) diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index defc6fc..f49decc 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -11,6 +11,10 @@ blockchains.iaas.uni.stuttgart.de.config.Application + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + 1 diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapterTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapterTest.java deleted file mode 100644 index 1429966..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumAdapterTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import java.io.File; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ExecutionException; - -import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; -import blockchains.iaas.uni.stuttgart.de.contracts.Permissions; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.crypto.CipherException; -import org.web3j.crypto.ECKeyPair; -import org.web3j.crypto.WalletUtils; -import org.web3j.tx.gas.DefaultGasProvider; - -/** - * To run these tests, you need ganache with the following mnemonic: - * smart contract composition - */ -class EthereumAdapterTest { - private static final String NETWORK_NAME = "eth-0"; - private static final String MESSAGE = "This was not a difficult task!"; - private final String BYTES_TYPE = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - private final String ADDRESS_TYPE = "{\n" + - "\t\"type\": \"string\",\n" + - "\t\"pattern\": \"^0x[a-fA-F0-9]{40}$\"\n" + - "}"; - private static final double REQUIRED_CONFIDENCE = 0.6; - private EthereumAdapter adapter; - private static final Logger log = LoggerFactory.getLogger(EthereumAdapterTest.class); - - @BeforeAll - static void initAll() throws URISyntaxException { - final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; - final File file = new File(Objects.requireNonNull( - EthereumAdapterTest.class.getClassLoader().getResource(DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)).toURI()); - ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); - manager.resetConnectionProfiles(); - manager.loadConnectionProfilesFromFile(file); - } - - @BeforeEach - void init() { - this.adapter = (EthereumAdapter) AdapterManager.getInstance().getAdapter(NETWORK_NAME); - } - - @Test - void testConnectionToNode() { - Assertions.assertEquals("true", this.adapter.testConnectionToNode()); - } - - @Test - void testSendTransaction() throws ExecutionException, InterruptedException { - final String toAddress = "0x182761AC584C0016Cdb3f5c59e0242EF9834fef0"; - final BigDecimal value = new BigDecimal(5000); - LinearChainTransaction result = (LinearChainTransaction) this.adapter.submitTransaction(toAddress, value, REQUIRED_CONFIDENCE).get(); - log.debug("transaction hash is: " + result.getTransactionHash()); - } - - @Test - void testInvokeSmartContract() throws Exception { - Permissions contract = this.deployContract(); - String smartContractPath = contract.getContractAddress(); - String functionIdentifier = "setPublicKey"; - byte[] bytes = MESSAGE.getBytes(); - String argument = new BigInteger(bytes).toString(16); - List inputs = Collections.singletonList(new Parameter("publicKey", BYTES_TYPE, argument)); - List outputs = Collections.emptyList(); - LinearChainTransaction init = (LinearChainTransaction) this.adapter.invokeSmartContract(smartContractPath, functionIdentifier, inputs, outputs, REQUIRED_CONFIDENCE, 0).get(); - log.info("initial transaction {}", init.getTransactionHash()); - functionIdentifier = "getPublicKey"; - inputs = Collections.singletonList(new Parameter("ethereumAddress", ADDRESS_TYPE, "0x90645Dc507225d61cB81cF83e7470F5a6AA1215A")); - outputs = Collections.singletonList(new Parameter("return", BYTES_TYPE, null)); - Transaction result = this.adapter.invokeSmartContract(smartContractPath, functionIdentifier, inputs, outputs, REQUIRED_CONFIDENCE, 0).get(); - String value = result.getReturnValues().get(0).getValue(); - log.debug(value); - String retrievedMessage = new String(new BigInteger(value, 16).toByteArray(), StandardCharsets.UTF_8); - Assertions.assertEquals(MESSAGE, retrievedMessage); - log.debug(retrievedMessage); - } - - @Test - @Disabled - void createNewKeystoreFile() throws CipherException, IOException { - final String filePath = "C:\\Ethereum\\keystore"; - final File file = new File(filePath); - final String password = "123456789"; - final String privateKey = "6871412854632d2ccd9c99901f5a0a3d838b31dbc6bfecae5f2382d6b7658bbf"; - ECKeyPair pair = ECKeyPair.create(new BigInteger(privateKey, 16)); - WalletUtils.generateWalletFile(password, pair, file, false); - } - - @Test - @Disabled - void testBlockNumbers() throws IOException { - LocalDateTime from = LocalDateTime.of(2019, 12, 27, 10, 50); - LocalDateTime to = LocalDateTime.of(2019, 12, 27, 10, 56); - long fromBlockNumber = this.adapter.getBlockAfterIsoDate(from); - long toBlockNumber = this.adapter.getBlockAfterIsoDate(to) - 1; - // sanity check - Assertions.assertTrue((toBlockNumber - fromBlockNumber) * 12 < Duration.between(from, to).getSeconds() * 2); - log.info("From: {} to: {}", fromBlockNumber, toBlockNumber); - } - - @Test - @Disabled - void testExtremeBlockNumbers() throws IOException { - LocalDateTime from = LocalDateTime.of(2001, 12, 27, 10, 50); - LocalDateTime to = LocalDateTime.of(2029, 12, 27, 10, 56); - long fromBlockNumber = this.adapter.getBlockAfterIsoDate(from); - long toBlockNumber = this.adapter.getBlockAfterIsoDate(to); - // sanity check - Assertions.assertEquals(0, fromBlockNumber); - Assertions.assertEquals(Long.MAX_VALUE, toBlockNumber); - log.info("From: {} to: {}", fromBlockNumber, toBlockNumber); - } - - Permissions deployContract() throws ExecutionException, InterruptedException, IOException { - Permissions contract = Permissions.deploy(this.adapter.getWeb3j(), this.adapter.getCredentials(), - new DefaultGasProvider()).sendAsync().get(); - Assertions.assertTrue(contract.isValid()); - - return contract; - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapperTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapperTest.java deleted file mode 100644 index d1652ad..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/EthereumTypeMapperTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Bytes; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Utf8String; -import org.web3j.abi.datatypes.generated.Bytes8; -import org.web3j.abi.datatypes.generated.Int160; -import org.web3j.abi.datatypes.generated.Uint160; - -import static org.junit.jupiter.api.Assertions.*; - -class EthereumTypeMapperTest { - @Test - void testTypes(){ - final String stringType = "{\n" + - "\t\"type\": \"string\"\n" + - "}"; - Class result = EthereumTypeMapper.getEthereumType(stringType); - Assertions.assertEquals(Utf8String.class, result); - final String addressType = "{\n" + - "\t\"type\": \"string\",\n" + - "\t\"pattern\": \"^0x[a-fA-F0-9]{40}$\"\n" + - "}"; - result = EthereumTypeMapper.getEthereumType(addressType); - Assertions.assertEquals(Address.class, result); - final String uint160Type = "{\n" + - "\t\"type\": \"integer\",\n" + - " \t\"minimum\": 0,\n" + - " \t\"maximum\": 1461501637330902918203684832716283019655932542975\n" + - "}"; - result = EthereumTypeMapper.getEthereumType(uint160Type); - - Assertions.assertEquals(Uint160.class, result); - - final String int160Type = "{\n" + - "\t\"type\": \"integer\",\n" + - " \t\"minimum\": -730750818665451459101842416358141509827966271488,\n" + - " \t\"maximum\": 730750818665451459101842416358141509827966271487\n" + - "}"; - result = EthereumTypeMapper.getEthereumType(int160Type); - Assertions.assertEquals(Int160.class, result); - - final String bytes8 = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"maxItems\": 8,\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - result = EthereumTypeMapper.getEthereumType(bytes8); - Assertions.assertEquals(Bytes8.class, result); - - final String bytes = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - result = EthereumTypeMapper.getEthereumType(bytes); - Assertions.assertEquals(DynamicBytes.class, result); - } - -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoderTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoderTest.java deleted file mode 100644 index aa0e751..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/ParameterEncoderTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; - -import javax.xml.bind.DatatypeConverter; - -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Bool; -import org.web3j.abi.datatypes.DynamicBytes; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Utf8String; -import org.web3j.abi.datatypes.generated.Bytes8; -import org.web3j.abi.datatypes.generated.Int160; -import org.web3j.abi.datatypes.generated.Uint160; - -class ParameterEncoderTest { - @Test - void testParameterEncoding() { - Parameter parameter = new Parameter(); - - final String stringType = "{\n" + - "\t\"type\": \"string\"\n" + - "}"; - parameter.setType(stringType); - parameter.setValue("hello world!"); - Type result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Utf8String.class, result.getClass()); - Assertions.assertEquals("hello world!", ((Utf8String) result).getValue()); - - final String addressType = "{\n" + - "\t\"type\": \"string\",\n" + - "\t\"pattern\": \"^0x[a-fA-F0-9]{40}$\"\n" + - "}"; - parameter.setType(addressType); - parameter.setValue("0x52908400098527886E0F7030069857D2E4169EE7"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Address.class, result.getClass()); - Assertions.assertEquals("0x52908400098527886E0F7030069857D2E4169EE7".toLowerCase(), ((Address) result).getValue()); - - final String uint160Type = "{\n" + - "\t\"type\": \"integer\",\n" + - " \t\"minimum\": 0,\n" + - " \t\"maximum\": 1461501637330902918203684832716283019655932542975\n" + - "}"; - parameter.setType(uint160Type); - parameter.setValue("1"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Uint160.class, result.getClass()); - Assertions.assertEquals("1", ((Uint160) result).getValue().toString(10)); - - final String int160Type = "{\n" + - "\t\"type\": \"integer\",\n" + - " \t\"minimum\": -730750818665451459101842416358141509827966271488,\n" + - " \t\"maximum\": 730750818665451459101842416358141509827966271487\n" + - "}"; - parameter.setType(int160Type); - parameter.setValue("-1"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Int160.class, result.getClass()); - Assertions.assertEquals("-1", ((Int160) result).getValue().toString(10)); - - final String bytes8 = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"maxItems\": 8,\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - parameter.setType(bytes8); - parameter.setValue("aabbccdd11223344"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Bytes8.class, result.getClass()); - Assertions.assertArrayEquals(DatatypeConverter.parseHexBinary("aabbccdd11223344"), ((Bytes8) result).getValue()); - - final String bytes = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - parameter.setType(bytes); - parameter.setValue("aabbccdd11223344"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(DynamicBytes.class, result.getClass()); - Assertions.assertArrayEquals(DatatypeConverter.parseHexBinary("aabbccdd11223344"), ((DynamicBytes) result).getValue()); - - final String bool = "{\"type\": \"boolean\"}"; - parameter.setType(bool); - parameter.setValue("true"); - result = ParameterEncoder.encode(parameter); - Assertions.assertEquals(Bool.class, result.getClass()); - Assertions.assertEquals(true, ((Bool) result).getValue()); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java deleted file mode 100644 index 7889c8b..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019-2022 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.fabric; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.ExecutionException; - -import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import blockchains.iaas.uni.stuttgart.de.model.Transaction; -import org.apache.commons.lang3.RandomStringUtils; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * In order for this test to succeed: - * 1- follow the steps of running the first Fabric tutorial at: https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html (use the javascript smart contract) - * 2- execute the enrollAdmin.js and the registerUser.js node programs - * 3- alter the local hosts file by adding the following entries: - * 127.0.0.1 orderer.example.com - * 127.0.0.1 peer0.org1.example.com - * 127.0.0.1 peer0.org2.example.com - * 127.0.0.1 peer1.org1.example.com - * 127.0.0.1 peer1.org2.example.com - * - * This ensures that the SDK is able to find the orderer and network peers. - */ -@Disabled -class FabricAdapterTest { - private static final String NETWORK_NAME = "fabric-0"; - private static final String CHANNEL_NAME = "mychannel"; - private static final String CHAINCODE_NAME = "fabcar"; - private static final Logger log = LoggerFactory.getLogger(FabricAdapterTest.class); - - private FabricAdapter adapter; - - @BeforeEach - public void initialize() { - String connectionProfile = "{ \"fabric-0\" : {\n" + - " \"@type\": \"fabric\",\n" + - " \"walletPath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\ems\\\\javascript\\\\wallet\",\n" + - " \"userName\": \"user1\",\n" + - " \"connectionProfilePath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\first-network\\\\connection-org1.json\"\n" + - " }}"; - ConnectionProfilesManager.getInstance().loadConnectionProfilesFromJson(connectionProfile); - adapter = (FabricAdapter) AdapterManager.getInstance().getAdapter(NETWORK_NAME); - } - - @Test - public void testRoundTrip() throws ExecutionException, InterruptedException { - String path = String.format("%s/%s", CHANNEL_NAME, CHAINCODE_NAME); - final String id = String.format("CAR%s", RandomStringUtils.randomNumeric(6)); - this.adapter.invokeSmartContract( - path, - "createCar", - Arrays.asList( - new Parameter("id", "string", id), - new Parameter("make", "string", "Mercedes"), - new Parameter("model", "string", "clk"), - new Parameter("colour", "string", "Black"), - new Parameter("owner", "string", "Ghareeb")), - Collections.emptyList(), - 1.0, - 0).get(); - - Transaction result = this.adapter.invokeSmartContract( - path, - "queryAllCars", - new ArrayList<>(), - new ArrayList<>(), - 1.0, - 0).get(); - String value = result.getReturnValues().get(0).getValue(); - log.debug("Looking for Id: " + id); - Assertions.assertTrue(value.contains(id)); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluatorTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluatorTest.java deleted file mode 100644 index 364b94f..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/BooleanExpressionEvaluatorTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import java.util.Collections; - -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class BooleanExpressionEvaluatorTest { - - @Test - void testEvaluateExpressionWithStringVariable() throws Exception { - final String intType = "{ \"type\": \"integer\"} "; - final String expression = "newValue <= 500"; - final Parameter parameter = Parameter.builder() - .name("newValue") - .type(intType) - .value("499") - .build(); - assertTrue(BooleanExpressionEvaluator.evaluate(expression, Collections.singletonList(parameter))); - parameter.setValue("501"); - assertFalse(BooleanExpressionEvaluator.evaluate(expression, Collections.singletonList(parameter))); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapperTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapperTest.java deleted file mode 100644 index a007c04..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/JsonSchemaToJavaTypeMapperTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import javax.xml.bind.DatatypeConverter; - -import blockchains.iaas.uni.stuttgart.de.model.Parameter; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class JsonSchemaToJavaTypeMapperTest { - - @Test - void test() { - Parameter parameter = new Parameter(); - - final String stringType = "{\n" + - "\t\"type\": \"string\"\n" + - "}"; - parameter.setType(stringType); - parameter.setValue("hello world!"); - Object result = JsonSchemaToJavaTypeMapper.map(parameter); - Assertions.assertEquals(String.class, result.getClass()); - Assertions.assertEquals("hello world!", result); - - final String addressType = "{\n" + - "\t\"type\": \"string\",\n" + - "\t\"pattern\": \"^0x[a-fA-F0-9]{40}$\"\n" + - "}"; - parameter.setType(addressType); - parameter.setValue("0x52908400098527886E0F7030069857D2E4169EE7"); - result = JsonSchemaToJavaTypeMapper.map(parameter); - Assertions.assertEquals(String.class, result.getClass()); - Assertions.assertEquals("0x52908400098527886E0F7030069857D2E4169EE7".toLowerCase(), result.toString().toLowerCase()); - final String uintType = "{\n" + - "\t\"type\": \"integer\"\n" + - "}"; - parameter.setType(uintType); - parameter.setValue("-1"); - result = JsonSchemaToJavaTypeMapper.map(parameter); - Assertions.assertEquals(Long.class, result.getClass()); - Assertions.assertEquals(-1L, result); - - final String bytes = "{\n" + - "\t\"type\": \"array\",\n" + - "\t\"items\": {\n" + - "\t\t\"type\": \"string\",\n" + - "\t\t\"pattern\": \"^[a-fA-F0-9]{2}$\"\n" + - "\t}\n" + - "}"; - parameter.setType(bytes); - parameter.setValue("[aa,bb,cc,dd,11,22,33,44]"); - result = JsonSchemaToJavaTypeMapper.map(parameter); - Assertions.assertEquals(Object[].class, result.getClass()); - byte[] resultAsArray = new byte[((Object[]) result).length]; - - for (int i = 0; i < resultAsArray.length; i++) { - resultAsArray[i] = (Byte)((Object[]) result)[i]; - } - - Assertions.assertArrayEquals(DatatypeConverter.parseHexBinary("aabbccdd11223344") - , resultAsArray); - - final String bool = "{\"type\": \"boolean\"}"; - parameter.setType(bool); - parameter.setValue("true"); - result = JsonSchemaToJavaTypeMapper.map(parameter); - Assertions.assertEquals(Boolean.class, result.getClass()); - Assertions.assertEquals(true, result); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculatorTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculatorTest.java deleted file mode 100644 index 5aeb3c4..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/utils/PoWConfidenceCalculatorTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.adaptation.utils; - -import blockchains.iaas.uni.stuttgart.de.model.Block; -import blockchains.iaas.uni.stuttgart.de.model.LinearChainTransaction; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class PoWConfidenceCalculatorTest { - private final long DEPTH = 12; - private final double Q = 0.2; - - @Test - void getCurrentConfidence() { - - final PoWConfidenceCalculator calculator = new PoWConfidenceCalculator(); - final Block blockEth = new Block(); - blockEth.setNumberAsLong(1); - final LinearChainTransaction transactionEth = new LinearChainTransaction(); - transactionEth.setBlock(blockEth); - calculator.setCurrentBlockchainHeight(1 + DEPTH); - calculator.setAdversaryRatio(Q); - double result = calculator.getCurrentConfidence(transactionEth); - double ETH_EXPECTED_CONFIDENCE = 0.99970567; - Assertions.assertEquals(0, MathUtils.doubleCompare(result, ETH_EXPECTED_CONFIDENCE)); - } - - @Test - void getEquivalentDepth() { - final PoWConfidenceCalculator calculator = new PoWConfidenceCalculator(); - calculator.setAdversaryRatio(Q); - Assertions.assertEquals(DEPTH, calculator.getEquivalentBlockDepth(0.999)); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java b/src/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java deleted file mode 100644 index 63201c3..0000000 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart - * Author: Ghareeb Falazi - * - * This program and the accompanying materials are made available under the - * terms the Apache Software License 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - *******************************************************************************/ - -package blockchains.iaas.uni.stuttgart.de.connectionprofiles; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.BitcoinConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.EthereumConnectionProfile; -import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.FabricConnectionProfile; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class ConnectionProfileManagerTest { - private void assertProfiles(ConnectionProfilesManager manager) { - Assertions.assertNotNull(manager); - Map gatewayMap = manager.getConnectionProfiles(); - Assertions.assertNotNull(gatewayMap); - Assertions.assertEquals(3, gatewayMap.size()); - Set keySet = gatewayMap.keySet(); - Assertions.assertTrue(keySet.contains("eth-0")); - Assertions.assertTrue(keySet.contains("btc-0")); - Assertions.assertTrue(keySet.contains("fabric-0")); - Assertions.assertTrue(gatewayMap.get("eth-0") instanceof EthereumConnectionProfile); - Assertions.assertTrue(gatewayMap.get("btc-0") instanceof BitcoinConnectionProfile); - Assertions.assertTrue(gatewayMap.get("fabric-0") instanceof FabricConnectionProfile); - } - - @Test - void testLoadFromFile() throws URISyntaxException { - final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; - final File file = new File(Objects.requireNonNull( - ConnectionProfileManagerTest.class.getClassLoader().getResource(DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)).toURI()); - ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); - manager.resetConnectionProfiles(); - manager.loadConnectionProfilesFromFile(file); - assertProfiles(manager); - } - - @Test - void testLoadFromString() { - ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); - manager.resetConnectionProfiles(); - String json = "{\n" + - " \"eth-0\": {\n" + - " \"@type\": \"ethereum\",\n" + - " \"nodeUrl\":\"http://localhost:7545\",\n" + - " \"keystorePath\":\"C:\\\\Ethereum\\\\keystore\\\\UTC--2019-05-30T11-21-08.970000000Z--90645dc507225d61cb81cf83e7470f5a6aa1215a.json\",\n" + - " \"keystorePassword\":\"123456789\",\n" + - " \"adversaryVotingRatio\": \"0.2\"\n" + - " },\n" + - " \"btc-0\" : {\n" + - " \"@type\": \"bitcoin\",\n" + - " \"rpcProtocol\": \"http\",\n" + - " \"rpcHost\": \"129.69.214.211\",\n" + - " \"rpcPort\": \"8332\",\n" + - " \"rpcUser\": \"falazigb\",\n" + - " \"rpcPassword\": \"123456789\",\n" + - " \"httpAuthScheme\": \"Basic\",\n" + - " \"notificationAlertPort\": \"5158\",\n" + - " \"notificationBlockPort\": \"5159\",\n" + - " \"notificationWalletPort\": \"5160\",\n" + - " \"adversaryVotingRatio\": \"0.1\"\n" + - " },\n" + - " \"fabric-0\" : {\n" + - " \"@type\": \"fabric\",\n" + - " \"walletPath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\fabcar\\\\javascript\\\\wallet\",\n" + - " \"userName\": \"user1\",\n" + - " \"connectionProfilePath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\first-network\\\\connection-org1.json\"\n" + - " }\n" + - "}"; - manager.loadConnectionProfilesFromJson(json); - assertProfiles(manager); - } - - @Test - void testInitialFile() throws IOException { - // just in case :) - ConnectionProfilesManager.initialConfigurationFilePath.toFile().delete(); - ConnectionProfilesManager.resetInstance(); - ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); - Assertions.assertEquals(0, manager.getConnectionProfiles().size()); - final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; - - try (InputStream stream = ConnectionProfileManagerTest.class.getClassLoader().getResourceAsStream( - DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)) { - FileUtils.copyInputStreamToFile(Objects.requireNonNull(stream), ConnectionProfilesManager.initialConfigurationFilePath.toFile()); - } - - ConnectionProfilesManager.resetInstance(); - manager = ConnectionProfilesManager.getInstance(); - Assertions.assertEquals(3, manager.getConnectionProfiles().size()); - ConnectionProfilesManager.initialConfigurationFilePath.toFile().delete(); - } -} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java similarity index 93% rename from src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java rename to test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java index 6f7e5fc..a79373c 100644 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java +++ b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/AdapterManagerTest.java @@ -11,9 +11,9 @@ package blockchains.iaas.uni.stuttgart.de.adaptation; -import blockchains.iaas.uni.stuttgart.de.adaptation.interfaces.BlockchainAdapter; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; -import blockchains.iaas.uni.stuttgart.de.exceptions.BlockchainIdNotFoundException; +import blockchains.iaas.uni.stuttgart.de.api.exceptions.BlockchainIdNotFoundException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/TestEthereumAdapter.java b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/TestEthereumAdapter.java new file mode 100644 index 0000000..5b5187e --- /dev/null +++ b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/ethereum/TestEthereumAdapter.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2022 Institute for the Architecture of Application System - University of Stuttgart + * Author: Akshay Patel + * + * This program and the accompanying materials are made available under the + * terms the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + *******************************************************************************/ +package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.ethereum; + +import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; +import blockchains.iaas.uni.stuttgart.de.api.IAdapterExtension; +import blockchains.iaas.uni.stuttgart.de.api.interfaces.BlockchainAdapter; +import blockchains.iaas.uni.stuttgart.de.api.model.LinearChainTransaction; +import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; +import blockchains.iaas.uni.stuttgart.de.management.BlockchainPluginManager; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.*; +import org.pf4j.PluginState; +import org.pf4j.PluginWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.web3j.crypto.CipherException; +import org.web3j.crypto.ECKeyPair; +import org.web3j.crypto.WalletUtils; + +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + +public class TestEthereumAdapter { + // Add -Dpf4j.pluginsDir= -DethereumPluginJarPath= + + private static final Logger log = LoggerFactory.getLogger(TestEthereumAdapter.class); + private static final String NETWORK_NAME = "eth-0"; + private static final double REQUIRED_CONFIDENCE = 0.6; + private final BlockchainPluginManager pluginManager = BlockchainPluginManager.getInstance(); + private final Path pluginPath = Paths.get(System.getProperty("ethereumPluginJarPath")); + + @BeforeEach + public void setUp() { + clearPluginDirectory(); + } + + @AfterEach + public void tearDown() { + clearPluginDirectory(); + } + + @Test + public void testLoadEthereumPlugin() throws IOException { + + // Basic test to check if plugin is loaded correctly + + assert pluginManager.getPlugins().size() == 0; + + Path uploadedPluginPath = Paths.get(pluginManager.getPluginsPath() + "/ethereum.jar"); + + Files.copy(pluginPath, uploadedPluginPath); + + pluginManager.loadJar(pluginPath); + Assertions.assertEquals(1, pluginManager.getPlugins().size()); + + PluginWrapper pluginWrapper = pluginManager.getPlugins().get(0); + String pluginId = pluginWrapper.getPluginId(); + + Assertions.assertEquals("ethereum-plugin", pluginId); + + Assertions.assertEquals(PluginState.RESOLVED, pluginManager.getPluginState(pluginId)); + pluginManager.startPlugin(pluginId); + + Assertions.assertEquals(PluginState.STARTED, pluginManager.getPluginState(pluginId)); + + } + + @Test + public void testSendEthereumTransaction() throws IOException, URISyntaxException, ExecutionException, InterruptedException { + + Path uploadedPluginPath = Paths.get(pluginManager.getPluginsPath() + "/ethereum.jar"); + Files.copy(pluginPath, uploadedPluginPath); + pluginManager.loadJar(pluginPath); + + String pluginId = pluginManager.getPlugins().get(0).getPluginId(); + pluginManager.startPlugin(pluginId); + + assert pluginManager.getPluginState(pluginId) == PluginState.STARTED; + + List adapterExtensions = pluginManager.getExtensions(); + assert adapterExtensions.size() == 1; + + final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; + + final File file = new File(Objects.requireNonNull( + TestEthereumAdapter.class.getClassLoader().getResource(DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)).toURI()); + + ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); + manager.resetConnectionProfiles(); + manager.loadConnectionProfilesFromFile(file); + + BlockchainAdapter adapter = AdapterManager.getInstance().getAdapter(NETWORK_NAME); + Assertions.assertEquals("true", adapter.testConnection()); + + final String toAddress = "0x182761AC584C0016Cdb3f5c59e0242EF9834fef0"; + final BigDecimal value = new BigDecimal(5000); + LinearChainTransaction result = (LinearChainTransaction) adapter.submitTransaction(toAddress, value, REQUIRED_CONFIDENCE).get(); + log.debug("transaction hash is: " + result.getTransactionHash()); + } + + private void clearPluginDirectory() { + Path path = pluginManager.getPluginsPath(); + final File[] files = path.toFile().listFiles(); + for (File f : files) f.delete(); + } + + private Map getConfiguration() { + Map map = new HashMap<>(); + map.put("nodeUrl", "http://localhost:7545/"); + map.put("keystorePath", "/account.json"); + map.put("averageBlockTimeSeconds", "2"); + map.put("keystorePassword", "123456789"); + map.put("adversaryVotingRatio", 0.2); + map.put("pollingTimeSeconds", 2); + + return map; + } + + void createNewKeystoreFile() throws CipherException, IOException { + final String filePath = "C:\\Ethereum\\keystore"; + final File file = new File(filePath); + final String password = "123456789"; + final String privateKey = "6871412854632d2ccd9c99901f5a0a3d838b31dbc6bfecae5f2382d6b7658bbf"; + ECKeyPair pair = ECKeyPair.create(new BigInteger(privateKey, 16)); + WalletUtils.generateWalletFile(password, pair, file, false); + } + + /* + * Creating account.json file using node 16 + * + ```bash + npm install web3 + ``` + + ```javascript + var Web3 = require('web3'); + var web3 = new Web3(Web3.givenProvider || 'ws://localhost:7545'); + var privateKey=""; + var password="123456789"; + var JsonWallet = web3.eth.accounts.encrypt(privateKey, password); + console.log(JSON.stringify(JsonWallet) + ``` + Copy the output to a file `account.json` on the machine. + * */ +} diff --git a/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java new file mode 100644 index 0000000..000be43 --- /dev/null +++ b/test/java/blockchains/iaas/uni/stuttgart/de/adaptation/adapters/fabric/FabricAdapterTest.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart + * Author: Ghareeb Falazi + * + * This program and the accompanying materials are made available under the + * terms the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + *******************************************************************************/ + +package blockchains.iaas.uni.stuttgart.de.adaptation.adapters.fabric; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.ExecutionException; + +import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager; +import blockchains.iaas.uni.stuttgart.de.connectionprofiles.ConnectionProfilesManager; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Transaction; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * In order for this test to succeed: + * 1- follow the steps of running the first Fabric tutorial at: https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html (use the javascript smart contract) + * 2- execute the enrollAdmin.js and the registerUser.js node programs + * 3- alter the local hosts file by adding the following entries: + * 127.0.0.1 orderer.example.com + * 127.0.0.1 peer0.org1.example.com + * 127.0.0.1 peer0.org2.example.com + * 127.0.0.1 peer1.org1.example.com + * 127.0.0.1 peer1.org2.example.com + * + * This ensures that the SDK is able to find the orderer and network peers. + */ +@Disabled +class FabricAdapterTest { +// private static final String NETWORK_NAME = "fabric-0"; +// private static final String CHANNEL_NAME = "mychannel"; +// private static final String CHAINCODE_NAME = "fabcar"; +// private static final Logger log = LoggerFactory.getLogger(FabricAdapterTest.class); +// +// private FabricAdapter adapter; +// +// @BeforeEach +// public void initialize() { +// String connectionProfile = "{ \"fabric-0\" : {\n" + +// " \"@type\": \"fabric\",\n" + +// " \"walletPath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\ems\\\\javascript\\\\wallet\",\n" + +// " \"userName\": \"user1\",\n" + +// " \"connectionProfilePath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\first-network\\\\connection-org1.json\"\n" + +// " }}"; +// ConnectionProfilesManager.getInstance().loadConnectionProfilesFromJson(connectionProfile); +// adapter = (FabricAdapter) AdapterManager.getInstance().getAdapter(NETWORK_NAME); +// } +// +// @Test +// public void testRoundTrip() throws ExecutionException, InterruptedException { +// String path = String.format("%s/%s", CHANNEL_NAME, CHAINCODE_NAME); +// final String id = String.format("CAR%s", RandomStringUtils.randomNumeric(6)); +// this.adapter.invokeSmartContract( +// path, +// "createCar", +// Arrays.asList( +// new Parameter("id", "string", id), +// new Parameter("make", "string", "Mercedes"), +// new Parameter("model", "string", "clk"), +// new Parameter("colour", "string", "Black"), +// new Parameter("owner", "string", "Ghareeb")), +// Collections.emptyList(), +// 1.0).get(); +// +// Transaction result = this.adapter.invokeSmartContract( +// path, +// "queryAllCars", +// new ArrayList<>(), +// new ArrayList<>(), +// 1.0).get(); +// String value = result.getReturnValues().get(0).getValue(); +// log.debug("Looking for Id: " + id); +// Assertions.assertTrue(value.contains(id)); +// } +} \ No newline at end of file diff --git a/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java b/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java new file mode 100644 index 0000000..295ee57 --- /dev/null +++ b/test/java/blockchains/iaas/uni/stuttgart/de/connectionprofiles/ConnectionProfileManagerTest.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2019 Institute for the Architecture of Application System - University of Stuttgart + * Author: Ghareeb Falazi + * + * This program and the accompanying materials are made available under the + * terms the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + *******************************************************************************/ + +package blockchains.iaas.uni.stuttgart.de.connectionprofiles; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +//import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.BitcoinConnectionProfile; +//import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.EthereumConnectionProfile; +//import blockchains.iaas.uni.stuttgart.de.connectionprofiles.profiles.FabricConnectionProfile; +//import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ConnectionProfileManagerTest { +// private void assertProfiles(ConnectionProfilesManager manager) { +// Assertions.assertNotNull(manager); +// Map gatewayMap = manager.getConnectionProfiles(); +// Assertions.assertNotNull(gatewayMap); +// Assertions.assertEquals(3, gatewayMap.size()); +// Set keySet = gatewayMap.keySet(); +// Assertions.assertTrue(keySet.contains("eth-0")); +// Assertions.assertTrue(keySet.contains("btc-0")); +// Assertions.assertTrue(keySet.contains("fabric-0")); +// Assertions.assertTrue(gatewayMap.get("eth-0") instanceof EthereumConnectionProfile); +// Assertions.assertTrue(gatewayMap.get("btc-0") instanceof BitcoinConnectionProfile); +// Assertions.assertTrue(gatewayMap.get("fabric-0") instanceof FabricConnectionProfile); +// } + +// @Test +// void testLoadFromFile() throws URISyntaxException { +// final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; +// final File file = new File(Objects.requireNonNull( +// ConnectionProfileManagerTest.class.getClassLoader().getResource(DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)).toURI()); +// ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); +// manager.resetConnectionProfiles(); +// manager.loadConnectionProfilesFromFile(file); +// assertProfiles(manager); +// } +// +// @Test +// void testLoadFromString() { +// ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); +// manager.resetConnectionProfiles(); +// String json = "{\n" + +// " \"eth-0\": {\n" + +// " \"@type\": \"ethereum\",\n" + +// " \"nodeUrl\":\"http://localhost:7545\",\n" + +// " \"keystorePath\":\"C:\\\\Ethereum\\\\keystore\\\\UTC--2019-05-30T11-21-08.970000000Z--90645dc507225d61cb81cf83e7470f5a6aa1215a.json\",\n" + +// " \"keystorePassword\":\"123456789\",\n" + +// " \"adversaryVotingRatio\": \"0.2\"\n" + +// " },\n" + +// " \"btc-0\" : {\n" + +// " \"@type\": \"bitcoin\",\n" + +// " \"rpcProtocol\": \"http\",\n" + +// " \"rpcHost\": \"129.69.214.211\",\n" + +// " \"rpcPort\": \"8332\",\n" + +// " \"rpcUser\": \"falazigb\",\n" + +// " \"rpcPassword\": \"123456789\",\n" + +// " \"httpAuthScheme\": \"Basic\",\n" + +// " \"notificationAlertPort\": \"5158\",\n" + +// " \"notificationBlockPort\": \"5159\",\n" + +// " \"notificationWalletPort\": \"5160\",\n" + +// " \"adversaryVotingRatio\": \"0.1\"\n" + +// " },\n" + +// " \"fabric-0\" : {\n" + +// " \"@type\": \"fabric\",\n" + +// " \"walletPath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\fabcar\\\\javascript\\\\wallet\",\n" + +// " \"userName\": \"user1\",\n" + +// " \"connectionProfilePath\": \"C:\\\\Users\\\\falazigb\\\\Documents\\\\GitHub\\\\fabric\\\\fabric-samples\\\\first-network\\\\connection-org1.json\"\n" + +// " }\n" + +// "}"; +// manager.loadConnectionProfilesFromJson(json); +// assertProfiles(manager); +// } +// +// @Test +// void testInitialFile() throws IOException { +// // just in case :) +// ConnectionProfilesManager.initialConfigurationFilePath.toFile().delete(); +// ConnectionProfilesManager.resetInstance(); +// ConnectionProfilesManager manager = ConnectionProfilesManager.getInstance(); +// Assertions.assertEquals(0, manager.getConnectionProfiles().size()); +// final String DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME = "gatewayConfiguration.json"; +// +// try (InputStream stream = ConnectionProfileManagerTest.class.getClassLoader().getResourceAsStream( +// DEFAULT_CONNECTION_PROFILES_CONFIGURATION_FILE_NAME)) { +// FileUtils.copyInputStreamToFile(Objects.requireNonNull(stream), ConnectionProfilesManager.initialConfigurationFilePath.toFile()); +// } +// +// ConnectionProfilesManager.resetInstance(); +// manager = ConnectionProfilesManager.getInstance(); +// Assertions.assertEquals(3, manager.getConnectionProfiles().size()); +// ConnectionProfilesManager.initialConfigurationFilePath.toFile().delete(); +// } +} \ No newline at end of file diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManagerTest.java b/test/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManagerTest.java similarity index 100% rename from src/test/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManagerTest.java rename to test/java/blockchains/iaas/uni/stuttgart/de/management/SubscriptionManagerTest.java diff --git a/src/test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java b/test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java similarity index 97% rename from src/test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java rename to test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java index b6657f0..5d7a681 100644 --- a/src/test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java +++ b/test/java/blockchains/iaas/uni/stuttgart/de/restapi/model/request/InvokeSmartContractFunctionRequestTest.java @@ -18,7 +18,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; -import blockchains.iaas.uni.stuttgart.de.model.Parameter; +import blockchains.iaas.uni.stuttgart.de.api.model.Parameter; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/test/resources/gatewayConfiguration.json b/test/resources/gatewayConfiguration.json similarity index 83% rename from src/test/resources/gatewayConfiguration.json rename to test/resources/gatewayConfiguration.json index b3bfc3b..da1da4d 100644 --- a/src/test/resources/gatewayConfiguration.json +++ b/test/resources/gatewayConfiguration.json @@ -2,9 +2,9 @@ "eth-0": { "@type": "ethereum", "nodeUrl":"http://localhost:7545", - "keystorePath":"C:\\Ethereum\\keystore\\UTC--2019-05-30T11-21-08.970000000Z--90645dc507225d61cb81cf83e7470f5a6aa1215a.json", + "keystorePath":"/account.json", "keystorePassword":"123456789", - "adversaryVotingRatio": "0.2", + "adversaryVotingRatio": 0.2, "pollingTimeSeconds": 2 }, "btc-0" : {