Source: chain/server.js

'use strict';

const jayson = require('jayson');
const cors = require('cors');
const compression = require("compression");

const BeOnBlockChain = require("./BeOnBlockChain");
const Transaction = require("../lib/Transaction");
const config = require("./config");
const utils = require("../lib/utils");

const blockchain = new BeOnBlockChain(config);

/**
 * Returns all the blocks or a specific block
 * @param {string} [blkNum] the block number to return
 * @param {string} [fromBlkNum] the from block number to return
 * @param {string} [toBlkNum] the to block number to return
 */
const getBlocks = async (blkNum, fromBlkNum, toBlkNum) => {
  if (blkNum != 0 && !blkNum) {
    let blocks = await blockchain.db.getBlocks(false);
    return blocks.map(b => b.toJSON());
  }
  if (fromBlkNum && toBlkNum) {
    let blocks = await blockchain.db.getBlocksInRange(fromBlkNum, toBlkNum);
    return blocks.map(b => b.toJSON());
  }
  blkNum = blkNum || 0;
  let block = await blockchain.db.getBlock(blkNum);
  if (block) {
    return [block.toJSON()];
  }
  return [];
}
/**
 * Returns the latest block
 */
const getLatestBlock = async () => {
  let block = await blockchain.db.getLatestBlock();
  return block.toJSON();
}
/**
 * Returns current utxos
 */
const getUTXOs = async () => {
  return blockchain.getUTXO()
}
/**
 * Returns current pending txpools
 */
const getPendingTxs = async () => {
  return blockchain.getTXPool()
}

const getPendingExits = async () => {
  return blockchain.db.getPendingExits()
}

const getUTXOsByAddress = async (address) => {
  return blockchain.db.getUTXOsByAddress(address);
}

const getTxByHash = async (hash) => {
  return blockchain.db.getTxByHash(hash);
}

const getBlockByTxHash = async (hash) => {
  return blockchain.db.getBlockByTxHash(hash);
}

const getUTXO = async (blkNum, txIndex, oIndex) => {
  return blockchain.db.getUTXO(blkNum, txIndex, oIndex);
}

const getPendingTxsByAddress = async (address) => {

}
const getPendingExitsByAddress = async (address) => {

}

/**
 * Submit a confirm signature for transaction txIndex in block blkNum
 * @param {number} blkNum the block number
 * @param {number} txIndex the transaction index in the block blkNum
 * @param {string} confirmSignature the confirmation signature to use to confirm the transaction  in hex string, i.e., "0x..."
 */
const confirmTx = async (blkNum, txIndex, confirmSignature) => {
  let data = await blockchain.getTxHashRoot(blkNum, txIndex);
  let {
    txHash,
    root,
    sig1,
    sig2
  } = data;
  if (!blockchain.rootChain.isValidConfirmSig(txHash, root, sig1, confirmSignature)) {
    return {
      "status": "error",
      "error": "Confirmation signature is not valid"
    };
  }
  blockchain.setConfirmSignature(blkNum, txIndex, confirmSignature);
  return {
    "status": "OK"
  };
}

/**
 * Submit a confirm signature for transaction txIndex in block blkNum using the private key to sign for it
 * @param {number} blkNum the block number
 * @param {number} txIndex the transaction index in the block blkNum
 * @param {string} key the private key used to sign the confirmation in hex string, i.e., "0x..."
 */
const trustedConfirmTx = async (blkNum, txIndex, key) => {
  let confirmSignature = blockchain.generateConfirmSig(blkNum, txIndex, key);
  if (!confirmSignature) {
    return {
      "status": "error",
      "error": "Confirmation signature is not valid"
    };
  }
  blockchain.setConfirmSignature(blkNum, txIndex, confirmSignature);
  return {
    "status": "OK"
  };
}

/**
 * Submit a transaction by spending from to to for amount of token using the confirm signature and the from's private key to sign.
 * The confirm signature is optional if the input of the spending UTXO is owned by from
 * @param {string} [token="0x0000000000000000000000000000000000000000"] token address in hex string, i.e., "0x..."
 * @param {string} from from address in hex string, i.e., "0x..."
 * @param {string} to to address in hex string, i.e., "0x..."
 * @param {number} amount the amount to send
 * @param {string} [confirmSig] confirmation signature in hex string, i.e., "0x..."
 * @param {string} key private key of from in hex string, i.e., "0x..."
 */
const trustedTransact = async (token, from, to, amount, confirmSig, key) => {
  if (!token) {
    token = "0x0000000000000000000000000000000000000000";
  }
  let unsignedTx = await blockchain.createUnsignedTransaction(token, from, to, amount, confirmSig);
  let signature = blockchain.rootChain.signTransactionKey(unsignedTx.hash(), key);
  unsignedTx.setSignature(signature);
  let tx = await blockchain.submitTransaction(unsignedTx);
  return tx.toJSON()
}

/**
 * Create a transaction by spending from to to for amount of token using the confirm signature
 * To be signed before submitting
 * The confirm signature is optional if the input of the spending UTXO is owned by from
 * @param {string} [token="0x0000000000000000000000000000000000000000"] token address in hex string, i.e., "0x..."
 * @param {string} from from address in hex string, i.e., "0x..."
 * @param {string} to to address in hex string, i.e., "0x..."
 * @param {number} amount the amount to send
 * @param {string} [confirmSig] confirmation signature in hex string, i.e., "0x..."
 */
const transact = async (token, from, to, amount, confirmSig) => {
  if (!token) {
    token = "0x0000000000000000000000000000000000000000";
  }
  let unsignedTx = await blockchain.createUnsignedTransaction(token, from, to, amount, confirmSig);
  return unsignedTx.toJSON()
}

/**
 * Submit a signed transaction to Plasma chain
 * @param {json} signedTransaction  signed transaction json object from toJSON() function of the Transaction.
 */
const submitTransact = async (signedTransaction) => {
  console.log("signedTransaction", signedTransaction);
  let signedTx = Transaction.fromJSON(signedTransaction);
  console.log("signedTx", signedTx);
  let tx = await blockchain.submitTransaction(signedTx);
  return tx.toJSON();
}

/**
 * Submit a signed transaction to Ethereum chain
 * @param {string} signedTransaction signed transaction in hex string, i.e., "0x..."
 */
const submitSignedTransaction = async (signedTransaction) => {
  let result = await blockchain.rootChain.submitSignedTransaction(signedTransaction);
  return result;
}

/**
 * Create a deposit object to be signed with web3.eth.accounts.signTransaction and submit 
 * with submitSignedTransaction(signedTransaction)
 * @param {string} address from address in hex string, i.e., "0x..."
 * @param {string} token token address in hex string, i.e., "0x..."
 * @param {number} amount amount
 */
const deposit = async (address, token, amount) => {
  let result = await blockchain.rootChain.createDeposit(address, token, amount);
  return result;
}

/**
 * Deposit into the plasma chain from address with token of amount using the private key of the address
 * @param {string} address from address in hex string, i.e., "0x..."
 * @param {string} token token address in hex string, i.e., "0x..."
 * @param {number} amount amount
 * @param {string} key private key of address in hex string, i.e., "0x..."
 */
const trustedDeposit = async (address, token, amount, key) => {
  let result = await blockchain.rootChain.deposit(address, token, amount, key);
  return result;
}

/**
 * Create an object that start exiting the deposit from the plasma chain to be signed with web3.eth.accounts.signTransaction and submit with submitSignedTransaction(signedTransaction)
 * @param {number} blkNum the block number of the deposit transaction
 * @param {string} token token address in hex string, i.e., "0x..."
 * @param {number} amount amount
 * @param {string} from from address in hex string, i.e., "0x..."
 */
const startDepositExit = async (blkNum, token, amount, from) => {
  let depositPos = blkNum * 1000000000;
  const result = await blockchain.rootChain.createStartDepositWithdrawal(depositPos, token, amount, from);
  return {
    result,
    depositPos
  };
}

/**
 * Start exiting the deposit from the plasma chain 
 * @param {number} blkNum the block number of the deposit transaction
 * @param {string} token token address in hex string, i.e., "0x..."
 * @param {number} amount amount
 * @param {string} from from address in hex string, i.e., "0x..."
 * @param {string} key private key of from address in hex string, i.e., "0x..."
 */
const trustedStartDepositExit = async (blkNum, token, amount, from, key) => {
  let depositPos = blkNum * 1000000000;
  const result = await blockchain.rootChain.startDepositWithdrawal(depositPos, token, amount, from, key);
  return {
    result,
    depositPos
  };
}

/**
 * Start exiting the plasma chain object to be signed with web3.eth.accounts.signTransaction and submit with 
 * @param {number} blkNum the block number of the utxo to exit
 * @param {number} txIndex the transaction index of the utxo to exit
 * @param {number} oIndex the output index of the utxo to exit [0,1]
 * @param {string} from from address in hex string, i.e., "0x..."
 * @param {string} [confirmSigs] confirm signature from the owner of the input utxo in hex string, i.e., "0x..."
 */
const startExit = async (blkNum, txIndex, oIndex, from, confirmSigs) => {
  blkNum = +blkNum;
  txIndex = +txIndex;
  oIndex = +oIndex;
  let utxoPos = blkNum * 1000000000 + txIndex * 10000 + oIndex;

  const p = await blockchain.getTransactionProofInBlock(blkNum, txIndex);
  let txData = p.tx;
  let block = await blockchain.db.getBlock(blkNum);
  confirmSigs = confirmSigs || block.confirmations[txIndex];

  // if (!confirmSigs) {
  //   let tx = Transaction.fromTxData(txData);
  //   let block1 = await blockchain.db.getBlock(tx.blkNum1);
  //   let block2 = await blockchain.db.getBlock(tx.blkNum2);
  //   console.log("1",tx.blkNum1, tx.txIndex1, tx.oIndex1);
  //   console.log("2",tx.blkNum2, tx.txIndex2, tx.oIndex2);
  //   confirmSigs = utils.concatHex(block1.confirmations[tx.txIndex1], block2.confirmations[tx.txIndex2]);
  // }

  // console.log(confirmSigs.length, confirmSigs);
  let proof = p.proof;
  const result = await blockchain.rootChain.createStartWithdrawal(blkNum, txIndex, oIndex, txData, proof, confirmSigs, from);
  return {
    result,
    utxoPos
  };
}

/**
 * Exit immediately
 * Child chain checks the validity of the withdraw by seeing if the utxo exists.
 * Child chain creates a withdrawal transaction on the chain and then submit immediate withdrawal to Ethereum main chain
 */
const immediateExit = async () => {

}

/**
 * Start exiting the plasma chain 
 * @param {number} blkNum the block number of the utxo to exit
 * @param {number} txIndex the transaction index of the utxo to exit
 * @param {number} oIndex the output index of the utxo to exit [0,1]
 * @param {string} [confirmSigs] confirm signature from the owner of the input utxo in hex string, i.e., "0x..."
 * @param {string} from from address in hex string, i.e., "0x..."
 * @param {string} key private key of from address in hex string, i.e., "0x..."
 */
const trustedStartExit = async (blkNum, txIndex, oIndex, confirmSigs, from, key) => {
  blkNum = +blkNum
  oIndex = +oIndex
  txIndex = +txIndex
  let utxoPos = blkNum * 1000000000 + txIndex * 10000 + oIndex;
  let block = await blockchain.db.getBlock(blkNum);
  confirmSigs = confirmSigs || block.confirmations[txIndex];
  const p = await blockchain.getTransactionProofInBlock(blkNum, txIndex);
  let txData = p.tx;
  let proof = p.proof;
  const result = await blockchain.rootChain.startWithdrawal(blkNum, txIndex, oIndex, txData, proof, confirmSigs, from, key);
  return {
    result,
    utxoPos
  };
}

/**
 * Challenge and exit  object to be signed with web3.eth.accounts.signTransaction and submit with 
 * @param {number} eUtxoPos the eUtxoPos of the exit that you are challenging
 * @param {number} blkNum the block number of the utxo to exit used to proof
 * @param {number} txIndex the transaction index of the utxo to exit used to proof
 * @param {number} oIndex the output index of the utxo to exit [0,1] used to proof
 * @param {string} [confirmSig] confirm signature from the owner of the input utxo in hex string, i.e., "0x..."
 * @param {string} from from address in hex string, i.e., "0x..."
 */
const challengeExit = async (eUtxoPos, blkNum, txIndex, oIndex, confirmSig, from) => {
  let block = await blockchain.db.getBlock(blkNum);
  confirmSig = confirmSig || block.confirmations[txIndex];
  const p = await blockchain.getTransactionProofInBlock(blkNum, txIndex);
  let txData = p.tx;
  let proof = p.proof;

  let result = await blockchain.rootChain.createChallengeWithdrawal(eUtxoPos, blkNum,
    txIndex, oIndex, txData, proof, confirmSig, from);
  return {
    result
  };
}

/**
 * Challenge and exit
 * @param {number} eUtxoPos the eUtxoPos of the exit that you are challenging
 * @param {number} blkNum the block number of the utxo to exit used to proof
 * @param {number} txIndex the transaction index of the utxo to exit used to proof
 * @param {number} oIndex the output index of the utxo to exit [0,1] used to proof
 * @param {string} [confirmSig] confirm signature from the owner of the input utxo in hex string, i.e., "0x..."
 * @param {string} address address in hex string, i.e., "0x..."
 * @param {string} key private key of address in hex string, i.e., "0x..."
 */
const trustedChallengeExit = async (eUtxoPos, blkNum, txIndex, oIndex, confirmSig, address, key) => {
  let block = await blockchain.db.getBlock(blkNum);
  confirmSig = confirmSig || block.confirmations[txIndex];
  const p = await blockchain.getTransactionProofInBlock(blkNum, txIndex);
  let txData = p.tx;
  let proof = p.proof;

  let result = await blockchain.rootChain.challengeWithdrawal(eUtxoPos, blkNum,
    txIndex, oIndex, txData, proof, confirmSig, address, key);
  return {
    result
  };
}

/**
 * Finalize exit using from address and its private key object to be signed with web3.eth.accounts.signTransaction and submit with 
 * @param {string} address address in hex string, i.e., "0x..."
 */
const finalizeExit = async (address) => {
  let result = await blockchain.rootChain.createFinalizeWithdrawal(address);
  return {
    result
  };
}

/**
 * Finalize exit using from address and its private key
 * @param {string} address address in hex string, i.e., "0x..."
 * @param {string} key private key of address in hex string, i.e., "0x..."
 */
const trustedFinalizeExit = async (address, key) => {
  let result = await blockchain.rootChain.finalizeWithdrawal(address, key);
  return {
    result
  };
}

const getUnconfirmedConfirmationHashes = async (address) => {
  let result = await blockchain.db.getUnconfirmedConfirmationHashes(address);
  return {
    result
  };
}

const getUnconfirmedTransactions = async (address) => {
  let result = await blockchain.db.getUnconfirmedTransactions(address);
  return {
    result
  };
}

const connect = require('connect');
const jsonParser = require('body-parser').json;
const app = connect();

// create a server
var server = jayson.server({
  challengeExit: async (args, callback) => {
    try {
      let {
        eUtxoPos,
        blkNum,
        txIndex,
        oIndex,
        address
      } = args;
      let result = await challengeExit(eUtxoPos, blkNum, txIndex, oIndex, address);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedChallengeExit: async (args, callback) => {
    try {
      let {
        eUtxoPos,
        blkNum,
        txIndex,
        oIndex,
        address,
        key
      } = args;
      let result = await trustedChallengeExit(eUtxoPos, blkNum, txIndex, oIndex, address, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  confirmTx: async (args, callback) => {
    try {
      let {
        blkNum,
        txIndex,
        confirmSignature
      } = args;
      let result = await confirmTx(blkNum, txIndex, confirmSignature);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  finalizeExit: async (args, callback) => {
    try {
      let {
        address
      } = args;
      let result = await finalizeExit(address);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedFinalizeExit: async (args, callback) => {
    try {
      let {
        address,
        key
      } = args;
      let result = await trustedFinalizeExit(address, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  startDepositExit: async (args, callback) => {
    try {
      let {
        blkNum,
        token,
        amount,
        from
      } = args;
      let result = await startDepositExit(blkNum, token, amount, from);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedStartDepositExit: async (args, callback) => {
    try {
      let {
        blkNum,
        token,
        amount,
        from,
        key
      } = args;
      let result = await trustedStartDepositExit(blkNum, token, amount, from, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  startExit: async (args, callback) => {
    try {
      let {
        blkNum,
        txIndex,
        oIndex,
        from,
        confirmSigs
      } = args;
      let result = await startExit(blkNum, txIndex, oIndex, from, confirmSigs);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedStartExit: async (args, callback) => {
    try {
      let {
        blkNum,
        txIndex,
        oIndex,
        from,
        confirmSigs,
        key
      } = args;
      let result = await trustedStartExit(blkNum, txIndex, oIndex, from, confirmSigs, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  submitTransact: async (args, callback) => {
    try {
      let {
        signedTransaction
      } = args;
      let result = await submitTransact(signedTransaction);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  submitSignedTransaction: async (args, callback) => {
    try {
      let {
        signedTransaction
      } = args;
      let result = await submitSignedTransaction(signedTransaction);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  transact: async (args, callback) => {
    try {
      let {
        token,
        from,
        to,
        amount,
        confirmSig
      } = args;
      let result = await transact(token, from, to, amount, confirmSig);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedConfirmTx: async (args, callback) => {
    try {
      let {
        blkNum,
        txIndex,
        key
      } = args;
      let result = await trustedConfirmTx(blkNum, txIndex, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  deposit: async (args, callback) => {
    try {
      let {
        address,
        token,
        amount
      } = args;
      let result = await deposit(address, token, amount);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedDeposit: async (args, callback) => {
    try {
      let {
        address,
        token,
        amount,
        key
      } = args;
      let result = await trustedDeposit(address, token, amount, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  trustedTransact: async (args, callback) => {
    try {
      let {
        token,
        from,
        to,
        amount,
        confirmSig,
        key
      } = args;
      let result = await trustedTransact(token, from, to, amount, confirmSig, key);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getLatestBlock: async (args, callback) => {
    try {
      let result = await getLatestBlock();
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getPendingExits: async (args, callback) => {
    try {
      // let {
      //   blkNum,
      //   fromBlkNum,
      //   toBlkNum
      // } = args;
      let result = await getPendingExits();
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getBlocks: async (args, callback) => {
    try {
      let {
        blkNum,
        fromBlkNum,
        toBlkNum
      } = args;
      let result = await getBlocks(blkNum, fromBlkNum, toBlkNum);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getUTXOs: async (args, callback) => {
    try {
      let result = await getUTXOs();
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getPendingTxs: async (args, callback) => {
    try {
      let result = await getPendingTxs();
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getUTXOsByAddress: async (args, callback) => {
    try {
      let {
        address
      } = args;
      let result = await getUTXOsByAddress(address);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getUTXO: async (args, callback) => {
    try {
      let {
        blkNum,
        txIndex,
        oIndex
      } = args;
      let result = await getUTXO(blkNum, txIndex, oIndex);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }

  },
  getTxByHash: async (args, callback) => {
    try {
      let {
        hash
      } = args;
      let result = await getTxByHash(hash);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getBlockByTxHash: async (args, callback) => {
    try {
      let {
        hash
      } = args;
      let result = await getBlockByTxHash(hash);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getUnconfirmedTransactions: async (args, callback) => {
    try {
      let {
        address
      } = args;
      let result = await getUnconfirmedTransactions(address);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
  getUnconfirmedConfirmationHashes: async (args, callback) => {
    try {
      let {
        address
      } = args;
      let result = await getUnconfirmedConfirmationHashes(address);
      callback(null, {
        "status": "ok",
        "result": result,
      });
    } catch (e) {
      console.log(e);
      callback(null, {
        "status": "error",
        "error": e.message,
      });
    }
  },
});

app.use(compression({
  level: 9
}));
app.use(cors({
  methods: ['POST', 'GET']
}));
app.use(jsonParser());
app.use(server.middleware());

const start = async function () {
  await blockchain.connect()
  blockchain.startMining();
  app.listen(process.env.PORT || 3001);
}

start();