import { DB } from '@pigi/core-db' ; import { BigNumber , getLogger , logError , ONE , runInDomain , } from '@pigi/core-utils' ; import * as AsyncLock from 'async-lock' ; import * as domain from 'domain' ; import { SignedTransaction , RollupStateMachine , State , TransactionResult , TransactionStorage , } from '../types' ; import { NON_EXISTENT_SLOT_INDEX } from './utils' ; const log = getLogger ( 'rollup-state-machine' ) ; /**
 * A Rollup State Machine, facilitating state transitions and transactions for Optimistic Rollup.
 */ export class DefaultRollupStateMachine implements RollupStateMachine { private static readonly NEXT_TRANSACTION_NUMBER_KEY : Buffer = Buffer . from ( 'tx_num' ) ; private static readonly lockKey : string = 'lock' ; private static readonly emptyState : State = { slotIndex : NON_EXISTENT_SLOT_INDEX , balances : { } , } ; private readonly lock : AsyncLock ; private nextTransactionNumber : BigNumber ; param db returns public static async create ( db ) { const rsm = new DefaultRollupStateMachine ( db ) ; await rsm . init ( ) ; return rsm ; } private constructor ( private readonly db ) { this . lock = new AsyncLock ( { domainReentrant : true , } ) ; this . nextTransactionNumber = ONE ; } /**
     * Initializes the RollupStateMachine, loading necessary member variables from storage
     */ private async init ( ) { const nextTxNumBuffer = await this . db . get ( DefaultRollupStateMachine . NEXT_TRANSACTION_NUMBER_KEY ) ; if ( ! nextTxNumBuffer ) { log . info ( `No stored transaction number found. Starting fresh.` ) ; return ; } this . nextTransactionNumber = new BigNumber ( nextTxNumBuffer ) ; log . info ( `Initialized State Machine from DB with next transaction number ${ this . nextTransactionNumber . toString ( ) }` ) ; } public async getState ( slotIndex ) { return { } ; } public async applyTransaction ( signedTransaction , d ? ) { return runInDomain ( d , async ( ) => { log . debug ( `Acquiring lock to apply transaction: ${ JSON . stringify ( signedTransaction ) }` ) ; return this . lock . acquire ( DefaultRollupStateMachine . lockKey , async ( ) => { log . debug ( `Lock acquired. Applying transaction: ${ JSON . stringify ( signedTransaction ) }` ) ; const result = { signedTransaction } ; const modifiedStorage = [ ] ; const transactionResult = { transactionNumber : this . nextTransactionNumber , signedTransaction , modifiedStorage , } ; this . nextTransactionNumber = this . nextTransactionNumber . add ( ONE ) ; try { await this . db . put ( DefaultRollupStateMachine . NEXT_TRANSACTION_NUMBER_KEY , this . nextTransactionNumber . toBuffer ( ) ) ; } catch ( e ) { logError ( log , `Transaction succeeded. Failed to update next transaction number to [${ this . nextTransactionNumber . toString ( ) }].` , e ) ; throw e ; } return transactionResult ; } ) ; } ) ; } public async getTransactionResultsSince ( transactionNumber ) { return [ ] ; } }