UNPKG

navio-blsct

Version:

TypeScript bindings for the `libblsct` library used by the [Navio](https://nav.io/) blockchain to construct confidential transactions based on the BLS12-381 curve.

273 lines (237 loc) 8.18 kB
const fs = require('fs') const os = require('os') const path = require('path') const { spawnSync } = require('child_process') // TODO: turn this on for production builds const IS_PROD = false const DEV_BRANCH = 'add-missing-functionality' // git ls-remote https://github.com/nav-io/navio-core.git refs/heads/master const MASTER_SHA = '3f7805c30db897c787b9cae50a013f9c8cd20086' const getCfg = (isProd) => { baseDir = path.resolve(__dirname, '..') swigDir = path.join(baseDir, 'swig') navioCoreDir = path.join(baseDir, 'navio-core') dependsDir = path.join(navioCoreDir, 'depends') libsDir = path.join(baseDir, 'libs') bakDir = path.join(os.homedir(), '.navio-tmp') dependsBakDir = path.join(bakDir, 'depends') srcPath = path.join(navioCoreDir, "src") blsPath = path.join(srcPath, "bls") blsLibPath = path.join(blsPath, "lib") mclPath = path.join(blsPath, "mcl") mclLibPath = path.join(mclPath, "lib") const srcDotAFiles = [ path.join(srcPath, "libblsct.a"), path.join(srcPath, "libunivalue_blsct.a"), path.join(blsLibPath, "libbls384_256.a"), path.join(mclLibPath, "libmcl.a"), ] const destDotAFiles = [ path.join(libsDir, "libblsct.a"), path.join(libsDir, "libunivalue_blsct.a"), path.join(libsDir, "libbls384_256.a"), path.join(libsDir, "libmcl.a"), ] return { swigDir, stdCpp: '-std=c++20', navioCoreRepo: isProd ? 'https://github.com/nav-io/navio-core' : 'https://github.com/gogoex/navio-core', navioCoreMasterSha: isProd ? MASTER_SHA : '', navioCoreBranch: isProd ? '' : DEV_BRANCH, navioCoreDir, dependsDir, dependsBakDir, srcDotAFiles, destDotAFiles, libsDir, } } const exec = (cmd) => { const isRoot = process.getuid && process.getuid() === 0 if (!isRoot) { cmd = ['sudo', ...cmd] } const res = spawnSync(cmd[0], cmd.slice(1), { stdio: 'inherit' }) if (res.status !== 0) { throw new Error(`Failed to execute ${cmd.join(' ')}: ${JSON.stringify(res)}`) } } const detectPkgManager = () => { const exists = (cmd) => { const res = spawnSync('which', [cmd]) return res.status === 0 } if (exists('apt-get')) { return 'apt-get' } else { return undefined } } const installSystemDeps = () => { const platform = os.platform() console.log(`Platform: ${platform}`) if (platform === 'darwin') { console.log('Installing system dependencies w/ brew...') spawnSync('brew', ['install', 'swig', 'autoconf', 'automake', 'libtool', 'pkg-config', 'git']) } else if (platform === 'linux') { const pm = detectPkgManager() if (pm !== undefined) { console.log(`Installing system dependencies w/ ${pm}...`) if (pm === 'apt-get') { exec(['apt-get', 'update']) exec(['apt-get', 'install', '-y', 'swig', 'autoconf', 'automake', 'libtool', 'pkg-config', 'git', 'python3', 'build-essential']) } else { // should not be reached } } else { console.log('No supported package manager found') } } else { console.log(`Unsupported platform: ${platform}`) } } const getDepArchDir = (dependsDir) => { if (!fs.existsSync(dependsDir)) { throw new Error(`${dependsDir} not found`) } const arches = [ 'x86_64', 'i686', 'mips', 'arm', 'aarch64', 'powerpc', 'riscv32', 'riscv64', 's390x' ] const files = fs.readdirSync(dependsDir, { withFileTypes: true }) for (const file of files) { if ( file.isDirectory() && arches.some(arch => file.name.startsWith(arch)) ) { console.log(`Found dependency arch dir: ${file.name}`) return path.resolve(dependsDir, file.name) } } throw new Error(`Failed to find dependency arch dir in ${dependsDir}`) } const gitCloneNavioCore = (cfg) => { // Remove existing directory if (fs.existsSync(cfg.navioCoreDir)) { fs.rmSync(cfg.navioCoreDir, { recursive: true, force: true }) console.log(`Removed exisitng navio-core dir`) } else { console.log(`No existing navio-core dir found`) } const cmd = ['git', 'clone', '--depth', '1'] if (cfg.navioCoreBranch !== '') { cmd.push('--branch', cfg.navioCoreBranch) console.log(`Using navio-core ${cfg.navioCoreBranch} branch...`) } else { console.log(`Using navio-core master branch...`) } cmd.push(cfg.navioCoreRepo, cfg.navioCoreDir) const res = spawnSync(cmd[0], cmd.slice(1)) if (res.status !== 0) { throw new Error(`${cmd.join(' ')} failed: ${JSON.stringify(res)}`) } console.log(`Cloned navio-core`) if (cfg.navioCoreMasterSha !== '') { const cwd = cfg.navioCoreDir { const cmd = ['git', 'fetch', '--depth', '1', 'origin', cfg.navioCoreMasterSha] const res = spawnSync(cmd[0], cmd.slice(1), { cwd }) if (res.status !== 0) { throw new Error(`${cmd.join(' ')} failed: ${JSON.stringify(res)}`) } console.log(`Fetched navio-core commit ${cfg.navioCoreMasterSha}`) } { const cmd = ['git', 'checkout', cfg.navioCoreMasterSha] const res = spawnSync(cmd[0], cmd.slice(1), { cwd }) if (res.status !== 0) { throw new Error(`${cmd.join(' ')} failed: ${JSON.stringify(res)}`) } console.log(`Checked out navio-core commit ${cfg.navioCoreMasterSha}`) } } } const buildDepends = (cfg, numCpus) => { if (fs.existsSync(cfg.dependsBakDir)) { console.log('Copying the backup of dependency dir...') fs.cpSync(cfg.dependsBakDir, cfg.dependsDir, { recursive: true }) } else { console.log('Building navio-core dependencies...') const res = spawnSync('make', ['-j', numCpus], { cwd: cfg.dependsDir }) if (res.status !== 0) { throw new Error(`Failed to build dependencies: ${JSON.stringify(res)}`) } console.log('Creating backup of depends dir...') fs.cpSync(cfg.dependsDir, cfg.dependsBakDir, { recursive: true }) } return getDepArchDir(cfg.dependsDir) } const buildLibBlsct = (cfg, numCpus, depArchDir) => { // run autogen.sh console.log('Running autogen.sh...') const autogenRes = spawnSync('./autogen.sh', [], { cwd: cfg.navioCoreDir }) if (autogenRes.status !== 0) { throw new Error(`autogen.sh failed: ${JSON.stringify(autogenRes)}`) } // run configure console.log(`Running configure...`) const configureRes = spawnSync('./configure', [ `--prefix=${depArchDir}`, '--enable-build-libblsct-only' ], { cwd: cfg.navioCoreDir, }) if (configureRes.status !== 0) { throw new Error(`Running configure failed: ${JSON.stringify(configureRes)}`) } // build libblsct console.log('Building libblsct...') const makeRes = spawnSync('make', ['-j', numCpus], { cwd: cfg.navioCoreDir, }) if (makeRes.status !== 0) { throw new Error(`Building libblsct failed: ${JSON.stringify(makeRes)}`) } // prepare a fresh backup dir if (fs.existsSync(cfg.libsDir)) { fs.rmSync(cfg.libsDir, { recursive: true, force: true }) } fs.mkdirSync(cfg.libsDir, { recursive: true }) // copy .a files to the libs dir const src_dest = cfg.srcDotAFiles.map((src, i) => [src, cfg.destDotAFiles[i]]); for(const [src, dest] of src_dest) { console.log(`Copying ${src} to ${dest}...`) fs.copyFileSync(src, dest) } } const buildSwigWrapper = (cfg) => { console.log('Building swig wrapper...') const res = spawnSync( 'swig', ['-c++', '-javascript', '-node', 'blsct.i'], { cwd: cfg.swigDir } ) if (res.status !== 0) { throw new Error(`Failed to build swig wrapper: ${JSON.stringify(res)}`) } } const main = () => { const cfg = getCfg(IS_PROD) const numCpus = os.cpus().length installSystemDeps() gitCloneNavioCore(cfg) // if .a files have been built, copy them from the backup dir if (cfg.destDotAFiles.every(file => fs.existsSync(file))) { const src_dest = cfg.srcDotAFiles.map((src, i) => [src, cfg.destDotAFiles[i]]); for(const [src, dest] of src_dest) { console.log(`Copying ${dest} to ${src}...`) fs.copyFileSync(dest, src) } } // otherwise, build them and create backups else { depArchDir = buildDepends(cfg, numCpus) buildLibBlsct(cfg, numCpus, depArchDir) } buildSwigWrapper(cfg) } main()