Skip to content

Commit

Permalink
feat: process signed messages
Browse files Browse the repository at this point in the history
  • Loading branch information
mistakia committed Jun 18, 2024
1 parent e633e74 commit 9c7703d
Show file tree
Hide file tree
Showing 10 changed files with 501 additions and 57 deletions.
57 changes: 33 additions & 24 deletions api/routes/auth/message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ACCOUNT_TRACKING_MINIMUM_BALANCE,
REPRESENTATIVE_TRACKING_MINIMUM_VOTING_WEIGHT
} from '#constants'
import { process_community_message } from '#libs-server'

const router = express.Router()

Expand All @@ -29,9 +30,9 @@ router.post('/?', async (req, res) => {
public_key,
operation,
content,
tags,
tags = [],

references,
references = [],

created_at,

Expand Down Expand Up @@ -68,7 +69,12 @@ router.post('/?', async (req, res) => {
}

// operation must be SET or DELETE
const allowed_operations = ['SET', 'SET_ACCOUNT_META', 'SET_BLOCK_META']
const allowed_operations = [
'SET',
'SET_ACCOUNT_META',
'SET_REPRESENTATIVE_META',
'SET_BLOCK_META'
]
if (!allowed_operations.includes(operation)) {
return res.status(400).json({ error: 'Invalid operation' })
}
Expand Down Expand Up @@ -117,37 +123,31 @@ router.post('/?', async (req, res) => {
}

// public_key can be a linked keypair or an existing nano account
const linked_accounts = await db('account_keys')

const linked_account = await db('account_keys')
.select('account')
.where({ public_key })
.whereNull('revoked_at')
const nano_account = encode_nano_address({
public_key_buf: Buffer.from(public_key, 'hex')
})
.first()

const all_accounts = [
...linked_accounts.map((row) => row.account),
nano_account
]
const message_nano_account = linked_account
? linked_account.account
: encode_nano_address({
public_key_buf: Buffer.from(public_key, 'hex')
})

const accounts_info = []
for (const account of all_accounts) {
const account_info = await rpc.accountInfo({ account })
if (account_info) {
accounts_info.push(account_info)
}
}
const account_info = await rpc.accountInfo({
account: message_nano_account
})

// check if any of the accounts have a balance beyond the tracking threshold
const has_balance = accounts_info.some((account_info) =>
new BigNumber(account_info.balance).gte(ACCOUNT_TRACKING_MINIMUM_BALANCE)
const has_balance = new BigNumber(account_info?.balance || 0).gte(
ACCOUNT_TRACKING_MINIMUM_BALANCE
)

// check if any of the accounts have weight beyond the tracking threshold
const has_weight = accounts_info.some((account_info) =>
new BigNumber(account_info.weight).gte(
REPRESENTATIVE_TRACKING_MINIMUM_VOTING_WEIGHT
)
const has_weight = new BigNumber(account_info?.weight || 0).gte(
REPRESENTATIVE_TRACKING_MINIMUM_VOTING_WEIGHT
)

if (has_balance || has_weight) {
Expand Down Expand Up @@ -175,6 +175,15 @@ router.post('/?', async (req, res) => {
.merge()
}

try {
await process_community_message({
message,
message_account: message_nano_account
})
} catch (error) {
logger(error)
}

res.status(200).send({
version,

Expand Down
14 changes: 8 additions & 6 deletions cli/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ const send_message_handler = async (type, block_hash = null) => {
{ name: 'donation_address', message: 'Donation Address:' },
{ name: 'cpu_model', message: 'CPU Model:' },
{ name: 'cpu_cores', message: 'CPU Cores:' },
{ name: 'ram_amount', message: 'RAM Amount:' },
{ name: 'reddit_username', message: 'Reddit Username:' },
{ name: 'twitter_username', message: 'Twitter Username:' },
{ name: 'discord_username', message: 'Discord Username:' },
{ name: 'github_username', message: 'GitHub Username:' },
{ name: 'ram', message: 'RAM Amount (GB):' },
{ name: 'reddit', message: 'Reddit Username:' },
{ name: 'twitter', message: 'Twitter Username:' },
{ name: 'discord', message: 'Discord Username:' },
{ name: 'github', message: 'GitHub Username:' },
{ name: 'email', message: 'Email:' },
{ name: 'website_url', message: 'Website URL:' }
{ name: 'website', message: 'Website URL:' }
]
break
case 'update-account-meta':
Expand Down Expand Up @@ -244,6 +244,8 @@ const send_message_handler = async (type, block_hash = null) => {
let operation = ''
switch (type) {
case 'update-rep-meta':
operation = 'SET_REPRESENTATIVE_META'
break
case 'update-account-meta':
operation = 'SET_ACCOUNT_META'
break
Expand Down
18 changes: 17 additions & 1 deletion db/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ CREATE TABLE `accounts` (
-- --------------------------------------------------------

--
-- Table structure for table `accounts_changelog`
--

DROP TABLE IF EXISTS `accounts_changelog`;

CREATE TABLE `accounts_changelog` (
`account` char(65) NOT NULL,
`column` varchar(65) NOT NULL,
`previous_value` varchar(1000) CHARACTER SET utf8mb4 DEFAULT '',
`new_value` varchar(1000) CHARACTER SET utf8mb4 DEFAULT '',
`timestamp` int(11) NOT NULL,
UNIQUE `change` (`account`, `column`, `previous_value`(60), `new_value`(60))
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;

-- ----------------------------------------------------------
-- Table structure for table `account_keys`
--

Expand Down Expand Up @@ -225,7 +240,7 @@ CREATE TABLE `nano_community_messages` (
`entry_clock` int(10) unsigned DEFAULT NULL,
`chain_clock` int(10) unsigned DEFAULT NULL,
`public_key` varchar(64) NOT NULL,
`operation` varchar(10) NOT NULL,
`operation` varchar(50) NOT NULL,
`content` text CHARACTER SET utf8mb4 DEFAULT NULL,
`tags` text CHARACTER SET utf8mb4 DEFAULT NULL,
`references` text CHARACTER SET utf8mb4 DEFAULT NULL,
Expand Down Expand Up @@ -295,6 +310,7 @@ CREATE TABLE `representatives_meta_index` (
`bandwidth_description` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`ram` int(3) DEFAULT NULL,
`ram_description` varchar(255) DEFAULT NULL,
`donation_address` char(65) DEFAULT NULL,

`description` varchar(1000) CHARACTER SET utf8mb4 DEFAULT NULL,
`dedicated` tinyint(1) DEFAULT NULL,
Expand Down
3 changes: 3 additions & 0 deletions libs-server/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as update_account } from './update-account.mjs'
export { default as update_representative_meta } from './update-representative-meta.mjs'
export { default as process_community_message } from './process-community-message.mjs'
116 changes: 116 additions & 0 deletions libs-server/process-community-message.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import debug from 'debug'

import update_account from './update-account.mjs'
import update_representative_meta from './update-representative-meta.mjs'

const log = debug('process-community-message')

const process_set_representative_meta = async ({
message_content,
message_account
}) => {
if (!message_content) {
log(
`No message content found for SET_REPRESENTATIVE_META message from ${message_account}`
)
return
}

const { alias } = message_content
if (alias) {
await update_account({
account_address: message_account,
update: { alias }
})
}

const {
cpu_cores,
description,
donation_address,
cpu_model,
ram,
reddit,
twitter,
discord,
github,
email,
website
} = message_content

await update_representative_meta({
representative_account_address: message_account,
update: {
cpu_cores,
description,
donation_address,
cpu_model,
ram,
reddit,
twitter,
discord,
github,
email,
website
}
})
}

const process_set_account_meta = async ({
message_content,
message_account
}) => {
if (!message_content) {
log(
`No message content found for SET_ACCOUNT_META message from ${message_account}`
)
return
}

const { alias } = message_content
if (alias) {
await update_account({
account_address: message_account,
update: { alias }
})
}
}

export default async function process_community_message({
message,
message_account
}) {
let message_content
try {
message_content = JSON.parse(message.content)
} catch (error) {
log(`Error parsing message content: ${error}`)
return
}

if (!message_content) {
log(
`No message content found for ${message.operation} message from ${message_account}`
)
return
}

switch (message.operation) {
case 'SET_ACCOUNT_META':
return process_set_account_meta({
message,
message_content,
message_account
})

case 'SET_REPRESENTATIVE_META':
return process_set_representative_meta({
message,
message_content,
message_account
})

default:
log(`Unsupported message operation: ${message.operation}`)
}
}
Loading

0 comments on commit 9c7703d

Please sign in to comment.