Browse Source

Include contractAddress in OrbitDB Identity

develop
Ezerous 4 years ago
parent
commit
bfb5e75254
  1. 5
      packages/concordia-app/src/options/breezeOptions.js
  2. 3
      packages/concordia-app/src/options/web3Options.js
  3. 2
      packages/concordia-app/src/orbit/levelUtils.js
  4. 10
      packages/concordia-app/src/orbit/orbitUtils.js
  5. 42
      packages/concordia-app/src/orbit/ΕthereumIdentityProvider.js
  6. 16
      packages/concordia-app/src/redux/sagas/orbitSaga.js
  7. 6
      packages/concordia-app/src/redux/sagas/peerDbReplicationSaga.js
  8. 4
      packages/concordia-app/src/views/Topic/TopicCreate/index.jsx
  9. 1
      packages/concordia-contracts/index.js

5
packages/concordia-app/src/options/breezeOptions.js

@ -1,10 +1,5 @@
import { orbitConstants } from '@ezerous/breeze';
import web3Options from './web3Options';
import EthereumIdentityProvider from '../orbit/ΕthereumIdentityProvider';
const { web3 } = web3Options;
EthereumIdentityProvider.setWeb3(web3);
const breezeOptions = {
ipfs: {
config: {

3
packages/concordia-app/src/options/web3Options.js

@ -1,12 +1,9 @@
import Web3 from 'web3';
import EthereumIdentityProvider from '../orbit/ΕthereumIdentityProvider';
const { WEB3_URL, WEB3_PORT } = process.env;
const web3 = new Web3(Web3.givenProvider || `ws://${WEB3_URL}:${WEB3_PORT}`);
EthereumIdentityProvider.setWeb3(web3);
const web3Options = {
web3,
};

2
packages/concordia-app/src/orbit/levelUtils.js

@ -10,7 +10,7 @@ async function storeIdentitySignaturePubKey(key, signaturePubKey) {
}
// If it exists, it returns the identity.signatures.publicKey for the given key (key is the
// concatenation of identity.publicKey + identity.signatures.id
// concatenation of identity.publicKey + identity.signatures.id)
async function getIdentitySignaturePubKey(key) {
try {
return await concordiaDB.get(key);

10
packages/concordia-app/src/orbit/orbitUtils.js

@ -1,4 +1,6 @@
// https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#address
import EthereumIdentityProvider from './ΕthereumIdentityProvider';
async function determineDBAddress({
orbit, dbName, type, identityId,
}) {
@ -8,4 +10,10 @@ async function determineDBAddress({
return `/orbitdb/${ipfsMultihash}/${dbName}`;
}
export default determineDBAddress;
async function determineKVAddress({ orbit, dbName, userAddress }) {
return determineDBAddress({
orbit, dbName, type: 'keyvalue', identityId: userAddress + EthereumIdentityProvider.contractAddress,
});
}
export default determineKVAddress;

42
packages/concordia-app/src/orbit/ΕthereumIdentityProvider.js

@ -12,13 +12,22 @@ class EthereumIdentityProvider extends IdentityProvider {
+ 'Please use setWeb3(web3) first!');
}
if (!EthereumIdentityProvider.contractAddress) {
throw new Error(`${LOGGING_PREFIX}Couldn't create identity, because contractAddress wasn't set. `
+ 'Please use setContractAddress(contractAddress) first!');
}
super(options);
// Orbit's Identity Id (user's Ethereum address) - Optional (will be grabbed later if omitted)
const { id } = options;
if (id) {
if (EthereumIdentityProvider.web3.utils.isAddress(id)) this.id = options.id;
else throw new Error(`${LOGGING_PREFIX}Couldn't create identity, because an invalid id was supplied.`);
const { userAddress, contractAddress } = EthereumIdentityProvider.splitId(id);
if (EthereumIdentityProvider.web3.utils.isAddress(userAddress)
&& EthereumIdentityProvider.contractAddress === contractAddress) {
this.id = id;
this.userAddress = userAddress;
} else throw new Error(`${LOGGING_PREFIX}Couldn't create identity, because an invalid id was supplied.`);
}
}
@ -32,8 +41,8 @@ class EthereumIdentityProvider extends IdentityProvider {
throw new Error(`${LOGGING_PREFIX}Couldn't create identity, because no web3 accounts were found (
locked Metamask?).`);
}
[this.id] = accounts;
[this.userAddress] = accounts;
this.id = this.userAddress + EthereumIdentityProvider.contractAddress;
}
return this.id;
}
@ -44,7 +53,7 @@ class EthereumIdentityProvider extends IdentityProvider {
const signaturePubKey = await getIdentitySignaturePubKey(data);
if (signaturePubKey) {
const identityInfo = {
id: this.id,
userAddress: this.userAddress,
pubKeySignId: data,
signaturePubKey,
};
@ -61,7 +70,7 @@ class EthereumIdentityProvider extends IdentityProvider {
// eslint-disable-next-line consistent-return
async doSignIdentity(data) {
try {
const signaturePubKey = await EthereumIdentityProvider.web3.eth.personal.sign(data, this.id, '');
const signaturePubKey = await EthereumIdentityProvider.web3.eth.personal.sign(data, this.userAddress, '');
if (process.env.NODE_ENV === 'development') {
storeIdentitySignaturePubKey(data, signaturePubKey)
.then(() => {
@ -84,10 +93,12 @@ class EthereumIdentityProvider extends IdentityProvider {
}
static async verifyIdentity(identity) {
const { userAddress } = EthereumIdentityProvider.splitId(identity.id);
// Verify that identity was signed by the ID
return new Promise((resolve) => {
resolve(EthereumIdentityProvider.web3.eth.accounts.recover(identity.publicKey + identity.signatures.id,
identity.signatures.publicKey) === identity.id);
identity.signatures.publicKey) === userAddress);
});
}
@ -95,7 +106,7 @@ class EthereumIdentityProvider extends IdentityProvider {
// Verify that identity was signed by the ID
return new Promise((resolve) => {
resolve(EthereumIdentityProvider.web3.eth.accounts.recover(identityInfo.pubKeySignId,
identityInfo.signaturePubKey) === identityInfo.id);
identityInfo.signaturePubKey) === identityInfo.userAddress);
});
}
@ -103,8 +114,23 @@ class EthereumIdentityProvider extends IdentityProvider {
static setWeb3(web3) {
EthereumIdentityProvider.web3 = web3;
}
// Initialize by supplying a contract's address (to be used as a point of reference)
static setContractAddress(contractAddress) {
EthereumIdentityProvider.contractAddress = contractAddress;
}
static splitId(id) {
const regex = /(0x.*)(0x.*)/g;
const match = regex.exec(id);
if (match && match.length === 3) {
return { userAddress: match[1], contractAddress: match[2] };
}
throw new Error(`${LOGGING_PREFIX}Invalid id ${id}! Couldn't split it to userAddress, contractAddress.`);
}
}
EthereumIdentityProvider.web3 = {};
EthereumIdentityProvider.contractAddress = {};
export default EthereumIdentityProvider;

16
packages/concordia-app/src/redux/sagas/orbitSaga.js

@ -1,11 +1,16 @@
import { put, all, take } from 'redux-saga/effects';
import {
call, put, all, take,
} from 'redux-saga/effects';
import { breezeActions } from '@ezerous/breeze';
import { drizzleActions } from '@ezerous/drizzle';
import { forumContract } from 'concordia-contracts';
import EthereumIdentityProvider from '../../orbit/ΕthereumIdentityProvider';
function* initOrbitDatabases(action) {
const { account, breeze } = action;
yield put(breezeActions.orbit.orbitInit(breeze, account)); // same as breeze.initOrbit(account);
yield put(breezeActions.orbit.orbitInit(breeze, account + EthereumIdentityProvider.contractAddress)); // same as breeze.initOrbit(account);
}
function* orbitSaga() {
@ -15,6 +20,13 @@ function* orbitSaga() {
take(drizzleActions.account.ACCOUNTS_FETCHED),
]);
const { drizzle: { web3 } } = res[0];
const networkId = yield call([web3.eth.net, web3.eth.net.getId]);
const contractAddress = forumContract.networks[networkId].address;
EthereumIdentityProvider.setContractAddress(contractAddress);
EthereumIdentityProvider.setWeb3(web3);
yield initOrbitDatabases({ breeze: res[1].breeze, account: res[2].accounts[0] });
}

6
packages/concordia-app/src/redux/sagas/peerDbReplicationSaga.js

@ -7,12 +7,12 @@ import {
ORBIT_DATABASE_REPLICATED,
ORBIT_DATABASE_WRITE,
} from '@ezerous/breeze/src/orbit/orbitActions';
import determineDBAddress from '../../orbit/orbitUtils';
import determineKVAddress from '../../orbit/orbitUtils';
import { FETCH_USER_DATABASE, UPDATE_ORBIT_DATA } from '../actions/peerDbReplicationActions';
function* fetchUserDb({ orbit, userAddress }) {
const peerDbAddress = yield call(determineDBAddress, {
orbit, dbName: 'topics', type: 'keyvalue', identityId: userAddress,
const peerDbAddress = yield call(determineKVAddress, {
orbit, dbName: 'topics', userAddress,
});
yield put(createOrbitDatabase(orbit, { name: peerDbAddress, type: 'keyvalue' }));

4
packages/concordia-app/src/views/Topic/TopicCreate/index.jsx

@ -81,12 +81,12 @@ const TopicCreate = (props) => {
const postsDb = Object.values(stores).find((store) => store.dbname === 'posts');
topicsDb
.put(topicId, { subject: subjectInput })
.put(topicId, { subject: subjectInput }, { pin: true })
.then(() => postsDb
.put(postId, {
subject: subjectInput,
content: messageInput,
}))
}, { pin: true }))
.then(() => {
history.push(`/topics/${topicId}`);
})

1
packages/concordia-contracts/index.js

@ -10,4 +10,5 @@ try {
module.exports = {
contracts: [Forum],
forumContract: Forum,
};

Loading…
Cancel
Save