Update ALM logic to continue displaying failed signatures from validators (#399)
This commit is contained in:
parent
efc433e9e0
commit
dc060387bc
@ -313,7 +313,7 @@ export const useMessageConfirmations = ({
|
|||||||
// Sets the message status based in the collected information
|
// Sets the message status based in the collected information
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
if (executionData.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS) {
|
if (executionData.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS && existsConfirmation(confirmations)) {
|
||||||
const newStatus = executionData.executionResult
|
const newStatus = executionData.executionResult
|
||||||
? CONFIRMATIONS_STATUS.SUCCESS
|
? CONFIRMATIONS_STATUS.SUCCESS
|
||||||
: CONFIRMATIONS_STATUS.SUCCESS_MESSAGE_FAILED
|
: CONFIRMATIONS_STATUS.SUCCESS_MESSAGE_FAILED
|
||||||
|
@ -33,7 +33,7 @@ export class BlockNumberProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
this.running = this.running - 1
|
this.running = this.running > 0 ? this.running - 1 : 0
|
||||||
|
|
||||||
if (!this.running) {
|
if (!this.running) {
|
||||||
clearTimeout(this.ref)
|
clearTimeout(this.ref)
|
||||||
|
@ -105,13 +105,13 @@ describe('getConfirmationsForTx', () => {
|
|||||||
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
|
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
|
||||||
expect(setSignatureCollected).toBeCalledTimes(1)
|
expect(setSignatureCollected).toBeCalledTimes(1)
|
||||||
|
|
||||||
expect(getValidatorFailedTransaction).toBeCalledTimes(0)
|
expect(getValidatorFailedTransaction).toBeCalledTimes(1)
|
||||||
expect(setFailedConfirmations).toBeCalledTimes(0)
|
expect(setFailedConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
expect(getValidatorPendingTransaction).toBeCalledTimes(0)
|
expect(getValidatorPendingTransaction).toBeCalledTimes(0)
|
||||||
expect(setPendingConfirmations).toBeCalledTimes(0)
|
expect(setPendingConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
expect(setResult.mock.calls[0][0]).toEqual(
|
expect(setResult.mock.calls[0][0]()).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
@ -243,13 +243,13 @@ describe('getConfirmationsForTx', () => {
|
|||||||
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
|
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
|
||||||
expect(setSignatureCollected).toBeCalledTimes(1)
|
expect(setSignatureCollected).toBeCalledTimes(1)
|
||||||
|
|
||||||
expect(getValidatorFailedTransaction).toBeCalledTimes(0)
|
expect(getValidatorFailedTransaction).toBeCalledTimes(1)
|
||||||
expect(setFailedConfirmations).toBeCalledTimes(0)
|
expect(setFailedConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
expect(getValidatorPendingTransaction).toBeCalledTimes(0)
|
expect(getValidatorPendingTransaction).toBeCalledTimes(0)
|
||||||
expect(setPendingConfirmations).toBeCalledTimes(0)
|
expect(setPendingConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
expect(setResult.mock.calls[0][0]).toEqual(
|
expect(setResult.mock.calls[0][0]()).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
@ -264,6 +264,93 @@ describe('getConfirmationsForTx', () => {
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
test('should set validator confirmations status, validator transactions, keep failed found transaction and not retry', async () => {
|
||||||
|
const validator4 = '0x9d2dC11C342F4eF3C5491A048D0f0eBCd2D8f7C3'
|
||||||
|
const validatorList = [validator1, validator2, validator3, validator4]
|
||||||
|
getValidatorConfirmation.mockImplementation(() => async (validator: string) => ({
|
||||||
|
validator,
|
||||||
|
status:
|
||||||
|
validator !== validator3 && validator !== validator4
|
||||||
|
? VALIDATOR_CONFIRMATION_STATUS.SUCCESS
|
||||||
|
: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
||||||
|
}))
|
||||||
|
getValidatorSuccessTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({
|
||||||
|
validator: validatorData.validator,
|
||||||
|
status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS,
|
||||||
|
txHash: validatorData.validator !== validator3 && validatorData.validator !== validator4 ? '0x123' : '',
|
||||||
|
timestamp: validatorData.validator !== validator3 && validatorData.validator !== validator4 ? 123 : 0
|
||||||
|
}))
|
||||||
|
getValidatorFailedTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({
|
||||||
|
validator: validatorData.validator,
|
||||||
|
status:
|
||||||
|
validatorData.validator === validator3
|
||||||
|
? VALIDATOR_CONFIRMATION_STATUS.FAILED
|
||||||
|
: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
|
||||||
|
txHash: validatorData.validator === validator3 ? '0x123' : '',
|
||||||
|
timestamp: validatorData.validator === validator3 ? 123 : 0
|
||||||
|
}))
|
||||||
|
getValidatorPendingTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({
|
||||||
|
validator: validatorData.validator,
|
||||||
|
status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
|
||||||
|
txHash: '',
|
||||||
|
timestamp: 0
|
||||||
|
}))
|
||||||
|
|
||||||
|
const setResult = jest.fn()
|
||||||
|
const setSignatureCollected = jest.fn()
|
||||||
|
const setFailedConfirmations = jest.fn()
|
||||||
|
const setPendingConfirmations = jest.fn()
|
||||||
|
|
||||||
|
await getConfirmationsForTx(
|
||||||
|
messageData,
|
||||||
|
web3,
|
||||||
|
validatorList,
|
||||||
|
bridgeContract,
|
||||||
|
confirmationContractMethod,
|
||||||
|
setResult,
|
||||||
|
requiredSignatures,
|
||||||
|
setSignatureCollected,
|
||||||
|
waitingBlocksResolved,
|
||||||
|
subscriptions,
|
||||||
|
timestamp,
|
||||||
|
getFailedTransactions,
|
||||||
|
setFailedConfirmations,
|
||||||
|
getPendingTransactions,
|
||||||
|
setPendingConfirmations,
|
||||||
|
getSuccessTransactions
|
||||||
|
)
|
||||||
|
|
||||||
|
unsubscribe()
|
||||||
|
|
||||||
|
expect(subscriptions.length).toEqual(0)
|
||||||
|
expect(setResult).toBeCalledTimes(2)
|
||||||
|
expect(getValidatorConfirmation).toBeCalledTimes(1)
|
||||||
|
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
|
||||||
|
expect(setSignatureCollected).toBeCalledTimes(1)
|
||||||
|
|
||||||
|
expect(getValidatorFailedTransaction).toBeCalledTimes(1)
|
||||||
|
expect(setFailedConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
|
expect(getValidatorPendingTransaction).toBeCalledTimes(0)
|
||||||
|
expect(setPendingConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
|
expect(setResult.mock.calls[0][0]()).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
|
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
||||||
|
{ validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
expect(setResult.mock.calls[1][0]).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '0x123', timestamp: 123 },
|
||||||
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '0x123', timestamp: 123 },
|
||||||
|
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
||||||
|
{ validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
test('should look for failed and pending transactions for not confirmed validators', async () => {
|
test('should look for failed and pending transactions for not confirmed validators', async () => {
|
||||||
// Validator1 success
|
// Validator1 success
|
||||||
// Validator2 failed
|
// Validator2 failed
|
||||||
@ -335,7 +422,7 @@ describe('getConfirmationsForTx', () => {
|
|||||||
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
|
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
|
||||||
expect(setPendingConfirmations).toBeCalledTimes(1)
|
expect(setPendingConfirmations).toBeCalledTimes(1)
|
||||||
|
|
||||||
expect(setResult.mock.calls[0][0]).toEqual(
|
expect(setResult.mock.calls[0][0]()).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
||||||
@ -419,7 +506,7 @@ describe('getConfirmationsForTx', () => {
|
|||||||
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
|
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
|
||||||
expect(setPendingConfirmations).toBeCalledTimes(0)
|
expect(setPendingConfirmations).toBeCalledTimes(0)
|
||||||
|
|
||||||
expect(setResult.mock.calls[0][0]).toEqual(
|
expect(setResult.mock.calls[0][0]()).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
|
||||||
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
getValidatorPendingTransaction,
|
getValidatorPendingTransaction,
|
||||||
getValidatorSuccessTransaction
|
getValidatorSuccessTransaction
|
||||||
} from './validatorConfirmationHelpers'
|
} from './validatorConfirmationHelpers'
|
||||||
|
import { ConfirmationParam } from '../hooks/useMessageConfirmations'
|
||||||
|
|
||||||
export const getConfirmationsForTx = async (
|
export const getConfirmationsForTx = async (
|
||||||
messageData: string,
|
messageData: string,
|
||||||
@ -43,9 +44,21 @@ export const getConfirmationsForTx = async (
|
|||||||
|
|
||||||
const successConfirmations = validatorConfirmations.filter(c => c.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
|
const successConfirmations = validatorConfirmations.filter(c => c.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
|
||||||
|
|
||||||
|
setResult((prevConfirmations: ConfirmationParam[]) => {
|
||||||
|
if (prevConfirmations && prevConfirmations.length) {
|
||||||
|
successConfirmations.forEach(validatorData => {
|
||||||
|
const index = prevConfirmations.findIndex(e => e.validator === validatorData.validator)
|
||||||
|
validatorConfirmations[index] = validatorData
|
||||||
|
})
|
||||||
|
return prevConfirmations
|
||||||
|
} else {
|
||||||
|
return validatorConfirmations
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const notSuccessConfirmations = validatorConfirmations.filter(c => c.status !== VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
|
const notSuccessConfirmations = validatorConfirmations.filter(c => c.status !== VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
|
||||||
|
|
||||||
// If signatures not collected, it needs to retry in the next blocks
|
// If signatures not collected, look for pending transactions
|
||||||
if (successConfirmations.length !== requiredSignatures) {
|
if (successConfirmations.length !== requiredSignatures) {
|
||||||
// Check if confirmation is pending
|
// Check if confirmation is pending
|
||||||
const validatorPendingConfirmationsChecks = await Promise.all(
|
const validatorPendingConfirmationsChecks = await Promise.all(
|
||||||
@ -63,49 +76,49 @@ export const getConfirmationsForTx = async (
|
|||||||
if (validatorPendingConfirmations.length > 0) {
|
if (validatorPendingConfirmations.length > 0) {
|
||||||
setPendingConfirmations(true)
|
setPendingConfirmations(true)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const undefinedConfirmations = validatorConfirmations.filter(
|
const undefinedConfirmations = validatorConfirmations.filter(
|
||||||
c => c.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
c => c.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
||||||
)
|
)
|
||||||
// Check if confirmation failed
|
|
||||||
const validatorFailedConfirmationsChecks = await Promise.all(
|
|
||||||
undefinedConfirmations.map(
|
|
||||||
getValidatorFailedTransaction(bridgeContract, messageData, timestamp, getFailedTransactions)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
const validatorFailedConfirmations = validatorFailedConfirmationsChecks.filter(
|
|
||||||
c => c.status === VALIDATOR_CONFIRMATION_STATUS.FAILED
|
|
||||||
)
|
|
||||||
validatorFailedConfirmations.forEach(validatorData => {
|
|
||||||
const index = validatorConfirmations.findIndex(e => e.validator === validatorData.validator)
|
|
||||||
validatorConfirmations[index] = validatorData
|
|
||||||
})
|
|
||||||
const messageConfirmationsFailed = validatorFailedConfirmations.length > validatorList.length - requiredSignatures
|
|
||||||
if (messageConfirmationsFailed) {
|
|
||||||
setFailedConfirmations(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const missingConfirmations = validatorConfirmations.filter(
|
// Check if confirmation failed
|
||||||
c => c.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || c.status === VALIDATOR_CONFIRMATION_STATUS.PENDING
|
const validatorFailedConfirmationsChecks = await Promise.all(
|
||||||
|
undefinedConfirmations.map(
|
||||||
|
getValidatorFailedTransaction(bridgeContract, messageData, timestamp, getFailedTransactions)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
const validatorFailedConfirmations = validatorFailedConfirmationsChecks.filter(
|
||||||
|
c => c.status === VALIDATOR_CONFIRMATION_STATUS.FAILED
|
||||||
|
)
|
||||||
|
validatorFailedConfirmations.forEach(validatorData => {
|
||||||
|
const index = validatorConfirmations.findIndex(e => e.validator === validatorData.validator)
|
||||||
|
validatorConfirmations[index] = validatorData
|
||||||
|
})
|
||||||
|
const messageConfirmationsFailed = validatorFailedConfirmations.length > validatorList.length - requiredSignatures
|
||||||
|
if (messageConfirmationsFailed) {
|
||||||
|
setFailedConfirmations(true)
|
||||||
|
}
|
||||||
|
|
||||||
if (missingConfirmations.length > 0) {
|
const missingConfirmations = validatorConfirmations.filter(
|
||||||
shouldRetry = true
|
c => c.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || c.status === VALIDATOR_CONFIRMATION_STATUS.PENDING
|
||||||
}
|
)
|
||||||
} else {
|
|
||||||
// If signatures collected, it should set other signatures as not required
|
if (successConfirmations.length !== requiredSignatures && missingConfirmations.length > 0) {
|
||||||
const notRequiredConfirmations = notSuccessConfirmations.map(c => ({
|
shouldRetry = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (successConfirmations.length === requiredSignatures) {
|
||||||
|
// If signatures collected, it should set other signatures not found as not required
|
||||||
|
const notRequiredConfirmations = missingConfirmations.map(c => ({
|
||||||
validator: c.validator,
|
validator: c.validator,
|
||||||
status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED
|
status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED
|
||||||
}))
|
}))
|
||||||
|
|
||||||
validatorConfirmations = [...successConfirmations, ...notRequiredConfirmations]
|
validatorConfirmations = [...validatorConfirmations, ...notRequiredConfirmations]
|
||||||
setSignatureCollected(true)
|
setSignatureCollected(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set confirmations to update UI and continue requesting the transactions for the signatures
|
|
||||||
setResult(validatorConfirmations)
|
|
||||||
|
|
||||||
// get transactions from success signatures
|
// get transactions from success signatures
|
||||||
const successConfirmationWithData = await Promise.all(
|
const successConfirmationWithData = await Promise.all(
|
||||||
validatorConfirmations
|
validatorConfirmations
|
||||||
|
Loading…
Reference in New Issue
Block a user