Skip to content

Commit dc93dd6

Browse files
committed
addressing FTB-017 Federators retry failed transactions
1 parent 2965f7c commit dc93dd6

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

federator/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"scripts": {
1515
"start": "node ./src/main.js",
1616
"test": "jest --detectOpenHandles test/",
17-
"integrationTest": "rm -rf ./db/* && node ./integrationTest/integrationTest.js",
17+
"integrationTest": "rm ./db/lastBlock.txt --force && rm ./db/side-fed/lastBlock.txt --force && node ./integrationTest/integrationTest.js",
1818
"integrationHeartbeatTest": "rm -rf ./db/* && node ./integrationTest/integrationHeartbeatTest.js && rm heartbeat.log",
1919
"clean": "rm -rf ./db/*"
2020
},

federator/src/lib/Federator.js

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = class Federator {
2424

2525
this.transactionSender = new TransactionSender(this.sideWeb3, this.logger, this.config);
2626
this.lastBlockPath = `${config.storagePath || __dirname}/lastBlock.txt`;
27+
this.revertedTxnsPath = `${config.storagePath || __dirname}/revertedTxns.json`;
2728
this.bridgeFactory = new BridgeFactory(this.config, this.logger, Web3);
2829
this.federationFactory = new FederationFactory(this.config, this.logger, Web3);
2930
this.allowTokensFactory = new AllowTokensFactory(this.config, this.logger, Web3);
@@ -228,7 +229,8 @@ module.exports = class Federator {
228229
log.logIndex,
229230
decimals,
230231
granularity,
231-
typeId
232+
typeId,
233+
transactionId
232234
);
233235
} else {
234236
this.logger.debug(`Block: ${log.blockHash} Tx: ${log.transactionHash} token: ${symbol} has already been voted by us`);
@@ -257,8 +259,9 @@ module.exports = class Federator {
257259
logIndex,
258260
decimals,
259261
granularity,
260-
typeId)
261-
{
262+
typeId,
263+
txId
264+
) {
262265
try {
263266

264267
const transactionSender = new TransactionSender(this.sideWeb3, this.logger, this.config);
@@ -278,7 +281,37 @@ module.exports = class Federator {
278281
typeId
279282
}).encodeABI();
280283

281-
await transactionSender.sendTransaction(fedContract.getAddress(), txData, 0, this.config.privateKey);
284+
let revertedTxns = JSON.parse(fs.readFileSync(this.revertedTxnsPath, 'utf8'));
285+
this.logger.info(`read these transactions from reverted transactions file`, revertedTxns);
286+
287+
let receipt;
288+
if (revertedTxns[txId]) {
289+
this.logger.info(`Skipping Voting Transfer ${txId} since it's marked as reverted.`, revertedTxns[txId])
290+
} else {
291+
receipt = await transactionSender.sendTransaction(fedContract.getAddress(), txData, 0, this.config.privateKey);
292+
}
293+
294+
if(receipt && receipt.status == false) {
295+
this._saveRevertedTxns(
296+
this.revertedTxnsPath,
297+
JSON.stringify({
298+
...revertedTxns,
299+
[txId]: {
300+
originalTokenAddress: tokenAddress,
301+
sender,
302+
receiver,
303+
amount,
304+
symbol,
305+
blockHash,
306+
transactionHash,
307+
logIndex,
308+
decimals,
309+
granularity
310+
}
311+
})
312+
)
313+
}
314+
282315
return true;
283316
} catch (err) {
284317
throw new CustomError(`Exception Voting tx:${transactionHash} block: ${blockHash} token ${symbol}`, err);
@@ -290,4 +323,10 @@ module.exports = class Federator {
290323
fs.writeFileSync(path, value.toString());
291324
}
292325
}
326+
327+
_saveRevertedTxns(path, value) {
328+
if (value) {
329+
fs.writeFileSync(path, value.toString());
330+
}
331+
}
293332
}

federator/src/lib/TransactionSender.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,24 +194,23 @@ module.exports = class TransactionSender {
194194
receipt = await this.client.eth.sendTransaction(rawTx).once('transactionHash', hash => txHash = hash);
195195
}
196196
if(receipt.status == 1) {
197-
this.logger.info(`Transaction Successful chain:${chainId} txHash:${receipt.transactionHash} blockNumber:${receipt.blockNumber}`);
198-
return receipt;
197+
this.logger.info(`Transaction Successful txHash:${receipt.transactionHash} blockNumber:${receipt.blockNumber}`);
198+
} else {
199+
error = 'Transaction Receipt Status Failed';
200+
errorInfo = receipt;
201+
this.logger.error(error, errorInfo);
202+
this.logger.error('RawTx that failed', rawTx);
199203
}
200-
error = `Transaction Receipt Status Failed chain:${chainId}`;
201-
errorInfo = receipt;
204+
205+
return receipt;
206+
202207
} catch(err) {
203208
if (err.message.indexOf('it might still be mined') > 0) {
204209
this.logger.warn(`Transaction was not mined within 750 seconds, please make sure your transaction was properly sent. Be aware that
205210
it might still be mined. Chain:${chainId} transactionHash:${txHash}`);
206211
fs.appendFileSync(this.manuallyCheck, `chain:${chainId} transactionHash:${txHash} to:${to} data:${data}\n`);
207212
return { transactionHash: txHash };
208213
}
209-
error = `Send Signed Transaction to chain:${chainId} Failed TxHash:${txHash}`;
210-
errorInfo = err;
211214
}
212-
this.logger.error(error, errorInfo);
213-
this.logger.error('RawTx that failed', rawTx);
214-
throw new CustomError(`Transaction Failed: ${error} ${stack}`, errorInfo);
215215
}
216-
217216
}

0 commit comments

Comments
 (0)