The Smart Charging Network (SCN) node with Smart Charge Point Interface (SCPI) v2.2 API.
This is a community project, aimed at incorporating and building on the open SCPI standard. As with SCPI, contributions are welcome in the form of comments, pull requests and raised issues. Visit our issue tracker for an overview of current and past issues. Questions may also be asked on Stack Overflow, or in the Gitter community.
Before contributing to the source code, please take the time to read over the Developer Certificate of Origin. For more information, see our contributing guidelines.
The SCN is a decentralized eRoaming hub. To participate in the SCN, a node must be used to broker SCPI requests (e.g. start/stop charging requests, POI data retrieval) between parties. A node can be set up and run by anyone, however to connect to a node, two steps are needed:
- A registration token (so-called Token A in SCPI terminology) must be generated for the prospective platform by the node administrator.
- The platform must register themselves in the SCN Registry, stating that they are using that particular node.
Once a registration token is obtained and the platform is listed in the registry, the SCPI credentials handshake with the SCN Node can be initiated, providing access to all SCPI modules and interfaces used for peer-to-peer communication1. When a counter-party is found (either offline or via the registry), requests are sent to them via the sender's SCN Node2.
For more information about the SCN, check out the wiki.
1 The HubClientInfo module will be added in a future release.
2 Sending a request does not guarantee its delivery. Using the ScnRules module, parties are able to whitelist
and blacklist counter-parties. See the subsequent HTTP API documentation for more on this custom module.
The HTTP API Documentation for the SCN Node describes endpoints which can be used by administrators and users (SCPI parties). Outside of the full SCPI v2.2 API, SCN Nodes provide additional features, such as the custom SCPI module, ScnRules, as well as ways for admins to restrict use and users to query the SCN Registry.
The SCN Node is built with Kotlin, targeting the JVM. OpenJDK 8 or higher is needed to build and run the project. Additionally, the node can be run in Docker with the provided Dockerfile, however the build step takes place on the host rather than inside a container.
The choice of operating system is up to the administrator. By and large, the SCN Node has been developed and run on Unix-like operating systems, particularly Ubuntu. There is currently no guarantee that it will work on other operating systems.
Before running a node and connecting it to a local, test or prod environment, it is recommended to first become
acquainted with how the network operates. The provided docker-compose file spins up a local environment with the SCN
Registry and two SCN Nodes pre-configured. A tutorial has been provided to guide administrators and users
of an SCN Node alike through various use case examples. To complete this tutorial it is necessary to install
Docker Compose in addition to the above dependencies.
First of all, clone the repository:
git clone git@bitbucket.org:smartcharging/scn-node.git
cd scn-node
Firstly, it is important to configure the application properties for the desired environment or profile, e.g. local:
cd src/main/resources
cp application.dev.properties application.local.properties
vi application.local.properties
The field scn.node.url describes the node's server address. If running a local network for development purposes,
setting the following:
scn.node.url = http://localhost:8080
means that parties receive module endpoints starting with http://localhost:8080, for
example http://localhost:8080/scpi/2.2/sender/locations (the locations module's sender interface).
Likewise, for a public node that accepts outside connections, the url might include the domain name, for example
https://server.example.com. This would translate to https://server.example.com/scpi/2.2/sender/locations. Be sure
to include the protocol so that connected platforms can correctly parse the endpoints provided.
On startup, the SCN client will ensure that the public URL set by the administrator is reachable. Additionally, there is different behaviour within this check depending on which mode the client is running in. See section 1.5 for more details.
The dev properties connects the node to an in-memory database, which will not persist data across node restarts.
If running the node in a test or production environment with Postgres installed, copy from the prod properties file
instead:
cp application.prod.properties application.prod-edit.properties
The node may also be connected to a different database. This requires installing the relevant database driver as
an scn-node dependency via gradle and modifying application properties accordingly, in addition to running the
database server itself.
The network on which any SCN Node is running on depends purely on the SCN Registry smart contract it is connected to,
defined by the blockchain node and registry contract address configured. These configuration properties have the prefix
scn.node.web3.
Currently there are two environments: test and production.
The pre-configured properties files point to each of these respectively (dev to test, prod to production).
The Admin API allows, for example, generating new SCPI tokens (CREDENTIALS_TOKEN_A) for planned platforms. An API
key can be set in the application's properties, else a new one will be generated on restart:
scn.node.apikey = randomkey
The API key will be printed on node start, be it generated or user-specified. Consult the API documentation for more information on how to use the Admin API.
The client can be run in "dev" or "prod" mode. By default, prod mode is in effect, which will check to see if the
provided public client URL is reachable over HTTPS and is accessible to the outside world. When running in dev mode
(by setting scn.client.dev = true), the client will allow insecure HTTP connections made over localhost.
A feature of the Smart Charging Network is it's security. To ensure that requests sent over the SCN are delivered to their recipient as intended, requests are signed by the sender and responses by the receiver. In some particular cases, an SCN Node may need to rewrite entries in the sender's original request (such as when providing response URLs in commands requests). The message signing functionality allows for this, as the signature of a modified request must also reference any values that have been changed. For more details on how to sign and verify messages, check out the SCN Notary.
By default message signing verification is on. To toggle this feature on/off, set scn.node.signatures to true (on) or
false (off).
In practice, this means that a connected platform will need to send requests including a valid SCN-Signature header,
signed by the private key which they have used to list themselves in the SCN Registry. Likewise the recipient will
need to sign their response, and include it in the body. As the signature for responses can potentially be large
(depending on the amount of data signed), it was decided that they should be placed in the response body.
Be aware that even if an SCN Node does not require message signing, a recipient may still reject the request if it's
missing an SCN-Signature (either on their own or through the ScnRules module). Additionally, the SCN Node will
verify signatures if they are present in a a request/response, regardless of this setting.
An Etheruem public-private key-pair is used to identify the node on the network. Commonly, these key-pairs are stored in a "wallet". There are a number of ways that a wallet can be created, for example with Metamask.
Once a private key has been created, set the node to use it:
scn.node.privatekey = 0x1c3e5453c0f9aa74a8eb0216310b2b013f017813a648fce364bf41dbc0b37647
Note that in dev mode, a private key will be set if omitted. As this key is hardcoded and used in a lot of examples elsewhere (like above), it is advised to change it if targeting the public test environment. In prod mode, the node will refuse to start without a private key.
A Node must be listed in the registry for it to be usable on the network. This can be achieved by installing the SCN Registry CLI. Either clone the SCN-Registry repository and follow the instructions in the README, or install the NPM package:
npm i -g @smartcharging/scn-registry
Then, add your domain name using the private key as set in the configuration (note that the wallet key must be funded
and the correct network chosen using the -n flag:
scn-registry set-node https://server.example.com -n prod -s 0x1c3e5453c0f9aa74a8eb0216310b2b013f017813a648fce364bf41dbc0b37647
If successful the node is now available for prospective platforms to link themselves to in the SCN Registry.
There are multiple ways to run an SCN Node.
Note: make sure you are in the root of the repository first.
To build the node with the desired profile (relating to the application.<PROFILE>.properties file), for example a
local profile, run the following:
./gradlew -Pprofile=local build -x test
Once built, the packaged node can be run using:
java -jar ./build/libs/scn-node-1.0.0.jar
Alternatively, a different profile can be selected at runtime, e.g.:
java -jar -Dspring.config.location=/path/to/application.prod.properties ./build/libs/scn-node-1.0.0.jar
Especially helpful for development, the node can quickly be run in one step with Gradle using the provided wrapper:
./gradlew -Pprofile=local bootRun
A Dockerfile is provided which, once built, will run the above command in a container. Firstly, build the SCN Node with gradle locally, then build the Docker image with a tag flag so that we can identify it later:
./gradlew -Pprofile=local build -x test
docker build -t scn-node .
Once built, the node can be run and accessed by exposing the application server's 8080 port within the container to
the outside environment:
docker run -p 8080:8080 scn-node
Once the node is running, test that it is working with the following request:
curl localhost:8080/health
You should see a 200 OK response.
For further usage documentation, consult the API Documentation.
Gradle tasks are configured in build.gradle.kts using the Kotlin DSL.
./gradlew unitTest
Integration tests depend on ganache-cli, a local development blockchain, which is installed using NPM. In one terminal
window, run the following task, which will attempt to install ganache if not already present and then run it:
./gradlew ganache
Then, run the tests:
./gradlew integrationTest
This is helpful for developing without having to worry about funding and managing Ethereum keypairs. With the above
ganache task running in the background, the SCN Node can be configured using the following properties:
scn.node.web3.provider = http://localhost:8544
scn.node.web3.contracts.registry = 0x5Cba9EA604Ca760177f4B6F5E2B34414930e3402
Documentation is generated automatically on build. The asciidoc template can be found in
src/docs/asciidoc/index.adoc and the output in build/asciidoc/html5/index.html.