Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
traylewin committed Nov 23, 2018
0 parents commit 3cff9a3
Show file tree
Hide file tree
Showing 33 changed files with 8,882 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
### VERIFER EXAMPLE .ENV

VERIFIER_PORT=8080

#EOS chain endpoint
ORE_NETWORK_URI='https://ore-staging.openrights.exchange:443'
ORE_NETWORK_CHAINID='a6df478d5593b4efb1ea20d13ba8a3efc1364ee0bf7dbd85d8d756831c0e3256'
EOS_TRANSACTION_EXPIRE_SECONDS=60

# the PEM-encoded secp256r1 private key that the verifier uses to identify itself
VERIFIER_PEM_PRIVATE_KEY='-----BEGIN EC PRIVATE KEY-----\n...'

# the EOS account and private key of the verifier
VERIFIER_ACCOUNT_NAME='verifier.ore'
VERIFIER_PRIVATE_KEY='5...'


# Name of the cpu contract deployed on chain
CPU_CONTRACT_NAME='token.ore'

# Cpu token symbol
CPU_TOKEN_SYMBOL='CPU'

# Name of the instrument contract deployed on chain
INSTRUMENT_CONTRACT_NAME='instr.ore'

# Name of the rights contract deployed on chain
RIGHTS_REGISTRY_CONTRACT_NAME='rights.ore'

# Name of the log contract deployed on chain
USAGE_LOG_CONTRACT_NAME='usagelog.ore'

NEW_RELIC_LICENSE_KEY=xxxxx

9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
.pem
.env
.env.staging
.env.prod
node_modules
private-key.pem
newrelic_agent.log

25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## About

The ORE Verifier is an off-chain oracle that verifies transactions for the Open Rights Exchange protocol

## Usage

Each ORE block producer may run one or more Verifier services. The URL of the running service, along with the Public key used by the Verifier to sign access tokens, must be provided to the ore-client library wanting to use this instance.

Endpoints:
- /discovery - Returns the active ORE blockchain URL (GET)
- /usage-update - Updates usage count of a right (POST)
- /verify - Processes request to access a protected right and returns an ore-access-token, target URL, and required additional parameters to access the right's endpoint (POST)
#

## To run

```bash
npm start
```

## Deploying to server

Pushing to the master or staging branch triggers a build using CircleCI to Google App Engine (See internal notes on how to change configuration and .env variables)

You can manually deploy to Google App Engine from a local workstation from within the app directory (and using a local .env) by running `gcloud -q app deploy app.yaml`
23 changes: 23 additions & 0 deletions app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2018, Google, Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# [START app_yaml]
# [START runtime]
runtime: nodejs
env: flex
#circleci build script will replace this value depending on prod ('web') or staging ('web-staging') push
service: verifier
# [END runtime]
default_expiration: "0m"

# [END app_yaml]
112 changes: 112 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# This configuration was automatically generated from a CircleCI 1.0 config.
# It should include any build commands you had along with commands that CircleCI
# inferred from your project structure. We strongly recommend you read all the
# comments in this file to understand the structure of CircleCI 2.0, as the idiom
# for configuration has changed substantially in 2.0 to allow arbitrary jobs rather
# than the prescribed lifecycle of 1.0. In general, we recommend using this generated
# configuration as a reference rather than using it in production, though in most
# cases it should duplicate the execution of your original 1.0 config.
version: 2
jobs:
build:
branches:
only:
- master
- staging
parallelism: 1
shell: /bin/bash --login
environment:
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
PYTHONPATH: ${PYTHONPATH}:${HOME}/google_appengine
GCLOUD_PROJECT: open-rights-exchange
SERVICE_VERSION: 1
# In CircleCI 2.0 you can now specify your own image, or use one of our pre-configured images.
# To see the list of pre-built images that CircleCI provides for most common languages see
# https://circleci.com/docs/2.0/circleci-images/
docker:
- image: circleci/build-image:ubuntu-14.04-XXL-upstart-1189-5614f37
command: /sbin/init
steps:
# Machine Setup
- checkout
# 'See docs on artifact collection here https://circleci.com/docs/2.0/artifacts/'
- run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS
- run:
command: nvm install 10.4.0 && nvm alias default 10.4.0
# Dependencies
# This would typically go in either a build or a build-and-test job when using workflows
# Restore the dependency cache
- restore_cache:
keys:
# This branch if available
- v1-dep-{{ .Branch }}-
# Default branch if not
- v1-dep-master-
# Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
- v1-dep-

# install gcloud and login to it
- run:
command: |
curl -o $HOME/google_appengine_1.9.30.zip https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.30.zip
unzip -q -d $HOME $HOME/google_appengine_1.9.30.zip
echo $GCLOUD_SERVICE_KEY | base64 --decode > ${HOME}/gcloud-service-key.json
echo $ENV_TEST | base64 --decode > ./.env
gcloud --quiet components update app
gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json
gcloud config set project $GCLOUD_PROJECT
# copy .env file from circleci injected environmental variables
- run:
command: |
if [ "$CIRCLE_BRANCH" == "master" ]
then
cp -rf ./scripts/config/prod.app.yaml ./app.yaml
echo $ENV_PROD | base64 --decode >> ./.env
fi
if [ "$CIRCLE_BRANCH" == "staging" ]
then
cp -rf ./scripts/config/staging.app.yaml ./app.yaml
echo $ENV_STAGING | base64 --decode >> ./.env
fi
# Run our Tests
# - run: python e2e_test.py

# deploy to Google Cloud
- run:
command: |
# deploy to AppEngine
#- ./scripts/deploy.sh --version=$SERVICE_VERSION
./scripts/deploy.sh
# Save dependency cache
- save_cache:
key: v1-dep-{{ .Branch }}-{{ epoch }}
paths:
# This is a broad list of cache paths to include many possible development environments
# You can probably delete some of these entries
- vendor/bundle
- ~/virtualenvs
- ~/.m2
- ~/.ivy2
- ~/.bundle
- ~/.go_workspace
- ~/.gradle
- ~/.cache/bower

# Test
# This would typically be a build job when using workflows, possibly combined with build
# This is based on your 1.0 configuration file or project settings
- run: 'true'

# Teardown
# Save test results
- store_test_results:
path: /tmp/circleci-test-results
# Save artifacts
- store_artifacts:
path: /tmp/circleci-artifacts
- store_artifacts:
path: /tmp/circleci-test-results
25 changes: 25 additions & 0 deletions dispatch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
dispatch:

# Deploy this file to update routings for this service
# $ gcloud config set project open-rights-exchange
# $ gcloud app deploy dispatch.yaml

# Default service serves the typical web resources and all static resources.
# - url: "*/favicon.ico"
# service: web

# Default service serves simple hostname request.
# - url: "openrights.exchange/*"
# service: default
# If we later add a website at www. ...
# - url: "www.openrights.exchange/*"
# service: web

- url: "verifier-staging.openrights.exchange/*"
service: verifier-staging

- url: "verifier.openrights.exchange/*"
service: verifier

- url: "explorer.openrights.exchange/*"
service: explorer
109 changes: 109 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require('dotenv').config()
require('newrelic')
const express = require('express')
const logger = require('morgan')
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
const {
URL
} = require('url')
const fetch = require('node-fetch')
const _ = require('lodash')
const verifierHandle = require('./src/verifier')
const fs = require('fs')
const cors = require('cors');

const getPath = (endpoint) => {
return new URL(endpoint).pathname
}

const buildServer = ({}) => {
const verifyHandler = verifierHandle.verifyHandler(verifier, privateKey, verifierPrivateKey, instrumentContractName, rightContractName, cpuContractName, cpuTokenSymbol, logContractName)
const usageHandler = verifierHandle.usageHandler(verifier, privateKey, logContractName)
const app = express()

app.use(cors());
app.options('*', cors())
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false
}))
app.use(cookieParser())
app.get('/healthcheck', (req, res) => {
res.status(200).send()
})

// Returns the endpoint to access blockchain
app.get('/discovery', (req, res) => {
const oreNetworkUri = process.env.ORE_NETWORK_URI
if (oreNetworkUri != null) {
res.status(200)
res.json({
oreNetworkUri
})
} else {
res.status(500)
res.json({
message: "ore network uri not found"
})
}
})

app.post(`/verify`, verifyHandler)
app.post(`/update-usage`, usageHandler)

// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found')
err.status = 404
next(err)
})

// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message
res.locals.error = req.app.get('env') === 'development' ? err : {}

// render the error page
res.status(err.status || 500)
res.json({
message: err.message,
error: err
})
})

const server = require('http').createServer(app);

return server
}

const port = process.env.VERIFIER_PORT || 3404

//verifier account
const verifier = process.env.VERIFIER_ACCOUNT_NAME
const privateKey = process.env.VERIFIER_PRIVATE_KEY
const verifierPrivateKey = process.env.VERIFIER_PEM_PRIVATE_KEY.replace(/\\n/g, '\n')
const instrumentContractName = process.env.INSTRUMENT_CONTRACT_NAME
const rightContractName = process.env.RIGHTS_REGISTRY_CONTRACT_NAME
const cpuContractName = process.env.CPU_CONTRACT_NAME
const cpuTokenSymbol = process.env.CPU_TOKEN_SYMBOL
const logContractName = process.env.USAGE_LOG_CONTRACT_NAME

const run = async () => {

const server = buildServer({
verifier,
privateKey,
verifierPrivateKey,
instrumentContractName,
rightContractName,
cpuContractName,
cpuTokenSymbol,
logContractName
})
server.listen(port, () => console.log(`listening on ${port}...`))
}

run()
32 changes: 32 additions & 0 deletions keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// creates a secp256r1 keypair for use with the verifier

const EC = require('elliptic').ec
const ec = new EC('p256')

const KeyEncoder = require('key-encoder')
const encoderOptions = {
// https://www.ietf.org/rfc/rfc5480.txt
curveParameters: [1, 2, 840, 10045, 3, 1, 7],
privatePEMOptions: {label: 'EC PRIVATE KEY'},
publicPEMOptions: {label: 'PUBLIC KEY'},
curve: ec
}
const keyEncoder = new KeyEncoder(encoderOptions)

const createKeyPair = () => {
const keys = ec.genKeyPair()

const privateKey = keys.priv.toString(16)
const publicKey = keys.getPublic().encode('hex')

const pemPrivateKey = keyEncoder.encodePrivate(privateKey, 'raw', 'pem')
const pemPublicKey = keyEncoder.encodePublic(publicKey, 'raw', 'pem')

return {
privateKey: pemPrivateKey,
publicKey: pemPublicKey
}
}
exports.createKeyPair = createKeyPair

createKeyPair
Loading

0 comments on commit 3cff9a3

Please sign in to comment.