Skip to content

Commit bcf1614

Browse files
authored
Merge the develop branch to the master branch, preparation to v3.6.0
This merge contains the following set of changes: * [Oracle, Fix] Add missing Ganache nonce error message (#651) * [ALM, Improvement] ALM: show manually added signatures (#653)
2 parents dbaf7fe + 16f3e9a commit bcf1614

14 files changed

+293
-209
lines changed

alm/src/components/ConfirmationsContainer.tsx

+23-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import { TransactionReceipt } from 'web3-eth'
33
import { useMessageConfirmations } from '../hooks/useMessageConfirmations'
44
import { MessageObject } from '../utils/web3'
55
import styled from 'styled-components'
6-
import { CONFIRMATIONS_STATUS } from '../config/constants'
6+
import { CONFIRMATIONS_STATUS, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
77
import { CONFIRMATIONS_STATUS_LABEL, CONFIRMATIONS_STATUS_LABEL_HOME } from '../config/descriptions'
88
import { SimpleLoading } from './commons/Loading'
99
import { ValidatorsConfirmations } from './ValidatorsConfirmations'
@@ -54,7 +54,9 @@ export const ConfirmationsContainer = ({
5454
home: { name: homeName },
5555
foreign: { name: foreignName }
5656
} = useStateProvider()
57-
const { requiredSignatures, validatorList } = useValidatorContract(fromHome, receipt ? receipt.blockNumber : 0)
57+
const src = useValidatorContract(fromHome, receipt ? receipt.blockNumber : 0)
58+
const [executionBlockNumber, setExecutionBlockNumber] = useState(0)
59+
const dst = useValidatorContract(!fromHome, executionBlockNumber || 'latest')
5860
const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt })
5961
const {
6062
confirmations,
@@ -71,11 +73,21 @@ export const ConfirmationsContainer = ({
7173
fromHome,
7274
homeStartBlock,
7375
foreignStartBlock,
74-
requiredSignatures,
75-
validatorList,
76+
requiredSignatures: src.requiredSignatures,
77+
validatorList: src.validatorList,
78+
targetValidatorList: dst.validatorList,
7679
blockConfirmations
7780
})
7881

82+
useEffect(
83+
() => {
84+
if (executionBlockNumber || executionData.status !== VALIDATOR_CONFIRMATION_STATUS.EXECUTION_SUCCESS) return
85+
86+
setExecutionBlockNumber(executionData.blockNumber)
87+
},
88+
[executionData.status, executionBlockNumber, executionData.blockNumber]
89+
)
90+
7991
const statusLabel = fromHome ? CONFIRMATIONS_STATUS_LABEL_HOME : CONFIRMATIONS_STATUS_LABEL
8092

8193
const parseDescription = () => {
@@ -114,20 +126,22 @@ export const ConfirmationsContainer = ({
114126
</MultiLine>
115127
</StatusDescription>
116128
<ValidatorsConfirmations
117-
confirmations={confirmations}
118-
requiredSignatures={requiredSignatures}
119-
validatorList={validatorList}
129+
confirmations={fromHome ? confirmations.filter(c => dst.validatorList.includes(c.validator)) : confirmations}
130+
requiredSignatures={dst.requiredSignatures}
131+
validatorList={dst.validatorList}
120132
waitingBlocksResolved={waitingBlocksResolved}
121133
/>
122134
{signatureCollected && (
123135
<ExecutionConfirmation
124136
message={message}
125137
executionData={executionData}
126138
isHome={!fromHome}
127-
signatureCollected={signatureCollected}
139+
confirmations={confirmations}
128140
setExecutionData={setExecutionData}
129141
executionEventsFetched={executionEventsFetched}
130142
setPendingExecution={setPendingExecution}
143+
dstRequiredSignatures={dst.requiredSignatures}
144+
dstValidatorList={dst.validatorList}
131145
/>
132146
)}
133147
</StyledConfirmationContainer>

alm/src/components/ExecutionConfirmation.tsx

+11-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useWindowWidth } from '@react-hook/window-size'
44
import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS, ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION } from '../config/constants'
55
import { SimpleLoading } from './commons/Loading'
66
import styled from 'styled-components'
7-
import { ExecutionData } from '../hooks/useMessageConfirmations'
7+
import { ConfirmationParam, ExecutionData } from '../hooks/useMessageConfirmations'
88
import { GreyLabel, RedLabel, SuccessLabel } from './commons/Labels'
99
import { ExplorerTxLink } from './commons/ExplorerTxLink'
1010
import { Thead, AgeTd, StatusTd } from './commons/Table'
@@ -22,20 +22,24 @@ export interface ExecutionConfirmationParams {
2222
message: MessageObject
2323
executionData: ExecutionData
2424
setExecutionData: Function
25-
signatureCollected: boolean | string[]
25+
confirmations: ConfirmationParam[]
2626
isHome: boolean
2727
executionEventsFetched: boolean
2828
setPendingExecution: Function
29+
dstRequiredSignatures: number
30+
dstValidatorList: string[]
2931
}
3032

3133
export const ExecutionConfirmation = ({
3234
message,
3335
executionData,
3436
setExecutionData,
35-
signatureCollected,
37+
confirmations,
3638
isHome,
3739
executionEventsFetched,
38-
setPendingExecution
40+
setPendingExecution,
41+
dstRequiredSignatures,
42+
dstValidatorList
3943
}: ExecutionConfirmationParams) => {
4044
const { foreign } = useStateProvider()
4145
const [safeExecutionAvailable, setSafeExecutionAvailable] = useState(false)
@@ -152,9 +156,11 @@ export const ExecutionConfirmation = ({
152156
safeExecutionAvailable={safeExecutionAvailable}
153157
messageData={message.data}
154158
setExecutionData={setExecutionData}
155-
signatureCollected={signatureCollected as string[]}
159+
confirmations={confirmations}
156160
setPendingExecution={setPendingExecution}
157161
setError={setError}
162+
requiredSignatures={dstRequiredSignatures}
163+
validatorList={dstValidatorList}
158164
/>
159165
</td>
160166
)}

alm/src/components/ManualExecutionButton.tsx

+20-37
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useStateProvider } from '../state/StateProvider'
1414
import { signatureToVRS, packSignatures } from '../utils/signatures'
1515
import { getSuccessExecutionData } from '../utils/getFinalizationEvent'
1616
import { TransactionReceipt } from 'web3-eth'
17-
import { useValidatorContract } from '../hooks/useValidatorContract'
17+
import { ConfirmationParam } from '../hooks/useMessageConfirmations'
1818

1919
const ActionButton = styled.button`
2020
color: var(--button-color);
@@ -31,18 +31,22 @@ interface ManualExecutionButtonParams {
3131
safeExecutionAvailable: boolean
3232
messageData: string
3333
setExecutionData: Function
34-
signatureCollected: string[]
34+
confirmations: ConfirmationParam[]
3535
setPendingExecution: Function
3636
setError: Function
37+
requiredSignatures: number
38+
validatorList: string[]
3739
}
3840

3941
export const ManualExecutionButton = ({
4042
safeExecutionAvailable,
4143
messageData,
4244
setExecutionData,
43-
signatureCollected,
45+
confirmations,
4446
setPendingExecution,
45-
setError
47+
setError,
48+
requiredSignatures,
49+
validatorList
4650
}: ManualExecutionButtonParams) => {
4751
const { foreign } = useStateProvider()
4852
const { library, activate, account, active } = useWeb3React()
@@ -52,55 +56,34 @@ export const ManualExecutionButton = ({
5256
const [title, setTitle] = useState('Loading')
5357
const [validSignatures, setValidSignatures] = useState<string[]>([])
5458

55-
const { requiredSignatures, validatorList } = useValidatorContract(false, 'latest')
56-
5759
useEffect(
5860
() => {
5961
if (
6062
!foreign.bridgeContract ||
6163
!foreign.web3 ||
62-
!signatureCollected ||
63-
!signatureCollected.length ||
64+
!confirmations ||
65+
!confirmations.length ||
6466
!requiredSignatures ||
6567
!validatorList ||
6668
!validatorList.length
6769
)
6870
return
6971

7072
const signatures = []
71-
const remainingValidators = Object.fromEntries(validatorList.map(validator => [validator, true]))
72-
for (let i = 0; i < signatureCollected.length && signatures.length < requiredSignatures; i++) {
73-
const { v, r, s } = signatureToVRS(signatureCollected[i])
73+
for (let i = 0; i < confirmations.length && signatures.length < requiredSignatures; i++) {
74+
const sig = confirmations[i].signature
75+
if (!sig) {
76+
continue
77+
}
78+
const { v, r, s } = signatureToVRS(sig)
7479
const signer = foreign.web3.eth.accounts.recover(messageData, `0x${v}`, `0x${r}`, `0x${s}`)
7580
if (validatorList.includes(signer)) {
76-
delete remainingValidators[signer]
77-
signatures.push(signatureCollected[i])
78-
}
79-
}
80-
81-
if (signatures.length < requiredSignatures) {
82-
console.log('On-chain collected signatures are not enough for message execution')
83-
const manualValidators = Object.keys(remainingValidators)
84-
const msgHash = foreign.web3.utils.sha3(messageData)!
85-
for (let i = 0; i < manualValidators.length && signatures.length < requiredSignatures; i++) {
86-
try {
87-
const overrideSignatures: {
88-
[key: string]: string
89-
} = require(`../snapshots/signatures_${manualValidators[i]}.json`)
90-
if (overrideSignatures[msgHash]) {
91-
console.log(`Adding manual signature from ${manualValidators[i]}`)
92-
signatures.push(overrideSignatures[msgHash])
93-
} else {
94-
console.log(`No manual signature from ${manualValidators[i]} was found`)
95-
}
96-
} catch (e) {
97-
console.log(`Signatures overrides are not present for ${manualValidators[i]}`)
98-
}
81+
signatures.push(sig)
9982
}
10083
}
10184

10285
if (signatures.length >= requiredSignatures) {
103-
setValidSignatures(signatures)
86+
setValidSignatures(signatures.slice(0, requiredSignatures))
10487
setTitle('Execute')
10588
setReady(true)
10689
} else {
@@ -110,11 +93,11 @@ export const ManualExecutionButton = ({
11093
[
11194
foreign.bridgeContract,
11295
foreign.web3,
113-
signatureCollected,
11496
validatorList,
11597
requiredSignatures,
11698
messageData,
117-
setValidSignatures
99+
setValidSignatures,
100+
confirmations
118101
]
119102
)
120103

alm/src/components/ValidatorsConfirmations.tsx

+24-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
33
import { useWindowWidth } from '@react-hook/window-size'
4-
import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
4+
import { RECENT_AGE, SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
55
import { SimpleLoading } from './commons/Loading'
66
import styled from 'styled-components'
77
import { ConfirmationParam } from '../hooks/useMessageConfirmations'
@@ -31,7 +31,9 @@ export const ValidatorsConfirmations = ({
3131
const getValidatorStatusElement = (validatorStatus = '') => {
3232
switch (validatorStatus) {
3333
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
34-
return <SuccessLabel>{validatorStatus}</SuccessLabel>
34+
case VALIDATOR_CONFIRMATION_STATUS.MANUAL:
35+
case VALIDATOR_CONFIRMATION_STATUS.FAILED_VALID:
36+
return <SuccessLabel>{VALIDATOR_CONFIRMATION_STATUS.SUCCESS}</SuccessLabel>
3537
case VALIDATOR_CONFIRMATION_STATUS.FAILED:
3638
return <RedLabel>{validatorStatus}</RedLabel>
3739
case VALIDATOR_CONFIRMATION_STATUS.PENDING:
@@ -58,26 +60,28 @@ export const ValidatorsConfirmations = ({
5860
</tr>
5961
</Thead>
6062
<tbody>
61-
{validatorList.map((validator, i) => {
62-
const filteredConfirmation = confirmations.filter(c => c.validator === validator)
63-
const confirmation = filteredConfirmation.length > 0 ? filteredConfirmation[0] : null
64-
const displayedStatus = confirmation && confirmation.status ? confirmation.status : ''
65-
const explorerLink = confirmation && confirmation.txHash ? getExplorerTxUrl(confirmation.txHash, true) : ''
66-
const elementIfNoTimestamp =
67-
displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.WAITING &&
68-
displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED ? (
69-
(displayedStatus === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || displayedStatus === '') &&
70-
waitingBlocksResolved ? (
71-
SEARCHING_TX
72-
) : (
73-
<SimpleLoading />
74-
)
75-
) : (
76-
''
77-
)
63+
{confirmations.map((confirmation, i) => {
64+
const displayedStatus = confirmation.status
65+
const explorerLink = getExplorerTxUrl(confirmation.txHash, true)
66+
let elementIfNoTimestamp: any = <SimpleLoading />
67+
switch (displayedStatus) {
68+
case '':
69+
case VALIDATOR_CONFIRMATION_STATUS.UNDEFINED:
70+
if (waitingBlocksResolved) {
71+
elementIfNoTimestamp = SEARCHING_TX
72+
}
73+
break
74+
case VALIDATOR_CONFIRMATION_STATUS.WAITING:
75+
case VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED:
76+
elementIfNoTimestamp = ''
77+
break
78+
case VALIDATOR_CONFIRMATION_STATUS.MANUAL:
79+
elementIfNoTimestamp = RECENT_AGE
80+
break
81+
}
7882
return (
7983
<tr key={i}>
80-
<td>{windowWidth < 850 ? formatTxHash(validator) : validator}</td>
84+
<td>{windowWidth < 850 ? formatTxHash(confirmation.validator) : confirmation.validator}</td>
8185
<StatusTd className="text-center">{getValidatorStatusElement(displayedStatus)}</StatusTd>
8286
<AgeTd className="text-center">
8387
{confirmation && confirmation.timestamp > 0 ? (

alm/src/config/constants.ts

+4
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,18 @@ export const CONFIRMATIONS_STATUS = {
5555

5656
export const VALIDATOR_CONFIRMATION_STATUS = {
5757
SUCCESS: 'Confirmed',
58+
MANUAL: 'Manual',
5859
EXECUTION_SUCCESS: 'Executed',
5960
FAILED: 'Failed',
61+
FAILED_VALID: 'Failed valid',
6062
PENDING: 'Pending',
6163
WAITING: 'Waiting',
6264
NOT_REQUIRED: 'Not required',
6365
UNDEFINED: 'UNDEFINED'
6466
}
6567

68+
export const RECENT_AGE = 'Recent'
69+
6670
export const SEARCHING_TX = 'Searching Transaction...'
6771

6872
export const INCORRECT_CHAIN_ERROR = `Incorrect chain chosen. Switch to ${FOREIGN_NETWORK_NAME} in the wallet.`

0 commit comments

Comments
 (0)