From 6703946b7de4535e7ed0152cb73ad4befc81bf18 Mon Sep 17 00:00:00 2001 From: VargaElod23 Date: Fri, 28 Apr 2023 14:10:47 +0300 Subject: [PATCH 1/3] WIP: start integration with backend --- services/delegation/src/config/delegation.ts | 2 +- .../modules/blockchain/blockchain.service.ts | 12 +++-- .../modules/delegation/delegation.service.ts | 48 ++----------------- .../src/modules/node/node.consumer.ts | 2 + 4 files changed, 16 insertions(+), 48 deletions(-) diff --git a/services/delegation/src/config/delegation.ts b/services/delegation/src/config/delegation.ts index 42a44d059..74e1a874c 100644 --- a/services/delegation/src/config/delegation.ts +++ b/services/delegation/src/config/delegation.ts @@ -27,7 +27,7 @@ export default registerAs('delegation', () => { testnetDelegation: ethers.BigNumber.from(1000000).mul( ethers.BigNumber.from(10).pow(18), ), - mainnetDelegation: ethers.BigNumber.from(10).pow(18), + mainnetDelegation: ethers.BigNumber.from(10).pow(18), // not sure why this is here testnetOwnNodes: ownNodes, undelegationConfirmationDelay: Number( process.env.NR_BLOCKS_UNDELEGATION_DELAY || 5, diff --git a/services/delegation/src/modules/blockchain/blockchain.service.ts b/services/delegation/src/modules/blockchain/blockchain.service.ts index 2d68b444b..9684db08c 100644 --- a/services/delegation/src/modules/blockchain/blockchain.service.ts +++ b/services/delegation/src/modules/blockchain/blockchain.service.ts @@ -30,6 +30,7 @@ export class BlockchainService { 'function getValidator(address validator) view returns (tuple(uint256 total_stake, uint256 commission_reward, uint16 commission, uint64 last_commission_change, address owner, string description, string endpoint) validator_info)', 'function getValidators(uint32 batch) view returns (tuple(address account, tuple(uint256 total_stake, uint256 commission_reward, uint16 commission, uint64 last_commission_change, address owner, string description, string endpoint) info)[] validators, bool end)', 'function registerValidator(address validator, bytes proof, bytes vrf_key, uint16 commission, string description, string endpoint) payable', + 'function addInternalValidator(address validator) external', ], this.provider, ).connect(this.wallet); @@ -74,10 +75,12 @@ export class BlockchainService { address: string, addressProof: string, vrfKey: string, + internal = false, ) { - await this.rebalanceOwnNodes(true); - try { + const validatorData = await this.contract.getValidator(address); + if (validatorData && validatorData.owner) return true; + const tx = await this.contract.registerValidator( address, addressProof, @@ -91,11 +94,14 @@ export class BlockchainService { }, ); await tx.wait(); + if (internal) { + const registration = await this.contract.addInternalValidator(address); + await registration.wait(); + } return true; } catch (e) { console.error(`Could not create validator ${address}`, e); } - return false; } diff --git a/services/delegation/src/modules/delegation/delegation.service.ts b/services/delegation/src/modules/delegation/delegation.service.ts index 5338b79bb..5d4872f9f 100644 --- a/services/delegation/src/modules/delegation/delegation.service.ts +++ b/services/delegation/src/modules/delegation/delegation.service.ts @@ -288,8 +288,10 @@ export class DelegationService { async ensureDelegation(nodeId: number, type: string, address: string) { // Check if node exists in the database let node: Node; + let isInternal = false; try { node = await this.nodeRepository.findOneOrFail({ id: nodeId }); + isInternal = node.isOwnValidator; } catch (e) { node = null; } @@ -350,6 +352,7 @@ export class DelegationService { address, node.addressProof, node.vrfKey, + isInternal, ); } if (type === NodeType.MAINNET) { @@ -358,6 +361,7 @@ export class DelegationService { address, node.addressProof, node.vrfKey, + isInternal, ); if (isCreatedOnchain) { toDelegate = totalNodeDelegation.sub( @@ -444,50 +448,6 @@ export class DelegationService { .outbound_deposits; } - async rebalanceMainnet() { - const ownNodes = await this.getOwnNodes('mainnet'); - - for (const node of ownNodes) { - const nodeEntity = await this.nodeRepository.findOne({ where: { node } }); - await this.ensureDelegation(nodeEntity?.id, NodeType.MAINNET, node); - } - } - - private async getOwnNodes(type: 'mainnet' | 'testnet'): Promise { - let endpoint: string; - if (type === 'mainnet') { - endpoint = this.config.get('ethereum.mainnetEndpoint'); - } else { - endpoint = this.config.get('ethereum.testnetEndpoint'); - } - - const state = await this.httpService - .post( - endpoint, - { - jsonrpc: '2.0', - method: 'taraxa_getConfig', - params: [], - id: 1, - }, - { - headers: { - 'Content-Type': 'application/json', - }, - }, - ) - .toPromise(); - - if (state.status !== 200) { - throw new Error('Failed to get DPOS stake'); - } - - const genesisState = state.data.result.final_chain.state.dpos.genesis_state; - const genesisStateKey = Object.keys(genesisState)[0]; - - return Object.keys(genesisState[genesisStateKey]); - } - async getDelegators() { const d = this.delegationRepository .createQueryBuilder('d') diff --git a/services/delegation/src/modules/node/node.consumer.ts b/services/delegation/src/modules/node/node.consumer.ts index 9e4a31dca..824f16888 100644 --- a/services/delegation/src/modules/node/node.consumer.ts +++ b/services/delegation/src/modules/node/node.consumer.ts @@ -94,6 +94,7 @@ export class NodeConsumer implements OnModuleInit { node.address, node.addressProof, node.vrfKey, + node.isOwnValidator, ); } @@ -103,6 +104,7 @@ export class NodeConsumer implements OnModuleInit { node.address, node.addressProof, node.vrfKey, + node.isOwnValidator, ); } await this.nodeRepository.save(node); From 1ac92733c33d4b854d357ec6cfedca3373b8fecd Mon Sep 17 00:00:00 2001 From: VargaElod23 Date: Fri, 28 Apr 2023 17:27:32 +0300 Subject: [PATCH 2/3] refactor cli to call new proxy contract --- services/delegation/.env.dist | 3 +- .../templates/configmap.yaml | 2 +- .../charts/community-delegation/values.yaml | 1 + services/delegation/src/config/delegation.ts | 15 -- services/delegation/src/config/ethereum.ts | 1 + .../modules/blockchain/blockchain.module.ts | 2 +- .../modules/blockchain/blockchain.service.ts | 133 +----------------- .../modules/delegation/delegation.service.ts | 18 --- .../src/modules/node/node.consumer.ts | 21 --- 9 files changed, 9 insertions(+), 187 deletions(-) diff --git a/services/delegation/.env.dist b/services/delegation/.env.dist index 64a461bb8..b10330ab0 100644 --- a/services/delegation/.env.dist +++ b/services/delegation/.env.dist @@ -13,4 +13,5 @@ MAINNET_EXPLORER_URL=https://explorer.mainnet.taraxa.io TESTNET_EXPLORER_URL=https://explorer.testnet.taraxa.io INDEXER_STAKING_URL=http://localhost:8000/subgraphs/name/taraxa_project/staking PORT=3001 -NR_BLOCKS_UNDELEGATION_DELAY=5 \ No newline at end of file +NR_BLOCKS_UNDELEGATION_DELAY=5 +DPOS_PROXY_ADDRESS=0x0000000000000000000000000000000000000000 \ No newline at end of file diff --git a/services/delegation/charts/community-delegation/templates/configmap.yaml b/services/delegation/charts/community-delegation/templates/configmap.yaml index 350b653a2..e10e96472 100644 --- a/services/delegation/charts/community-delegation/templates/configmap.yaml +++ b/services/delegation/charts/community-delegation/templates/configmap.yaml @@ -17,5 +17,5 @@ data: MAINNET_INDEXER_URL: {{ .Values.app.mainnetIndexerUrl | quote }} TESTNET_INDEXER_URL: {{ .Values.app.testnetIndexerUrl | quote }} INDEXER_STAKING_URL: {{ .Values.app.indexerStakingUrl | quote }} - TESTNET_OWN_NODES: {{ .Values.app.testnetOwnNodes | toJson | quote }} + DPOS_PROXY_ADDRESS: {{ .Values.app.dposProxyAddress | quote }} NODE_ENV: {{ .Values.app.environment | quote }} diff --git a/services/delegation/charts/community-delegation/values.yaml b/services/delegation/charts/community-delegation/values.yaml index aa01214ec..bdac959ff 100644 --- a/services/delegation/charts/community-delegation/values.yaml +++ b/services/delegation/charts/community-delegation/values.yaml @@ -16,6 +16,7 @@ app: dbCommunityName: taraxa-community-default queueHost: default-queue.address indexerStakingUrl: http://default-taraxa-indexer:8000/subgraphs/name/taraxa_project/staking + dposProxyAddress: '' serverPort: 3000 dbPort: 5432 diff --git a/services/delegation/src/config/delegation.ts b/services/delegation/src/config/delegation.ts index 74e1a874c..f9ef3105f 100644 --- a/services/delegation/src/config/delegation.ts +++ b/services/delegation/src/config/delegation.ts @@ -2,20 +2,6 @@ import { ethers } from 'ethers'; import { registerAs } from '@nestjs/config'; export default registerAs('delegation', () => { - let ownNodes = []; - - if (process.env.TESTNET_OWN_NODES !== '') { - try { - ownNodes = JSON.parse(process.env.TESTNET_OWN_NODES); - } catch (e) { - ownNodes = []; - console.error( - `Could not parse own nodes JSON`, - process.env.TESTNET_OWN_NODES, - ); - } - } - return { yield: 20, commissionChangeThreshold: 5, @@ -28,7 +14,6 @@ export default registerAs('delegation', () => { ethers.BigNumber.from(10).pow(18), ), mainnetDelegation: ethers.BigNumber.from(10).pow(18), // not sure why this is here - testnetOwnNodes: ownNodes, undelegationConfirmationDelay: Number( process.env.NR_BLOCKS_UNDELEGATION_DELAY || 5, ), diff --git a/services/delegation/src/config/ethereum.ts b/services/delegation/src/config/ethereum.ts index 981190b73..b1ea84c80 100644 --- a/services/delegation/src/config/ethereum.ts +++ b/services/delegation/src/config/ethereum.ts @@ -8,4 +8,5 @@ export default registerAs('ethereum', () => ({ testnetWallet: process.env.TESTNET_WALLET, mainnetIndexerUrl: process.env.MAINNET_INDEXER_URL, testnetIndexerUrl: process.env.TESTNET_INDEXER_URL, + dposProxyAddress: process.env.DPOS_PROXY_ADDRESS, })); diff --git a/services/delegation/src/modules/blockchain/blockchain.module.ts b/services/delegation/src/modules/blockchain/blockchain.module.ts index 55f18ff1d..19a1db348 100644 --- a/services/delegation/src/modules/blockchain/blockchain.module.ts +++ b/services/delegation/src/modules/blockchain/blockchain.module.ts @@ -21,7 +21,7 @@ const getProviders = () => [ ethereum.testnetEndpoint, ethereum.testnetWallet, delegation.testnetDelegation, - delegation.testnetOwnNodes, + ethereum.dposProxyAddress, ); }, inject: [delegationConfig.KEY, ethereumConfig.KEY], diff --git a/services/delegation/src/modules/blockchain/blockchain.service.ts b/services/delegation/src/modules/blockchain/blockchain.service.ts index 9684db08c..6a7372647 100644 --- a/services/delegation/src/modules/blockchain/blockchain.service.ts +++ b/services/delegation/src/modules/blockchain/blockchain.service.ts @@ -11,7 +11,7 @@ export class BlockchainService { endpoint: string, walletKey: string, public defaultDelegationAmount: ethers.BigNumber, - private ownNodes: string[], + dposProxyAddress: string, ) { this.provider = new ethers.providers.JsonRpcProvider({ url: endpoint, @@ -21,7 +21,7 @@ export class BlockchainService { this.wallet = new ethers.Wallet(walletKey, this.provider); this.contract = new ethers.Contract( - '0x00000000000000000000000000000000000000fe', + dposProxyAddress, [ 'function delegate(address validator) payable', 'function undelegate(address validator, uint256 amount) external', @@ -30,7 +30,6 @@ export class BlockchainService { 'function getValidator(address validator) view returns (tuple(uint256 total_stake, uint256 commission_reward, uint16 commission, uint64 last_commission_change, address owner, string description, string endpoint) validator_info)', 'function getValidators(uint32 batch) view returns (tuple(address account, tuple(uint256 total_stake, uint256 commission_reward, uint16 commission, uint64 last_commission_change, address owner, string description, string endpoint) info)[] validators, bool end)', 'function registerValidator(address validator, bytes proof, bytes vrf_key, uint16 commission, string description, string endpoint) payable', - 'function addInternalValidator(address validator) external', ], this.provider, ).connect(this.wallet); @@ -40,14 +39,8 @@ export class BlockchainService { endpoint: string, walletKey: string, defaultDelegationAmount: ethers.BigNumber, - ownNodes: string[], ) { - return new BlockchainService( - endpoint, - walletKey, - defaultDelegationAmount, - ownNodes, - ); + return new BlockchainService(endpoint, walletKey, defaultDelegationAmount); } async getCurrentBlockNumber() { @@ -75,7 +68,6 @@ export class BlockchainService { address: string, addressProof: string, vrfKey: string, - internal = false, ) { try { const validatorData = await this.contract.getValidator(address); @@ -94,10 +86,6 @@ export class BlockchainService { }, ); await tx.wait(); - if (internal) { - const registration = await this.contract.addInternalValidator(address); - await registration.wait(); - } return true; } catch (e) { console.error(`Could not create validator ${address}`, e); @@ -138,119 +126,4 @@ export class BlockchainService { const receipt = await tx.wait(); return receipt.blockNumber; } - - async rebalanceOwnNodes(addOneNode = false) { - if (this.ownNodes.length === 0) { - console.error(`Can't delegate to own nodes - No own nodes.`); - return false; - } - - // Getting all validators from contract (including own nodes) - const allValidators = await this.getAllValidators(); - if (allValidators.length === 0) { - console.error(`Can't delegate to own nodes - No validators in contract.`); - return false; - } - - // Getting all registered own nodes and total stake for each - const ownNodes = allValidators - .filter((validator) => - this.ownNodes - .map((node) => node.toLowerCase()) - .includes(validator.account.toLowerCase()), - ) - .map((validator) => ({ - address: validator.account, - stake: validator.info.total_stake, - })); - if (ownNodes.length === 0) { - console.error(`Can't delegate to own nodes - No own nodes in contract.`); - return false; - } - const totalStakeOwnNodes = ownNodes.reduce((prev, curr) => { - return prev.add(curr.stake); - }, ethers.BigNumber.from(0)); - - let numberOfCommunityNodes = allValidators.length - ownNodes.length; - if (addOneNode) { - numberOfCommunityNodes++; - } - - const totalStakeCommunityNodes = this.defaultDelegationAmount.mul( - numberOfCommunityNodes, - ); - const majorityStake = totalStakeCommunityNodes - .mul(2) - .add(this.defaultDelegationAmount); - - // If our node have 2 x stake of community nodes already, we exit - if (totalStakeOwnNodes.gte(majorityStake)) { - return; - } - - // Sorting own nodes in ascending order - ownNodes.sort((a, b) => { - if (a.stake.eq(b.stake)) { - return 0; - } - if (a.stake.gt(b.stake)) { - return 1; - } - return -1; - }); - - const avgStakeOwnNode = majorityStake.div(ownNodes.length); - let left = majorityStake.sub(totalStakeOwnNodes); - for (const ownNode of ownNodes) { - if (left.isZero()) { - break; - } - - if (ownNode.stake.gte(avgStakeOwnNode)) { - continue; - } - - const d = avgStakeOwnNode.sub(ownNode.stake); - let toDelegate = ethers.BigNumber.from(0); - if (d.gt(left)) { - toDelegate = ethers.BigNumber.from(left); - } else { - toDelegate = ethers.BigNumber.from(d); - } - - console.log(`Delegating ${toDelegate} to ${ownNode.address}`); - - try { - const tx = await this.contract.delegate(ownNode.address, { - gasPrice: this.provider.getGasPrice(), - value: toDelegate, - }); - await tx.wait(); - } catch (e) { - console.error( - `Can't delegate to own nodes - delegation call failed for node ${ownNode.address}`, - ); - break; - } - - left = left.sub(toDelegate); - } - } - - private async getAllValidators() { - let validators = []; - let page = 0; - let hasNextPage = true; - while (hasNextPage) { - try { - const allValidators = await this.contract.getValidators(page); - validators = [...validators, ...allValidators.validators]; - hasNextPage = !allValidators.end; - page++; - } catch (e) { - hasNextPage = false; - } - } - return validators; - } } diff --git a/services/delegation/src/modules/delegation/delegation.service.ts b/services/delegation/src/modules/delegation/delegation.service.ts index 5d4872f9f..3f7b930c5 100644 --- a/services/delegation/src/modules/delegation/delegation.service.ts +++ b/services/delegation/src/modules/delegation/delegation.service.ts @@ -288,10 +288,8 @@ export class DelegationService { async ensureDelegation(nodeId: number, type: string, address: string) { // Check if node exists in the database let node: Node; - let isInternal = false; try { node = await this.nodeRepository.findOneOrFail({ id: nodeId }); - isInternal = node.isOwnValidator; } catch (e) { node = null; } @@ -343,7 +341,6 @@ export class DelegationService { // add call to undelegation, create undelegation, save in db // await this.blockchainService.unregisterValidator(address); } else { - let toDelegate = totalNodeDelegation.sub(currentDelegation); if (!isNodeRegistered) { let isCreatedOnchain: boolean; if (type === NodeType.TESTNET) { @@ -352,23 +349,8 @@ export class DelegationService { address, node.addressProof, node.vrfKey, - isInternal, ); } - if (type === NodeType.MAINNET) { - isCreatedOnchain = - await this.mainnetBlockchainService.registerValidator( - address, - node.addressProof, - node.vrfKey, - isInternal, - ); - if (isCreatedOnchain) { - toDelegate = totalNodeDelegation.sub( - this.mainnetBlockchainService.defaultDelegationAmount, - ); - } - } if (node) { node.isCreatedOnchain = isCreatedOnchain; await this.nodeRepository.save(node); diff --git a/services/delegation/src/modules/node/node.consumer.ts b/services/delegation/src/modules/node/node.consumer.ts index 824f16888..a1cc47ffa 100644 --- a/services/delegation/src/modules/node/node.consumer.ts +++ b/services/delegation/src/modules/node/node.consumer.ts @@ -66,17 +66,6 @@ export class NodeConsumer implements OnModuleInit { } } - if (node.isMainnet()) { - try { - await this.mainnetBlockchainService.getValidator(node.address); - isCreatedOnchain = true; - } catch (e) { - this.logger.debug( - `${ENSURE_NODE_ONCHAIN_JOB} worker (job ${job.id}): Validator ${node.address} doesn't exist in contract`, - ); - } - } - if (isCreatedOnchain) { node.isCreatedOnchain = isCreatedOnchain; await this.nodeRepository.save(node); @@ -94,19 +83,9 @@ export class NodeConsumer implements OnModuleInit { node.address, node.addressProof, node.vrfKey, - node.isOwnValidator, ); } - if (node.isMainnet()) { - node.isCreatedOnchain = - await this.mainnetBlockchainService.registerValidator( - node.address, - node.addressProof, - node.vrfKey, - node.isOwnValidator, - ); - } await this.nodeRepository.save(node); } catch (e) { this.logger.error( From 11d8bae01399109b1b79b354ace2ac99bbbb4a8f Mon Sep 17 00:00:00 2001 From: VargaElod23 Date: Fri, 28 Apr 2023 17:29:15 +0300 Subject: [PATCH 3/3] fix diff for mainnet blockchain service --- .../src/modules/blockchain/blockchain.module.ts | 2 +- .../src/modules/blockchain/blockchain.service.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/services/delegation/src/modules/blockchain/blockchain.module.ts b/services/delegation/src/modules/blockchain/blockchain.module.ts index 19a1db348..0316ee36c 100644 --- a/services/delegation/src/modules/blockchain/blockchain.module.ts +++ b/services/delegation/src/modules/blockchain/blockchain.module.ts @@ -36,7 +36,7 @@ const getProviders = () => [ ethereum.mainnetEndpoint, ethereum.mainnetWallet, delegation.minDelegation, - [], + ethereum.dposProxyAddress, ); }, inject: [delegationConfig.KEY, ethereumConfig.KEY], diff --git a/services/delegation/src/modules/blockchain/blockchain.service.ts b/services/delegation/src/modules/blockchain/blockchain.service.ts index 6a7372647..275c8939f 100644 --- a/services/delegation/src/modules/blockchain/blockchain.service.ts +++ b/services/delegation/src/modules/blockchain/blockchain.service.ts @@ -39,8 +39,14 @@ export class BlockchainService { endpoint: string, walletKey: string, defaultDelegationAmount: ethers.BigNumber, + dposProxyAddress: string, ) { - return new BlockchainService(endpoint, walletKey, defaultDelegationAmount); + return new BlockchainService( + endpoint, + walletKey, + defaultDelegationAmount, + dposProxyAddress, + ); } async getCurrentBlockNumber() {