Merge pull request #220 from status-im/eth-dm-clean-up

This commit is contained in:
Franck Royer 2021-07-05 09:55:17 +10:00 committed by GitHub
commit db6bb95a9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 57 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- **Breaking**: Auto select peer if none provided for store and light push protocols. - **Breaking**: Auto select peer if none provided for store and light push protocols.
- Upgrade to `libp2p@0.31.7` and `libp2p-gossipsub@0.10.0` to avoid `TextEncoder` errors in ReactJS tests. - Upgrade to `libp2p@0.31.7` and `libp2p-gossipsub@0.10.0` to avoid `TextEncoder` errors in ReactJS tests.
- Disable keep alive by default as latest nim-waku release does not support ping protocol.
### Fixed ### Fixed
- Disable `keepAlive` if set to `0`. - Disable `keepAlive` if set to `0`.

View File

@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
import './App.css'; import './App.css';
import { Waku } from 'js-waku'; import { Waku } from 'js-waku';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { Web3Provider } from '@ethersproject/providers'; import { Signer } from '@ethersproject/abstract-signer';
import { KeyPair } from './crypto'; import { KeyPair } from './crypto';
import { Message } from './messaging/Messages'; import { Message } from './messaging/Messages';
import 'fontsource-roboto'; import 'fontsource-roboto';
@ -52,12 +52,18 @@ const useStyles = makeStyles({
flex: 1, flex: 1,
margin: '10px', margin: '10px',
}, },
wakuStatus: {}, wakuStatus: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
peers: {},
}); });
function App() { function App() {
const [waku, setWaku] = useState<Waku>(); const [waku, setWaku] = useState<Waku>();
const [provider, setProvider] = useState<Web3Provider>(); const [signer, setSigner] = useState<Signer>();
const [ethDmKeyPair, setEthDmKeyPair] = useState<KeyPair | undefined>(); const [ethDmKeyPair, setEthDmKeyPair] = useState<KeyPair | undefined>();
const [publicKeys, setPublicKeys] = useState<Map<string, string>>(new Map()); const [publicKeys, setPublicKeys] = useState<Map<string, string>>(new Map());
const [messages, setMessages] = useState<Message[]>([]); const [messages, setMessages] = useState<Message[]>([]);
@ -66,36 +72,37 @@ function App() {
const classes = useStyles(); const classes = useStyles();
useEffect(() => { useEffect(() => {
if (provider) return;
try { try {
window.ethereum.request({ method: 'eth_requestAccounts' }); window.ethereum
.request({ method: 'eth_requestAccounts' })
.then((accounts: string[]) => {
const _provider = new ethers.providers.Web3Provider(window.ethereum); const _provider = new ethers.providers.Web3Provider(window.ethereum);
setProvider(_provider); setAddress(accounts[0]);
setSigner(_provider.getSigner());
});
} catch (e) { } catch (e) {
console.error('No web3 provider available'); console.error('No web3 provider available');
} }
}, [provider]); }, [address, signer]);
useEffect(() => { let peers = 0;
provider
?.getSigner()
.getAddress()
.then((address) => setAddress(address));
});
let peers;
if (waku) { if (waku) {
peers = waku.libp2p.connectionManager.connections.size; peers = waku.libp2p.connectionManager.connections.size;
} }
let addressDisplay = '';
if (address) {
addressDisplay =
address.substr(0, 6) + '...' + address.substr(address.length - 4, 4);
}
return ( return (
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<div className={classes.root}> <div className={classes.root}>
<AppBar className={classes.appBar} position="static"> <AppBar className={classes.appBar} position="static">
<Toolbar> <Toolbar>
<Typography>Ethereum Direct Message</Typography>
<IconButton <IconButton
edge="end" edge="start"
className={classes.wakuStatus} className={classes.wakuStatus}
aria-label="waku-status" aria-label="waku-status"
> >
@ -104,7 +111,13 @@ function App() {
style={waku ? { color: green[500] } : {}} style={waku ? { color: green[500] } : {}}
/> />
</IconButton> </IconButton>
<Typography>{peers}</Typography> <Typography className={classes.peers} aria-label="connected-peers">
{peers} peer{peers && peers > 1 ? 's' : ''}
</Typography>
<Typography variant="h6" className={classes.title}>
Ethereum Direct Message
</Typography>
<Typography>{addressDisplay}</Typography>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
@ -125,7 +138,7 @@ function App() {
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)} setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
/> />
<BroadcastPublicKey <BroadcastPublicKey
signer={provider?.getSigner()} signer={signer}
ethDmKeyPair={ethDmKeyPair} ethDmKeyPair={ethDmKeyPair}
waku={waku} waku={waku}
/> />

View File

@ -1,13 +1,9 @@
import { Dispatch, SetStateAction, useEffect } from 'react'; import { Dispatch, SetStateAction, useEffect } from 'react';
import { Environment, getStatusFleetNodes, Waku, WakuMessage } from 'js-waku'; import { Environment, getStatusFleetNodes, Waku, WakuMessage } from 'js-waku';
import { import { decode, DirectMessage, PublicKeyMessage } from './messaging/wire';
bytesToHexStr,
decode,
DirectMessage,
PublicKeyMessage,
} from './messaging/wire';
import { decryptMessage, KeyPair, validatePublicKeyMessage } from './crypto'; import { decryptMessage, KeyPair, validatePublicKeyMessage } from './crypto';
import { Message } from './messaging/Messages'; import { Message } from './messaging/Messages';
import { byteArrayToHex } from './utils';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/proto'; export const PublicKeyContentTopic = '/eth-dm/1/public-key/proto';
export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json'; export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json';
@ -106,12 +102,7 @@ async function initWaku(): Promise<Waku> {
} }
function getNodes() { function getNodes() {
// Works with react-scripts
if (process?.env?.NODE_ENV === 'development') {
return getStatusFleetNodes(Environment.Test);
} else {
return getStatusFleetNodes(Environment.Prod); return getStatusFleetNodes(Environment.Prod);
}
} }
function handlePublicKeyMessage( function handlePublicKeyMessage(
@ -123,7 +114,7 @@ function handlePublicKeyMessage(
if (!msg.payload) return; if (!msg.payload) return;
const publicKeyMsg = PublicKeyMessage.decode(msg.payload); const publicKeyMsg = PublicKeyMessage.decode(msg.payload);
if (!publicKeyMsg) return; if (!publicKeyMsg) return;
const ethDmPublicKey = bytesToHexStr(publicKeyMsg.ethDmPublicKey); const ethDmPublicKey = byteArrayToHex(publicKeyMsg.ethDmPublicKey);
if (ethDmPublicKey === myPublicKey) return; if (ethDmPublicKey === myPublicKey) return;
const res = validatePublicKeyMessage(publicKeyMsg); const res = validatePublicKeyMessage(publicKeyMsg);
@ -131,7 +122,7 @@ function handlePublicKeyMessage(
if (res) { if (res) {
setter((prevPks: Map<string, string>) => { setter((prevPks: Map<string, string>) => {
prevPks.set(bytesToHexStr(publicKeyMsg.ethAddress), ethDmPublicKey); prevPks.set(byteArrayToHex(publicKeyMsg.ethAddress), ethDmPublicKey);
return new Map(prevPks); return new Map(prevPks);
}); });
} }

View File

@ -3,11 +3,8 @@ import '@ethersproject/shims';
import * as EthCrypto from 'eth-crypto'; import * as EthCrypto from 'eth-crypto';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { Signer } from '@ethersproject/abstract-signer'; import { Signer } from '@ethersproject/abstract-signer';
import { import { DirectMessage, PublicKeyMessage } from './messaging/wire';
bytesToHexStr, import { byteArrayToHex, hexToBuf } from './utils';
DirectMessage,
PublicKeyMessage,
} from './messaging/wire';
export interface KeyPair { export interface KeyPair {
privateKey: string; privateKey: string;
@ -33,21 +30,15 @@ export async function createPublicKeyMessage(
ethDmPublicKey: string ethDmPublicKey: string
): Promise<PublicKeyMessage> { ): Promise<PublicKeyMessage> {
const ethAddress = await web3Signer.getAddress(); const ethAddress = await web3Signer.getAddress();
const bytesEthDmPublicKey = Buffer.from( const bytesEthDmPublicKey = hexToBuf(ethDmPublicKey);
ethDmPublicKey.replace(/0x/, ''),
'hex'
);
const signature = await web3Signer.signMessage( const signature = await web3Signer.signMessage(
formatPublicKeyForSignature(bytesEthDmPublicKey) formatPublicKeyForSignature(bytesEthDmPublicKey)
); );
const bytesEthAddress = Buffer.from(ethAddress.replace(/0x/, ''), 'hex');
const bytesSignature = Buffer.from(signature.replace(/0x/, ''), 'hex');
return new PublicKeyMessage({ return new PublicKeyMessage({
ethDmPublicKey: bytesEthDmPublicKey, ethDmPublicKey: bytesEthDmPublicKey,
ethAddress: bytesEthAddress, ethAddress: hexToBuf(ethAddress),
signature: bytesSignature, signature: hexToBuf(signature),
}); });
} }
@ -58,7 +49,7 @@ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean {
const formattedMsg = formatPublicKeyForSignature(msg.ethDmPublicKey); const formattedMsg = formatPublicKeyForSignature(msg.ethDmPublicKey);
try { try {
const sigAddress = ethers.utils.verifyMessage(formattedMsg, msg.signature); const sigAddress = ethers.utils.verifyMessage(formattedMsg, msg.signature);
const sigAddressBytes = Buffer.from(sigAddress.replace(/0x/, ''), 'hex'); const sigAddressBytes = hexToBuf(sigAddress);
// Compare the actual byte arrays instead of strings that may differ in casing or prefixing. // Compare the actual byte arrays instead of strings that may differ in casing or prefixing.
const cmp = sigAddressBytes.compare(new Buffer(msg.ethAddress)); const cmp = sigAddressBytes.compare(new Buffer(msg.ethAddress));
console.log( console.log(
@ -86,7 +77,7 @@ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean {
*/ */
function formatPublicKeyForSignature(ethDmPublicKey: Uint8Array): string { function formatPublicKeyForSignature(ethDmPublicKey: Uint8Array): string {
return JSON.stringify({ return JSON.stringify({
ethDmPublicKey: bytesToHexStr(ethDmPublicKey), ethDmPublicKey: byteArrayToHex(ethDmPublicKey),
}); });
} }

View File

@ -56,11 +56,6 @@ export class PublicKeyMessage {
} }
} }
export function bytesToHexStr(bytes: Uint8Array): string {
const buf = new Buffer(bytes);
return buf.toString('hex');
}
/** /**
* Direct Encrypted Message used for private communication over the Waku network. * Direct Encrypted Message used for private communication over the Waku network.
*/ */

View File

@ -0,0 +1,8 @@
export function byteArrayToHex(bytes: Uint8Array): string {
const buf = new Buffer(bytes);
return buf.toString('hex');
}
export function hexToBuf(str: string): Buffer {
return Buffer.from(str.replace(/0x/, ''), 'hex');
}

View File

@ -76,7 +76,7 @@ export class Waku {
this.lightPush = lightPush; this.lightPush = lightPush;
this.keepAliveTimers = {}; this.keepAliveTimers = {};
const keepAlive = options.keepAlive !== undefined ? options.keepAlive : 10; const keepAlive = options.keepAlive !== undefined ? options.keepAlive : 0;
if (keepAlive !== 0) { if (keepAlive !== 0) {
libp2p.connectionManager.on('peer:connect', (connection: Connection) => { libp2p.connectionManager.on('peer:connect', (connection: Connection) => {

View File

@ -114,7 +114,7 @@ export class WakuRelay extends Gossipsub {
*/ */
public async send(message: WakuMessage): Promise<void> { public async send(message: WakuMessage): Promise<void> {
const msg = message.encode(); const msg = message.encode();
await super.publish(this.pubsubTopic, Buffer.from(msg)); await super.publish(this.pubsubTopic, new Buffer(msg));
} }
/** /**