Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615263
D13634.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
D13634.diff
View Options
diff --git a/apps/alias-server/index.js b/apps/alias-server/index.js
--- a/apps/alias-server/index.js
+++ b/apps/alias-server/index.js
@@ -24,12 +24,7 @@
polling: true,
});
-async function main(
- chronik,
- telegramBot,
- channelId,
- avalancheCheckWaitInterval,
-) {
+async function main(chronik, telegramBot, channelId, avalancheRpc) {
// Initialize db connection
const db = await initializeDb();
@@ -39,7 +34,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
);
if (aliasWebsocket && aliasWebsocket._subs && aliasWebsocket._subs[0]) {
const subscribedHash160 = aliasWebsocket._subs[0].scriptPayload;
@@ -47,13 +42,7 @@
}
// Get the latest alias information on app startup
- await handleAppStartup(
- chronik,
- db,
- telegramBot,
- channelId,
- avalancheCheckWaitInterval,
- );
+ await handleAppStartup(chronik, db, telegramBot, channelId, avalancheRpc);
// Set up your API endpoints
const app = express();
@@ -81,4 +70,4 @@
app.listen(config.express.port);
}
-main(chronik, telegramBot, channelId, config.avalancheCheckWaitInterval);
+main(chronik, telegramBot, channelId, secrets.avalancheRpc);
diff --git a/apps/alias-server/src/events.js b/apps/alias-server/src/events.js
--- a/apps/alias-server/src/events.js
+++ b/apps/alias-server/src/events.js
@@ -6,6 +6,7 @@
const config = require('../config');
const log = require('./log');
const { wait } = require('./utils');
+const { isFinalBlock } = require('./rpc');
module.exports = {
handleAppStartup: async function (
@@ -13,7 +14,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
) {
log(`Checking for new aliases on startup`);
// If this is app startup, get the latest tipHash and tipHeight by querying the blockchain
@@ -35,7 +36,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
tipHash,
tipHeight,
);
@@ -47,7 +48,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
tipHash,
tipHeight,
) {
@@ -90,10 +91,35 @@
}
}
+ // Initialize isAvalancheFinalized as false. Only set to true if you
+ // prove it so with a node rpc call
+ let isAvalancheFinalized = false;
+
for (let i = 0; i < config.avalancheCheckCount; i += 1) {
- // TODO check isFinalBlock
- wait(avalancheCheckWaitInterval);
- // TODO if isFinalBlock, break loop
+ // Check to see if block tipHash has been finalized by avalanche
+ try {
+ isAvalancheFinalized = await isFinalBlock(
+ avalancheRpc,
+ tipHash,
+ );
+ } catch (err) {
+ log(`Error in isFinalBlock for ${tipHash}`, err);
+ }
+ if (isAvalancheFinalized) {
+ // If isAvalancheFinalized, stop checking
+ break;
+ }
+ wait(config.avalancheCheckWaitInterval);
+ }
+
+ if (!isAvalancheFinalized) {
+ log(
+ `Block ${tipHash} is not avalanche finalized after ${
+ config.avalancheCheckWaitInterval *
+ config.avalancheCheckCount
+ } ms. Exiting handleBlockConnected().`,
+ );
+ return false;
}
// TODO Get the valid aliases already in the db
diff --git a/apps/alias-server/src/websocket.js b/apps/alias-server/src/websocket.js
--- a/apps/alias-server/src/websocket.js
+++ b/apps/alias-server/src/websocket.js
@@ -14,7 +14,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
) {
// Subscribe to chronik websocket
const ws = chronik.ws({
@@ -24,7 +24,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
msg,
);
},
@@ -41,7 +41,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
wsMsg = { type: 'BlockConnected' },
) {
log(`parseWebsocketMessage called on`, wsMsg);
@@ -60,7 +60,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
wsMsg.blockHash,
);
case 'AddedToMempool':
diff --git a/apps/alias-server/test/eventsTests.js b/apps/alias-server/test/eventsTests.js
--- a/apps/alias-server/test/eventsTests.js
+++ b/apps/alias-server/test/eventsTests.js
@@ -4,11 +4,14 @@
'use strict';
const assert = require('assert');
+const mockSecrets = require('../secrets.sample');
const { handleAppStartup } = require('../src/events');
const { MockChronikClient } = require('./mocks/chronikMock');
+const MockAdapter = require('axios-mock-adapter');
+const axios = require('axios');
describe('alias-server events.js', async function () {
- it('handleAppStartup calls handleBlockConnected with tipHeight', async function () {
+ it('handleAppStartup calls handleBlockConnected with tipHeight and completes function if block is avalanche finalized', async function () {
// Initialize chronik mock
const mockedChronik = new MockChronikClient();
@@ -24,17 +27,27 @@
output: mockBlockchaininfoResponse,
});
+ // Mock avalanche RPC call
+ // onNoMatch: 'throwException' helps to debug if mock is not being used
+ const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
+ // Mock response for rpc return of true for isfinalblock method
+ mock.onPost().reply(200, {
+ result: true,
+ error: null,
+ id: 'isfinalblock',
+ });
+
const db = null;
const telegramBot = null;
const channelId = null;
- const avalancheCheckWaitInterval = 0;
+ const { avalancheRpc } = mockSecrets;
const result = await handleAppStartup(
mockedChronik,
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
);
assert.deepEqual(
@@ -42,6 +55,47 @@
`Alias registrations updated to block ${mockBlockchaininfoResponse.tipHash} at height ${mockBlockchaininfoResponse.tipHeight}`,
);
});
+ it('handleAppStartup calls handleBlockConnected with tipHeight and returns false if block is not avalanche finalized', async function () {
+ // Initialize chronik mock
+ const mockedChronik = new MockChronikClient();
+
+ const mockBlockchaininfoResponse = {
+ tipHash:
+ '00000000000000000ce690f27bc92c46863337cc9bd5b7c20aec094854db26e3',
+ tipHeight: 786878,
+ };
+
+ // Tell mockedChronik what response we expect
+ mockedChronik.setMock('blockchainInfo', {
+ input: null,
+ output: mockBlockchaininfoResponse,
+ });
+
+ // Mock avalanche RPC call
+ // onNoMatch: 'throwException' helps to debug if mock is not being used
+ const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
+ // Mock response for rpc return of true for isfinalblock method
+ mock.onPost().reply(200, {
+ result: false,
+ error: null,
+ id: 'isfinalblock',
+ });
+
+ const db = null;
+ const telegramBot = null;
+ const channelId = null;
+ const { avalancheRpc } = mockSecrets;
+
+ const result = await handleAppStartup(
+ mockedChronik,
+ db,
+ telegramBot,
+ channelId,
+ avalancheRpc,
+ );
+
+ assert.deepEqual(result, false);
+ });
it('handleAppStartup returns false on chronik error', async function () {
// Initialize chronik mock
const mockedChronik = new MockChronikClient();
@@ -59,17 +113,19 @@
output: mockBlockchaininfoResponse,
});
+ // Function will not get to RPC call, no need for axios mock
+
const db = null;
const telegramBot = null;
const channelId = null;
- const avalancheCheckWaitInterval = 0;
+ const { avalancheRpc } = mockSecrets;
const result = await handleAppStartup(
mockedChronik,
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
);
assert.deepEqual(result, false);
diff --git a/apps/alias-server/test/mocks/chronikResponses.js b/apps/alias-server/test/mocks/chronikResponses.js
new file mode 100644
--- /dev/null
+++ b/apps/alias-server/test/mocks/chronikResponses.js
@@ -0,0 +1,11 @@
+// Copyright (c) 2023 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+'use strict';
+module.exports = {
+ mockBlock: {
+ blockInfo: {
+ height: 786878,
+ },
+ },
+};
diff --git a/apps/alias-server/test/websocketTests.js b/apps/alias-server/test/websocketTests.js
--- a/apps/alias-server/test/websocketTests.js
+++ b/apps/alias-server/test/websocketTests.js
@@ -10,6 +10,10 @@
parseWebsocketMessage,
} = require('../src/websocket');
const { MockChronikClient } = require('./mocks/chronikMock');
+const { mockBlock } = require('./mocks/chronikResponses');
+const mockSecrets = require('../secrets.sample');
+const MockAdapter = require('axios-mock-adapter');
+const axios = require('axios');
describe('alias-server websocket.js', async function () {
it('initializeWebsocket returns expected websocket object for a p2pkh address', async function () {
@@ -21,7 +25,7 @@
const db = null;
const telegramBot = null;
const channelId = null;
- const avalancheCheckWaitInterval = 0;
+ const { avalancheRpc } = mockSecrets;
const result = await initializeWebsocket(
mockedChronik,
@@ -29,7 +33,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
);
// Confirm websocket opened
@@ -50,7 +54,7 @@
const db = null;
const telegramBot = null;
const channelId = null;
- const avalancheCheckWaitInterval = 0;
+ const { avalancheRpc } = mockSecrets;
const result = await initializeWebsocket(
mockedChronik,
@@ -58,7 +62,7 @@
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
);
// Confirm websocket opened
@@ -70,13 +74,13 @@
{ scriptType: type, scriptPayload: hash },
]);
});
- it('parseWebsocketMessage correctly processes a chronik websocket BlockConnected message', async function () {
+ it('parseWebsocketMessage correctly processes a chronik websocket BlockConnected message if block is avalanche finalized', async function () {
// Initialize chronik mock
const mockedChronik = new MockChronikClient();
const db = null;
const telegramBot = null;
const channelId = null;
- const avalancheCheckWaitInterval = 0;
+ const { avalancheRpc } = mockSecrets;
const wsMsg = {
type: 'BlockConnected',
blockHash:
@@ -92,12 +96,22 @@
input: wsMsg.blockHash,
output: mockBlock,
});
+
+ // Mock avalanche RPC call
+ // onNoMatch: 'throwException' helps to debug if mock is not being used
+ const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
+ // Mock response for rpc return of true for isfinalblock method
+ mock.onPost().reply(200, {
+ result: true,
+ error: null,
+ id: 'isfinalblock',
+ });
const result = await parseWebsocketMessage(
mockedChronik,
db,
telegramBot,
channelId,
- avalancheCheckWaitInterval,
+ avalancheRpc,
wsMsg,
);
@@ -106,4 +120,43 @@
`Alias registrations updated to block ${wsMsg.blockHash} at height ${mockBlock.blockInfo.height}`,
);
});
+ it('parseWebsocketMessage calls handleBlockConnected, which exits if block is not avalanche finalized', async function () {
+ // Initialize chronik mock
+ const mockedChronik = new MockChronikClient();
+ const db = null;
+ const telegramBot = null;
+ const channelId = null;
+ const { avalancheRpc } = mockSecrets;
+ const wsMsg = {
+ type: 'BlockConnected',
+ blockHash:
+ '000000000000000015713b0407590ab1481fd7b8430f87e19cf768bec285ad55',
+ };
+
+ // Tell mockedChronik what response we expect
+ mockedChronik.setMock('block', {
+ input: wsMsg.blockHash,
+ output: mockBlock,
+ });
+
+ // Mock avalanche RPC call
+ // onNoMatch: 'throwException' helps to debug if mock is not being used
+ const mock = new MockAdapter(axios, { onNoMatch: 'throwException' });
+ // Mock response for rpc return of true for isfinalblock method
+ mock.onPost().reply(200, {
+ result: false,
+ error: null,
+ id: 'isfinalblock',
+ });
+ const result = await parseWebsocketMessage(
+ mockedChronik,
+ db,
+ telegramBot,
+ channelId,
+ avalancheRpc,
+ wsMsg,
+ );
+
+ assert.deepEqual(result, false);
+ });
});
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 22, 10:03 (20 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4546868
Default Alt Text
D13634.diff (14 KB)
Attached To
D13634: [alias-server] Check avalanche isFinalBlock in handleBlockConnected
Event Timeline
Log In to Comment