import * as Level from 'level' ; import { BaseDB , DB , EthereumEventProcessor } from '@pigi/core-db' ; import { DefaultSignatureProvider , DefaultSignatureVerifier , getLogger , } from '@pigi/core-utils' ; import cors = require ( 'cors' ) ; import { Contract , Wallet } from 'ethers' ; import { JsonRpcProvider } from 'ethers/providers' ; import * as fs from 'fs' ; import { config } from 'dotenv' ; import { resolve } from 'path' ; config ( { path : resolve ( __dirname , `../../../../config/.env` ) } ) ; import * as RollupChain from '../../../build/contracts/RollupChain.json' ; import { Address , RollupStateMachine , State } from '../../types' ; import { DefaultRollupStateMachine , getGenesisState } from '../../common' ; import { DefaultRollupBlockSubmitter } from '../rollup-block-submitter' ; import { RollupAggregator } from '../rollup-aggregator' ; import { AggregatorServer } from '../aggregator-server' ; const log = getLogger ( 'unipig-aggregator' ) ; const rollupContractAddress = process . env . ROLLUP_CONTRACT_ADDRESS ; const aggregatorMnemonic = process . env . AGGREGATOR_MNEMONIC ; const jsonRpcUrl = process . env . JSON_RPC_URL ; const transitionsPerBlock = parseInt ( process . env . TRANSITIONS_PER_BLOCK || '10' , 10 ) ; const blockSubmissionIntervalMillis = parseInt ( process . env . BLOCK_SUBMISSION_INTERVAL_MILLIS || '300' , 10 ) ; const authorizedFaucetAddress = process . env . AUTHORIZED_FAUCET_ADDRESS ; const genesisStateFilePath = process . env . GENESIS_STATE_RELATIVE_FILE_PATH ; let genesisState ; if ( ! ! genesisStateFilePath ) { genesisState = JSON . parse ( fs . readFileSync ( resolve ( __dirname , genesisStateFilePath ) ) . toString ( 'utf-8' ) ) ; log . info ( `Loaded genesis state from ${ genesisStateFilePath }. ${ genesisState . length } balances loaded.` ) ; } else { log . info ( 'No genesis state provided!' ) ; } if ( ! rollupContractAddress || ! aggregatorMnemonic || ! jsonRpcUrl ) { throw Error ( 'Missing environment variables. Set them and try again.' ) ; } const host = '0.0.0.0' ; const port = 3000 ; async function runAggregator ( ) { const levelOptions = { keyEncoding : 'binary' , valueEncoding : 'binary' , } ; const stateDB = new BaseDB ( ( await Level ( 'build/level/state' , levelOptions ) ) as any ) ; const blockDB = new BaseDB ( ( await Level ( 'build/level/blocks' , levelOptions ) ) as any , 4 ) ; const aggregatorWallet = Wallet . fromMnemonic ( aggregatorMnemonic ) . connect ( new JsonRpcProvider ( jsonRpcUrl ) ) ; const rollupStateMachine = await DefaultRollupStateMachine . create ( getGenesisState ( aggregatorWallet . address , genesisState ) , stateDB , aggregatorWallet . address ) ; log . debug ( `Connecting to contract [${ rollupContractAddress }] at [${ jsonRpcUrl }]` ) ; const contract = new Contract ( rollupContractAddress , RollupChain . interface , aggregatorWallet ) ; const blockSubmitterDB = new BaseDB ( ( await Level ( 'build/level/blockSubmitter' , levelOptions ) ) as any , 256 ) ; const blockSubmitter = await DefaultRollupBlockSubmitter . create ( blockSubmitterDB , contract ) ; log . debug ( `Connected` ) ; const aggregator = await RollupAggregator . create ( blockDB , rollupStateMachine , blockSubmitter , new DefaultSignatureProvider ( aggregatorWallet ) , DefaultSignatureVerifier . instance ( ) , transitionsPerBlock , blockSubmissionIntervalMillis , authorizedFaucetAddress ) ; const blockProcessorDB = new BaseDB ( ( await Level ( 'build/level/blockProcessor' , levelOptions ) ) as any , 256 ) ; const processor = new EthereumEventProcessor ( blockProcessorDB ) ; await processor . subscribe ( contract , 'NewRollupBlock' , aggregator , true ) ; const aggregatorServer = new AggregatorServer ( aggregator , host , port , [ cors ] ) ; aggregatorServer . listen ( ) ; console . log ( 'Listening on' , host + ':' + port ) ; } runAggregator ( ) ;