backend: refactor bot commands and identity registration into topics
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 32s Details

This commit is contained in:
Ladd Hoffman 2024-04-30 22:27:21 -05:00
parent b3371c84d9
commit 33a458aba1
8 changed files with 80 additions and 40 deletions

View File

@ -1,4 +1,4 @@
const { getClient } = require('../matrix-bot');
const { getMatrixClient } = require('../matrix-bot');
const { matrixUserToAuthorAddress } = require('../util/db');
const write = require('../util/forum/write');
const { dao, wallet } = require('../util/contracts');
@ -43,7 +43,7 @@ module.exports = async (req, res) => {
console.log('roomId', roomId);
console.log('eventId', eventId);
const client = getClient();
const client = getMatrixClient();
const event = await client.getEvent(roomId, eventId);
console.log('event', event);

View File

@ -5,9 +5,6 @@ const {
SimpleFsStorageProvider,
} = require('matrix-bot-sdk');
const { registerCommands } = require('./commands');
const { registerRoomEventHandler } = require('./room-events');
const {
MATRIX_HOMESERVER_URL,
MATRIX_ACCESS_TOKEN,
@ -17,32 +14,24 @@ const {
const storageProvider = new SimpleFsStorageProvider(BOT_STORAGE_PATH);
const cryptoProvider = new RustSdkCryptoStorageProvider(BOT_CRYPTO_STORAGE_PATH);
let client;
console.log('MATRIX_HOMESERVER_URL:', MATRIX_HOMESERVER_URL);
const client = new MatrixClient(
MATRIX_HOMESERVER_URL,
MATRIX_ACCESS_TOKEN,
storageProvider,
cryptoProvider,
);
let joinedRooms;
const { startOutboundQueue } = require('./outbound-queue');
const start = async () => {
console.log('MATRIX_HOMESERVER_URL:', MATRIX_HOMESERVER_URL);
client = new MatrixClient(
MATRIX_HOMESERVER_URL,
MATRIX_ACCESS_TOKEN,
storageProvider,
cryptoProvider,
);
// Automatically join a room to which we are invited
AutojoinRoomsMixin.setupOnClient(client);
joinedRooms = await client.getJoinedRooms();
console.log('joined rooms:', joinedRooms);
// Before we start the bot, register our command handler
registerCommands(client);
// Handler for custom events
registerRoomEventHandler(client);
client.start().then(() => {
console.log('Bot started!');
// Start the outbound queue
@ -50,9 +39,22 @@ const start = async () => {
});
};
const getClient = () => client;
const registerMessageHandler = (eventHandler) => {
client.on('room.message', (roomId, event) => eventHandler(client, roomId, event));
};
const registerEventHandler = (eventHandler) => {
client.on('room.event', (roomId, event) => {
if (event.state_key !== undefined) return; // state event
eventHandler(client, roomId, event);
});
};
const getMatrixClient = () => client;
module.exports = {
start,
getClient,
getMatrixClient,
registerMessageHandler,
registerEventHandler,
};

View File

@ -1,4 +1,5 @@
const { setTargetRoomId } = require('./outbound-queue');
const { registerMessageHandler } = require('../matrix-bot');
const { setTargetRoomId } = require('../matrix-bot/outbound-queue');
const {
appState,
@ -53,10 +54,10 @@ const handleCommand = async (client, roomId, event) => {
}
};
const registerCommands = (client) => {
client.on('room.message', (roomId, event) => handleCommand(client, roomId, event));
const start = () => {
registerMessageHandler(handleCommand);
};
module.exports = {
registerCommands,
start,
};

View File

@ -2,12 +2,16 @@ const proposalsNotifier = require('./proposals-notifier');
const validationPools = require('./validation-pools');
const work1 = require('./work1');
const rollup = require('./rollup');
const registerIdentity = require('./register-identity');
const botCommands = require('./bot-commands');
const start = () => {
proposalsNotifier.start();
validationPools.start();
work1.start();
rollup.start();
registerIdentity.start();
botCommands.start();
};
module.exports = {

View File

@ -4,8 +4,10 @@ const {
matrixUserToAuthorAddress,
authorAddressToMatrixUser,
} = require('../util/db');
const { registerEventHandler } = require('../matrix-bot');
const handleRegisterIdentity = async (client, roomId, event) => {
if (event.type !== 'io.dgov.identity.register') return;
const { message, signature } = event.content;
console.log('Received request to register identity');
let account;
@ -31,20 +33,10 @@ const handleRegisterIdentity = async (client, roomId, event) => {
}
};
const registerRoomEventHandler = (client) => {
client.on('room.event', (roomId, event) => {
// Note that state events can also be sent down this listener too
if (event.state_key !== undefined) return; // state event
switch (event.type) {
case 'io.dgov.identity.register':
handleRegisterIdentity(client, roomId, event);
break;
default:
}
});
const start = () => {
registerEventHandler(handleRegisterIdentity);
};
module.exports = {
registerRoomEventHandler,
start,
};

View File

@ -1,5 +1,7 @@
const { getContractAddressByNetworkName } = require('../util/contract-config');
const { registerDecider } = require('./validation-pools');
const { registerEventHandler } = require('../matrix-bot');
const { matrixPools } = require('../util/db');
const {
ETH_NETWORK,
@ -13,10 +15,44 @@ const start = async () => {
// If this is not sent by the work1 contract, it's not of interest here.
if (pool.sender !== rollupAddress) return false;
// TODO: to derive the expected content here, we need information from Matrix.
// A rollup post should contain
// - a list of off-chain validation pools
// - authorship corresponding to the result of those off-chain pools
if (!post.embeddedData?.matrixPools) return false;
// TODO: Compute expected result by fetching off-chain pool matrix events
// TODO: Or precompute? Since we want to be computing that anyway.
return false;
});
// We can use LevelDB to store information about validation pools
registerEventHandler(async (client, roomId, event) => {
switch (event.type) {
case 'io.dgov.pool.start': {
// Use the event id as the validation pool id
const poolId = event.event_id;
// TODO: This event should include validation pool params
console.log('Matrix pool started', { poolId });
await matrixPools.put(poolId, {});
break;
}
case 'io.dgov.pool.stake': {
// TODO: Keep track of stakes
break;
}
case 'io.dgov.pool.result': {
// This should be sent by the current batch worker
// TODO: Compare batch worker's result with ours to verify and provide early warning
break;
}
case 'io.dgov.rollup.submit': {
// TODO: Compare batch worker's result with ours to verify
break;
}
default:
}
});
};
module.exports = {

View File

@ -11,4 +11,5 @@ module.exports = {
referendumEventIds: new Level(`${dataDir}/referendumEventIds`, { keyEncoding: 'json' }),
matrixUserToAuthorAddress: new Level(`${dataDir}/matrixUserToAuthorAddress`),
authorAddressToMatrixUser: new Level(`${dataDir}/authorAddressToMatrixUser`),
matrixPools: new Level(`${dataDir}/matrixPools`, { valueEncoding: 'json' }),
};

View File

@ -63,6 +63,10 @@ contract Bench {
uint256 amount,
bool inFavor
) external {
require(
msg.sender == address(dao),
"Only DAO contract may call stakeOnValidationPool"
);
ValidationPool storage pool = validationPools[poolIndex];
require(
block.timestamp <= pool.props.endTime,