This commit is contained in:
Neal Conner 2017-11-11 17:16:28 -05:00 committed by Josh Harvey
parent 28979e475c
commit 548d285e5b
20 changed files with 216 additions and 227 deletions

View file

@ -1,54 +0,0 @@
variable "name" {}
variable "blockchain_cmd" {}
variable "blockchain_conf" {}
variable "ssh_key" {}
variable "size" {
default = "2gb"
}
variable "blockchain_dir" {
default = "./scratch/blockchains"
}
data "template_file" "supervisor_conf" {
template = "${file("./blockchains/supervisor.conf")}"
vars {
blockchain = "${var.name}"
blockchain_cmd = "${var.blockchain_cmd}"
}
}
resource "digitalocean_droplet" "blockchain_server" {
image = "debian-9-x64"
name = "${var.name}"
region = "ams2"
size = "${var.size}"
ssh_keys = ["${var.ssh_key}"]
connection {
type = "ssh"
user = "root"
private_key = "${file("${pathexpand("~/.ssh/id_rsa")}")}"
}
provisioner "file" {
content = "${data.template_file.supervisor_conf.rendered}"
destination = "/tmp/supervisor-${var.name}.conf"
}
provisioner "file" {
source = "${var.blockchain_dir}/${var.blockchain_conf}"
destination = "/tmp/${var.blockchain_conf}"
}
provisioner "remote-exec" {
script = "./blockchains/${var.name}/install.sh"
}
}
output "ip_address" {
value = "${digitalocean_droplet.blockchain_server.ipv4_address}"
}

View file

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -e
LOG_FILE=/tmp/install.log
apt-get update -y >> $LOG_FILE 2>&1
apt-get install -y ufw supervisor >> $LOG_FILE 2>&1
ufw allow 8332 >> $LOG_FILE 2>&1
ufw allow 22 >> $LOG_FILE 2>&1
ufw --force enable >> $LOG_FILE 2>&1
ufw status >> $LOG_FILE 2>&1
wget -q https://bitcoin.org/bin/bitcoin-core-0.14.2/bitcoin-0.14.2-x86_64-linux-gnu.tar.gz >> $LOG_FILE 2>&1
tar -xzf bitcoin-0.14.2-x86_64-linux-gnu.tar.gz >> $LOG_FILE 2>&1
cp bitcoin-0.14.2/bin/* /usr/local/bin >> $LOG_FILE 2>&1
mkdir ~/.bitcoin >> $LOG_FILE 2>&1
mv /tmp/bitcoin.conf ~/.bitcoin
mv /tmp/supervisor-bitcoin.conf /etc/supervisor/conf.d/bitcoin.conf >> $LOG_FILE 2>&1
service supervisor restart >> $LOG_FILE 2>&1

View file

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -e
LOG_FILE=/tmp/install.log
apt-get update -y >> $LOG_FILE 2>&1
apt-get install -y ufw supervisor >> $LOG_FILE 2>&1
ufw allow 8332 >> $LOG_FILE 2>&1
ufw allow 22 >> $LOG_FILE 2>&1
ufw --force enable >> $LOG_FILE 2>&1
ufw status >> $LOG_FILE 2>&1
wget -q https://www.dash.org/binaries/dashcore-0.12.1.5-linux64.tar.gz >> $LOG_FILE 2>&1
tar -xzf dashcore-0.12.1.5-linux64.tar.gz >> $LOG_FILE 2>&1
cp dashcore-0.12.1/bin/* /usr/local/bin >> $LOG_FILE 2>&1
mkdir ~/.dash >> $LOG_FILE 2>&1
mv /tmp/dash.conf ~/.bitocoin
mv /tmp/supervisor-dash.conf /etc/supervisor/conf.d/dash.conf >> $LOG_FILE 2>&1
service supervisor restart >> $LOG_FILE 2>&1

View file

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -e
LOG_FILE=/tmp/install.log
apt-get update -y >> $LOG_FILE 2>&1
apt-get install -y ufw supervisor >> $LOG_FILE 2>&1
ufw allow 8332 >> $LOG_FILE 2>&1
ufw allow 22 >> $LOG_FILE 2>&1
ufw --force enable >> $LOG_FILE 2>&1
ufw status >> $LOG_FILE 2>&1
wget -q https://download.litecoin.org/litecoin-0.14.2/linux/litecoin-0.14.2-x86_64-linux-gnu.tar.gz >> $LOG_FILE 2>&1
tar -xzf litecoin-0.14.2-x86_64-linux-gnu.tar.gz >> $LOG_FILE 2>&1
cp litecoin-0.14.2/bin/* /usr/local/bin >> $LOG_FILE 2>&1
mkdir ~/.litecoin >> $LOG_FILE 2>&1
mv /tmp/litecoin.conf ~/.litecoin
mv /tmp/supervisor-litecoin.conf /etc/supervisor/conf.d/litecoin.conf >> $LOG_FILE 2>&1
service supervisor restart >> $LOG_FILE 2>&1

View file

@ -1,7 +0,0 @@
[program:${blockchain}]
command=nice -n +6 /usr/local/bin/${blockchain_cmd} -datadir=/mnt/blockchain/${blockchain}
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/${blockchain}.err.log
stdout_logfile=/var/log/supervisor/${blockchain}.out.log
environment=HOME="/root"

View file

@ -1,7 +0,0 @@
[program:${blockchain}-tunnel]
command=autossh -L 8232:localhost:8232 -o "ExitOnForwardFailure yes" -fN -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" root@188.226.149.173
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/${blockchain}-tunnel.err.log
stdout_logfile=/var/log/supervisor/${blockchain}-tunnel.out.log
environment="AUTOSSH_GATETIME=0"

View file

@ -1,19 +0,0 @@
#!/usr/bin/env bash
set -e
LOG_FILE=/tmp/install.log
apt-get update -y >> $LOG_FILE 2>&1
apt-get install -y ufw supervisor libgomp1 >> $LOG_FILE 2>&1
ufw allow 8233 >> $LOG_FILE 2>&1
ufw allow 22 >> $LOG_FILE 2>&1
ufw --force enable >> $LOG_FILE 2>&1
ufw status >> $LOG_FILE 2>&1
wget -q https://z.cash/downloads/zcash-1.0.12-linux64.tar.gz >> $LOG_FILE 2>&1
tar -xzf zcash-1.0.12-linux64.tar.gz >> $LOG_FILE 2>&1
cp zcash-1.0.12/bin/* /usr/local/bin >> $LOG_FILE 2>&1
zcash-fetch-params >> $LOG_FILE 2>&1
mkdir ~/.zcash >> $LOG_FILE 2>&1
mv /tmp/zcash.conf ~/.zcash
mv /tmp/supervisor-zcash.conf /etc/supervisor/conf.d/zcash.conf >> $LOG_FILE 2>&1
service supervisor restart >> $LOG_FILE 2>&1

View file

@ -1,20 +0,0 @@
#!/usr/bin/env node
const path = require('path')
const crypto = require('crypto')
const fs = require('fs')
const options = require('../../lib/options')
const blockchainDir = options.blockchainDir
const confPath = path.resolve(blockchainDir, 'zcash.conf')
const password = crypto.randomBytes(32).toString('hex')
const conf = `rpcuser=username
rpcpassword=${password}
mainnet=1
addnode=mainnet.z.cash
dbcache=500
`
fs.writeFileSync(confPath, conf)

View file

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -e
LOG_FILE=/tmp/install.log
wget -q $UPGRADE_URL >> $LOG_FILE 2>&1
tar -xzf $UPGRADE_PACKAGE >> $LOG_FILE 2>&1
supervisorctl stop zcash >> $LOG_FILE 2>&1
cp $UPGRADE_PACKAGE/bin/* /usr/local/bin/ >> $LOG_FILE 2>&1
supervisorctl start zcash >> $LOG_FILE 2>&1

View file

@ -1,4 +0,0 @@
rpcuser=username
mainnet=1
addnode=mainnet.z.cash
dbcache=500

View file

@ -150,7 +150,7 @@ const mapLanguage = lang => {
const supportedLanguages = languageRec.supported
const languages = supportedLanguages.map(mapLanguage).filter(r => r)
const ALL_CRYPTOS = ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']
const ALL_CRYPTOS = ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']
function fetchData () {
return machineLoader.getMachineNames()
@ -161,13 +161,14 @@ function fetchData () {
{crypto: 'ETH', display: 'Ethereum'},
{crypto: 'LTC', display: 'Litecoin'},
{crypto: 'DASH', display: 'Dash'},
{crypto: 'ZEC', display: 'Zcash'}
{crypto: 'ZEC', display: 'Zcash'},
{crypto: 'BCH', display: 'BCH'}
],
languages: languages,
countries,
accounts: [
{code: 'bitpay', display: 'Bitpay', class: 'ticker', cryptos: ['BTC']},
{code: 'kraken', display: 'Kraken', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']},
{code: 'kraken', display: 'Kraken', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']},
{code: 'bitstamp', display: 'Bitstamp', class: 'ticker', cryptos: ['BTC', 'LTC']},
{code: 'coinbase', display: 'Coinbase', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC']},
{code: 'mock-ticker', display: 'Mock ticker', class: 'ticker', cryptos: ALL_CRYPTOS},
@ -176,9 +177,10 @@ function fetchData () {
{code: 'zcashd', display: 'zcashd', class: 'wallet', cryptos: ['ZEC']},
{code: 'litecoind', display: 'litecoind', class: 'wallet', cryptos: ['LTC']},
{code: 'dashd', display: 'dashd', class: 'wallet', cryptos: ['DASH']},
{code: 'bitcoincashd', display: 'bitcoincashd', class: 'wallet', cryptos: ['BCH']},
{code: 'bitgo', display: 'BitGo', class: 'wallet', cryptos: ['BTC']},
{code: 'bitstamp', display: 'Bitstamp', class: 'exchange', cryptos: ['BTC', 'LTC']},
{code: 'kraken', display: 'Kraken', class: 'exchange', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']},
{code: 'kraken', display: 'Kraken', class: 'exchange', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']},
{code: 'mock-wallet', display: 'Mock wallet', class: 'wallet', cryptos: ALL_CRYPTOS},
{code: 'no-exchange', display: 'No exchange', class: 'exchange', cryptos: ALL_CRYPTOS},
{code: 'mock-exchange', display: 'Mock exchange', class: 'exchange', cryptos: ALL_CRYPTOS},
@ -186,10 +188,10 @@ function fetchData () {
{code: 'mock-id-verify', display: 'Mock ID verifier', class: 'idVerifier'},
{code: 'twilio', display: 'Twilio', class: 'sms'},
{code: 'mailjet', display: 'Mailjet', class: 'email'},
{code: 'all-zero-conf', display: 'Always 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH']},
{code: 'all-zero-conf', display: 'Always 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH', 'BCH']},
{code: 'no-zero-conf', display: 'Always 1-conf', class: 'zeroConf', cryptos: ALL_CRYPTOS},
{code: 'blockcypher', display: 'Blockcypher', class: 'zeroConf', cryptos: ['BTC']},
{code: 'mock-zero-conf', display: 'Mock 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH']}
{code: 'mock-zero-conf', display: 'Mock 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH', 'BCH']}
],
machines: machineList.map(machine => ({machine: machine.deviceId, display: machine.name}))
}))

View file

@ -0,0 +1,31 @@
const path = require('path')
const coinUtils = require('../coin-utils')
const common = require('./common')
module.exports = {setup}
const coinRec = coinUtils.getCryptoCurrency('BCH')
function setup (dataDir) {
common.firewall([coinRec.defaultPort])
const config = buildConfig()
common.writeFile(path.resolve(dataDir, coinRec.configFile), config)
const cmd = `/usr/local/bin/${coinRec.daemon} -datadir=${dataDir} -conf=${dataDir}/bitcoincash.conf`
common.writeSupervisorConfig(coinRec, cmd)
}
function buildConfig () {
return `rpcuser=lamassuserver
rpcpassword=${common.randomPass()}
dbcache=500
server=1
connections=40
keypool=10000
prune=4000
daemon=0
bind=0.0.0.0:8334
rpcport=8335
`
}

View file

@ -3,6 +3,9 @@ const os = require('os')
const path = require('path')
const cp = require('child_process')
const fs = require('fs')
const _ = require('lodash/fp')
const logger = require('console-log-level')({level: 'info'})
module.exports = {
@ -18,8 +21,8 @@ module.exports = {
const BINARIES = {
BTC: {
url: 'https://bitcoin.org/bin/bitcoin-core-0.14.2/bitcoin-0.14.2-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-0.14.2/bin'
url: 'https://bitcoin.org/bin/bitcoin-core-0.15.1/bitcoin-0.15.1-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-0.15.1/bin'
},
ETH: {
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.7.2-1db4ecdc.tar.gz',
@ -30,12 +33,17 @@ const BINARIES = {
dir: 'zcash-1.0.12/bin'
},
DASH: {
url: 'https://www.dash.org/binaries/dashcore-0.12.1.5-linux64.tar.gz',
dir: 'dashcore-0.12.1/bin'
url: 'https://github.com/dashpay/dash/releases/download/v0.12.2.1/dashcore-0.12.2.1-linux64.tar.gz',
dir: 'dashcore-0.12.2/bin'
},
LTC: {
url: 'https://download.litecoin.org/litecoin-0.14.2/linux/litecoin-0.14.2-x86_64-linux-gnu.tar.gz',
dir: 'litecoin-0.14.2/bin'
},
BCH: {
url: 'https://download.bitcoinabc.org/0.16.1/linux/bitcoin-abc-0.16.1-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-abc-0.16.1/bin',
files: [['bitcoind', 'bitcoincashd'], ['bitcoin-cli', 'bitcoincash-cli']]
}
}
@ -90,7 +98,15 @@ function fetchAndInstall (coinRec) {
es(`wget -q ${url}`)
es(`tar -xzf ${downloadFile}`)
if (_.isEmpty(binaries.files)) {
es(`sudo cp ${binDir}/* /usr/local/bin`)
return
}
_.forEach(([source, target]) => {
es(`sudo cp ${binDir}/${source} /usr/local/bin/${target}`)
}, binaries.files)
}
function writeFile (path, content) {

View file

@ -21,7 +21,8 @@ const PLUGINS = {
LTC: require('./litecoin.js'),
ETH: require('./ethereum.js'),
DASH: require('./dash.js'),
ZEC: require('./zcash.js')
ZEC: require('./zcash.js'),
BCH: require('./bitcoincash.js')
}
module.exports = {run}

View file

@ -49,6 +49,15 @@ const CRYPTO_CURRENCIES = [
daemon: 'zcashd',
defaultPort: 8232,
unitScale: 8
},
{
cryptoCode: 'BCH',
display: 'BCH',
code: 'bitcoincash',
configFile: 'bitcoincash.conf',
daemon: 'bitcoincashd',
defaultPort: 8335,
unitScale: 8
}
]
@ -71,6 +80,7 @@ function buildUrl (cryptoCode, address) {
case 'ZEC': return `zcash:${address}`
case 'LTC': return `litecoin:${address}`
case 'DASH': return `dash:${address}`
case 'BCH': return `bitcoincash:${address}`
default: throw new Error(`Unsupported crypto: ${cryptoCode}`)
}
}

View file

@ -20,6 +20,10 @@ const PAIRS = {
DASH: {
USD: 'DASHUSD',
EUR: 'DASHEUR'
},
BCH: {
USD: 'BCHUSD',
EUR: 'BCHEUR'
}
}

View file

@ -0,0 +1,136 @@
const jsonRpc = require('../../common/json-rpc')
const bs58check = require('bs58check')
const BN = require('../../../bn')
const E = require('../../../error')
const coinUtils = require('../../../coin-utils')
const cryptoRec = coinUtils.getCryptoCurrency('BCH')
const configPath = coinUtils.configPath(cryptoRec)
const unitScale = cryptoRec.unitScale
const config = jsonRpc.parseConf(configPath)
const rpcConfig = {
username: config.rpcuser,
password: config.rpcpassword,
port: config.rpcport || cryptoRec.defaultPort
}
function fetch (method, params) {
return jsonRpc.fetch(rpcConfig, method, params)
}
function checkCryptoCode (cryptoCode) {
if (cryptoCode !== 'BCH') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode))
return Promise.resolve()
}
function accountBalance (account, cryptoCode, confirmations) {
return checkCryptoCode(cryptoCode)
.then(() => fetch('getbalance', ['', confirmations]))
.then(r => BN(r).shift(unitScale).round())
}
// We want a balance that includes all spends (0 conf) but only deposits that
// have at least 1 confirmation. getbalance does this for us automatically.
function balance (account, cryptoCode) {
return accountBalance(account, cryptoCode, 1)
}
function bchToBtcVersion (version) {
if (version === 0x1c) return 0x00
if (version === 0x28) return 0x05
return version
}
// Bitcoin-ABC only accepts BTC style addresses at this point,
// so we need to convert
function bchToBtcAddress (address) {
const buf = bs58check.decode(address)
const version = buf[0]
buf[0] = bchToBtcVersion(version)
return bs58check.encode(buf)
}
function sendCoins (account, address, cryptoAtoms, cryptoCode) {
const coins = cryptoAtoms.shift(-unitScale).toFixed(8)
const btcAddress = bchToBtcAddress(address)
return checkCryptoCode(cryptoCode)
.then(() => fetch('sendtoaddress', [btcAddress, coins]))
.catch(err => {
if (err.code === -6) throw new E.InsufficientFundsError()
throw err
})
}
function newAddress (account, info) {
return checkCryptoCode(info.cryptoCode)
.then(() => fetch('getnewaddress'))
}
function addressBalance (address, confs) {
const btcAddress = bchToBtcAddress(address)
return fetch('getreceivedbyaddress', [btcAddress, confs])
.then(r => BN(r).shift(unitScale).round())
}
function confirmedBalance (address, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => addressBalance(address, 1))
}
function pendingBalance (address, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => addressBalance(address, 0))
}
function getStatus (account, toAddress, requested, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'}
return pendingBalance(toAddress, cryptoCode)
.then(pending => {
if (pending.gte(requested)) return {status: 'authorized'}
if (pending.gt(0)) return {status: 'insufficientFunds'}
return {status: 'notSeen'}
})
})
}
function newFunding (account, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => {
const promises = [
accountBalance(account, cryptoCode, 0),
accountBalance(account, cryptoCode, 1),
newAddress(account, {cryptoCode})
]
return Promise.all(promises)
})
.then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({
fundingPendingBalance,
fundingConfirmedBalance,
fundingAddress
}))
}
function cryptoNetwork (account, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => parseInt(rpcConfig.port, 10) === 18332 ? 'test' : 'main')
}
module.exports = {
balance,
sendCoins,
newAddress,
getStatus,
newFunding,
cryptoNetwork
}

37
main.tf
View file

@ -1,37 +0,0 @@
module "zcash" {
source = "./blockchain"
name = "zcash"
blockchain_cmd = "zcashd"
blockchain_conf = "zcash.conf"
ssh_key = "${digitalocean_ssh_key.default.id}"
}
module "litecoin" {
source = "./blockchain"
name = "litecoin"
blockchain_cmd = "litecoind"
blockchain_conf = "litecoin.conf"
ssh_key = "${digitalocean_ssh_key.default.id}"
}
module "dash" {
source = "./blockchain"
name = "dash"
blockchain_cmd = "dashd"
blockchain_conf = "dash.conf"
ssh_key = "${digitalocean_ssh_key.default.id}"
}
module "bitcoin" {
source = "./blockchain"
name = "bitcoin"
blockchain_cmd = "bitcoind"
blockchain_conf = "bitcoin.conf"
ssh_key = "${digitalocean_ssh_key.default.id}"
}
resource "digitalocean_ssh_key" "default" {
name = "Lamassu Server"
public_key = "${file("${pathexpand("~/.ssh/id_rsa.pub")}")}"
}

View file

@ -2,7 +2,7 @@
"name": "lamassu-server",
"description": "bitcoin atm client server protocol module",
"keywords": [],
"version": "5.5.27",
"version": "5.5.28",
"license": "Unlicense",
"author": "Lamassu (https://lamassu.is)",
"dependencies": {
@ -50,7 +50,9 @@
"uuid": "^3.1.0",
"web3": "^0.19.1",
"winston": "^2.3.0",
"ws": "^3.1.0"
"ws": "^3.1.0",
"bitcore-lib": "^0.15.0",
"bitcore-lib-cash": "git+https://github.com/bitpay/bitcore-lib.git#cash"
},
"repository": {
"type": "git",