chore: remove unused files

This commit is contained in:
Rafael Taranto 2024-06-07 10:53:57 +01:00
parent 9ce126aee3
commit 7cdc56cfdd
303 changed files with 40 additions and 81654 deletions

87
tests/stress/child.js Normal file
View file

@ -0,0 +1,87 @@
const https = require('https')
const path = require('path')
const pify = require('pify')
const fs = pify(require('fs'))
const uuid = require('uuid')
const _ = require('lodash/fp')
const { PerformanceObserver, performance } = require('perf_hooks')
const utils = require('./utils')
const variables = require('./utils/variables')
var certificate = {}
var connectionInfo = {}
const getCert = machineIndex => {
const key = fs.readFile(path.resolve(__dirname, 'machines', `${machineIndex}`, 'client.key'))
const cert = fs.readFile(path.resolve(__dirname, 'machines', `${machineIndex}`, 'client.pem'))
return Promise.all([key, cert]).then(([key, cert]) => {
return { key, cert }
}).catch(err => {
console.error('The following error when reading the certificate: ', err)
return null
})
}
const getConnectionInfo = machineIndex => {
return fs.readFile(path.resolve(__dirname, 'machines', `${machineIndex}`, 'connection_info.json'))
}
let counter = 0
const requestTimes = []
let latestResponseTime = 0
const request = (machineIndex, pid) => {
performance.mark('A')
https.get({
hostname: 'localhost',
port: 3000,
path: '/poll?state=chooseCoin&model=unknown&version=7.5.0-beta.0&idle=true&pid=' + pid + '&sn=' + counter,
method: 'GET',
key: certificate.key,
cert: certificate.cert,
ca: connectionInfo.ca,
headers: {
date: new Date().toISOString(),
'request-id': uuid.v4()
}
}, res => {
res.on('data', (d) => {
performance.mark('B')
performance.measure('A to B', 'A', 'B')
console.log(`Machine ${machineIndex} || Avg request response time: ${_.mean(requestTimes).toFixed(3)} || Latest response time: ${latestResponseTime.toFixed(3)}`)
process.send({ message: Buffer.from(d).toString() })
})
})
counter++
}
const obs = new PerformanceObserver((items) => {
latestResponseTime = items.getEntries()[0].duration
requestTimes.push(latestResponseTime)
performance.clearMarks()
})
obs.observe({ entryTypes: ['measure'] })
process.on('message', async (msg) => {
console.log('Message from parent:', msg)
const promises = [getCert(msg.machineIndex), getConnectionInfo(msg.machineIndex)]
Promise.all(promises).then(values => {
certificate = values[0]
connectionInfo = JSON.parse(values[1])
}).catch(err => {
console.error('The following error occurred during certificate parsing: ', err)
})
if (msg.hasVariance) await new Promise(resolve => setTimeout(resolve, utils.randomIntFromInterval(1, variables.POLLING_INTERVAL)))
const pid = uuid.v4()
request(msg.machineIndex, pid)
setInterval(() => {
const pid = uuid.v4()
request(msg.machineIndex, pid)
}, 5000)
})

35
tests/stress/index.js Normal file
View file

@ -0,0 +1,35 @@
const { fork } = require('child_process')
const minimist = require('minimist')
const cmd = require('./scripts')
const variables = require('./utils/variables')
function createMachines (numberOfMachines) {
return cmd.execCommand(
`bash ./scripts/create-machines.sh ${numberOfMachines} ${variables.SERVER_CERT_PATH} ${variables.MACHINE_PATH}`
)
}
function startServer () {
const forked = fork('test-server.js')
forked.send('start')
}
async function run (args = minimist(process.argv.slice(2))) {
const NUMBER_OF_MACHINES = args._[0]
const HAS_VARIANCE = args.v || false
await createMachines(NUMBER_OF_MACHINES)
startServer()
for (let i = 1; i <= NUMBER_OF_MACHINES; i++) {
const forked = fork('child.js')
forked.send({ machineIndex: i, hasVariance: HAS_VARIANCE })
forked.on('message', msg => {
console.log(`Machine ${i} || ${msg}`)
})
}
}
run()

View file

@ -0,0 +1,47 @@
const db = require('../../lib/db')
const loadDummyTxData = () => {
const sql = `
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
INSERT INTO customers
VALUES ('99ac9999-9999-99e9-9999-9f99a9999999', null, null, null, null, null, null,
'load_test_customers', null, null, null, null, null, null, '2021-04-16 10:51:38',
'automatic', null, 'automatic', null, 'automatic', null, 'automatic', null, 'automatic',
null, 'automatic', null, null, null, null, null, null, 'automatic', null, null,
null, null, null, null, null, null, null, null, null, null)
ON CONFLICT DO NOTHING;
INSERT INTO cash_in_txs
SELECT uuid_generate_v4(), md5(random()::text), md5(random()::text), i::integer, 'BTC',
i::integer, 'EUR', null, null, null, null, now() - random() * INTERVAL '2 days', random() > 0.5,
random() > 0.5, random() > 0.5, now() - random() * INTERVAL '2 days', null, random() > 0.5,
random() > 0.5, i::integer, i::integer, 1, '99ac9999-9999-99e9-9999-9f99a9999999',
6, random() > 0.5, random() * (0.9-0.1) + 0.1::int, i::integer, random() > 0.5, null, null, false,
null, null, null
FROM generate_series(1, 5000000) as t(i);
INSERT INTO cash_out_txs
SELECT uuid_generate_v4(), md5(random()::text), md5(random()::text), i::integer, 'BTC',
i::integer, 'EUR', 'confirmed', random() > 0.5, random() > 0.5, random() > 0.5,
null, null, now() - random() * INTERVAL '2 days', now() - random() * INTERVAL '2 days', null,
random() > 0.5, random() > 0.5, random() > 0.5, 0, 1, 20, 50, null, '99ac9999-9999-99e9-9999-9f99a9999999',
random() * (40-1) + 1::int, now() - random() * INTERVAL '2 days', random() > 0.5, null,
random() * (0.9-0.1) + 0.1::int, i::integer, i::integer, null, null, null, null, null, null, null, null
FROM generate_series(1, 5000000) as t(i);
INSERT INTO logs
SELECT uuid_generate_v4(), md5(random()::text), 'info', now() - random() * INTERVAL '2 days',
'message', now() - random() * INTERVAL '2 days',0
FROM generate_series(1, 5000000) as t(i);
INSERT INTO bills
SELECT uuid_generate_v4(), i::integer, 'USD', '3d92c323-58c6-4172-9f30-91b80f0c653c',
i::integer, '2021-04-16 11:51:38', 'BTC', i::integer
FROM generate_series(1, 5000000) as t(i);
`
db.none(sql)
}
loadDummyTxData()

View file

@ -0,0 +1,231 @@
const db = require('../../lib/db')
const Pgp = require('pg-promise')()
const _ = require('lodash/fp')
const cashInTx = require('../../lib/cash-in/cash-in-tx')
const { CASH_OUT_TRANSACTION_STATES, REDEEMABLE_AGE } = require('../../lib/cash-out/cash-out-helper')
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel', 'scoreThresholdReached']
function filterTransaction () {
const sql = `EXPLAIN ANALYZE
SELECT DISTINCT * FROM (
SELECT 'type' AS type, 'Cash In' AS value UNION
SELECT 'type' AS type, 'Cash Out' AS value UNION
SELECT 'machine' AS type, name AS value FROM devices d INNER JOIN cash_in_txs t ON d.device_id = t.device_id UNION
SELECT 'machine' AS type, name AS value FROM devices d INNER JOIN cash_out_txs t ON d.device_id = t.device_id UNION
SELECT 'customer' AS type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') AS value
FROM customers c INNER JOIN cash_in_txs t ON c.id = t.customer_id
WHERE c.id_card_data::json->>'firstName' IS NOT NULL or c.id_card_data::json->>'lastName' IS NOT NULL UNION
SELECT 'customer' AS type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') AS value
FROM customers c INNER JOIN cash_out_txs t ON c.id = t.customer_id
WHERE c.id_card_data::json->>'firstName' IS NOT NULL or c.id_card_data::json->>'lastName' IS NOT NULL UNION
SELECT 'fiat' AS type, fiat_code AS value FROM cash_in_txs UNION
SELECT 'fiat' AS type, fiat_code AS value FROM cash_out_txs UNION
SELECT 'crypto' AS type, crypto_code AS value FROM cash_in_txs UNION
SELECT 'crypto' AS type, crypto_code AS value FROM cash_out_txs UNION
SELECT 'address' AS type, to_address AS value FROM cash_in_txs UNION
SELECT 'address' AS type, to_address AS value FROM cash_out_txs UNION
SELECT 'status' AS type, ${cashInTx.TRANSACTION_STATES} AS value FROM cash_in_txs UNION
SELECT 'status' AS type, ${CASH_OUT_TRANSACTION_STATES} AS value FROM cash_out_txs
) f`
return db.any(sql)
}
function filterCustomer () {
const sql = `EXPLAIN ANALYZE
SELECT DISTINCT * FROM (
SELECT 'phone' AS type, phone AS value FROM customers WHERE phone IS NOT NULL UNION
SELECT 'name' AS type, id_card_data::json->>'firstName' AS value FROM customers WHERE id_card_data::json->>'firstName' IS NOT NULL AND id_card_data::json->>'lastName' IS NULL UNION
SELECT 'name' AS type, id_card_data::json->>'lastName' AS value FROM customers WHERE id_card_data::json->>'firstName' IS NULL AND id_card_data::json->>'lastName' IS NOT NULL UNION
SELECT 'name' AS type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') AS value FROM customers WHERE id_card_data::json->>'firstName' IS NOT NULL AND id_card_data::json->>'lastName' IS NOT NULL UNION
SELECT 'address' as type, id_card_data::json->>'address' AS value FROM customers WHERE id_card_data::json->>'address' IS NOT NULL UNION
SELECT 'id' AS type, id_card_data::json->>'documentNumber' AS value FROM customers WHERE id_card_data::json->>'documentNumber' IS NOT NULL
) f`
return db.any(sql)
}
function getCustomerById (id) {
const passableErrorCodes = _.map(Pgp.as.text, TX_PASSTHROUGH_ERROR_CODES).join(',')
const sql = `EXPLAIN ANALYZE
select id, authorized_override, days_suspended, is_suspended, front_camera_path, front_camera_override,
phone, sms_override, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_override, us_ssn, us_ssn_override, sanctions, sanctions_at,
sanctions_override, total_txs, total_spent, created as last_active, fiat as last_tx_fiat,
fiat_code as last_tx_fiat_code, tx_class as last_tx_class, subscriber_info
from (
select c.id, c.authorized_override,
greatest(0, date_part('day', c.suspended_until - now())) as days_suspended,
c.suspended_until > now() as is_suspended,
c.front_camera_path, c.front_camera_override,
c.phone, c.sms_override, c.id_card_data, c.id_card_data_override, c.id_card_data_expiration,
c.id_card_photo_path, c.id_card_photo_override, c.us_ssn, c.us_ssn_override, c.sanctions,
c.sanctions_at, c.sanctions_override, c.subscriber_info, t.tx_class, t.fiat, t.fiat_code, t.created,
row_number() over (partition by c.id order by t.created desc) as rn,
sum(case when t.id is not null then 1 else 0 end) over (partition by c.id) as total_txs,
sum(case when error_code is null or error_code not in ($1^) then t.fiat else 0 end) over (partition by c.id) as total_spent
from customers c left outer join (
select 'cashIn' as tx_class, id, fiat, fiat_code, created, customer_id, error_code
from cash_in_txs where send_confirmed = true union
select 'cashOut' as tx_class, id, fiat, fiat_code, created, customer_id, error_code
from cash_out_txs where confirmed_at is not null) t on c.id = t.customer_id
where c.id = $2
) as cl where rn = 1`
return db.any(sql, [passableErrorCodes, id])
}
function simpleGetMachineLogs (deviceId, from = new Date(0).toISOString(), until = new Date().toISOString(), limit = null, offset = 0) {
const sql = `EXPLAIN ANALYZE
select id, log_level, timestamp, message from logs
where device_id=$1
and timestamp >= $2
and timestamp <= $3
order by timestamp desc, serial desc
limit $4
offset $5`
return db.any(sql, [ deviceId, from, until, limit, offset ])
}
function batchCashIn (
from = new Date(0).toISOString(),
until = new Date().toISOString(),
limit = null,
offset = 0,
id = null,
txClass = null,
machineName = null,
customerName = null,
fiatCode = null,
cryptoCode = null,
toAddress = null,
status = null,
simplified = false
) {
const cashInSql = `EXPLAIN ANALYZE
SELECT 'cashIn' AS tx_class, txs.*,
c.phone AS customer_phone,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') AS customer_name,
c.front_camera_path AS customer_front_camera_path,
c.id_card_photo_path AS customer_id_card_photo_path,
((NOT txs.send_confirmed) AND (txs.created <= now() - interval $1)) AS expired
FROM (SELECT *, ${cashInTx.TRANSACTION_STATES} AS txStatus FROM cash_in_txs) AS txs
LEFT OUTER JOIN customers c ON txs.customer_id = c.id
INNER JOIN devices d ON txs.device_id = d.device_id
WHERE txs.created >= $2 AND txs.created <= $3 ${
id !== null ? `AND txs.device_id = $6` : ``
}
AND ($7 is null or $7 = 'Cash In')
AND ($8 is null or d.name = $8)
AND ($9 is null or concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') = $9)
AND ($10 is null or txs.fiat_code = $10)
AND ($11 is null or txs.crypto_code = $11)
AND ($12 is null or txs.to_address = $12)
AND ($13 is null or txs.txStatus = $13)
AND (fiat > 0)
ORDER BY created DESC limit $4 offset $5`
return db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status])
}
function batchCashOut (
from = new Date(0).toISOString(),
until = new Date().toISOString(),
limit = null,
offset = 0,
id = null,
txClass = null,
machineName = null,
customerName = null,
fiatCode = null,
cryptoCode = null,
toAddress = null,
status = null,
simplified = false
) {
const cashOutSql = `EXPLAIN ANALYZE
SELECT 'cashOut' AS tx_class,
txs.*,
actions.tx_hash,
c.phone AS customer_phone,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') AS customer_name,
c.front_camera_path AS customer_front_camera_path,
c.id_card_photo_path AS customer_id_card_photo_path,
(extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $1 AS expired
FROM (SELECT *, ${CASH_OUT_TRANSACTION_STATES} AS txStatus FROM cash_out_txs) txs
INNER JOIN cash_out_actions actions ON txs.id = actions.tx_id
AND actions.action = 'provisionAddress'
LEFT OUTER JOIN customers c ON txs.customer_id = c.id
INNER JOIN devices d ON txs.device_id = d.device_id
WHERE txs.created >= $2 AND txs.created <= $3 ${
id !== null ? `AND txs.device_id = $6` : ``
}
AND ($7 is null or $7 = 'Cash Out')
AND ($8 is null or d.name = $8)
AND ($9 is null or concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') = $9)
AND ($10 is null or txs.fiat_code = $10)
AND ($11 is null or txs.crypto_code = $11)
AND ($12 is null or txs.to_address = $12)
AND ($13 is null or txs.txStatus = $13)
AND (fiat > 0)
ORDER BY created DESC limit $4 offset $5`
return db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status])
}
function getTx (txId, txClass) {
const cashInSql = `EXPLAIN ANALYZE
select 'cashIn' as tx_class, txs.*,
((not txs.send_confirmed) and (txs.created <= now() - interval $1)) as expired
from cash_in_txs as txs
where txs.id=$2`
const cashOutSql = `EXPLAIN ANALYZE
select 'cashOut' as tx_class,
txs.*,
(extract(epoch from (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $2 as expired
from cash_out_txs txs
where txs.id=$1`
return txClass === 'cashIn'
? db.any(cashInSql, [cashInTx.PENDING_INTERVAL, txId])
: db.any(cashOutSql, [txId, REDEEMABLE_AGE])
}
function getTxAssociatedData (txId, txClass) {
const billsSql = `EXPLAIN ANALYZE select 'bills' as bills, b.* from bills b where cash_in_txs_id = $1`
const actionsSql = `EXPLAIN ANALYZE select 'cash_out_actions' as cash_out_actions, actions.* from cash_out_actions actions where tx_id = $1`
return txClass === 'cashIn'
? db.any(billsSql, [txId])
: db.any(actionsSql, [txId])
}
const run = () => {
const deviceId = '7526924341dc4a57f02b6411a85923de' // randomly generated by the load script
const customerId = '99ac9999-9999-99e9-9999-9f99a9999999' // hardcoded on the current load script
const cashOutTxId = 'c402a7ae-b8f7-4781-8080-1e9ab76d62b5' // randomly generated by the load script
const cashInTxId = '4d8d89f4-7d77-4d30-87e8-be9de05deea7' // randomly generated by the load script
const getExecutionTime = _.compose(_.get('QUERY PLAN'), _.last)
Promise.all([filterCustomer(), filterTransaction(), getCustomerById(customerId), simpleGetMachineLogs(deviceId), batchCashIn(), batchCashOut(),
getTx(cashInTxId, 'cashIn'), getTx(cashOutTxId, 'cashOut'), getTxAssociatedData(cashInTxId, 'cashIn'), getTxAssociatedData(cashOutTxId, 'cashOut')])
.then(([filterCustomer, filterTransaction, getCustomerById, logs, batchCashIn, batchCashOut, getTxCashOut, getTxCashIn,
getTxAssociatedDataCashIn, getTxAssociatedDataCashOut]) => {
console.log(`filterCustomer => ${getExecutionTime(filterCustomer)}`)
console.log(`filterTransaction => ${getExecutionTime(filterTransaction)}`)
console.log(`getCustomerById => ${getExecutionTime(getCustomerById)}`)
console.log(`batchCashOut + batchCashIn => ${getExecutionTime(batchCashOut) + ' + ' + getExecutionTime(batchCashIn)} `)
console.log(`getTx (cash-out) => ${getExecutionTime(getTxCashOut)}`)
console.log(`getTx (cash-in) => ${getExecutionTime(getTxCashIn)}`)
console.log(`getTxAssociatedData (cash-in) => ${getExecutionTime(getTxAssociatedDataCashIn)}`)
console.log(`getTxAssociatedDataCashOut (cash-out) => ${getExecutionTime(getTxAssociatedDataCashOut)}`)
})
}
run()

View file

@ -0,0 +1,61 @@
#!/bin/bash
set -e
if [ $# -eq 0 ]
then
echo "usage: ./build-machines [number_of_machines] /path/to/server/cert/lamassu_op_root_ca.pem /path/to/machine/" && exit 1
fi
case $1 in
''|*[!0-9]*) echo "usage: ./build-machines [number_of_machines] /path/to/server/cert/lamassu_op_root_ca.pem /path/to/machine/" && exit 1;;
esac
SERVER_CERT=$(perl -pe 's/\n/\\n/' < $2)
if [ -z "$SERVER_CERT" ]
then
echo "Lamassu-op-root-ca.pem is empty" && exit 1
fi
# Remove old folders
rm -rf ./machines/*
# Create stress database
sudo -u postgres psql postgres -c "drop database if exists lamassu_stress"
sudo -u postgres psql postgres -c "create database lamassu_stress with template lamassu"
START=1
END=$1
for (( c=$START; c<=$END; c++ ))
do
echo "Creating machine $c out of $END..."
NUMBER=$c
mkdir -p ./machines/$NUMBER/
cp "$3"/data/client.sample.pem ./machines/$NUMBER/
cp "$3"/data/client.sample.key ./machines/$NUMBER/
cat > ./machines/$NUMBER/connection_info.json << EOL
{"host":"localhost","ca":"$SERVER_CERT"}
EOL
echo 'Generating certs...'
node ./utils/init-cert.js $NUMBER
# Get device_id
DEVICE_ID=`openssl x509 -outform der -in ./machines/$NUMBER/client.pem | sha256sum | cut -d " " -f 1`
# Update db config
NEW_CONFIG=$(node ./utils/save-config.js $NUMBER $DEVICE_ID)
sudo -u postgres psql "lamassu_stress" << EOF
insert into user_config(type, data, created, valid)
values('config', '$NEW_CONFIG', now(), 't')
EOF
# Add device on db
sudo -u postgres psql "lamassu_stress" << EOF
insert into devices(device_id, cashbox, cassette1, cassette2, paired, display, created, name, last_online, location)
values ('$DEVICE_ID', 0, 0, 0, 't', 't', now(), $NUMBER, now(), '{}'::json)
EOF
done
echo "Done!"

View file

@ -0,0 +1,32 @@
const exec = require('child_process').exec
/**
* Execute simple shell command (async wrapper).
* @param {String} cmd
* @return {Object} { stdout: String, stderr: String }
*/
function execCommand (cmd) {
return new Promise(function (resolve, reject) {
const proc = exec(cmd, (err, stdout, stderr) => {
if (err) {
reject(err)
} else {
resolve({ stdout, stderr })
}
})
proc.stdout.on('data', data => {
console.log(data)
})
proc.stderr.on('data', data => {
console.log(data)
})
proc.on('exit', code => {
console.log('child process exited with code ' + code.toString())
})
})
}
module.exports = { execCommand }

View file

@ -0,0 +1,7 @@
const cmd = require('./scripts')
process.on('message', async (msg) => {
console.log('Message from parent:', msg)
await cmd.execCommand(`node --prof LAMASSU_DB=STRESS_TEST ../../bin/lamassu-server`)
})

View file

@ -0,0 +1,2 @@
{"config":{"wallets_BTC_coin":"BTC","wallets_BTC_wallet":"mock-wallet","wallets_BTC_ticker":"mock-ticker","wallets_BTC_exchange":"mock-exchange","wallets_BTC_zeroConf":"all-zero-conf","locale_id":"32cc539a-78e6-4a1d-96d8-31b7aa628e1f","locale_country":"US","locale_fiatCurrency":"USD","locale_languages":["en-US"],"locale_cryptoCurrencies":["BTC"],"commissions_minimumTx":1,"commissions_fixedFee":1,"commissions_cashOut":1,"commissions_cashIn":1,"commissions_id":"719b9dd9-1444-42fc-918a-f8b2265513ac"}}

View file

@ -0,0 +1,5 @@
function randomIntFromInterval (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
module.exports = { randomIntFromInterval }

View file

@ -0,0 +1,12 @@
const path = require('path')
const variables = require('./variables')
const { init } = require(`../${variables.MACHINE_PATH}/lib/pairing`)
const number = process.argv[2]
const certPath = {
cert: path.resolve(process.cwd(), 'machines', number, 'client.pem'),
key: path.resolve(process.cwd(), 'machines', number, 'client.key')
}
init(certPath)

View file

@ -0,0 +1,3 @@
const config = require('./default-config.json')
console.log(JSON.stringify(config))

View file

@ -0,0 +1,7 @@
const SERVER_CERT_PATH = `../../certs/Lamassu_OP_Root_CA.pem`
const MACHINE_PATH = `../../../lamassu-machine`
// Request timers
const POLLING_INTERVAL = 5000
module.exports = { SERVER_CERT_PATH, MACHINE_PATH, POLLING_INTERVAL }