Skip to content

Commit

Permalink
#3 Feat: implement pandwidth provider logic
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanBlacky committed Feb 7, 2019
1 parent 09eb4ad commit 3f28a02
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ db
.env
.vscode
test.js
.npmrc
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
"author": "golos.io",
"license": "GPL-3.0",
"dependencies": {
"gls-core-service": "^2.16.1"
"@types/node-fetch": "^2.1.4",
"@types/text-encoding": "0.0.35",
"cyberwayjs": "^20.0.0-beta3.4",
"gls-core-service": "^2.16.1",
"node-fetch": "^2.3.0",
"text-encoding": "^0.7.0"
},
"prettier": {
"singleQuote": true,
Expand Down
17 changes: 15 additions & 2 deletions src/data/env.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
const env = process.env;

if (!env.CMN_PROVIDER_WIF) {
throw new Error('Env variable CMN_PROVIDER_WIF is required!');
}

if (!env.CMN_PROVIDER_USERNAME) {
throw new Error('Env variable CMN_PROVIDER_USERNAME is required!');
}

if (!env.CMN_CYBERWAY_HTTP_URL) {
throw new Error('Env variable CMN_CYBERWAY_HTTP_URL is required!');
}
module.exports = {
GLS_CONNECTOR_HOST: env.GLS_CONNECTOR_HOST || '127.0.0.0',
GLS_CONNECTOR_PORT: env.GLS_CONNECTOR_PORT || 3000,
GLS_PROVIDER_WIF: env.GLS_PROVIDER_WIF,
GLS_PROVIDER_USERNAME: env.GLS_PROVIDER_USERNAME,
CMN_PROVIDER_WIF: env.CMN_PROVIDER_WIF,
CMN_PROVIDER_USERNAME: env.CMN_PROVIDER_USERNAME,
CMN_PROVIDER_PUBLIC_KEY: env.CMN_PROVIDER_PUBLIC_KEY,
GLS_CHANNEL_TTL: env.GLS_CHANNEL_TTL || 1000,
CMN_CYBERWAY_HTTP_URL: env.CMN_CYBERWAY_HTTP_URL,
};
111 changes: 65 additions & 46 deletions src/services/BandwidthProvider.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,70 @@
const { TextEncoder, TextDecoder } = require('text-encoding'); // node only; native TextEncoder/Decoder
const core = require('gls-core-service');
const fetch = require('node-fetch'); // node only; not needed in browsers
const { JsonRpc, Api } = require('cyberwayjs');
const JsSignatureProvider = require('cyberwayjs/dist/eosjs-jssig').default;
const BasicService = core.services.Basic;
const env = require('../data/env');
const { GLS_PROVIDER_WIF, GLS_PROVIDER_USERNAME } = env;
const {
CMN_PROVIDER_WIF,
CMN_PROVIDER_PUBLIC_KEY,
CMN_PROVIDER_USERNAME,
CMN_CYBERWAY_HTTP_URL,
} = env;

const rpc = new JsonRpc(CMN_CYBERWAY_HTTP_URL, { fetch });

const requiredKeys = [CMN_PROVIDER_PUBLIC_KEY];
const signatureProviderBP = new JsSignatureProvider([CMN_PROVIDER_WIF]);

const api = new Api({
rpc,
signatureProviderBP,
textDecoder: new TextDecoder(),
textEncoder: new TextEncoder(),
});

class BandwidthProvider extends BasicService {
constructor({ whitelist }) {
super();

this.whitelist = whitelist;

// we cannot use the service until it's authorized in blockchain
this._authorized = false;

// these are null by default
this._sign = null;
this._secret = null;
}

async start() {
await this.authorize();
start() {
// do nothing, just override default
}

serviceReady() {
// service is ready when and only then there it is authorized and has not-null secret and sign
return this._authorized && this._secret && this._sign;
}
async _signTransaction({ transaction, chainId }) {
const transactionBW = await signatureProviderBP.sign({
chainId,
requiredKeys,
serializedTransaction: transaction.serializedTransaction,
});

async authorize() {
try {
// first call `auth.generateSecret`
const secret = 'secret';
// store the given secret
this._secret = secret;
// secondly, sign the test vote transaction with the secret as a permlink and a user as a voter and the active key
// store the xsign
const xsign = 'sign';
this._sign = xsign;
// send `auth.authorize` request with a secret as a secret, xsign as a sign and user from env as a user

this._authorized = true;
} catch (error) {
console.error(error);
process.exit(1);
}
const transactionBoth = {
...transaction,
signatures: [...transaction.signatures, ...transactionBW.signatures],
serializedTransaction: transaction.serializedTransaction,
};

const { signatures, serializedTransaction } = transactionBoth;

return { signatures, serializedTransaction };
}

async provideBandwidth({ routing: { channelId }, auth: { user }, params: { transaction } }) {
if (!this.serviceReady()) {
await this.authorize();
}
async _sendTransaction({ signatures, serializedTransaction }) {
return await api.pushSignedTransaction({
signatures,
serializedTransaction,
});
}

async provideBandwidth({
routing: { channelId },
auth: { user },
params: { transaction, chainId },
}) {
const isAllowed = await this.whitelist.isAllowed({ channelId, user });

if (!isAllowed) {
Expand All @@ -59,20 +74,24 @@ class BandwidthProvider extends BasicService {
};
}

/*
Контракт: eosio
Действие: providebw
Аргументы: (name provider, name account):
* provider - аккаунт, который предоставляет свой бендвич для выполнения транзакции
* account - аккаунт пользователя, которому предоставляется бендвич
const serializedTransactionBuffer = Uint8Array.from(transaction.serializedTransaction);
transaction.serializedTransaction = serializedTransactionBuffer;

Выполняемое действие:
Предоставить бендвич для выполнения действий другому пользователю. При включении данного действия в транзакцию, CPU/NET бендвич за действия в данной транзакции будут списаны с аккаунты provider вместо их списания с аккаунта account.
const deserializedTransaction = await api.deserializeTransactionWithActions(
transaction.serializedTransaction
);

Данная операция требует разрешения от пользователя provider.
const shouldProvideBandwidth = deserializedTransaction.actions.find(action => {
return action.name === 'providebw' && action.data.provider === CMN_PROVIDER_USERNAME;
});

let transactionToSend = transaction;

if (shouldProvideBandwidth) {
transactionToSend = await this._signTransaction({ transaction, chainId });
}

Данная операция сейчас доступна на тестнете cyberway, но пока не запущен системный смарт-контракт ее действие невозможно увидеть, так как выключен подсчет бендвича.
*/
return await this._sendTransaction(transactionToSend);
}
}

Expand Down

0 comments on commit 3f28a02

Please sign in to comment.