Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/dashmate/src/status/scopes/platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,15 @@ export default function getPlatformScopeFactory(
}

info.version = version;
info.protocolVersion = parseInt(tenderdashStatus.node_info.protocol_version.app, 10);
// Prefer live application_info.version (current after in-process upgrades).
// Tenderdash may omit application_info entirely (json omitempty when ABCIInfo
// fails, or older builds without the field). Fall back to
// node_info.protocol_version.app only then — that snapshot can be stale, so it
// must not win when the live field is present.
const appProtocolVersion = tenderdashStatus.application_info?.version
?? tenderdashStatus.node_info.protocol_version.app;
info.protocolVersion = parseInt(appProtocolVersion, 10);
// abci_info app_version reflects the installed software's desired/supported version.
info.desiredProtocolVersion = tenderdashAbciInfo.response.app_version;
info.listening = listening;
info.latestBlockHeight = latestBlockHeight;
Expand Down
74 changes: 73 additions & 1 deletion packages/dashmate/test/unit/status/scopes/platform.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,22 @@ describe('getPlatformScopeFactory', () => {
mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' });
mockMNOWatchProvider.returns(Promise.resolve('OPEN'));

// node_info.protocol_version.app can be stale after in-process upgrades;
// protocolVersion must come from application_info.version (live).
const mockStatus = {
node_info: {
protocol_version: {
p2p: '10',
block: '14',
app: '3',
app: '11',
},
version: '0',
network: 'test',
moniker: 'test',
},
application_info: {
version: '3',
},
sync_info: {
catching_up: false,
latest_app_hash: 'DEADBEEF',
Expand Down Expand Up @@ -157,6 +162,67 @@ describe('getPlatformScopeFactory', () => {
expect(scope).to.deep.equal(expectedScope);
});

it('should fall back to node_info app protocol when application_info is absent', async () => {
mockDetermineDockerStatus.returns(DockerStatusEnum.running);
mockRpcClient.mnsync.withArgs('status').returns({ result: { IsSynced: true } });
mockRpcClient.getBlockchainInfo.returns({
result: {
softforks: {
mn_rr: { active: true, height: 1337 },
},
},
});
mockDockerCompose.isServiceRunning.returns(true);
mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci status').resolves({ exitCode: 0, out: '' });
mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' });
mockMNOWatchProvider.returns(Promise.resolve('OPEN'));

// When application_info is omitted (omitempty / unavailable), status must still
// report a numeric protocolVersion from node_info.protocol_version.app.
const mockStatus = {
node_info: {
protocol_version: {
p2p: '10',
block: '14',
app: '3',
},
version: '0',
network: 'test',
moniker: 'test',
},
sync_info: {
catching_up: false,
latest_app_hash: 'DEADBEEF',
latest_block_height: 1,
latest_block_hash: 'DEADBEEF',
latest_block_time: 1337,
},
};
const mockNetInfo = { n_peers: 6, listening: true };
const mockAbciInfo = {
response: {
version: '1.4.1',
app_version: 4,
last_block_height: 90,
last_block_app_hash: 's0CySQxgRg96DrnJ7HCsql+k/Sk4JiT3y0psCaUI3TI=',
},
};

mockFetch
.onFirstCall()
.returns(Promise.resolve({ json: () => Promise.resolve(mockStatus) }))
.onSecondCall()
.returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) }))
.onThirdCall()
.resolves({ json: () => Promise.resolve(mockAbciInfo) });

const scope = await getPlatformScope(config);

expect(scope.tenderdash.serviceStatus).to.equal(ServiceStatusEnum.up);
expect(scope.tenderdash.protocolVersion).to.equal(3);
expect(scope.tenderdash.desiredProtocolVersion).to.equal(4);
});

it('should return platform syncing when it is catching up', async () => {
mockDetermineDockerStatus.returns(DockerStatusEnum.running);
mockRpcClient.mnsync.withArgs('status').returns({ result: { IsSynced: true } });
Expand All @@ -182,6 +248,9 @@ describe('getPlatformScopeFactory', () => {
network: 'test',
moniker: 'test',
},
application_info: {
version: '3',
},
sync_info: {
catching_up: true,
latest_app_hash: 'DEADBEEF',
Expand Down Expand Up @@ -445,6 +514,9 @@ describe('getPlatformScopeFactory', () => {
network: 'test',
moniker: 'test',
},
application_info: {
version: '3',
},
sync_info: {
catching_up: false,
latest_app_hash: 'DEADBEEF',
Expand Down
Loading