diff --git a/.pnp.cjs b/.pnp.cjs index 20a490bf267..7c47bf30fb6 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2236,10 +2236,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@dashevo/abci", [ - ["npm:0.21.0", { - "packageLocation": "./.yarn/cache/@dashevo-abci-npm-0.21.0-a57b183e5f-da404cd07c.zip/node_modules/@dashevo/abci/", + ["https://github.com/dashevo/js-abci.git#commit=aa3dfe8e13d9ced6cf71f6ab233bd1c7e33d044c", { + "packageLocation": "./.yarn/cache/@dashevo-abci-https-6a91ed2e9b-f333af58ac.zip/node_modules/@dashevo/abci/", "packageDependencies": [ - ["@dashevo/abci", "npm:0.21.0"], + ["@dashevo/abci", "https://github.com/dashevo/js-abci.git#commit=aa3dfe8e13d9ced6cf71f6ab233bd1c7e33d044c"], ["bl", "npm:1.2.3"], ["protobufjs", "https://github.com/jawid-h/protobuf.js.git#commit=8b91c72dca68fd6c418078fd2358c4969425dcdc"], ["protocol-buffers-encodings", "npm:1.1.1"] @@ -2576,7 +2576,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./packages/js-drive/", "packageDependencies": [ ["@dashevo/drive", "workspace:packages/js-drive"], - ["@dashevo/abci", "npm:0.21.0"], + ["@dashevo/abci", "https://github.com/dashevo/js-abci.git#commit=aa3dfe8e13d9ced6cf71f6ab233bd1c7e33d044c"], ["@dashevo/dapi-grpc", "workspace:packages/dapi-grpc"], ["@dashevo/dashcore-lib", "npm:0.19.28"], ["@dashevo/dashd-rpc", "npm:2.3.1"], diff --git a/.yarn/cache/@dashevo-abci-npm-0.21.0-a57b183e5f-da404cd07c.zip b/.yarn/cache/@dashevo-abci-https-6a91ed2e9b-f333af58ac.zip similarity index 85% rename from .yarn/cache/@dashevo-abci-npm-0.21.0-a57b183e5f-da404cd07c.zip rename to .yarn/cache/@dashevo-abci-https-6a91ed2e9b-f333af58ac.zip index 56747f413cc..43e5deebea3 100644 Binary files a/.yarn/cache/@dashevo-abci-npm-0.21.0-a57b183e5f-da404cd07c.zip and b/.yarn/cache/@dashevo-abci-https-6a91ed2e9b-f333af58ac.zip differ diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index d54a972f54a..e5bad839f02 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -105,7 +105,7 @@ module.exports = { }, tenderdash: { docker: { - image: 'dashpay/tenderdash:0.6.0', + image: 'dashpay/tenderdash:0.7.0-dev.4', }, p2p: { port: 26656, diff --git a/packages/dashmate/docker-compose.platform.yml b/packages/dashmate/docker-compose.platform.yml index 7e3a8bcc202..f13e03de097 100644 --- a/packages/dashmate/docker-compose.platform.yml +++ b/packages/dashmate/docker-compose.platform.yml @@ -46,6 +46,7 @@ services: - INITIAL_CORE_CHAINLOCKED_HEIGHT=${PLATFORM_DRIVE_TENDERDASH_GENESIS_INITIAL_CORE_CHAIN_LOCKED_HEIGHT:-1} - VALIDATOR_SET_LLMQ_TYPE=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_LLMQ_TYPE:?err} - NETWORK=${NETWORK} + - TENDERDASH_P2P_PORT=${PLATFORM_DRIVE_TENDERDASH_P2P_PORT} command: yarn workspace @dashevo/drive abci drive_tenderdash: diff --git a/packages/js-drive/.env.example b/packages/js-drive/.env.example index d215e5908d9..1ba48a12385 100644 --- a/packages/js-drive/.env.example +++ b/packages/js-drive/.env.example @@ -91,3 +91,5 @@ LOG_STATE_REPOSITORY=false LOG_MERK=false NODE_ENV=production + +TENDERDASH_P2P_PORT=26656 diff --git a/packages/js-drive/lib/abci/handlers/validator/createValidatorSetUpdate.js b/packages/js-drive/lib/abci/handlers/validator/createValidatorSetUpdate.js index dc2f3bce397..60287f54b5e 100644 --- a/packages/js-drive/lib/abci/handlers/validator/createValidatorSetUpdate.js +++ b/packages/js-drive/lib/abci/handlers/validator/createValidatorSetUpdate.js @@ -18,9 +18,12 @@ const { function createValidatorSetUpdate(validatorSet) { const validatorUpdates = validatorSet.getValidators() .map((validator) => { + const networkInfo = validator.getNetworkInfo(); + const validatorUpdate = new ValidatorUpdate({ power: validator.getVotingPower(), proTxHash: validator.getProTxHash(), + nodeAddress: `tcp://${networkInfo.getHost()}:${networkInfo.getPort()}`, }); if (validator.getPublicKeyShare()) { diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 962ad3183b7..1ab1845acad 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -288,6 +288,7 @@ function createDIContainer(options) { return Long.fromString(options.FEATURE_FLAGS_CONTRACT_BLOCK_HEIGHT); }), + tenderdashP2pPort: asValue(options.TENDERDASH_P2P_PORT), }); /** diff --git a/packages/js-drive/lib/validator/Validator.js b/packages/js-drive/lib/validator/Validator.js index 613a24c99b0..daefdb63af4 100644 --- a/packages/js-drive/lib/validator/Validator.js +++ b/packages/js-drive/lib/validator/Validator.js @@ -3,10 +3,12 @@ const PublicKeyShareIsNotPresentError = require('./errors/PublicKeyShareIsNotPre class Validator { /** * @param {Buffer} proTxHash + * @param {ValidatorNetworkInfo} networkInfo * @param {Buffer} [pubKeyShare] */ - constructor(proTxHash, pubKeyShare = undefined) { + constructor(proTxHash, networkInfo, pubKeyShare = undefined) { this.proTxHash = proTxHash; + this.networkInfo = networkInfo; this.pubKeyShare = pubKeyShare; } @@ -36,12 +38,22 @@ class Validator { return Validator.DEFAULT_DASH_VOTING_POWER; } + /** + * Get network info + * + * @returns {ValidatorNetworkInfo} + */ + getNetworkInfo() { + return this.networkInfo; + } + /** * @param {Object} member + * @param {ValidatorNetworkInfo} networkInfo * @param {boolean} [pubKeyShareRequired=false] * @return {Validator} */ - static createFromQuorumMember(member, pubKeyShareRequired = false) { + static createFromQuorumMember(member, networkInfo, pubKeyShareRequired = false) { const proTxHash = Buffer.from(member.proTxHash, 'hex'); let pubKeyShare; @@ -51,7 +63,7 @@ class Validator { throw new PublicKeyShareIsNotPresentError(member); } - return new Validator(proTxHash, pubKeyShare); + return new Validator(proTxHash, networkInfo, pubKeyShare); } } diff --git a/packages/js-drive/lib/validator/ValidatorNetworkInfo.js b/packages/js-drive/lib/validator/ValidatorNetworkInfo.js new file mode 100644 index 00000000000..91593bd4f8f --- /dev/null +++ b/packages/js-drive/lib/validator/ValidatorNetworkInfo.js @@ -0,0 +1,29 @@ +class ValidatorNetworkInfo { + /** + * + * @param {string} host + * @param {number} port + */ + constructor(host, port) { + this.host = host; + this.port = port; + } + + /** + * Get validator host + * @returns {string} + */ + getHost() { + return this.host; + } + + /** + * Get validator port + * @returns {number} + */ + getPort() { + return this.port; + } +} + +module.exports = ValidatorNetworkInfo; diff --git a/packages/js-drive/lib/validator/ValidatorSet.js b/packages/js-drive/lib/validator/ValidatorSet.js index 7bf14a82b1c..976e894522d 100644 --- a/packages/js-drive/lib/validator/ValidatorSet.js +++ b/packages/js-drive/lib/validator/ValidatorSet.js @@ -1,5 +1,6 @@ const Validator = require('./Validator'); const ValidatorSetIsNotInitializedError = require('./errors/ValidatorSetIsNotInitializedError'); +const ValidatorNetworkInfo = require('./ValidatorNetworkInfo'); class ValidatorSet { /** @@ -8,6 +9,7 @@ class ValidatorSet { * @param {fetchQuorumMembers} fetchQuorumMembers * @param {number} validatorSetLLMQType * @param {RpcClient} coreRpcClient + * @param {number} tenderdashP2pPort */ constructor( simplifiedMasternodeList, @@ -15,12 +17,14 @@ class ValidatorSet { fetchQuorumMembers, validatorSetLLMQType, coreRpcClient, + tenderdashP2pPort, ) { this.simplifiedMasternodeList = simplifiedMasternodeList; this.getRandomQuorum = getRandomQuorum; this.fetchQuorumMembers = fetchQuorumMembers; this.validatorSetLLMQType = validatorSetLLMQType; this.coreRpcClient = coreRpcClient; + this.tenderdashP2pPort = tenderdashP2pPort; this.quorum = null; this.validators = []; @@ -133,9 +137,21 @@ class ValidatorSet { const isThisNodeMember = !!quorumMembers .find((member) => member.valid && member.proTxHash === proTxHash); - this.validators = quorumMembers + const validMasternodesList = this.simplifiedMasternodeList + .getStore() + .getCurrentSML() + .getValidMasternodesList(); + + this.validators = await Promise.all(quorumMembers .filter((member) => member.valid) - .map((member) => Validator.createFromQuorumMember(member, isThisNodeMember)); + .map(async (member) => { + const masternode = validMasternodesList + .find((mnEntry) => mnEntry.proRegTxHash === member.proTxHash); + + const networkInfo = new ValidatorNetworkInfo(masternode.getIp(), this.tenderdashP2pPort); + + return Validator.createFromQuorumMember(member, networkInfo, isThisNodeMember); + })); } } diff --git a/packages/js-drive/package.json b/packages/js-drive/package.json index a4ef3f7f9b8..f2ba5cc69f4 100644 --- a/packages/js-drive/package.json +++ b/packages/js-drive/package.json @@ -63,7 +63,7 @@ "sinon-chai": "^3.7.0" }, "dependencies": { - "@dashevo/abci": "~0.21.0", + "@dashevo/abci": "github:dashevo/js-abci#v0.22-dev", "@dashevo/dapi-grpc": "workspace:~", "@dashevo/dashcore-lib": "~0.19.28", "@dashevo/dashd-rpc": "^2.3.1", diff --git a/packages/js-drive/test/unit/abci/handlers/validator/createValidatorSetUpdate.spec.js b/packages/js-drive/test/unit/abci/handlers/validator/createValidatorSetUpdate.spec.js index 6e83418f48d..30c170d277f 100644 --- a/packages/js-drive/test/unit/abci/handlers/validator/createValidatorSetUpdate.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/validator/createValidatorSetUpdate.spec.js @@ -8,6 +8,7 @@ const { const { expect } = require('chai'); const createValidatorSetUpdate = require('../../../../../lib/abci/handlers/validator/createValidatorSetUpdate'); +const ValidatorNetworkInfo = require('../../../../../lib/validator/ValidatorNetworkInfo'); describe('createValidatorSetUpdate', () => { let validatorSetMock; @@ -20,10 +21,12 @@ describe('createValidatorSetUpdate', () => { getPublicKeyShare: this.sinon.stub(), getVotingPower: this.sinon.stub(), getProTxHash: this.sinon.stub(), + getNetworkInfo: this.sinon.stub(), }; validatorMock.getVotingPower.returns(Buffer.alloc(2, 32)); validatorMock.getProTxHash.returns(Buffer.alloc(3, 32)); + validatorMock.getNetworkInfo.returns(new ValidatorNetworkInfo('192.168.65.2', 26656)); validatorSetMock = { getValidators: this.sinon.stub(), diff --git a/packages/js-drive/test/unit/validator/Validator.spec.js b/packages/js-drive/test/unit/validator/Validator.spec.js index 418add48e0f..c3544e8140b 100644 --- a/packages/js-drive/test/unit/validator/Validator.spec.js +++ b/packages/js-drive/test/unit/validator/Validator.spec.js @@ -1,15 +1,26 @@ const { expect } = require('chai'); const Validator = require('../../../lib/validator/Validator'); +const ValidatorNetworkInfo = require('../../../lib/validator/ValidatorNetworkInfo'); describe('Validator', () => { - describe('createFromQuorumMember', () => { + let networkInfo; + let host; + let port; + + beforeEach(() => { + host = '192.168.65.2'; + port = 26656; + networkInfo = new ValidatorNetworkInfo(host, port); + }); + + describe('#createFromQuorumMember', () => { it('should create an instance from quorum member info', () => { const memberInfo = { proTxHash: Buffer.alloc(0, 32).toString('hex'), pubKeyShare: Buffer.alloc(1, 32).toString('hex'), }; - const instance = Validator.createFromQuorumMember(memberInfo); + const instance = Validator.createFromQuorumMember(memberInfo, networkInfo); expect(instance).to.be.an.instanceOf(Validator); expect(instance.getProTxHash()).to.deep.equal( @@ -18,6 +29,9 @@ describe('Validator', () => { expect(instance.getPublicKeyShare()).to.deep.equal( Buffer.from(memberInfo.pubKeyShare, 'hex'), ); + expect(instance.getNetworkInfo()).to.be.an.instanceOf(ValidatorNetworkInfo); + expect(instance.getNetworkInfo().getHost()).to.equal(host); + expect(instance.getNetworkInfo().getPort()).to.equal(port); }); }); }); diff --git a/packages/js-drive/test/unit/validator/ValidatorNetworkInfo.spec.js b/packages/js-drive/test/unit/validator/ValidatorNetworkInfo.spec.js new file mode 100644 index 00000000000..92ba6b25946 --- /dev/null +++ b/packages/js-drive/test/unit/validator/ValidatorNetworkInfo.spec.js @@ -0,0 +1,24 @@ +const ValidatorNetworkInfo = require('../../../lib/validator/ValidatorNetworkInfo'); + +describe('ValidatorNetworkInfo', () => { + let validatorNetworkInfo; + let host; + let port; + + beforeEach(() => { + host = '192.168.65.2'; + port = 26656; + }); + + it('should return host', () => { + validatorNetworkInfo = new ValidatorNetworkInfo(host, port); + + expect(validatorNetworkInfo.getHost()).to.equal(host); + }); + + it('should return port', () => { + validatorNetworkInfo = new ValidatorNetworkInfo(host, port); + + expect(validatorNetworkInfo.getPort()).to.equal(port); + }); +}); diff --git a/packages/js-drive/test/unit/validator/ValidatorSet.spec.js b/packages/js-drive/test/unit/validator/ValidatorSet.spec.js index 0405fd0713d..82885a699d3 100644 --- a/packages/js-drive/test/unit/validator/ValidatorSet.spec.js +++ b/packages/js-drive/test/unit/validator/ValidatorSet.spec.js @@ -2,6 +2,7 @@ const Long = require('long'); const QuorumEntry = require('@dashevo/dashcore-lib/lib/deterministicmnlist/QuorumEntry'); +const SimplifiedMNListEntry = require('@dashevo/dashcore-lib/lib/deterministicmnlist/SimplifiedMNListEntry'); const ValidatorSet = require('../../../lib/validator/ValidatorSet'); const getSmlFixture = require('../../../lib/test/fixtures/getSmlFixture'); const ValidatorSetIsNotInitializedError = require('../../../lib/validator/errors/ValidatorSetIsNotInitializedError'); @@ -18,6 +19,7 @@ describe('ValidatorSet', () => { let quorumEntry; let coreHeight; let coreRpcClientMock; + let validatorNetworkPort; let validatorSetLLMQType; @@ -42,6 +44,24 @@ describe('ValidatorSet', () => { getQuorumsOfType: this.sinon.stub().returns( getSmlFixture()[0].newQuorums.filter((quorum) => quorum.llmqType === 1), ), + getValidMasternodesList: this.sinon.stub().returns([ + new SimplifiedMNListEntry({ + proRegTxHash: 'c286807d463b06c7aba3b9a60acf64c1fc03da8c1422005cd9b4293f08cf0562', + confirmedHash: '4eb56228c535db3b234907113fd41d57bcc7cdcb8e0e00e57590af27ee88c119', + service: '192.168.65.2:20101', + pubKeyOperator: '809519c5f6f3be1c08782ac42ae9a83b6c7205eba43f9a96a4f032ec7a73f1a7c25fa78cce0d6d9c135f7e2c28527179', + votingAddress: 'yXmprXYP51uzfMyndtWwxz96MnkCKkFc9x', + isValid: true, + }), + new SimplifiedMNListEntry({ + proRegTxHash: 'a3e1edc6bd352eeaf0ae58e30781ef4b127854241a3fe7fddf36d5b7e1dc2b3f', + confirmedHash: '27a0b637b56af038c45e2fd1f06c2401c8dadfa28ca5e0d19ca836cc984a8378', + service: '192.168.65.2:20201', + pubKeyOperator: '987a4873caba62cd45a2f7d4aa6d94519ee6753e9bef777c927cb94ade768a542b0ff34a93231d3a92b4e75ffdaa366e', + votingAddress: 'ycL7L4mhYoaZdm9TH85svvpfeKtdfo249u', + isValid: true, + }), + ]), }; smlStoreMock = { @@ -86,12 +106,15 @@ describe('ValidatorSet', () => { masternode: this.sinon.stub().throws(notMasternodeError), }; + validatorNetworkPort = 26656; + validatorSet = new ValidatorSet( simplifiedMasternodeListMock, getRandomQuorumMock, fetchQuorumMembersMock, validatorSetLLMQType, coreRpcClientMock, + validatorNetworkPort, ); }); @@ -111,6 +134,8 @@ describe('ValidatorSet', () => { validatorSetLLMQType, quorumEntry.quorumHash, ); + + expect(smlStoreMock.getCurrentSML().getValidMasternodesList).to.be.calledOnce(); }); it('should throw an error if the node is a quorum member and doesn\'t receive public key shares', async () => { @@ -157,6 +182,8 @@ describe('ValidatorSet', () => { validatorSetLLMQType, quorumEntry.quorumHash, ); + + expect(smlStoreMock.getCurrentSML().getValidMasternodesList).to.be.calledOnce(); }); it('should not rotate validator set if height not divisible by ROTATION_BLOCK_INTERVAL', async () => { diff --git a/packages/platform-test-suite/test/e2e/contacts.spec.js b/packages/platform-test-suite/test/e2e/contacts.spec.js index c27278b9eb4..e665ea0fb0b 100644 --- a/packages/platform-test-suite/test/e2e/contacts.spec.js +++ b/packages/platform-test-suite/test/e2e/contacts.spec.js @@ -26,10 +26,10 @@ describe('e2e', () => { type: 'object', indices: [ { - name: "ownerId", + name: 'ownerId', properties: [{ $ownerId: 'asc' }], unique: true, - }, + }, ], properties: { avatarUrl: { @@ -49,12 +49,12 @@ describe('e2e', () => { type: 'object', indices: [ { - name: "onwerIdToUserId", + name: 'onwerIdToUserId', properties: [ { $ownerId: 'asc' }, - { toUserId: 'asc' } + { toUserId: 'asc' }, ], - unique: true + unique: true, }, ], properties: { diff --git a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js index 5aa156fa8ae..92ac99408f6 100644 --- a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js +++ b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js @@ -134,7 +134,7 @@ describe('Platform', () => { type: 'object', indices: [ { - name: "firstNameLastName", + name: 'firstNameLastName', properties: [ { firstName: 'asc' }, { lastName: 'asc' }, diff --git a/yarn.lock b/yarn.lock index 64219ef4450..6632b4396d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1264,14 +1264,14 @@ __metadata: languageName: node linkType: hard -"@dashevo/abci@npm:~0.21.0": - version: 0.21.0 - resolution: "@dashevo/abci@npm:0.21.0" +"@dashevo/abci@github:dashevo/js-abci#v0.22-dev": + version: 0.20.0 + resolution: "@dashevo/abci@https://github.com/dashevo/js-abci.git#commit=aa3dfe8e13d9ced6cf71f6ab233bd1c7e33d044c" dependencies: bl: ^1.2.3 protobufjs: "github:jawid-h/protobuf.js#fix/buffer-conversion" protocol-buffers-encodings: ^1.1.0 - checksum: da404cd07c70018676bf45de091a9cda63ac37e85d76ebf9935b33635018ac941574c5bee5182f6d3a52d17879a6d33979f143ea327e9b7eaadf3efbd35bc935 + checksum: f333af58acc2129c0199db8b1174d84ae770030a66a3d9dae23130faf3c0aa159f814ae0c91a465548ccac9dd41e469ea8e36b02e292bc4cf2e78abadbea6e52 languageName: node linkType: hard @@ -1588,7 +1588,7 @@ __metadata: version: 0.0.0-use.local resolution: "@dashevo/drive@workspace:packages/js-drive" dependencies: - "@dashevo/abci": ~0.21.0 + "@dashevo/abci": "github:dashevo/js-abci#v0.22-dev" "@dashevo/dapi-grpc": "workspace:~" "@dashevo/dashcore-lib": ~0.19.28 "@dashevo/dashd-rpc": ^2.3.1