diff --git a/app/modules/crawler/index.ts b/app/modules/crawler/index.ts index 25a509dd1b3c8810b8764e93aca67f2cbacdad9d..61b4a0aa090c9230cf025db2eada56c9d76fca32 100644 --- a/app/modules/crawler/index.ts +++ b/app/modules/crawler/index.ts @@ -49,8 +49,8 @@ export const CrawlerDependency = { return crawler.sandboxPull(server) }, - synchronize: (currency: string, server:Server, onHost:string, onPort:number, upTo:number, chunkLength:number) => { - const strategy = new RemoteSynchronizer(currency, onHost, onPort, server, chunkLength) + synchronize: (server:Server, onHost:string, onPort:number, upTo:number, chunkLength:number) => { + const strategy = new RemoteSynchronizer(onHost, onPort, server, chunkLength) const remote = new Synchroniser(server, strategy) const syncPromise = (async () => { await server.dal.disableChangesAPI() @@ -70,8 +70,8 @@ export const CrawlerDependency = { * @param {number} onPort * @returns {Promise<any>} */ - testForSync: (currency: string, server:Server, onHost:string, onPort:number) => { - return RemoteSynchronizer.test(currency, onHost, onPort, server.conf.pair) + testForSync: (server:Server, onHost:string, onPort:number) => { + return RemoteSynchronizer.test(onHost, onPort, server.conf.pair) } }, @@ -86,7 +86,6 @@ export const CrawlerDependency = { { value: '--slow', desc: 'Download slowly the blokchcain (for low connnections).'}, { value: '--readfilesystem',desc: 'Also read the filesystem to speed up block downloading.'}, { value: '--minsig <minsig>', desc: 'Minimum pending signatures count for `crawl-lookup`. Default is 5.'}, - { value: '--up-to <block-number>', desc: 'Block number to reach.'}, ], cli: [{ @@ -95,8 +94,7 @@ export const CrawlerDependency = { preventIfRunning: true, onDatabaseExecute: async (server:Server, conf:ConfDTO, program:any, params:any): Promise<any> => { const source = params[0] - let currency = params[1] - const to = program.upTo + const to = params[1] const HOST_PATTERN = /^[^:/]+(:[0-9]{1,5})?$/ const FILE_PATTERN = /^(\/.+)$/ if (!source || !(source.match(HOST_PATTERN) || source.match(FILE_PATTERN))) { @@ -129,10 +127,7 @@ export const CrawlerDependency = { const sp = source.split(':') const onHost = sp[0] const onPort = parseInt(sp[1] ? sp[1] : '443') // Defaults to 443 - if (!currency) { - throw 'currency parameter is required for network synchronization' - } - strategy = new RemoteSynchronizer(currency, onHost, onPort, server, CommonConstants.SYNC_BLOCKS_CHUNK, noShufflePeers === true, otherDAL) + strategy = new RemoteSynchronizer(onHost, onPort, server, CommonConstants.SYNC_BLOCKS_CHUNK, noShufflePeers === true, otherDAL) } else { strategy = new LocalPathSynchronizer(source, server, CommonConstants.SYNC_BLOCKS_CHUNK) } diff --git a/app/modules/crawler/lib/sync/ChunkGetter.ts b/app/modules/crawler/lib/sync/ChunkGetter.ts index a7bc61d591ae0049dd4b713e2dc90949beb0d32b..abef759ff54ad82d6e44d454c798d5f7073222dd 100644 --- a/app/modules/crawler/lib/sync/ChunkGetter.ts +++ b/app/modules/crawler/lib/sync/ChunkGetter.ts @@ -11,6 +11,7 @@ import {Watcher} from "./Watcher" import {cliprogram} from "../../../../lib/common-libs/programOptions" import {Querable, querablep} from "../../../../lib/common-libs/querable" import {AbstractSynchronizer} from "./AbstractSynchronizer" +import {Underscore} from "../../../../lib/common-libs/underscore" const logger = NewLogger() @@ -48,7 +49,13 @@ export class ChunkGetter { private downloadedChunks = 0 private writtenChunks = 0 private numberOfChunksToDownload:number + + // --- Downloading slots and speed handling --- private parallelDownloads = cliprogram.slow ? 1 : 5 + private aSlotWasAdded = 0 + private MAX_DELAY_PER_DOWNLOAD = cliprogram.slow ? 15000 : 5000 + private lastAvgDelay = this.MAX_DELAY_PER_DOWNLOAD + private maxDownloadAdvance = 10 // 10 chunks can be downloaded even if 10th chunk above is not completed private MAX_DOWNLOAD_TIMEOUT = 15000 private writeDAL: FileDAL @@ -139,12 +146,15 @@ export class ChunkGetter { } } else if (handler.state === 'DOWNLOADED') { + // Chaining test: we must wait for upper chunk to be completed (= downloaded + chained) const chunk = await handler.chunk if (chunk.length === 0 && handler.downloader === this.fsDownloader) { // Retry with P2P handler.downloader = this.p2PDownloader ;(handler as any).state = 'WAITING' + remainingDownloads++ + continue } if (isTopChunk || this.downloadHandlers[i + 1].state === 'COMPLETED') { const fileName = this.syncStrategy.getChunkRelativePath(i) @@ -157,15 +167,19 @@ export class ChunkGetter { if (!chainsWell) { if (handler.downloader === this.p2PDownloader) { if (chunk.length === 0) { - logger.error('No block was downloaded') + logger.error('No block was downloaded for chunk#%s', i) } - logger.warn("Chunk #%s is DOES NOT CHAIN CORRECTLY. Retrying.", i) + logger.warn("Chunk #%s DOES NOT CHAIN CORRECTLY. Retrying.", i) } handler.downloader = this.p2PDownloader // If ever the first call does not chains well, we try using P2P ;(handler as any).state = 'WAITING' i++ } else { - logger.info("Chunk #%s read from filesystem.", i) + if (handler.downloader === this.fsDownloader) { + logger.info("Chunk #%s read from filesystem.", i) + + } + logger.info("Chunk #%s chains well.", i) let doWrite = handler.downloader !== this.fsDownloader || !(await this.writeDAL.confDAL.coreFS.exists(fileName)) if (doWrite) { @@ -187,6 +201,40 @@ export class ChunkGetter { (handler as any).chunk = undefined } this.downloadedChunks++ + + if (handler.downloader === this.p2PDownloader) { + + // Speed resolution + const peers = await this.p2PDownloader.getTimesToAnswer() + const downloading = Underscore.filter(peers, (p) => p.ttas.length > 0) + const currentAvgDelay = downloading.length === 0 ? 0 : downloading.reduce((sum:number, c) => { + const tta = Math.round(c.ttas.reduce((sum:number, tta:number) => sum + tta, 0) / c.ttas.length) + return sum + tta; + }, 0) / downloading.length + if (!cliprogram.slow) { + // Check the impact of an added node (not first time) + if (!this.aSlotWasAdded) { + // We try to add a node + const newValue = Math.min(this.p2PDownloader.maxSlots, this.parallelDownloads + 1) + if (newValue !== this.parallelDownloads) { + this.parallelDownloads = newValue + this.aSlotWasAdded = i + logger.info('AUGMENTED DOWNLOAD SLOTS! Now has %s slots', this.parallelDownloads) + } + } else if (this.aSlotWasAdded && this.aSlotWasAdded - i > 5) { // We measure every 5 blocks + this.aSlotWasAdded = 0 + const decelerationPercent = !this.lastAvgDelay ? 0 : currentAvgDelay / this.lastAvgDelay - 1 + const addedNodePercent = 1 / downloading.length + logger.info('Deceleration = %s (%s/%s), AddedNodePercent = %s', decelerationPercent, currentAvgDelay, this.lastAvgDelay, addedNodePercent) + if (decelerationPercent > addedNodePercent) { + this.parallelDownloads = Math.max(1, this.parallelDownloads - 1); // We reduce the number of slots, but we keep at least 1 slot + logger.info('REDUCED DOWNLOAD SLOT! Now has %s slots', this.parallelDownloads) + } + } + } + this.lastAvgDelay = currentAvgDelay + } + this.watcher.downloadPercent(parseInt((this.downloadedChunks / this.numberOfChunksToDownload * 100).toFixed(0))) // We pre-save blocks only for non-cautious sync if (this.nocautious) { diff --git a/app/modules/crawler/lib/sync/P2PSyncDownloader.ts b/app/modules/crawler/lib/sync/P2PSyncDownloader.ts index cefe9aca7691848ee3be1141c8e9bdb3ccc11c85..ccceac4d4ce387a35aedb78adb6e0c6ae14d3bcc 100644 --- a/app/modules/crawler/lib/sync/P2PSyncDownloader.ts +++ b/app/modules/crawler/lib/sync/P2PSyncDownloader.ts @@ -81,7 +81,7 @@ export class P2PSyncDownloader implements ISyncDownloader { } let syncApi: any = null try { - syncApi = await RemoteSynchronizer.getSyncAPI(this.currency, apis, this.keypair) + syncApi = await RemoteSynchronizer.getSyncAPI(apis, this.keypair) const manualp = newManualPromise<boolean>() manualp.resolve(true) const node: ProfiledNode = { diff --git a/app/modules/crawler/lib/sync/RemoteSynchronizer.ts b/app/modules/crawler/lib/sync/RemoteSynchronizer.ts index 9463a33ae8dba3da14e6f5ffbd47a6f3093a3bb8..8b1aedd780f5703b894bb54ab906b4fd21f8787a 100644 --- a/app/modules/crawler/lib/sync/RemoteSynchronizer.ts +++ b/app/modules/crawler/lib/sync/RemoteSynchronizer.ts @@ -16,7 +16,6 @@ import {BlockDTO} from "../../../../lib/dto/BlockDTO" import {PeerDTO} from "../../../../lib/dto/PeerDTO" import {connect} from "../connect" import {NewLogger} from "../../../../lib/logger" -import {CrawlerConstants} from "../constants" import {cliprogram} from "../../../../lib/common-libs/programOptions" import {Watcher} from "./Watcher" import {PeeringService} from "../../../../service/PeeringService" @@ -45,6 +44,7 @@ const logger = NewLogger() export class RemoteSynchronizer extends AbstractSynchronizer { + private currency:string private node:IRemoteContacter private peer:PeerDTO private shuffledPeers: JSONDBPeer[] @@ -53,12 +53,9 @@ export class RemoteSynchronizer extends AbstractSynchronizer { private to: number private localNumber: number private watcher: Watcher - private static contacterOptions = { - timeout: CrawlerConstants.SYNC_LONG_TIMEOUT - } + private endpoint: string = "" constructor( - private readonly currency: string, private host: string, private port: number, private server:Server, @@ -82,7 +79,7 @@ export class RemoteSynchronizer extends AbstractSynchronizer { } getCurrency(): string { - return this.currency + return this.currency || 'unknown-currency' } getPeer(): PeerDTO { @@ -98,10 +95,12 @@ export class RemoteSynchronizer extends AbstractSynchronizer { } async init(): Promise<void> { - const syncApi = await RemoteSynchronizer.getSyncAPI(this.currency, [{ host: this.host, port: this.port }], this.server.conf.pair) + const syncApi = await RemoteSynchronizer.getSyncAPI([{ host: this.host, port: this.port }], this.server.conf.pair) if (!syncApi.api) { throw Error(DataErrors[DataErrors.CANNOT_CONNECT_TO_REMOTE_FOR_SYNC]) } + this.currency = syncApi.currency + this.endpoint = syncApi.endpoint this.node = syncApi.api this.peer = PeerDTO.fromJSONObject(syncApi.peering) logger.info("Try with %s %s", this.peer.getURL(), this.peer.pubkey.substr(0, 6)) @@ -114,9 +113,10 @@ export class RemoteSynchronizer extends AbstractSynchronizer { ;(this.node as any).pubkey = this.peer.pubkey } - public static async getSyncAPI(currency: string, hosts: { isBMA?: boolean, isWS2P?: boolean, host: string, port: number, path?: string }[], keypair: Keypair) { + public static async getSyncAPI(hosts: { isBMA?: boolean, isWS2P?: boolean, host: string, port: number, path?: string }[], keypair: Keypair) { let api: IRemoteContacter|undefined let peering: any + let endpoint = "" for (const access of hosts) { const host = access.host const port = access.port @@ -129,6 +129,7 @@ export class RemoteSynchronizer extends AbstractSynchronizer { const contacter = await connect(PeerDTO.fromJSONObject({ endpoints: [`BASIC_MERKLED_API ${host} ${port}${path && ' ' + path || ''}`]}), 3000) peering = await contacter.getPeer() api = new BMARemoteContacter(contacter) + endpoint = 'BASIC_MERKLED_API ' + host + ' ' + port + ((path && ' ' + path) || '') } catch (e) { logger.warn(`Node does not support BMA at address ${host} :${port}, trying WS2P...`) } @@ -147,14 +148,15 @@ export class RemoteSynchronizer extends AbstractSynchronizer { logger.warn('Receiving push messages, which are not allowed during a SYNC.', json) } }), - new WS2PPubkeySyncLocalAuth(currency, pair, '00000000'), - new WS2PPubkeyRemoteAuth(currency, pair), + new WS2PPubkeySyncLocalAuth("", pair, '00000000'), + new WS2PPubkeyRemoteAuth("", pair), // The currency will be set by the remote node undefined ) try { const requester = WS2PRequester.fromConnection(connection) peering = await requester.getPeer() api = new WS2PRemoteContacter(requester) + endpoint = 'WS2P 99999999 ' + host + ' ' + port + ((path && ' ' + path) || '') } catch (e) { logger.warn(`Node does not support WS2P at address ${host} :${port} either.`) } @@ -170,12 +172,11 @@ export class RemoteSynchronizer extends AbstractSynchronizer { if (!peering) { throw Error(DataErrors[DataErrors.NO_PEERING_AVAILABLE_FOR_SYNC]) } - if (peering.currency !== currency) { - throw Error(DataErrors[DataErrors.WRONG_CURRENCY_DETECTED]) - } return { api, - peering + peering, + endpoint, + currency: peering.currency } } @@ -191,6 +192,19 @@ export class RemoteSynchronizer extends AbstractSynchronizer { peers = await this.node.getPeers() } + // Add current peer if it is not returned (example of a local node) + peers.push({ + version: 1, + currency: '', + status: 'UP', + first_down: null, + last_try: null, + pubkey: '', + block: '', + signature: '', + endpoints: [this.endpoint] + }) + peers = peers.filter(p => { if (!p) return false let hasWS2P = false @@ -234,8 +248,8 @@ export class RemoteSynchronizer extends AbstractSynchronizer { return this.node.getBlock(number) } - static async test(currency: string, host: string, port: number, keypair: Keypair): Promise<BlockDTO> { - const syncApi = await RemoteSynchronizer.getSyncAPI(currency, [{ host, port }], keypair) + static async test(host: string, port: number, keypair: Keypair): Promise<BlockDTO> { + const syncApi = await RemoteSynchronizer.getSyncAPI([{ host, port }], keypair) const current = await syncApi.api.getCurrent() if (!current) { throw Error(DataErrors[DataErrors.REMOTE_HAS_NO_CURRENT_BLOCK]) diff --git a/app/modules/ws2p/lib/WS2PConnection.ts b/app/modules/ws2p/lib/WS2PConnection.ts index edee56a93ea7dba901411b57a7b9fcb3abea31ff..acb39587474fdc5c5fde2ea391de9b21a79ee27c 100644 --- a/app/modules/ws2p/lib/WS2PConnection.ts +++ b/app/modules/ws2p/lib/WS2PConnection.ts @@ -21,6 +21,8 @@ import {TransactionDTO} from "../../../lib/dto/TransactionDTO" import {PeerDTO} from "../../../lib/dto/PeerDTO" import {WS2PConstants} from './constants'; import {WebSocket} from "../../../lib/common-libs/websocket" +import {ManualPromise, newManualPromise} from "../../../lib/common-libs/manual-promise" +import {DataErrors} from "../../../lib/common-libs/errors" const SocksProxyAgent = require('socks-proxy-agent'); const nuuid = require('node-uuid'); @@ -61,7 +63,8 @@ export interface WS2PAuth { } export interface WS2PRemoteAuth extends WS2PAuth { - registerCONNECT(type: 'CONNECT'|'SYNC', ws2pVersion:number, challenge:string, sig: string, pub: string, ws2pId:string): Promise<boolean> + givenCurrency: Promise<string> + registerCONNECT(type: 'CONNECT'|'SYNC', ws2pVersion:number, challenge:string, sig: string, pub: string, currency: string, ws2pId:string): Promise<boolean> sendACK(ws:any): Promise<void> registerOK(sig: string): Promise<boolean> isAuthenticatedByRemote(): boolean @@ -75,6 +78,7 @@ export interface WS2PLocalAuth extends WS2PAuth { registerACK(sig: string, pub: string): Promise<boolean> sendOK(ws:any): Promise<void> isRemoteAuthenticated(): boolean + currency: string } /** @@ -91,6 +95,7 @@ export class WS2PPubkeyRemoteAuth implements WS2PRemoteAuth { protected serverAuthResolve:()=>void protected serverAuthReject:(err:any)=>void protected isSyncConnection = false + public givenCurrency: ManualPromise<string> constructor( protected currency:string, @@ -102,6 +107,11 @@ export class WS2PPubkeyRemoteAuth implements WS2PRemoteAuth { this.serverAuthResolve = resolve this.serverAuthReject = reject }) + this.givenCurrency = newManualPromise() + // If the currency is already provided, resolve the promise immediately + if (currency) { + this.givenCurrency.resolve(currency) + } } getVersion() { @@ -127,12 +137,20 @@ export class WS2PPubkeyRemoteAuth implements WS2PRemoteAuth { })) } - async registerCONNECT(type: 'CONNECT'|'SYNC', ws2pVersion:number, challenge:string, sig: string, pub: string, ws2pId:string = ""): Promise<boolean> { + async registerCONNECT(type: 'CONNECT'|'SYNC', ws2pVersion:number, challenge:string, sig: string, pub: string, currency: string, ws2pId:string = ""): Promise<boolean> { this.isSyncConnection = type === 'SYNC' const allow = await this.tellIsAuthorizedPubkey(pub, this.isSyncConnection) if (!allow) { return false } + // If the connection was not aware of the currency beforehand, let's give the remote node's value + if (!this.currency && currency) { + this.currency = currency + } + else if (this.currency && this.currency !== currency && currency) { + throw Error(DataErrors[DataErrors.WRONG_CURRENCY_DETECTED]) + } + this.givenCurrency.resolve(this.currency) const challengeMessage = (ws2pVersion > 1) ? `WS2P:${type}:${this.currency}:${pub}:${ws2pId}:${challenge}`:`WS2P:${type}:${this.currency}:${pub}:${challenge}` Logger.log('registerCONNECT >>> ' + challengeMessage) const verified = verify(challengeMessage, sig, pub) @@ -179,7 +197,7 @@ export class WS2PPubkeyLocalAuth implements WS2PLocalAuth { protected isSync: boolean constructor( - protected currency:string, + public currency:string, protected pair:Key, protected ws2pId:string, protected tellIsAuthorizedPubkey:(pub: string) => Promise<boolean> = () => Promise.resolve(true) @@ -204,7 +222,8 @@ export class WS2PPubkeyLocalAuth implements WS2PLocalAuth { pub: this.pair.pub, ws2pid: this.ws2pId, challenge: this.challenge, - sig + sig, + currency: this.currency, // This is necessary for SYNC: because the currency is supposed not to be known by the remote })) return this.serverAuth } else if (ws2pVersion == 1) { @@ -215,7 +234,8 @@ export class WS2PPubkeyLocalAuth implements WS2PLocalAuth { auth: `${connectWord}`, pub: this.pair.pub, challenge: this.challenge, - sig + sig, + currency: this.currency, // This is necessary for SYNC: because the currency is supposed not to be known by the remote })) return this.serverAuth } @@ -260,12 +280,12 @@ export class WS2PPubkeyLocalAuth implements WS2PLocalAuth { export class WS2PPubkeySyncLocalAuth extends WS2PPubkeyLocalAuth { constructor( - protected currency:string, + currency:string, // Only here for function signature purpose protected pair:Key, protected ws2pId:string, protected tellIsAuthorizedPubkey:(pub: string) => Promise<boolean> = () => Promise.resolve(true) ) { - super(currency, pair, ws2pId, tellIsAuthorizedPubkey) + super("", pair, ws2pId, tellIsAuthorizedPubkey) this.isSync = true } } @@ -450,6 +470,19 @@ export class WS2PConnection { (async () => { await this.onWsOpened try { + + // First: wait to know about the currency name. It can be given spontaneously by the remote node, + // or be already given if we know it before any exchange. + const currency = await this.remoteAuth.givenCurrency + // Then make some checks about its value + if (this.localAuth.currency && this.localAuth.currency !== currency) { + throw Error(DataErrors[DataErrors.WRONG_CURRENCY_DETECTED]) + } + // Eventually give the information to localAuth, which will now be able to start the connection (currency is required for WS2P messages) + if (!this.localAuth.currency) { + this.localAuth.currency = currency + } + await this.localAuth.sendCONNECT(this.ws, this.ws2pVersion) await Promise.all([ this.localAuth.authenticationIsDone(), @@ -497,7 +530,7 @@ export class WS2PConnection { if (this.expectedPub && data.pub !== this.expectedPub) { await this.errorDetected(WS2P_ERR.INCORRECT_PUBKEY_FOR_REMOTE) } else { - const valid = await this.remoteAuth.registerCONNECT(data.auth, this.ws2pVersion, data.challenge, data.sig, data.pub, (this.ws2pVersion > 1) ? data.ws2pID:"") + const valid = await this.remoteAuth.registerCONNECT(data.auth, this.ws2pVersion, data.challenge, data.sig, data.pub, data.currency, (this.ws2pVersion > 1) ? data.ws2pID:"") if (valid) { await this.remoteAuth.sendACK(this.ws) } else { diff --git a/test/integration/misc/cli.ts b/test/integration/misc/cli.ts index e7a1b3c8f0eb90b0e7e97bc4c6d52a5dd9411474..355e7f6e5d4971469e5f8470742f613c8d3d6425 100644 --- a/test/integration/misc/cli.ts +++ b/test/integration/misc/cli.ts @@ -126,14 +126,14 @@ describe("CLI", function() { it('sync 7 blocks (fast)', async () => { await execute(['reset', 'data']); - await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), 'duniter_unit_test_currency', '--nocautious', '--nointeractive', '--noshuffle', '--up-to', '7']); + await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), '--nocautious', '--nointeractive', '--noshuffle', '7']); const res = await execute(['export-bc', '--nostdout']); res[res.length - 1].should.have.property('number').equal(7); res.should.have.length(7 + 1); // blocks #0..#7 }) it('sync 4 blocks (cautious)', async () => { - await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), 'duniter_unit_test_currency', '--nointeractive', '--up-to', '11']); + await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), '--nointeractive', '11']); const res = await execute(['export-bc', '--nostdout']); res[res.length - 1].should.have.property('number').equal(11); res.should.have.length(11 + 1); @@ -146,7 +146,7 @@ describe("CLI", function() { }) it('[spawn] sync 10 first blocks --memory', async () => { - await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), 'duniter_unit_test_currency', '--memory', '--cautious', '--nointeractive', '--up-to', '10']); + await execute(['sync', fakeServer.host + ':' + String(fakeServer.port), '--memory', '--cautious', '--nointeractive', '10']); }) }); diff --git a/test/integration/tools/toolbox.ts b/test/integration/tools/toolbox.ts index 907414f1a8dbcfde809c24da57aa5007a4c65afc..b775d5354c21f35a85b5ce9e2b3ef5d8a9bbf2ae 100644 --- a/test/integration/tools/toolbox.ts +++ b/test/integration/tools/toolbox.ts @@ -699,7 +699,7 @@ export class TestingServer { const connection = WS2PConnection.newConnectionToAddress(1, `ws://${HOST}:${port}`, new WS2PServerMessageHandler(this._server, api.getCluster()), - new constructor(this.conf.currency, pair, ws2pId), + new constructor("", pair, ws2pId), new WS2PPubkeyRemoteAuth(this.conf.currency, pair) ) return WS2PRequester.fromConnection(connection) diff --git a/test/integration/ws2p/ws2p_connection.ts b/test/integration/ws2p/ws2p_connection.ts index ebdb2add42a793e5f42b5b3fbe656b6d7dbb1128..72c1ebcaa8773ee1f13243df19f53e76f0d86516 100644 --- a/test/integration/ws2p/ws2p_connection.ts +++ b/test/integration/ws2p/ws2p_connection.ts @@ -60,7 +60,7 @@ describe('WS2P', () => { }) it('should be able to create a connection', async () => { - const ws2p = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:' + portA, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth()) + const ws2p = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:' + portA, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth(gtest)) const res = await ws2p.request({ name: 'head' }) assert.deepEqual({ bla: 'aa' }, res) }) @@ -139,7 +139,7 @@ describe('WS2P', () => { it('should accept the connection if the server answers with a good signature', async () => { const keypair = new Key('HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP') - const ws2p = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:20903', new WS2PMutedHandler(), new WS2PPubkeyLocalAuth(gtest, keypair, ""), new WS2PNoRemoteAuth(), undefined, { + const ws2p = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:20903', new WS2PMutedHandler(), new WS2PPubkeyLocalAuth(gtest, keypair, ""), new WS2PNoRemoteAuth(gtest), undefined, { connectionTimeout: 1000, requestTimeout: 1000 }) @@ -171,7 +171,7 @@ describe('WS2P', () => { async answerToRequest(json: any): Promise<WS2PResponse> { return { answer: 'world' } } - }), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth()) + }), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth(gtest)) s1.connect().catch(e => logger.error('WS2P: newConnectionFromWebSocketServer connection error')) break case 1: @@ -182,7 +182,7 @@ describe('WS2P', () => { async answerToRequest(json: any): Promise<WS2PResponse> { return { answer: 'this is s2![j = ' + (j++) + ']' } } - }), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth()) + }), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth(gtest)) s2.connect().catch(e => logger.error('WS2P: newConnectionFromWebSocketServer connection error')) break } @@ -196,7 +196,7 @@ describe('WS2P', () => { it('should be able to create connections and make several requests', async () => { // connection 1 - const c1 = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:' + portB, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth()) + const c1 = WS2PConnection.newConnectionToAddress(1, 'ws://localhost:' + portB, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth(gtest)) assert.deepEqual({ answer: 'world' }, await c1.request({ name: 'hello!' })) assert.deepEqual({ answer: 'world' }, await c1.request({ name: 'hello2!' })) assert.equal(s1.nbRequests, 0) @@ -208,7 +208,7 @@ describe('WS2P', () => { assert.equal(s1.nbPushsByRemote, 0) assert.equal(c1.nbPushsByRemote, 0) // connection 2 - const c2 = WS2PConnection.newConnectionToAddress(1 ,'ws://localhost:' + portB, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth()) + const c2 = WS2PConnection.newConnectionToAddress(1 ,'ws://localhost:' + portB, new WS2PMutedHandler(), new WS2PNoLocalAuth(), new WS2PNoRemoteAuth(gtest)) assert.deepEqual({ answer: 'this is s2![j = 0]' }, await c2.request({ name: 'test?' })) assert.deepEqual({ answer: 'this is s2![j = 1]' }, await c2.request({ name: 'test!' })) assert.deepEqual({ answer: 'this is s2![j = 2]' }, await c2.request({ name: 'test!!!' })) @@ -427,10 +427,18 @@ class WS2PNoLocalAuth implements WS2PLocalAuth { async authenticationIsDone(): Promise<void> { } + + currency: string } class WS2PNoRemoteAuth implements WS2PRemoteAuth { + givenCurrency: Promise<string> + + constructor(currency: string) { + this.givenCurrency = Promise.resolve(currency) + } + getVersion(): number { return 1 } @@ -442,7 +450,8 @@ class WS2PNoRemoteAuth implements WS2PRemoteAuth { async sendACK(ws: any): Promise<void> { } - async registerCONNECT(type: 'CONNECT'|'SYNC', version:number, challenge:string, sig: string, pub: string, ws2pId:string): Promise<boolean> { + async registerCONNECT(type: 'CONNECT'|'SYNC', version:number, challenge:string, sig: string, pub: string, currency:string, ws2pId:string): Promise<boolean> { + this.givenCurrency = Promise.resolve(currency) return true } diff --git a/test/integration/ws2p/ws2p_sync.ts b/test/integration/ws2p/ws2p_sync.ts index 23dd3aa7002b4ac5d9a3f622ac5a1708db75b6e1..2e1e65018c195055dc56c48e8dfa794c8cf7bb2c 100644 --- a/test/integration/ws2p/ws2p_sync.ts +++ b/test/integration/ws2p/ws2p_sync.ts @@ -54,7 +54,7 @@ describe('WS2P sync', () => writeBasicTestWith2Users((test) => { const s2 = NewTestingServer({ pair: cat.keypair }) await s2.initWithDAL() // We sync on s1 - await CrawlerDependency.duniter.methods.synchronize(s1.conf.currency, s2._server, ws2p.host, ws2p.port, 2, 2).syncPromise + await CrawlerDependency.duniter.methods.synchronize(s2._server, ws2p.host, ws2p.port, 2, 2).syncPromise assertNotNull(await s2.dal.getCurrentBlockOrNull()) }) }))