Skip to content

Commit

Permalink
Merge pull request #1593 from skalenetwork/ticket-1541/improved-trans…
Browse files Browse the repository at this point in the history
…fer-loop-protection

ticket-1541 Fixed transfer loop over-run conditions
  • Loading branch information
sergiy-skalelabs authored Sep 19, 2023
2 parents ac99e34 + 24d1c6c commit 024521c
Showing 1 changed file with 158 additions and 109 deletions.
267 changes: 158 additions & 109 deletions npms/skale-ima/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -846,32 +846,55 @@ async function callbackAllMessagesSign( optsTransfer, err, jarrMessages, joGlueR
}

async function handleAllMessagesSigning( optsTransfer ) {
await optsTransfer.fnSignMessages(
optsTransfer.nTransferLoopCounter,
optsTransfer.jarrMessages, optsTransfer.nIdxCurrentMsgBlockStart,
optsTransfer.chainNameSrc,
optsTransfer.joExtraSignOpts,
async function( err, jarrMessages, joGlueResult ) {
await callbackAllMessagesSign( optsTransfer, err, jarrMessages, joGlueResult );
} ).catch( ( err ) => {
// callback fn as argument of optsTransfer.fnSignMessages
optsTransfer.bErrorInSigningMessages = true;
try {
const promiseComplete = new Promise( function( resolve, reject ) {
const doHandlingWorkForAllMessagesSigning = async function() {
await optsTransfer.fnSignMessages(
optsTransfer.nTransferLoopCounter,
optsTransfer.jarrMessages, optsTransfer.nIdxCurrentMsgBlockStart,
optsTransfer.chainNameSrc,
optsTransfer.joExtraSignOpts,
async function( err, jarrMessages, joGlueResult ) {
await callbackAllMessagesSign(
optsTransfer, err, jarrMessages, joGlueResult );
resolve( true );
} ).catch( ( err ) => {
// callback fn as argument of optsTransfer.fnSignMessages
optsTransfer.bErrorInSigningMessages = true;
if( log.verboseGet() >= log.verboseReversed().error ) {
const strError = owaspUtils.extractErrorMessage( err );
const strErrorMessage = optsTransfer.strLogPrefix +
cc.error( "Problem in transfer handler(in signer): " ) +
cc.warning( strError );
optsTransfer.details.write( strErrorMessage + "\n" );
if( log.id != optsTransfer.details.id )
log.write( strErrorMessage + "\n" );
imaTransferErrorHandling.saveTransferError(
optsTransfer.strTransferErrorCategoryName,
optsTransfer.details.toString() );
}
reject( err );
} );
};
doHandlingWorkForAllMessagesSigning();
} );
await Promise.all( [ promiseComplete ] );
return true;
} catch ( err ) {
if( log.verboseGet() >= log.verboseReversed().error ) {
if( log.verboseGet() >= log.verboseReversed().error ) {
const strError = owaspUtils.extractErrorMessage( err );
const strErrorMessage = optsTransfer.strLogPrefix +
cc.error( "Problem in transfer handler: " ) +
cc.warning( strError );
optsTransfer.details.write( strErrorMessage + "\n" );
if( log.id != optsTransfer.details.id )
log.write( strErrorMessage + "\n" );
}
const strError = owaspUtils.extractErrorMessage( err );
const strErrorMessage = optsTransfer.strLogPrefix +
cc.error( "Problem in transfer handler(general): " ) +
cc.warning( strError );
optsTransfer.details.write( strErrorMessage + "\n" );
if( log.id != optsTransfer.details.id )
log.write( strErrorMessage + "\n" );
imaTransferErrorHandling.saveTransferError(
optsTransfer.strTransferErrorCategoryName,
optsTransfer.details.toString() );
}
} );
return true;
return false;
}
}

async function checkOutgoingMessageEvent( optsTransfer, joSChain ) {
Expand Down Expand Up @@ -1249,29 +1272,18 @@ async function doMainTransferLoopActions( optsTransfer ) {
return true;
}

let gIsOneTransferInProgressInThisThread = false;

export async function doTransfer(
strDirection,
joRuntimeOpts,
ethersProviderSrc,
joMessageProxySrc,
joAccountSrc,
ethersProviderDst,
joMessageProxyDst,
joAccountDst,
chainNameSrc,
chainNameDst,
chainIdSrc,
chainIdDst,
strDirection, joRuntimeOpts,
ethersProviderSrc, joMessageProxySrc, joAccountSrc,
ethersProviderDst, joMessageProxyDst, joAccountDst,
chainNameSrc, chainNameDst, chainIdSrc, chainIdDst,
joDepositBoxMainNet, // for logs validation on mainnet
joTokenManagerSChain, // for logs validation on s-chain
nTransactionsCountInBlock,
nTransferSteps,
nMaxTransactionsCount,
nBlockAwaitDepth,
nBlockAge,
fnSignMessages,
joExtraSignOpts,
transactionCustomizerDst
nTransferSteps, nMaxTransactionsCount, nBlockAwaitDepth, nBlockAge,
fnSignMessages, joExtraSignOpts, transactionCustomizerDst
) {
const optsTransfer = {
strDirection: strDirection,
Expand Down Expand Up @@ -1319,101 +1331,138 @@ export async function doTransfer(
arrLogRecordReferences: []
};
++ gTransferLoopCounter;
optsTransfer.strGatheredDetailsName =
optsTransfer.strDirection + "/#" + optsTransfer.nTransferLoopCounter +
"-" + "doTransfer-A" + "-" +
optsTransfer.strGatheredDetailsName = optsTransfer.strDirection + "/#" +
optsTransfer.nTransferLoopCounter + "-" + "doTransfer-A" + "-" +
optsTransfer.chainNameSrc + "-->" + optsTransfer.chainNameDst;
optsTransfer.strGatheredDetailsName_colored =
cc.bright( optsTransfer.strDirection ) + cc.debug( "/" ) + cc.attention( "#" ) +
cc.sunny( optsTransfer.nTransferLoopCounter ) + cc.debug( "-" ) +
cc.info( "doTransfer-A-" ) + cc.debug( "-" ) + cc.notice( optsTransfer.chainNameSrc ) +
cc.debug( "-->" ) + cc.notice( optsTransfer.chainNameDst );
optsTransfer.strGatheredDetailsName_colored = cc.bright( optsTransfer.strDirection ) +
cc.debug( "/" ) + cc.attention( "#" ) + cc.sunny( optsTransfer.nTransferLoopCounter ) +
cc.debug( "-" ) + cc.info( "doTransfer-A-" ) + cc.debug( "-" ) +
cc.notice( optsTransfer.chainNameSrc ) + cc.debug( "-->" ) +
cc.notice( optsTransfer.chainNameDst );
optsTransfer.details = optsTransfer.imaState.isDynamicLogInDoTransfer
? log : log.createMemoryStream( true );
optsTransfer.strLogPrefixShort = cc.bright( optsTransfer.strDirection ) + cc.debug( "/" ) +
cc.attention( "#" ) + cc.sunny( optsTransfer.nTransferLoopCounter ) + " ";
optsTransfer.strLogPrefix = optsTransfer.strLogPrefixShort + cc.info( "transfer loop from " ) +
cc.notice( optsTransfer.chainNameSrc ) + cc.info( " to " ) +
cc.notice( optsTransfer.chainNameDst ) + cc.info( ":" ) + " ";
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Message signing is " ) +
cc.onOff( optsTransfer.imaState.bSignMessages ) + "\n" );
if( gIsOneTransferInProgressInThisThread ) {
if( log.verboseGet() >= log.verboseReversed().warning ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Transfer loop step is skipped because " +
"previous one is still in progress" ) + "\n" );
}
if( log.exposeDetailsGet() && optsTransfer.details.exposeDetailsTo ) {
optsTransfer.details.exposeDetailsTo(
log, optsTransfer.strGatheredDetailsName, true );
}
optsTransfer.details.close();
return false;
}
if( optsTransfer.fnSignMessages == null ||
optsTransfer.fnSignMessages == undefined ||
( ! optsTransfer.imaState.bSignMessages )
) {
try {
gIsOneTransferInProgressInThisThread = true;
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Using internal signing stub function" ) + "\n" );
cc.debug( "Message signing is " ) +
cc.onOff( optsTransfer.imaState.bSignMessages ) + "\n" );
}
optsTransfer.fnSignMessages = async function(
nTransferLoopCounter, jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName,
joExtraSignOpts, fnAfter
if( optsTransfer.fnSignMessages == null || optsTransfer.fnSignMessages == undefined ||
( ! optsTransfer.imaState.bSignMessages )
) {
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Message signing callback was " ) + cc.error( "not provided" ) +
cc.debug( " to IMA, first real message index is:" ) +
cc.info( nIdxCurrentMsgBlockStart ) + cc.debug( ", have " ) +
cc.info( optsTransfer.jarrMessages.length ) +
cc.debug( " message(s) to process " ) +
cc.j( optsTransfer.jarrMessages ) + "\n" );
cc.debug( "Using internal signing stub function" ) + "\n" );
}
optsTransfer.fnSignMessages = async function(
nTransferLoopCounter, jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName,
joExtraSignOpts, fnAfter
) {
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Message signing callback was " ) + cc.error( "not provided" ) +
cc.debug( " to IMA, first real message index is:" ) +
cc.info( nIdxCurrentMsgBlockStart ) + cc.debug( ", have " ) +
cc.info( optsTransfer.jarrMessages.length ) +
cc.debug( " message(s) to process " ) +
cc.j( optsTransfer.jarrMessages ) + "\n" );
}
await fnAfter( null, jarrMessages, null ); // null - no error, null - no signatures
};
} else {
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Using externally provided signing function" ) + "\n" );
}
await fnAfter( null, jarrMessages, null ); // null - no error, null - no signatures
};
} else {
if( log.verboseGet() >= log.verboseReversed().debug ) {
optsTransfer.details.write( optsTransfer.strLogPrefix +
cc.debug( "Using externally provided signing function" ) + "\n" );
}
}
optsTransfer.nTransactionsCountInBlock = optsTransfer.nTransactionsCountInBlock || 5;
optsTransfer.nTransferSteps = optsTransfer.nTransferSteps || Number.MAX_SAFE_INTEGER;
optsTransfer.nMaxTransactionsCount =
optsTransfer.nMaxTransactionsCount || Number.MAX_SAFE_INTEGER;
if( optsTransfer.nTransactionsCountInBlock < 1 )
optsTransfer.nTransactionsCountInBlock = 1;
if( optsTransfer.nBlockAwaitDepth < 0 )
optsTransfer.nBlockAwaitDepth = 0;
if( optsTransfer.nBlockAge < 0 )
optsTransfer.nBlockAge = 0;
try {
if( ! ( await doQueryOutgoingMessageCounter( optsTransfer ) ) )
return false;
if( ! ( await doMainTransferLoopActions( optsTransfer ) ) )
optsTransfer.nTransactionsCountInBlock = optsTransfer.nTransactionsCountInBlock || 5;
optsTransfer.nTransferSteps = optsTransfer.nTransferSteps || Number.MAX_SAFE_INTEGER;
optsTransfer.nMaxTransactionsCount =
optsTransfer.nMaxTransactionsCount || Number.MAX_SAFE_INTEGER;
if( optsTransfer.nTransactionsCountInBlock < 1 )
optsTransfer.nTransactionsCountInBlock = 1;
if( optsTransfer.nBlockAwaitDepth < 0 )
optsTransfer.nBlockAwaitDepth = 0;
if( optsTransfer.nBlockAge < 0 )
optsTransfer.nBlockAge = 0;
try {
if( ! ( await doQueryOutgoingMessageCounter( optsTransfer ) ) ) {
gIsOneTransferInProgressInThisThread = false;
return false;
}
if( ! ( await doMainTransferLoopActions( optsTransfer ) ) ) {
gIsOneTransferInProgressInThisThread = false;
return false;
}
} catch ( err ) {
if( log.verboseGet() >= log.verboseReversed().critical ) {
const strError = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
cc.error( " Error in " ) + optsTransfer.strGatheredDetailsName_colored +
cc.error( " during " + optsTransfer.strActionName + ": " ) +
cc.warning( owaspUtils.extractErrorMessage( err ) ) +
cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n";
optsTransfer.details.write( strError );
if( log.id != optsTransfer.details.id )
log.write( strError );
}
optsTransfer.details.exposeDetailsTo( log,
optsTransfer.strGatheredDetailsName, false );
imaTransferErrorHandling.saveTransferError(
optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() );
optsTransfer.details.close();
gIsOneTransferInProgressInThisThread = false;
return false;
}
imaGasUsage.printGasUsageReportFromArray( "TRANSFER " + optsTransfer.chainNameSrc +
" -> " + optsTransfer.chainNameDst, optsTransfer.jarrReceipts, optsTransfer.details );
if( optsTransfer.details ) {
if( log.exposeDetailsGet() && optsTransfer.details.exposeDetailsTo ) {
optsTransfer.details.exposeDetailsTo(
log, optsTransfer.strGatheredDetailsName, true );
}
optsTransfer.details.close();
}
if( ! optsTransfer.bErrorInSigningMessages ) {
imaTransferErrorHandling.saveTransferSuccess(
optsTransfer.strTransferErrorCategoryName );
}
gIsOneTransferInProgressInThisThread = false;
return true;
} catch ( err ) {
if( log.verboseGet() >= log.verboseReversed().critical ) {
const strError = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
cc.error( " Error in " ) + optsTransfer.strGatheredDetailsName_colored +
cc.error( " during " + optsTransfer.strActionName + ": " ) +
cc.warning( owaspUtils.extractErrorMessage( err ) ) +
cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) +
"\n";
optsTransfer.details.write( strError );
if( log.id != optsTransfer.details.id )
log.write( strError );
gIsOneTransferInProgressInThisThread = false;
if( log.verboseGet() >= log.verboseReversed().error ) {
const strError = owaspUtils.extractErrorMessage( err );
optsTransfer.details.write( optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
cc.error( " Transfer loop step failed with error: " ) + cc.warning( strError ) +
cc.error( " in " ) + threadInfo.threadDescription() +
cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" );
}
optsTransfer.details.exposeDetailsTo( log, optsTransfer.strGatheredDetailsName, false );
imaTransferErrorHandling.saveTransferError(
optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() );
optsTransfer.details.close();
return false;
}
imaGasUsage.printGasUsageReportFromArray(
"TRANSFER " + optsTransfer.chainNameSrc + " -> " +
optsTransfer.chainNameDst, optsTransfer.jarrReceipts, optsTransfer.details );
if( optsTransfer.details ) {
if( log.exposeDetailsGet() && optsTransfer.details.exposeDetailsTo ) {
optsTransfer.details.exposeDetailsTo(
log, optsTransfer.strGatheredDetailsName, true );
}
optsTransfer.details.close();
return false;
}
if( ! optsTransfer.bErrorInSigningMessages )
imaTransferErrorHandling.saveTransferSuccess( optsTransfer.strTransferErrorCategoryName );
return true;
}

export async function doAllS2S( // s-chain --> s-chain
Expand Down

0 comments on commit 024521c

Please sign in to comment.