Skip to content

Commit

Permalink
fix(dapi): invalid state transition failed with already in chain error
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov committed Oct 22, 2024
1 parent 93425cf commit 5267e4a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const UnavailableGrpcError = require('@dashevo/grpc-common/lib/server/error/UnavailableGrpcError');
const ResourceExhaustedGrpcError = require('@dashevo/grpc-common/lib/server/error/ResourceExhaustedGrpcError');
const logger = require('../../../../logger');

/**
* @param {jaysonClient} rpcClient
* @param {string} uri
* @param {Object} params
* @return {Promise<any>}
*/
async function request(rpcClient, uri, params = {}) {
let response;
try {
response = await rpcClient.request(uri, params);
} catch (e) {
if (e.message === 'socket hang up') {
throw new UnavailableGrpcError('Tenderdash is not available');
}

e.message = `Failed to fetch cached transaction: ${e.message}`;

throw e;
}

const { result, error: jsonRpcError } = response;

if (jsonRpcError) {
if (typeof jsonRpcError.data === 'string') {
if (jsonRpcError.data.includes('too_many_resets')) {
throw new ResourceExhaustedGrpcError('tenderdash is not responding: too many requests');
}
}

const error = new Error();
Object.assign(error, jsonRpcError);

logger.error(error, `Unexpected JSON RPC error during broadcasting state transition: ${JSON.stringify(jsonRpcError)}`);

throw error;
}

return result;
}

/**
*
* @param {jaysonClient} rpcClient
* @return {fetchCachedStateTransitionResult}
*/
function fetchCachedStateTransitionResultFactory(rpcClient) {
/**
* @typedef fetchCachedStateTransitionResult
* @param {Buffer} stBytes
* @return {Promise<Object>}
*/
return async function fetchCachedStateTransitionResult(stBytes) {
// Subscribing to future result
const stHash = crypto.createHash('sha256')
.update(stBytes)
.digest();

// Search cached state transition in mempool
// rpcClient.request('/unconfirmed_txs');

// Search in blockchain data
const result = await request(rpcClient, '/tx', { hash: `0x${stHash.toString('hex')}` });


};
}

module.exports = fetchCachedStateTransitionResultFactory;
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ const logger = require('../../../logger');
/**
* @param {jaysonClient} rpcClient
* @param {createGrpcErrorFromDriveResponse} createGrpcErrorFromDriveResponse
* @param {fetchCachedStateTransitionResult} fetchCachedStateTransitionResult
*
* @returns {broadcastStateTransitionHandler}
*/
function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDriveResponse) {
function broadcastStateTransitionHandlerFactory(
rpcClient,
createGrpcErrorFromDriveResponse,
fetchCachedStateTransitionResult) {
/**
* @typedef broadcastStateTransitionHandler
*
Expand All @@ -38,7 +42,9 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr
throw new InvalidArgumentGrpcError('State Transition is not specified');
}

const tx = Buffer.from(stByteArray)
const stBytes = Buffer.from(stByteArray);

const tx = stBytes
.toString('base64');

let response;
Expand All @@ -55,14 +61,15 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr
throw e;
}

const {
result,
error: jsonRpcError,
} = response;
let { result } = response;
const { error: jsonRpcError } = response;

if (jsonRpcError) {
if (typeof jsonRpcError.data === 'string') {
if (jsonRpcError.data === 'tx already exists in cache') {
result = fetchCachedStateTransitionResult(stBytes);


throw new AlreadyExistsGrpcError('state transition already in chain');
}

Expand Down

0 comments on commit 5267e4a

Please sign in to comment.