Repository: shardeum/shardeum
File: src/index.ts (TypeScript)

Code before:
  //make a trustless query which will check 3 random archivers and call the endpoint with hash=true
  let archiverList = getFinalArchiverList()
  archiverList = getRandom(archiverList, archiverList.length >= 3 ? 3 : archiverList.length)
  const values: {
    hash: string
    archiver: Archiver
  }[] = []
  for (const archiver of archiverList) {
    try {
      const res = await axios.get<{ networkAccountHash: string,
        sign: {
          owner: string,
          sig: string
        } 
      }>(
        `http://${archiver.ip}:${archiver.port}/get-network-account?hash=true`
      )
      if (!res.data) {
        /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: did not get network account from archiver private key. Use default configs.')
        throw new Error(`fetchNetworkAccountFromArchiver() from pk:${archiver.publicKey} returned null`)
      }
      const isFromArchiver = archiver.publicKey === res.data.sign.owner
      if (!isFromArchiver) {
        throw new Error(`The response signature is not the same from archiver pk:${archiver.publicKey}`)
      }
      const isResponseVerified = verify(res.data)
      if (!isResponseVerified) {
        throw new Error(`The response signature is not the same from archiver pk:${archiver.publicKey}`)
      }
      values.push({
        hash: res.data.networkAccountHash as string,
        archiver,
      })
    } catch (ex) {
      //dont let one bad archiver crash us !
      /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', `error: ${ex?.message}`)
    }
  }

  //make sure there was a majority winner for the hash
  const majorityValue = findMajorityResult(values, (v) => v.hash)
  if (!majorityValue) {
    /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: no majority found for archivers get-network-account result. Use default configs.')
    throw new Error(`no majority found for archivers get-network-account result `)
  }
  try {
    const res = await axios.get<{ networkAccount: WrappedAccount }>(
      `http://${majorityValue.archiver.ip}:${majorityValue.archiver.port}/get-network-account?hash=false`
    )
    if (!res.data) {
      /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: did not get network account from archiver private key, returned null. Use default configs.')

Review comment (suggestion):
We have the expected public key of the archiver from the archiver list. Please use this as the expected pk and do not trust the pk that is included in the returned object

const isResponseVerified = verify(res.data, archiver.publicKey)

Code after:
  //make a trustless query which will check 3 random archivers and call the endpoint with hash=true
  let archiverList = getFinalArchiverList()
  archiverList = getRandom(archiverList, archiverList.length >= 3 ? 3 : archiverList.length)
  const values: {
    hash: string
    archiver: Archiver
  }[] = []
  for (const archiver of archiverList) {
    try {
      const res = await axios.get<{ networkAccountHash: string,
        sign: {
          owner: string,
          sig: string
        } 
      }>(
        `http://${archiver.ip}:${archiver.port}/get-network-account?hash=true`
      )
      if (!res.data) {
        /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: did not get network account from archiver private key. Use default configs.')
        throw new Error(`fetchNetworkAccountFromArchiver() from pk:${archiver.publicKey} returned null`)
      }
      const isFromArchiver = archiver.publicKey === res.data.sign.owner
      if (!isFromArchiver) {
        throw new Error(`The response signature is not the same from archiver pk:${archiver.publicKey}`)
      }
      const isResponseVerified = verify(res.data, archiver.publicKey)
      if (!isResponseVerified) {
        throw new Error(`The response signature is not the same from archiver pk:${archiver.publicKey}`)
      }
      values.push({
        hash: res.data.networkAccountHash as string,
        archiver,
      })
    } catch (ex) {
      //dont let one bad archiver crash us !
      /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', `error: ${ex?.message}`)
    }
  }

  //make sure there was a majority winner for the hash
  const majorityValue = findMajorityResult(values, (v) => v.hash)
  if (!majorityValue) {
    /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: no majority found for archivers get-network-account result. Use default configs.')
    throw new Error(`no majority found for archivers get-network-account result `)
  }
  try {
    const res = await axios.get<{ networkAccount: WrappedAccount }>(
      `http://${majorityValue.archiver.ip}:${majorityValue.archiver.port}/get-network-account?hash=false`
    )
    if (!res.data) {
      /* prettier-ignore */ nestedCountersInstance.countEvent('network-config-operation', 'failure: did not get network account from archiver private key, returned null. Use default configs.')