Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move eth-kv store as an example to human-protocol monorepo #18

Merged
merged 9 commits into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
"escrow-dashboard:start": "yarn workspace @human-protocol/escrow-dashboard start",
"escrow-dashboard:test": "yarn workspace @human-protocol/escrow-dashboard test",
"escrow-dashboard:lint": "yarn workspace @human-protocol/escrow-dashboard lint",
"eth-kvstore:lint": "yarn workspace @human-protocol/eth-kvstore-gui lint",
"fortune:test": "yarn workspace @human-protocol/fortune test",
"fortune:lint": "yarn workspace @human-protocol/fortune lint",
"test": "concurrently npm:core:test npm:subgraph:test npm:escrow-dashboard:test npm:fortune:test",
"lint": "concurrently npm:core:lint npm:subgraph:lint npm:escrow-dashboard:lint npm:fortune:lint",
"lint": "concurrently npm:core:lint npm:subgraph:lint npm:escrow-dashboard:lint npm:fortune:lint npm:eth-kvstore:lint",
"prepare": "husky install"
},
"workspaces": [
Expand All @@ -31,11 +32,12 @@
"@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"@typescript-eslint/utils": "^5.42.1",
"concurrently": "^7.5.0",
"dotenv": "^16.0.3",
"eslint": "^8.26.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^27.1.3",
"eslint-plugin-jest": "^27.1.5",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.1",
"jest": "^27.5.1",
Expand Down
23 changes: 23 additions & 0 deletions packages/core/contracts/KVStore.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;

contract KVStore {
uint private constant MAX_STRING_LENGTH = 1000;
mapping(address => mapping(string => string)) private store;

function get(
address _account,
string memory _key
) public view returns (string memory) {
return store[_account][_key];
}

function set(string memory _key, string memory _value) public {
require(
bytes(_key).length <= MAX_STRING_LENGTH &&
bytes(_value).length <= MAX_STRING_LENGTH,
'Maximum string length'
);
store[msg.sender][_key] = _value;
}
}
1 change: 1 addition & 0 deletions packages/core/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const config: HardhatUserConfig = {
url: process.env.FORKING_URL,
}
: undefined,
chainId: 1337,
},
tenderly: {
url: `https://rpc.tenderly.co/fork/${process.env.TENDERLY_FORK_ID}`,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"verify": "hardhat verify",
"test": "hardhat test",
"test:coverage": "hardhat coverage",
"local": "hardhat node",
"local": "concurrently --hide 0 \"hardhat node\" \"yarn deploy:local\"",
"deploy": "hardhat run scripts/deploy.ts",
"deploy:local": "yarn deploy --network localhost",
"lint": "eslint .",
Expand Down Expand Up @@ -51,6 +51,7 @@
"hardhat-abi-exporter": "^2.10.1",
"hardhat-contract-sizer": "^2.6.1",
"hardhat-gas-reporter": "^1.0.9",
"openpgp": "5.5.0",
"prettier-plugin-solidity": "^1.0.0-beta.24",
"solidity-coverage": "^0.8.2",
"tenderly": "^0.0.2",
Expand Down
6 changes: 6 additions & 0 deletions packages/core/scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ async function main() {

// Configure RewardPool in Staking
// await stakingContract.setRewardPool(rewardPoolContract.address);

const KVStore = await ethers.getContractFactory('KVStore');
const kvStoreContract = await KVStore.deploy();
await kvStoreContract.deployed();

console.log('KVStore Address: ', kvStoreContract.address);
}

main().catch((error) => {
Expand Down
91 changes: 91 additions & 0 deletions packages/core/test/KVStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { expect } from 'chai';
import { ethers } from 'hardhat';
import { Signer } from 'ethers';
import { KVStore } from '../typechain-types';
import fs from 'fs';
import path from 'path';
import * as openpgp from 'openpgp';

describe('KVStore', function () {
let accountOne: Signer, accountTwo: Signer;
let kvStore: KVStore;

this.beforeAll(async () => {
[accountOne, accountTwo] = await ethers.getSigners();

const KVStore = await ethers.getContractFactory('KVStore');

kvStore = await KVStore.deploy();
});

it('returns a correct value to the address storing the key-value pair', async () => {
await kvStore.set('satoshi', 'nakamoto');
const value = await kvStore.get(accountOne.getAddress(), 'satoshi');
expect(value).equal('nakamoto');
});

it('returns a correct value to another address', async () => {
await kvStore.set('satoshi', 'nakamoto');
const value = await kvStore
.connect(accountTwo)
.get(accountOne.getAddress(), 'satoshi');
expect(value).equal('nakamoto');
});

it("doesn't allow storing a too long key", async () => {
await expect(
kvStore.set(
'satoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamoto',
'satoshi'
)
).to.be.revertedWith('Maximum string length');
});

it("doesn't allow storing a too long value", async () => {
await expect(
kvStore.set(
'satoshi',
'satoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamotosatoshinakamoto'
)
).to.be.revertedWith('Maximum string length');
});

it('outputs an address on deployment', async () => {
expect(typeof kvStore.address).equal('string');
expect(kvStore.address.length).greaterThanOrEqual(10);
});

it('store public key and its ipfs hash on smart contract', async () => {
await kvStore.set(
'public_key',
'bafkreieadxyvobae4a2ww7tytw37dw2ihvvbujj5npjepurraavtaoczcq'
);

const value = await kvStore.get(accountOne.getAddress(), 'public_key');
expect(value).equal(
'bafkreieadxyvobae4a2ww7tytw37dw2ihvvbujj5npjepurraavtaoczcq'
);
});

it('should store encrypted value and decrypt the value', async () => {
const encrypted = fs.readFileSync(
path.resolve(__dirname, './encrypted_message.txt'),
{ encoding: 'utf8', flag: 'r' }
);
const privkey = fs.readFileSync(
path.resolve(__dirname, './private_key_for_testing'),
{ encoding: 'utf8', flag: 'r' }
);
await kvStore.set('satoshi', encrypted);
const value = await kvStore.get(accountOne.getAddress(), 'satoshi');
expect(value).equal(encrypted);
const message = await openpgp.readMessage({
armoredMessage: encrypted,
});
const { data: decrypted } = await openpgp.decrypt({
message,
decryptionKeys: await openpgp.readPrivateKey({ armoredKey: privkey }),
});
expect(decrypted).equal('H');
});
});
18 changes: 18 additions & 0 deletions packages/core/test/encrypted_message.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-----BEGIN PGP MESSAGE-----

wcFMAwQbsrOc53jzAQ/9FQBU3lay2J/RUQU4zo03iT4rOAhN7uQm9BmIdsp/
ravrKJP46nR70RNo1U1wIow8lDNPkCayttr/nH4YYlsa7gnDj4D+2S7W0kU6
yDQHV6bbz1oo1fPVd4w6lJcRIjPhL12QRoshSfdOEQPjiVE3PW/P6mJGfGLj
TddGFD18rALVF1AiIwjiOT/zz6iYPG9WmJE5E5VtVRHryD/LEiph9eYDwMlC
HxBADlQA7EcQdTH0oEhOqf3V9j+xrn/QCWKDB2PI4jJEa8qIUxvf2GRDhJln
Kj6Qpvtk2RZgSJCP6Zp8h5HZeTr+v0D3GVrXwKdnsAag2fklo0yUvjJ/QoCs
60k2kjkqzaCnNxbhEUC4qYFK7DIOp0OI/CqG9iyAQbcASC7nm4qs1joCHMAN
JHdVSOEpukIME8RUuCCIXXH7/NOL6IyPwtGFu72LjsEEiDOGZedAW+a71GtI
LvxcKO2dSGVx9f0z5vIllK21ldPN7sCnU3eRwfz4apCStBciAKtV6zv76WwN
OfCWo29eoS2za4D8zQS7Dpsk2y+BvjROOGUTnf7iA9kRct97KiEXkVycCUTv
M0ituhWXBITBycXZJNXR/FX4lZvEAOcgjzE2YE6jViJQZlWi1wpoEhnrxuLk
GZwAZS2WFEfCGpg82QLjLl6j+dmpf4eNw02hS1djJhbSPQGFV+WM/qjzw2Eq
HSodkwCKwGnU+52FuwA9ovliUYW4otkS2NQKfGnBZEUjW5J3mc7IWD8/OV2r
eMCWL4Y=
=3hWE
-----END PGP MESSAGE-----
111 changes: 111 additions & 0 deletions packages/core/test/private_key_for_testing
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----

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
wumndWv/YXQ2et6mvZhbcbMFkrIYy1QMixp5ig==
=qeVo
-----END PGP PRIVATE KEY BLOCK-----
4 changes: 4 additions & 0 deletions packages/examples/eth-kvstore-gui/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REACT_APP_NFT_STORAGE_API=
REACT_APP_CONTRACT=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
REACT_APP_ALCHEMY_ID=
REACT_APP_API_URL=https://web-gui-ruby.vercel.app
4 changes: 4 additions & 0 deletions packages/examples/eth-kvstore-gui/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REACT_APP_NFT_STORAGE_API=
REACT_APP_CONTRACT=0x05877184aB2ddAb0F9D1fa6c573392fCe7A7a74a
REACT_APP_ALCHEMY_ID=
REACT_APP_API_URL=
24 changes: 24 additions & 0 deletions packages/examples/eth-kvstore-gui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vercel
Loading