Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#####################################################################
# Chainpoint Node Configuration
# Chainpoint Gateway Configuration
#####################################################################

# Chainpont Core Connection IP List
Expand All @@ -18,7 +18,7 @@ AGGREGATION_INTERVAL_SECONDS=60
MAX_SATOSHI_PER_HASH=10

# Proof expiration period
# The length of time proofs as stored on the node for retrieval before pruning, in minutes
# The length of time proofs as stored on this Gateway for retrieval before pruning, in minutes
#
# When omitted, the default value is 1440
#
Expand Down Expand Up @@ -47,7 +47,7 @@ GET_PROOFS_MAX=250

# Network Configuration
# If manually specifying Cores using CHAINPOINT_CORE_CONNECT_IP_LIST,
# it is the Node operators responsibility to ensure that this network matches
# it is the Gateway operator's responsibility to ensure that this network matches
# the network of the Cores to which it is connecting, otherwise failure will result.
#
# Valid values are 'mainnet' and 'testnet'. When omitted, the default value is 'mainnet'
Expand All @@ -63,3 +63,9 @@ LND_SOCKET=lnd:10009

# Public IP address for the Lightning node
LND_PUBLIC_IP=<your IP here>

# The size of each channel in satoshis
# CHANNEL_AMOUNT=200000

# The required size of the wallet
# FUND_AMOUNT=600000
34 changes: 20 additions & 14 deletions chainpoint-gateway-openapi-3.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
openapi: 3.0.0
info:
title: 'Chainpoint Node'
description: 'Documentation for the Chainpoint Node API'
version: '2.0.0'
title: 'Chainpoint Gateway'
description: 'Documentation for the Chainpoint Gateway API'
version: '1.0.0'
license:
name: 'Apache 2.0'
url: 'https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)'
servers:
- url: 'http://35.231.41.69'
description: 'Development server (produces testnet proofs)'
- url: 'http://3.17.155.208'
description: 'Mainnet Gateway A'
- url: 'http://18.191.50.129'
description: 'Mainnet Gateway B'
- url: 'http://18.224.185.143'
description: 'Mainnet Gateway C'
- url: 'http://3.136.178.15'
description: 'Testnet Gateway A (produces testnet proofs)'
- url: 'http://3.135.209.139'
description: 'Testnet Gateway B (produces testnet proofs)'
- url: 'http://18.222.108.78'
description: 'Testnet Gateway C (produces testnet proofs)'
paths:
'/hashes':
post:
Expand Down Expand Up @@ -182,11 +192,11 @@ paths:
- 'Calendar'
'/config':
get:
summary: 'Retrieves some basic information for the Node'
operationId: 'getNodeConfig'
summary: 'Retrieves some basic information for the Gateway'
operationId: 'getGatewayConfig'
responses:
'200':
description: 'Basic information about the Node and it''s environment'
description: 'Basic information about the Gateway and it''s environment'
content:
'application/json':
schema:
Expand Down Expand Up @@ -247,18 +257,14 @@ components:
proof:
type: 'object'
example:
'@context': 'https://w3id.org/chainpoint/v3'
'@context': 'https://w3id.org/chainpoint/v4'
type: 'Chainpoint'
hash: '11cd8a380e8d5fd3ac47c1f880390341d40b11485e8ae946d8fa3d466f23fe89'
proof_id: '577c6c90-78d5-11e9-9c57-010a193d9f8c'
hash_received: '2019-05-17T18:55:30Z'
branches:
- label: 'cal_anchor_branch'
ops:
- l: 'node_id:577c6c90-78d5-11e9-9c57-010a193d9f8c'
- op: 'sha-256'
- l: 'core_id:5a22fb80-78d5-11e9-8186-01d1f712eccc'
- op: 'sha-256'
- l: 'nistv2:1558119240000:eb591780782f746fda5e7ac8011064fda657ae451bd1ae6b71e2f5d7e24e9d49bdc25db6d901ccf8736bbf135c451d1edc9c6065b577d69f3fd9be6a1a8d0763'
- op: 'sha-256'
- l: '1766c5a6c10cf8ae5cce76c6d89cb9bc8696a2acf8e7ed4dbe05a71802cae38a'
Expand Down Expand Up @@ -357,7 +363,7 @@ tags:
- name: 'Calendar'
description: 'Chainpoint calendar transaction data'
- name: 'Config'
description: 'Configuration information about the Node'
description: 'Configuration information about the Gateway'
externalDocs:
description: 'Find out more about Chainpoint'
url: 'https://chainpoint.org'
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ services:

# Lightning node
lnd:
image: tierion/lnd:${NETWORK:-testnet}
image: tierion/lnd:${NETWORK:-testnet}-0.9.2
user: ${USERID}:${GROUPID}
entrypoint: './start-lnd.sh'
container_name: lnd-node
Expand Down
4 changes: 2 additions & 2 deletions init/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const initQuestionConfig = [
{
type: 'input',
name: 'LND_PUBLIC_IP',
message: "Enter your Node's Public IP Address:",
message: "Enter your Gateway's Public IP Address:",
validate: input => {
if (input) {
return validator.isIP(input, 4)
Expand Down Expand Up @@ -143,7 +143,7 @@ async function createDockerSecretsAsync(initAnswers, walletInfo) {
await utils.sleepAsync(2000) // wait for swarm to initialize
await exec.quiet([
`printf ${walletInfo.walletSecret} | docker secret create HOT_WALLET_PASS -`,
`printf ${walletInfo.cipherSeedMnemonic.join(' ')} | docker secret create HOT_WALLET_SEED -`,
`printf '${walletInfo.cipherSeedMnemonic.join(' ')}' | docker secret create HOT_WALLET_SEED -`,
`printf ${walletInfo.newAddress} | docker secret create HOT_WALLET_ADDRESS -`
])
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion ip-blacklist.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ip-blacklist.txt
#
# Add a single IPv4 address per line that you'd
# like to block from connecting to this Node.
# like to block from connecting to this Gateway.
#
# Lines beginning with '#' are ignored.
20 changes: 10 additions & 10 deletions lib/aggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ async function aggregateSubmitAndPersistAsync() {
merkleTools.addLeaves(leaves)
merkleTools.makeTree()

let nodeProofDataItems = []
let gatewayProofDataItems = []
aggregationRoot = merkleTools.getMerkleRoot().toString('hex')
let treeSize = merkleTools.getLeafCount()

for (let x = 0; x < treeSize; x++) {
// push the hash_id and corresponding proof onto the array
let nodeProofDataItem = {}
nodeProofDataItem.proofId = hashesForTree[x].proof_id
nodeProofDataItem.hash = hashesForTree[x].hash
nodeProofDataItem.proofState = merkleTools.getProof(x, true)
nodeProofDataItems.push(nodeProofDataItem)
let gatewayProofDataItem = {}
gatewayProofDataItem.proofId = hashesForTree[x].proof_id
gatewayProofDataItem.hash = hashesForTree[x].hash
gatewayProofDataItem.proofState = merkleTools.getProof(x, true)
gatewayProofDataItems.push(gatewayProofDataItem)
}

// submit merkle root to Core
Expand Down Expand Up @@ -116,17 +116,17 @@ async function aggregateSubmitAndPersistAsync() {
proofId: submitResult.proofId
}
})
nodeProofDataItems = nodeProofDataItems.map(nodeProofDataItem => {
nodeProofDataItem.submission = {
gatewayProofDataItems = gatewayProofDataItems.map(gatewayProofDataItem => {
gatewayProofDataItem.submission = {
submitId: submitId,
cores: coreInfo
}
return nodeProofDataItem
return gatewayProofDataItem
})

// persist these proofDataItems to storage
try {
await rocksDB.saveProofStatesBatchAsync(nodeProofDataItems)
await rocksDB.saveProofStatesBatchAsync(gatewayProofDataItems)
} catch (error) {
throw new Error(`Unable to persist proof state data to disk : ${error.message}`)
}
Expand Down
16 changes: 8 additions & 8 deletions lib/api-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const apiConfig = require('./endpoints/config.js')
// RESTIFY SETUP
// 'version' : all routes will default to this version
const httpOptions = {
name: 'chainpoint-node',
name: 'chainpoint-gateway',
version: '2.0.0',
formatters: {
'application/json': restify.formatters['application/json; q=0.4'],
Expand All @@ -42,17 +42,17 @@ const httpOptions = {
}

const TOR_IPS_KEY = 'blacklist:tor:ips'
const CHAINPOINT_NODE_HTTP_PORT = process.env.CHAINPOINT_NODE_PORT || 8080
const CHAINPOINT_GATEWAY_HTTP_PORT = process.env.CHAINPOINT_NODE_PORT || 8080

// state indicating if the Node is ready to accept new hashes for processing
// state indicating if the Gateway is ready to accept new hashes for processing
let acceptingHashes = true

let registrationPassed = true

// the list of IP to refuse connections from
let IPBlacklist = []

// middleware to ensure the Node is accepting hashes
// middleware to ensure the Gateway is accepting hashes
function ensureAcceptingHashes(req, res, next) {
if (!acceptingHashes || !registrationPassed) {
return next(new errors.ServiceUnavailableError('Service is not currently accepting hashes'))
Expand All @@ -70,7 +70,7 @@ async function refreshIPBlacklistAsync() {
async function getTorExitIPAsync() {
let options = {
headers: {
'User-Agent': `chainpoint-node/${version}`
'User-Agent': `chainpoint-gateway/${version}`
},
method: 'GET',
uri: 'https://check.torproject.org/exit-addresses',
Expand Down Expand Up @@ -293,7 +293,7 @@ function setupCommonRestifyConfigAndRoutes(server) {
...applyMiddleware([throttle(15, 5)]),
apiVerify.postProofsForVerificationAsync
)
// get configuration information for this Node
// get configuration information for this Gateway
server.get({ path: '/config', version: '2.0.0' }, ...applyMiddleware([throttle(1, 1)]), apiConfig.getConfigInfoAsync)

server.get({ path: '/login', version: '2.0.0' }, function(req, res, next) {
Expand All @@ -312,9 +312,9 @@ async function startInsecureRestifyServerAsync() {

// Begin listening for requests
return new Promise((resolve, reject) => {
restifyServer.listen(CHAINPOINT_NODE_HTTP_PORT, err => {
restifyServer.listen(CHAINPOINT_GATEWAY_HTTP_PORT, err => {
if (err) return reject(err)
logger.info(`App : Chainpoint Node listening on port ${CHAINPOINT_NODE_HTTP_PORT}`)
logger.info(`App : Chainpoint Gateway listening on port ${CHAINPOINT_GATEWAY_HTTP_PORT}`)
return resolve(restifyServer)
})
})
Expand Down
2 changes: 1 addition & 1 deletion lib/cached-proofs.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ async function getCachedCoreProofsAsync(coreSubmissions) {
for (let submitId in coreSubmissionsLookup) {
coreSubmissionsLookup[submitId].anchorsComplete = _.isNil(coreSubmissionsLookup[submitId].proof)
? []
: utils.parseAnchorsComplete(coreSubmissionsLookup[submitId].proof, env.NETWORK)
: utils.parseCoreProofAnchorsComplete(coreSubmissionsLookup[submitId].proof, env.NETWORK)
}

// cache any new results returned from Core
Expand Down
29 changes: 20 additions & 9 deletions lib/cores.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
let env = require('./parse-env.js').env

let rp = require('request-promise-native')
const { version } = require('../package.json')
const retry = require('async-retry')
const { Lsat } = require('lsat-js')
const _ = require('lodash')
Expand All @@ -31,15 +30,20 @@ let CONNECTED_CORE_LN_URIS = []

let coreConnectionCount = 1

// In some cases we may want a list of all Core Nodes (whether or not the Chainpoint Node is connected to it or not)
// In some cases we may want a list of all Cores (whether or not the Chainpoint Gateway is connected to it or not)
let ALL_CORE_IPS = []

// This is the local in-memory cache of calendar transactions
// CORE_TX_CACHE is an object keyed by txId, storing the transaction object
let CORE_TX_CACHE = {}

// Initialize the Lightning grpc object
let lnd = new lightning(env.LND_SOCKET, env.NETWORK)
// This is the LND object used to interact with the Lightning node
// This value gets initialized on startup
let lnd = null

function initializeLightningObject() {
lnd = new lightning(env.LND_SOCKET, env.NETWORK)
}

async function connectAsync() {
// Retrieve the list of Core IPs we can work with
Expand All @@ -54,15 +58,21 @@ async function connectAsync() {
let connectedCoreIPResult = await getConnectedCoreIPsAsync(coreIPList, coreConnectionCount)
// warn users about env mismatch
if (connectedCoreIPResult.networkMismatch)
logger.warn(`Unable to connect to Cores with a different network setting. This Node is set to '${env.NETWORK}'`)
logger.warn(`Unable to connect to Cores with a different network setting. This Gateway is set to '${env.NETWORK}'`)
// ensure we have successfully communicated with `coreConnectionCount` Cores
// if we have not, the Node cannot continue, log error and exit
// if we have not, the Gateway cannot continue, log error and exit
if (!connectedCoreIPResult.connected) {
throw new Error(`Unable to connect to ${coreConnectionCount} Core(s) as required`)
}
CONNECTED_CORE_IPS = connectedCoreIPResult.ips
CONNECTED_CORE_LN_URIS = connectedCoreIPResult.lnUris

await establishLndPeersAndChannelsAsync()

logger.info(`App : Core IPs : ${CONNECTED_CORE_IPS}`)
}

let establishLndPeersAndChannelsAsync = async () => {
let done = false
while (!done) {
try {
Expand All @@ -78,8 +88,6 @@ async function connectAsync() {
utils.sleepAsync(2000)
}
}

logger.info(`App : Core IPs : ${CONNECTED_CORE_IPS}`)
}

async function waitForSync() {
Expand Down Expand Up @@ -261,7 +269,6 @@ async function createCoreLNDChannelsAsync(lnUris) {
}

async function coreRequestAsync(options, coreIP, retryCount = 3, timeout = 500) {
options.headers['X-Node-Version'] = version
options.uri = `http://${coreIP}${options.uriPath}`

let response
Expand Down Expand Up @@ -503,6 +510,7 @@ function parse402Response(response) {
}

module.exports = {
initializeLightningObject: initializeLightningObject,
connectAsync: connectAsync,
coreRequestAsync: coreRequestAsync,
submitHashAsync: submitHashAsync,
Expand Down Expand Up @@ -533,5 +541,8 @@ module.exports = {
},
getLn: () => {
return lnd
},
clearEPC: () => {
establishLndPeersAndChannelsAsync = async () => {}
}
}
3 changes: 3 additions & 0 deletions lib/endpoints/hashes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const _ = require('lodash')
const utils = require('../utils.js')
const BLAKE2s = require('blake2s-js')
let rocksDB = require('../models/RocksDB.js')
const logger = require('../logger.js')

// Generate a v1 UUID (time-based)
// see: https://github.com/kelektiv/node-uuid
Expand Down Expand Up @@ -191,6 +192,8 @@ async function postHashesAsync(req, res, next) {
return next(new errors.InvalidArgumentError('invalid JSON body, invalid hashes present'))
}

logger.info(`Incoming hash from ${utils.getClientIP(req)}`)

let responseObj = generatePostHashesResponse(req.params.hashes)

// store hash data for later aggregation
Expand Down
Loading