All files / src/genesisBlock resolveGenesisBlocks.js

93.62% Statements 44/47
85.71% Branches 12/14
91.67% Functions 11/12
93.48% Lines 43/46
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 1293x             3x 3x   3x   3x 15x 15x     15x 31x     15x       15x           16x 9x 9x     15x     3x 12x 38x             3x 15x 22x 22x           3x 15x 9x     6x     6x       17x 17x 15x         2x         6x           3x 31x     31x       31x         31x 31x       31x 31x                           31x 31x     3x        
const interbit = require('interbit-core')
 
const {
  config: {
    selectors: { getChains, getChainValidators, getAdminValidators }
  },
  constants: { ROOT_CHAIN_ALIAS }
} = require('interbit-covenant-tools')
const { getChainId } = require('./genesisBlockSelectors')
 
const log = require('../log')
 
const resolveGenesisBlocks = (config, originalManifest, covenants) => {
  const chainsConfig = getChains(config)
  const resolvedChainAliases = originalManifest
    ? Object.keys(originalManifest.chains)
    : []
  const unresolvedChainConfigs = Object.entries(chainsConfig).filter(
    ([chainAlias]) => resolvedChainAliases.indexOf(chainAlias) === -1
  )
 
  Iif (!unresolvedChainConfigs) {
    return originalManifest.genesisBlocks
  }
 
  const newlyResolvedChains = resolveChains(
    unresolvedChainConfigs,
    covenants,
    config
  )
 
  if (!resolvedChainAliases.find(alias => alias === ROOT_CHAIN_ALIAS)) {
    const rootGenesisBlock = createGenesisBlock(ROOT_CHAIN_ALIAS, config)
    newlyResolvedChains[ROOT_CHAIN_ALIAS] = rootGenesisBlock
  }
 
  return mergeResolutions(config, originalManifest, newlyResolvedChains)
}
 
const resolveChainIds = genesisBlocks =>
  Object.entries(genesisBlocks).reduce(
    (prev, [chainAlias, genesisBlock]) => ({
      ...prev,
      [chainAlias]: getChainId(genesisBlock)
    }),
    {}
  )
 
const resolveChains = (unresolvedChains, covenants, config) =>
  unresolvedChains.reduce((prev, [chainAlias, chainConfig]) => {
    const genesisBlock = createGenesisBlock(chainAlias, config)
    return {
      ...prev,
      [chainAlias]: genesisBlock
    }
  }, {})
 
const mergeResolutions = (config, originalManifest, newlyResolvedChains) => {
  if (!originalManifest) {
    return newlyResolvedChains
  }
 
  const configuredChains = Object.keys(getChains(config)).concat(
    ROOT_CHAIN_ALIAS
  )
  const resolvedChains = configuredChains.reduce(
    (prev, configuredChainAlias) => {
      // if the chain is configured include it
      const configuredGenesisBlock =
        originalManifest.genesisBlocks[configuredChainAlias]
      if (configuredGenesisBlock) {
        return {
          ...prev,
          [configuredChainAlias]: configuredGenesisBlock
        }
      }
      return prev
    },
    {}
  )
 
  return {
    ...newlyResolvedChains,
    ...resolvedChains
  }
}
 
const createGenesisBlock = (chainAlias, config) => {
  log.info(`BUILDING GENESIS FOR ${chainAlias}`)
 
  const validators =
    chainAlias === ROOT_CHAIN_ALIAS
      ? getAdminValidators(config)
      : getChainValidators(chainAlias, config)
 
  Iif (!validators.length) {
    throw new Error(
      `interbit build: Error building manifest. No validators specified for "${chainAlias}" chain`
    )
  }
  const blockMaster = validators[0]
  let configBuilder = interbit
    .genesisConfigBuilder()
    .setBlockMaster({ blockMaster })
 
  validators
    .filter(validator => validator !== blockMaster)
    .forEach(validator => {
      configBuilder = configBuilder.addRootKey({ rootKey: validator })
    })
 
  // NOTE: We cannot add joins here because they are a two way operation and both
  // side requires the other's chain ID to resolve its join. This means that the
  // genesis block for the other has to have been created but it can't have been
  // created unless the other side has resolved its genesis block which means...
  // ... deploy will have to do the the joining
 
  // NOTE: Might not be the right idea to include covenant hash in here per #258 #218 #267
  // ... try it and see if it messes with the chain IDs and it's better to apply the
  // covenants in the watcher
  const builtConfig = configBuilder.build()
  return interbit.createGenesisBlock({ config: builtConfig })
}
 
module.exports = {
  resolveGenesisBlocks,
  resolveChainIds
}