From 506aa864980f0b6a2808b5d85d038533d55ce1f8 Mon Sep 17 00:00:00 2001 From: Aslan Askarov Date: Sat, 18 Mar 2023 10:18:36 +0100 Subject: [PATCH 01/22] wip: migrating towards ESM --- local.sh | 5 +- package.json | 3 +- rt/src/{Asserts.ts => Asserts.mts} | 23 ++++--- rt/src/{Atom.ts => Atom.mts} | 8 +-- rt/src/{Authority.ts => Authority.mts} | 8 +-- rt/src/{BaseFunction.ts => BaseFunction.mts} | 8 +-- ...EqualityChecker.ts => EqualityChecker.mts} | 8 +-- rt/src/{Level.ts => Level.mts} | 4 +- rt/src/{LocalObject.ts => LocalObject.mts} | 6 +- rt/src/{Lval.ts => Lval.mts} | 8 +-- ...ilboxInterface.ts => MailboxInterface.mts} | 4 +- ...ilboxProcessor.ts => MailboxProcessor.mts} | 36 +++++------ rt/src/{NodeManager.ts => NodeManager.mts} | 6 +- rt/src/{RawClosure.ts => RawClosure.mts} | 6 +- rt/src/{RawList.ts => RawList.mts} | 10 +-- ...eTaintAction.ts => ReceiveTaintAction.mts} | 0 rt/src/{Record.ts => Record.mts} | 12 ++-- ...ntimeInterface.ts => RuntimeInterface.mts} | 10 +-- .../{SandboxStatus.ts => SandboxStatus.mts} | 2 +- rt/src/{Scheduler.ts => Scheduler.mts} | 28 +++++---- ...lerInterface.ts => SchedulerInterface.mts} | 2 +- rt/src/{SysState.ts => SysState.mts} | 2 +- rt/src/{Thread.ts => Thread.mts} | 27 ++++---- rt/src/{TroupeError.ts => TroupeError.mts} | 4 +- .../{TroupeRawValue.ts => TroupeRawValue.mts} | 4 +- rt/src/{TroupeTypes.ts => TroupeTypes.mts} | 0 rt/src/{TrustManager.ts => TrustManager.mts} | 11 ++-- rt/src/UnitBase.js | 10 --- rt/src/UnitBase.mts | 8 +++ rt/src/UnitVal.mts | 6 ++ rt/src/UnitVal.ts | 6 -- rt/src/UserRuntime.mts | 61 +++++++++++++++++++ rt/src/UserRuntime.ts | 61 ------------------- rt/src/{ValuesUtil.ts => ValuesUtil.mts} | 12 ++-- ...UserRuntimeZero.ts => UserRuntimeZero.mts} | 33 +++++----- rt/src/builtins/{adv.ts => adv.mts} | 11 ++-- .../builtins/{attenuate.ts => attenuate.mts} | 10 +-- .../{debugutils.ts => debugutils.mts} | 8 +-- .../{declassify.ts => declassify.mts} | 11 ++-- rt/src/builtins/{exit.ts => exit.mts} | 10 +-- rt/src/builtins/{getTime.ts => getTime.mts} | 6 +- rt/src/builtins/{levelops.ts => levelops.mts} | 8 +-- .../{localarrays.ts => localarrays.mts} | 14 ++--- rt/src/builtins/{math.ts => math.mts} | 9 ++- .../builtins/{mboxclear.ts => mboxclear.mts} | 4 +- rt/src/builtins/{mkuuid.ts => mkuuid.mts} | 4 +- rt/src/builtins/{monitor.ts => monitor.mts} | 6 +- rt/src/builtins/{nodeutil.ts => nodeutil.mts} | 8 +-- rt/src/builtins/{persist.ts => persist.mts} | 15 +++-- rt/src/builtins/{pini.ts => pini.mts} | 8 +-- .../{raiseTrust.ts => raiseTrust.mts} | 14 ++--- rt/src/builtins/{receive.ts => receive.mts} | 20 +++--- .../{runtimeassert.ts => runtimeassert.mts} | 4 +- rt/src/builtins/{sandbox.ts => sandbox.mts} | 25 ++++---- rt/src/builtins/{self.ts => self.mts} | 5 +- rt/src/builtins/{send.ts => send.mts} | 4 +- rt/src/builtins/{service.ts => service.mts} | 4 +- rt/src/builtins/{sleep.ts => sleep.mts} | 8 +-- rt/src/builtins/{spawn.ts => spawn.mts} | 10 +-- rt/src/builtins/{stdio.ts => stdio.mts} | 15 +++-- rt/src/builtins/{string.ts => string.mts} | 10 +-- .../{stringToInt.ts => stringToInt.mts} | 4 +- rt/src/builtins/{toString.ts => toString.mts} | 4 +- rt/src/builtins/{whereis.ts => whereis.mts} | 26 ++++---- rt/src/{deserialize.ts => deserialize.mts} | 30 ++++----- rt/src/dev/relay.ts | 2 +- rt/src/levels/{singleton.ts => singleton.mts} | 14 +++-- rt/src/levels/{tagsets.ts => tagsets.mts} | 20 +++--- rt/src/{loadLibs.ts => loadLibs.mts} | 7 ++- .../{loadLibsAsync.ts => loadLibsAsync.mts} | 7 ++- rt/src/{logger.ts => logger.mts} | 3 +- rt/src/options.mts | 3 + rt/src/options.ts | 5 -- rt/src/p2p/{mkaliases.js => mkaliases.ts} | 24 +++++--- rt/src/p2p/mkid.ts | 5 +- rt/src/p2p/p2p.ts | 15 +++-- rt/src/p2p/p2pconfig.js | 7 ++- rt/src/{process.ts => process.mts} | 6 +- rt/src/{runId.ts => runId.mts} | 0 ...ntimeMonitored.ts => runtimeMonitored.mts} | 56 ++++++++--------- rt/src/{serialize.ts => serialize.mts} | 19 +++--- rt/src/troupe.js | 20 ------ rt/src/troupe.mts | 24 ++++++++ rt/tsconfig.json | 8 +-- 84 files changed, 519 insertions(+), 483 deletions(-) rename rt/src/{Asserts.ts => Asserts.mts} (94%) rename rt/src/{Atom.ts => Atom.mts} (67%) rename rt/src/{Authority.ts => Authority.mts} (69%) rename rt/src/{BaseFunction.ts => BaseFunction.mts} (82%) rename rt/src/{EqualityChecker.ts => EqualityChecker.mts} (92%) rename rt/src/{Level.ts => Level.mts} (75%) rename rt/src/{LocalObject.ts => LocalObject.mts} (74%) rename rt/src/{Lval.ts => Lval.mts} (94%) rename rt/src/{MailboxInterface.ts => MailboxInterface.mts} (73%) rename rt/src/{MailboxProcessor.ts => MailboxProcessor.mts} (94%) rename rt/src/{NodeManager.ts => NodeManager.mts} (94%) rename rt/src/{RawClosure.ts => RawClosure.mts} (85%) rename rt/src/{RawList.ts => RawList.mts} (90%) rename rt/src/{ReceiveTaintAction.ts => ReceiveTaintAction.mts} (100%) rename rt/src/{Record.ts => Record.mts} (80%) rename rt/src/{RuntimeInterface.ts => RuntimeInterface.mts} (62%) rename rt/src/{SandboxStatus.ts => SandboxStatus.mts} (97%) rename rt/src/{Scheduler.ts => Scheduler.mts} (93%) rename rt/src/{SchedulerInterface.ts => SchedulerInterface.mts} (93%) rename rt/src/{SysState.ts => SysState.mts} (80%) rename rt/src/{Thread.ts => Thread.mts} (97%) rename rt/src/{TroupeError.ts => TroupeError.mts} (95%) rename rt/src/{TroupeRawValue.ts => TroupeRawValue.mts} (74%) rename rt/src/{TroupeTypes.ts => TroupeTypes.mts} (100%) rename rt/src/{TrustManager.ts => TrustManager.mts} (81%) delete mode 100644 rt/src/UnitBase.js create mode 100644 rt/src/UnitBase.mts create mode 100644 rt/src/UnitVal.mts delete mode 100644 rt/src/UnitVal.ts create mode 100644 rt/src/UserRuntime.mts delete mode 100644 rt/src/UserRuntime.ts rename rt/src/{ValuesUtil.ts => ValuesUtil.mts} (76%) rename rt/src/builtins/{UserRuntimeZero.ts => UserRuntimeZero.mts} (93%) rename rt/src/builtins/{adv.ts => adv.mts} (90%) rename rt/src/builtins/{attenuate.ts => attenuate.mts} (86%) rename rt/src/builtins/{debugutils.ts => debugutils.mts} (93%) rename rt/src/builtins/{declassify.ts => declassify.mts} (92%) rename rt/src/builtins/{exit.ts => exit.mts} (84%) rename rt/src/builtins/{getTime.ts => getTime.mts} (86%) rename rt/src/builtins/{levelops.ts => levelops.mts} (91%) rename rt/src/builtins/{localarrays.ts => localarrays.mts} (91%) rename rt/src/builtins/{math.ts => math.mts} (84%) rename rt/src/builtins/{mboxclear.ts => mboxclear.mts} (93%) rename rt/src/builtins/{mkuuid.ts => mkuuid.mts} (85%) rename rt/src/builtins/{monitor.ts => monitor.mts} (93%) rename rt/src/builtins/{nodeutil.ts => nodeutil.mts} (80%) rename rt/src/builtins/{persist.ts => persist.mts} (80%) rename rt/src/builtins/{pini.ts => pini.mts} (93%) rename rt/src/builtins/{raiseTrust.ts => raiseTrust.mts} (87%) rename rt/src/builtins/{receive.ts => receive.mts} (95%) rename rt/src/builtins/{runtimeassert.ts => runtimeassert.mts} (89%) rename rt/src/builtins/{sandbox.ts => sandbox.mts} (89%) rename rt/src/builtins/{self.ts => self.mts} (80%) rename rt/src/builtins/{send.ts => send.mts} (97%) rename rt/src/builtins/{service.ts => service.mts} (82%) rename rt/src/builtins/{sleep.ts => sleep.mts} (78%) rename rt/src/builtins/{spawn.ts => spawn.mts} (91%) rename rt/src/builtins/{stdio.ts => stdio.mts} (93%) rename rt/src/builtins/{string.ts => string.mts} (85%) rename rt/src/builtins/{stringToInt.ts => stringToInt.mts} (89%) rename rt/src/builtins/{toString.ts => toString.mts} (95%) rename rt/src/builtins/{whereis.ts => whereis.mts} (86%) rename rt/src/{deserialize.ts => deserialize.mts} (94%) rename rt/src/levels/{singleton.ts => singleton.mts} (66%) rename rt/src/levels/{tagsets.ts => tagsets.mts} (88%) rename rt/src/{loadLibs.ts => loadLibs.mts} (96%) rename rt/src/{loadLibsAsync.ts => loadLibsAsync.mts} (93%) rename rt/src/{logger.ts => logger.mts} (90%) create mode 100644 rt/src/options.mts delete mode 100644 rt/src/options.ts rename rt/src/p2p/{mkaliases.js => mkaliases.ts} (67%) rename rt/src/{process.ts => process.mts} (86%) rename rt/src/{runId.ts => runId.mts} (100%) rename rt/src/{runtimeMonitored.ts => runtimeMonitored.mts} (91%) rename rt/src/{serialize.ts => serialize.mts} (95%) delete mode 100644 rt/src/troupe.js create mode 100644 rt/src/troupe.mts diff --git a/local.sh b/local.sh index 4a0494c..aa2603a 100755 --- a/local.sh +++ b/local.sh @@ -1,10 +1,11 @@ #!/bin/sh -tmp=`mktemp` +tmp=`mktemp`.js $TROUPE/bin/troupec $1 --output=$tmp + if [ $? -eq 0 ]; then - node --stack-trace-limit=1000 $TROUPE/rt/built/troupe.js -f=$tmp --localonly #--debug + node --stack-trace-limit=1000 $TROUPE/rt/built/troupe.mjs -f=$tmp --localonly #--debug rm $tmp else exit $? diff --git a/package.json b/package.json index b3363e4..f1a5177 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "license": "ISC", "dependencies": { "@nodeutils/defaults-deep": "^1.1.0", - "chalk": "^4.1.0", + "@types/node": "^18.15.3", + "chalk": "^5.2.0", "find-free-port": "^2.0.0", "it-length-prefixed": "^3.0.1", "it-pipe": "^1.1.0", diff --git a/rt/src/Asserts.ts b/rt/src/Asserts.mts similarity index 94% rename from rt/src/Asserts.ts rename to rt/src/Asserts.mts index fedb35d..01f9614 100644 --- a/rt/src/Asserts.ts +++ b/rt/src/Asserts.mts @@ -1,19 +1,18 @@ -import { Thread, Capability } from './Thread'; +import { Thread, Capability } from './Thread.mjs'; -const { isListFlagSet, isTupleFlagSet } = require('./ValuesUtil.js'); -const proc = require('./process.js'); +import { isListFlagSet, isTupleFlagSet } from './ValuesUtil.mjs'; +import * as proc from './process.mjs'; const ProcessID = proc.ProcessID; -import { Level } from './Level'; -import { Authority } from './Authority' -import options = require('./options.js'); -import { TroupeType } from './TroupeTypes'; -const levels = options; +import { Level } from './Level.mjs'; +import { Authority } from './Authority.mjs' +import * as levels from './options.mjs'; +import { TroupeType } from './TroupeTypes.mjs'; const flowsTo = levels.flowsTo; -import { getRuntimeObject } from './SysState'; -import { __nodeManager } from './NodeManager'; -import { TroupeAggregateRawValue, TroupeRawValue } from './TroupeRawValue'; -import { LVal } from './Lval'; +import { getRuntimeObject } from './SysState.mjs'; +import { __nodeManager } from './NodeManager.mjs'; +import { TroupeAggregateRawValue, TroupeRawValue } from './TroupeRawValue.mjs'; +// import { LVal } from './Lval'; function _thread() { return getRuntimeObject().__sched.__currentThread diff --git a/rt/src/Atom.ts b/rt/src/Atom.mts similarity index 67% rename from rt/src/Atom.ts rename to rt/src/Atom.mts index 8356254..5aa9fdb 100644 --- a/rt/src/Atom.ts +++ b/rt/src/Atom.mts @@ -1,7 +1,7 @@ -import runId from "./runId" -import { TroupeType } from "./TroupeTypes" -import { TroupeRawValue } from "./TroupeRawValue"; -import levels = require ('./options') +import runId from "./runId.mjs" +import { TroupeType } from "./TroupeTypes.mjs" +import { TroupeRawValue } from "./TroupeRawValue.mjs"; +import * as levels from './options.mjs' let rt_uuid = runId diff --git a/rt/src/Authority.ts b/rt/src/Authority.mts similarity index 69% rename from rt/src/Authority.ts rename to rt/src/Authority.mts index 4b153f7..de2cec1 100644 --- a/rt/src/Authority.ts +++ b/rt/src/Authority.mts @@ -1,8 +1,8 @@ -import { Level } from "./Level"; -import { BOT } from "./options"; +import { Level } from "./Level.mjs"; +import { BOT } from "./options.mjs"; -import { TroupeRawValue } from "./TroupeRawValue"; -import { TroupeType } from "./TroupeTypes"; +import { TroupeRawValue } from "./TroupeRawValue.mjs"; +import { TroupeType } from "./TroupeTypes.mjs"; export class Authority implements TroupeRawValue { authorityLevel: Level; diff --git a/rt/src/BaseFunction.ts b/rt/src/BaseFunction.mts similarity index 82% rename from rt/src/BaseFunction.ts rename to rt/src/BaseFunction.mts index d73c940..851b20f 100644 --- a/rt/src/BaseFunction.ts +++ b/rt/src/BaseFunction.mts @@ -1,7 +1,7 @@ -import {ClosureType, TroupeType} from './TroupeTypes' -import {TroupeAggregateRawValue} from './TroupeRawValue' -import levels from './options' -import { getRuntimeObject } from './SysState' +import {ClosureType, TroupeType} from './TroupeTypes.mjs' +import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' +import * as levels from './options.mjs' +import { getRuntimeObject } from './SysState.mjs' export function BaseFunctionWithExplicitArg(f, name = null) : TroupeAggregateRawValue{ diff --git a/rt/src/EqualityChecker.ts b/rt/src/EqualityChecker.mts similarity index 92% rename from rt/src/EqualityChecker.ts rename to rt/src/EqualityChecker.mts index b0802b2..e4659af 100644 --- a/rt/src/EqualityChecker.ts +++ b/rt/src/EqualityChecker.mts @@ -1,7 +1,7 @@ -import {TroupeType} from './TroupeTypes' -import {LVal} from './Lval' -const proc = require('./process.js'); -import levels = require ('./options') +import {TroupeType} from './TroupeTypes.mjs' +import {LVal} from './Lval.mjs' +import * as proc from './process.mjs' +import * as levels from './options.mjs' diff --git a/rt/src/Level.ts b/rt/src/Level.mts similarity index 75% rename from rt/src/Level.ts rename to rt/src/Level.mts index a62a478..4880730 100644 --- a/rt/src/Level.ts +++ b/rt/src/Level.mts @@ -1,5 +1,5 @@ -import { TroupeType } from "./TroupeTypes"; -import { TroupeRawValue } from "./TroupeRawValue"; +import { TroupeType } from "./TroupeTypes.mjs"; +import { TroupeRawValue } from "./TroupeRawValue.mjs"; // import levels from './options'; export abstract class Level implements TroupeRawValue { diff --git a/rt/src/LocalObject.ts b/rt/src/LocalObject.mts similarity index 74% rename from rt/src/LocalObject.ts rename to rt/src/LocalObject.mts index 8787b78..eeb7a73 100644 --- a/rt/src/LocalObject.ts +++ b/rt/src/LocalObject.mts @@ -1,6 +1,6 @@ -import {TroupeType} from './TroupeTypes' -import {TroupeRawValue} from './TroupeRawValue' -import levels from './options' +import {TroupeType} from './TroupeTypes.mjs' +import {TroupeRawValue} from './TroupeRawValue.mjs' +import * as levels from './options.mjs' export class LocalObject implements TroupeRawValue { _troupeType : TroupeType diff --git a/rt/src/Lval.ts b/rt/src/Lval.mts similarity index 94% rename from rt/src/Lval.ts rename to rt/src/Lval.mts index 98b87fd..d39bc68 100644 --- a/rt/src/Lval.ts +++ b/rt/src/Lval.mts @@ -1,7 +1,7 @@ -import levels = require ('./options') -import { Level } from "./Level"; -import * as Ty from './TroupeTypes'; -import { TroupeRawValue } from './TroupeRawValue'; +import * as levels from './options.mjs' +import { Level } from "./Level.mjs"; +import * as Ty from './TroupeTypes.mjs'; +import { TroupeRawValue } from './TroupeRawValue.mjs'; export class LVal implements TroupeRawValue{ val: any; diff --git a/rt/src/MailboxInterface.ts b/rt/src/MailboxInterface.mts similarity index 73% rename from rt/src/MailboxInterface.ts rename to rt/src/MailboxInterface.mts index 9c5e418..e737dc9 100644 --- a/rt/src/MailboxInterface.ts +++ b/rt/src/MailboxInterface.mts @@ -1,5 +1,5 @@ -import { Level } from "./Level"; -import { ReceiveTaintAction } from "./ReceiveTaintAction"; +import { Level } from "./Level.mjs"; +import { ReceiveTaintAction } from "./ReceiveTaintAction.mjs"; export interface MailboxInterface { // rcv(pc: any, pc2: any, handlers: any, boost_level: any, taintLimit?: Level, taintAction?: ReceiveTaintAction ); diff --git a/rt/src/MailboxProcessor.ts b/rt/src/MailboxProcessor.mts similarity index 94% rename from rt/src/MailboxProcessor.ts rename to rt/src/MailboxProcessor.mts index 94ecf2e..346c0d2 100644 --- a/rt/src/MailboxProcessor.ts +++ b/rt/src/MailboxProcessor.mts @@ -1,21 +1,23 @@ -import { assertIsHandler, assertIsNTuple, assertIsFunction } from "./Asserts"; -import { mkTuple } from "./ValuesUtil"; -import { SchedulerInterface } from "./SchedulerInterface"; -import { __unit } from "./UnitVal"; -import { RuntimeInterface } from "./RuntimeInterface"; - -// const {LVal, MbVal} = require('./Lval.js'); -const yargs = require ('yargs') +import { assertIsHandler, assertIsNTuple, assertIsFunction } from "./Asserts.mjs"; +import { mkTuple } from "./ValuesUtil.mjs"; +import { SchedulerInterface } from "./SchedulerInterface.mjs"; +import { __unit } from "./UnitVal.mjs"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; + +import yargs from 'yargs' let logLevel = yargs.argv.debugmailbox ? 'debug': 'info' -const logger = require('./logger.js').mkLogger('MBX', logLevel); -const debug = x => logger.debug(x) -const SandboxStatus = require('./SandboxStatus.js').HandlerState; -import levels, {lub,flowsTo} from './options' -import { ReceiveTaintAction } from "./ReceiveTaintAction"; -import { LVal, MbVal } from "./Lval"; -import { MailboxInterface } from "./MailboxInterface"; -import { Level } from "./Level"; -import { Thread } from "./Thread"; + +import { mkLogger } from './logger.mjs' +const logger = mkLogger('MBX', logLevel); +const debug = x => logger.debug(x); +import { HandlerState as SandboxStatus } from './SandboxStatus.mjs' ; +import {lub,flowsTo} from './options.mjs' +import * as levels from './options.mjs' +import { ReceiveTaintAction } from "./ReceiveTaintAction.mjs"; +import { LVal, MbVal } from "./Lval.mjs"; +import { MailboxInterface } from "./MailboxInterface.mjs"; +import { Level } from "./Level.mjs"; +import { Thread } from "./Thread.mjs"; function createMessage(msg, fromNodeId, pc) { diff --git a/rt/src/NodeManager.ts b/rt/src/NodeManager.mts similarity index 94% rename from rt/src/NodeManager.ts rename to rt/src/NodeManager.mts index 1003dbf..2ff8bea 100644 --- a/rt/src/NodeManager.ts +++ b/rt/src/NodeManager.mts @@ -1,7 +1,7 @@ 'use strict' -const fs = require('fs') -import levels from "./options"; +import * as fs from 'node:fs' +import * as levels from "./options.mjs"; import yargs from 'yargs' class Node { @@ -19,7 +19,7 @@ class NodeManager { constructor () { let aliases = yargs.argv.aliases - ? JSON.parse ( fs.readFileSync(yargs.argv.aliases, 'utf8')) + ? JSON.parse ( fs.readFileSync(yargs.argv.aliases as string, 'utf8')) : {} diff --git a/rt/src/RawClosure.ts b/rt/src/RawClosure.mts similarity index 85% rename from rt/src/RawClosure.ts rename to rt/src/RawClosure.mts index 54b58f6..c42539e 100644 --- a/rt/src/RawClosure.ts +++ b/rt/src/RawClosure.mts @@ -1,6 +1,6 @@ -import {TroupeAggregateRawValue} from './TroupeRawValue' -import {ClosureType, TroupeType} from './TroupeTypes' -import levels from './options' +import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' +import {ClosureType, TroupeType} from './TroupeTypes.mjs' +import * as levels from './options.mjs' export function RawClosure (e, _t, f) : TroupeAggregateRawValue { let closure:any = () => { return f (e) diff --git a/rt/src/RawList.ts b/rt/src/RawList.mts similarity index 90% rename from rt/src/RawList.ts rename to rt/src/RawList.mts index ca40cf7..211de69 100644 --- a/rt/src/RawList.ts +++ b/rt/src/RawList.mts @@ -1,8 +1,8 @@ -import {TroupeType} from './TroupeTypes' -import {TroupeAggregateRawValue} from './TroupeRawValue' -import {LVal, listStringRep} from './Lval' -import { Level } from './Level' -import levels from './options' +import {TroupeType} from './TroupeTypes.mjs' +import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' +import {LVal, listStringRep} from './Lval.mjs' +import { Level } from './Level.mjs' +import * as levels from './options.mjs' export abstract class RawList implements TroupeAggregateRawValue { diff --git a/rt/src/ReceiveTaintAction.ts b/rt/src/ReceiveTaintAction.mts similarity index 100% rename from rt/src/ReceiveTaintAction.ts rename to rt/src/ReceiveTaintAction.mts diff --git a/rt/src/Record.ts b/rt/src/Record.mts similarity index 80% rename from rt/src/Record.ts rename to rt/src/Record.mts index 696a1d8..0de634c 100644 --- a/rt/src/Record.ts +++ b/rt/src/Record.mts @@ -1,9 +1,9 @@ -import {TroupeType} from './TroupeTypes' -import {TroupeAggregateRawValue} from './TroupeRawValue' -import {LVal, listStringRep} from './Lval' -import { Level } from './Level' -import levels from './options' -import { assertIsRecord } from './Asserts' +import {TroupeType} from './TroupeTypes.mjs' +import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' +import {LVal, listStringRep} from './Lval.mjs' +import { Level } from './Level.mjs' +import * as levels from './options.mjs' +import { assertIsRecord } from './Asserts.mjs' export class Record implements TroupeAggregateRawValue { diff --git a/rt/src/RuntimeInterface.ts b/rt/src/RuntimeInterface.mts similarity index 62% rename from rt/src/RuntimeInterface.ts rename to rt/src/RuntimeInterface.mts index 63c7dc1..f212b8a 100644 --- a/rt/src/RuntimeInterface.ts +++ b/rt/src/RuntimeInterface.mts @@ -1,7 +1,7 @@ -import { SchedulerInterface } from "./SchedulerInterface"; -import { Thread } from "./Thread"; -import { LVal } from './Lval' -import { MailboxInterface } from "./MailboxInterface"; +import { SchedulerInterface } from "./SchedulerInterface.mjs"; +import { Thread } from "./Thread.mjs"; +import { LVal } from './Lval.mjs' +import { MailboxInterface } from "./MailboxInterface.mjs"; export interface RuntimeInterface { cleanup(): Promise @@ -13,7 +13,7 @@ export interface RuntimeInterface { debug(arg0: string); __sched: SchedulerInterface __mbox : MailboxInterface - sendMessageNoChecks(toPid: any, message: import("./Lval").LVal, arg2?: boolean): any; + sendMessageNoChecks(toPid: any, message: import("./Lval.mjs").LVal, arg2?: boolean): any; ret(arg0: any); // ret_raw () // tailcall(funclos: any, __unit: any); diff --git a/rt/src/SandboxStatus.ts b/rt/src/SandboxStatus.mts similarity index 97% rename from rt/src/SandboxStatus.ts rename to rt/src/SandboxStatus.mts index c91f82d..72d6694 100644 --- a/rt/src/SandboxStatus.ts +++ b/rt/src/SandboxStatus.mts @@ -1,4 +1,4 @@ -import { Level } from "./Level"; +import { Level } from "./Level.mjs"; export interface HnState { isNormal (): boolean diff --git a/rt/src/Scheduler.ts b/rt/src/Scheduler.mts similarity index 93% rename from rt/src/Scheduler.ts rename to rt/src/Scheduler.mts index df20eb4..2b86386 100644 --- a/rt/src/Scheduler.ts +++ b/rt/src/Scheduler.mts @@ -1,19 +1,21 @@ 'use strict'; import { v4 as uuidv4} from 'uuid' -import { Thread } from './Thread'; -import runId from './runId'; -import { __unit } from './UnitVal'; -import { mkTuple } from './ValuesUtil'; -import { SchedulerInterface } from './SchedulerInterface'; -import { RuntimeInterface } from './RuntimeInterface'; -import { LVal } from './Lval.js' -import {ProcessID, pid_equals} from './process' -import SandboxStatus from './SandboxStatus' -import {ThreadError, TroupeError} from './TroupeError' -import levels, {lub} from './options' -const yargs = require('yargs'); +import { Thread } from './Thread.mjs'; +import runId from './runId.mjs'; +import { __unit } from './UnitVal.mjs'; +import { mkTuple } from './ValuesUtil.mjs'; +import { SchedulerInterface } from './SchedulerInterface.mjs'; +import { RuntimeInterface } from './RuntimeInterface.mjs'; +import { LVal } from './Lval.mjs' +import {ProcessID, pid_equals} from './process.mjs' +import SandboxStatus from './SandboxStatus.mjs' +import {ThreadError, TroupeError} from './TroupeError.mjs' +import {lub} from './options.mjs' +// import * as levels from './options' +import yargs from 'yargs'; const showStack = yargs.argv.showStack -const logger = require('./logger.js').mkLogger('scheduler'); +import { mkLogger } from './logger.mjs' +const logger = mkLogger('scheduler'); const info = x => logger.info(x) const debug = x => logger.debug(x) diff --git a/rt/src/SchedulerInterface.ts b/rt/src/SchedulerInterface.mts similarity index 93% rename from rt/src/SchedulerInterface.ts rename to rt/src/SchedulerInterface.mts index c45564c..742f3b8 100644 --- a/rt/src/SchedulerInterface.ts +++ b/rt/src/SchedulerInterface.mts @@ -1,4 +1,4 @@ -import { Thread } from "./Thread"; +import { Thread } from "./Thread.mjs"; export interface SchedulerInterface { // tailToTroupeFun(f: any, arg:any) diff --git a/rt/src/SysState.ts b/rt/src/SysState.mts similarity index 80% rename from rt/src/SysState.ts rename to rt/src/SysState.mts index 45caef0..7bb42e1 100644 --- a/rt/src/SysState.ts +++ b/rt/src/SysState.mts @@ -1,4 +1,4 @@ -import { RuntimeInterface } from "./RuntimeInterface"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; let __state: RuntimeInterface = null; diff --git a/rt/src/Thread.ts b/rt/src/Thread.mts similarity index 97% rename from rt/src/Thread.ts rename to rt/src/Thread.mts index fd9578e..181ae62 100644 --- a/rt/src/Thread.ts +++ b/rt/src/Thread.mts @@ -1,23 +1,24 @@ -import levels = require ('./options') -import { LVal, LValCopyAt } from './Lval.js'; -import { HandlerError, ImplementationError, StrThreadError } from './TroupeError.js'; +import * as levels from './options.mjs' +import { LVal, LValCopyAt } from './Lval.mjs'; +import { HandlerError, ImplementationError, StrThreadError } from './TroupeError.mjs'; import yargs from 'yargs'; let logLevel = yargs.argv.debug? 'debug' : 'info' -const logger = require('./logger.js').mkLogger('thread', logLevel); +import { mkLogger } from './logger.mjs' +const logger = mkLogger('thread', logLevel); const debug = x => logger.debug(x) let lub = levels.lub; let flowsTo = levels.flowsTo import { v4 as uuidv4} from 'uuid' -import { TroupeType } from './TroupeTypes' -import { assertIsFunction, assertIsFunctionRaw } from './Asserts'; -import { RuntimeInterface } from './RuntimeInterface'; -import { __unit } from './UnitVal'; -import { Level } from './Level'; -import { SchedulerInterface } from './SchedulerInterface'; -import { getRuntimeObject } from './SysState'; -import SandboxStatus, { HnState } from './SandboxStatus'; -import HandlerState from './SandboxStatus'; +import { TroupeType } from './TroupeTypes.mjs' +import { assertIsFunction, assertIsFunctionRaw } from './Asserts.mjs' +import { RuntimeInterface } from './RuntimeInterface.mjs'; +import { __unit } from './UnitVal.mjs'; +import { Level } from './Level.mjs'; +import { SchedulerInterface } from './SchedulerInterface.mjs'; +import { getRuntimeObject } from './SysState.mjs'; +import SandboxStatus, { HnState } from './SandboxStatus.mjs'; +import HandlerState from './SandboxStatus.mjs'; let isPiniMode = yargs.argv.pini?true:false; diff --git a/rt/src/TroupeError.ts b/rt/src/TroupeError.mts similarity index 95% rename from rt/src/TroupeError.ts rename to rt/src/TroupeError.mts index 2b67aaf..ea7720a 100644 --- a/rt/src/TroupeError.ts +++ b/rt/src/TroupeError.mts @@ -1,7 +1,7 @@ -import { Thread } from "./Thread"; +import { Thread } from "./Thread.mjs"; // import colors = require('colors/safe'); import chalk from 'chalk' -import { SchedulerInterface } from "./SchedulerInterface"; +import { SchedulerInterface } from "./SchedulerInterface.mjs"; export abstract class TroupeError extends Error { abstract handleError (sched: SchedulerInterface) : void diff --git a/rt/src/TroupeRawValue.ts b/rt/src/TroupeRawValue.mts similarity index 74% rename from rt/src/TroupeRawValue.ts rename to rt/src/TroupeRawValue.mts index ca0db90..78d5e0d 100644 --- a/rt/src/TroupeRawValue.ts +++ b/rt/src/TroupeRawValue.mts @@ -1,5 +1,5 @@ -import {TroupeType} from './TroupeTypes' -import { Level } from './Level' +import {TroupeType} from './TroupeTypes.mjs' +import { Level } from './Level.mjs' export interface TroupeRawValue { _troupeType: TroupeType; diff --git a/rt/src/TroupeTypes.ts b/rt/src/TroupeTypes.mts similarity index 100% rename from rt/src/TroupeTypes.ts rename to rt/src/TroupeTypes.mts diff --git a/rt/src/TrustManager.ts b/rt/src/TrustManager.mts similarity index 81% rename from rt/src/TrustManager.ts rename to rt/src/TrustManager.mts index c0466cf..59b2763 100644 --- a/rt/src/TrustManager.ts +++ b/rt/src/TrustManager.mts @@ -1,14 +1,15 @@ -import levels from "./options"; +import * as levels from "./options.mjs"; import yargs from "yargs"; -import fs from 'fs' -import { Level } from "./Level"; -import { __nodeManager } from "./NodeManager"; +import * as fs from 'node:fs'; +import { Level } from "./Level.mjs"; +import { __nodeManager } from "./NodeManager.mjs"; const { readFile } = fs.promises let logLevel = yargs.argv.debug ? 'debug' : 'info'; -const logger = require('./logger.js').mkLogger('RTM', logLevel); +import { mkLogger } from './logger.mjs' +const logger = mkLogger('RTM', logLevel); export let _trustMap = {} diff --git a/rt/src/UnitBase.js b/rt/src/UnitBase.js deleted file mode 100644 index 8540e23..0000000 --- a/rt/src/UnitBase.js +++ /dev/null @@ -1,10 +0,0 @@ -const level = require('./options.js'); - - -theBaseUnit = { stringRep: () => "()" - , _is_unit : true - , _troupeType : 0 /* UNIT */ - , dataLevel : level.BOT - } ; - -module.exports = theBaseUnit; \ No newline at end of file diff --git a/rt/src/UnitBase.mts b/rt/src/UnitBase.mts new file mode 100644 index 0000000..6e3fac5 --- /dev/null +++ b/rt/src/UnitBase.mts @@ -0,0 +1,8 @@ +import * as levels from './options.mjs' + + +export let __unitbase = { stringRep: () => "()" + , _is_unit : true + , _troupeType : 0 /* UNIT */ + , dataLevel : levels.BOT + } ; diff --git a/rt/src/UnitVal.mts b/rt/src/UnitVal.mts new file mode 100644 index 0000000..38ff43e --- /dev/null +++ b/rt/src/UnitVal.mts @@ -0,0 +1,6 @@ +import {__unitbase} from './UnitBase.mjs' +import * as levels from './options.mjs'; +import { LVal } from './Lval.mjs'; + +export let __unit = new LVal (__unitbase, levels.BOT, levels.BOT) + diff --git a/rt/src/UnitVal.ts b/rt/src/UnitVal.ts deleted file mode 100644 index 8a1b9c9..0000000 --- a/rt/src/UnitVal.ts +++ /dev/null @@ -1,6 +0,0 @@ -import __unitbase from './UnitBase' -import levels from './options'; -import { LVal } from './Lval'; - -export let __unit = new LVal (__unitbase, levels.BOT, levels.BOT) - diff --git a/rt/src/UserRuntime.mts b/rt/src/UserRuntime.mts new file mode 100644 index 0000000..43b6ea8 --- /dev/null +++ b/rt/src/UserRuntime.mts @@ -0,0 +1,61 @@ +import { UserRuntimeZero } from './builtins/UserRuntimeZero.mjs' +import { BuiltinStdIo } from './builtins/stdio.mjs' +import { BuiltinMath } from './builtins/math.mjs' +import { BuiltinDebugUtils } from './builtins/debugutils.mjs' +import { BuiltinPini } from './builtins/pini.mjs' +import { BuiltinMonitors } from './builtins/monitor.mjs' +import { BuiltinSleep } from './builtins/sleep.mjs' +import { BuiltinLevOps } from './builtins/levelops.mjs' +import { BuiltinMboxClear } from './builtins/mboxclear.mjs' +import { BuiltinMkUuid } from './builtins/mkuuid.mjs' +import { BuiltinPersist } from './builtins/persist.mjs' +import { BuiltinNodeUtils } from './builtins/nodeutil.mjs' +import { BuiltinSelf } from './builtins/self.mjs' +import { BuiltinExit } from './builtins/exit.mjs' +import { BuiltinAdv } from './builtins/adv.mjs' +import { BuiltinGetTime } from './builtins/getTime.mjs' +import { BuiltinStringToInt } from './builtins/stringToInt.mjs' +import { BuiltinToString } from './builtins/toString.mjs' +import { BuiltinSend } from './builtins/send.mjs' +import { BuiltinSpawn } from './builtins/spawn.mjs' +import { BuiltinReceive } from './builtins/receive.mjs' +import { BuiltinAttenuate } from './builtins/attenuate.mjs' +import { BuiltinRegistry } from './builtins/whereis.mjs' +import { BuiltinDeclassify } from './builtins/declassify.mjs' +import { BuiltinRaiseTrust } from './builtins/raiseTrust.mjs' +import { BuiltinSandbox } from './builtins/sandbox.mjs' +import { BuiltinLocalArrays } from './builtins/localarrays.mjs' +import { RuntimeAssert } from './builtins/runtimeassert.mjs' +import { BuiltinService } from './builtins/service.mjs' +import { BuiltinString } from './builtins/string.mjs' + +let BuiltSpawnSendReceive = x => BuiltinSpawn(BuiltinSend(BuiltinReceive(x))) + +export const UserRuntime = + BuiltinString ( + BuiltinService ( + RuntimeAssert( + BuiltinLocalArrays( + BuiltinSandbox( + BuiltinRaiseTrust( + BuiltinDeclassify ( + BuiltinRegistry( + BuiltinAttenuate( + BuiltSpawnSendReceive( + BuiltinStringToInt( + BuiltinToString( + BuiltinGetTime( + BuiltinAdv( + BuiltinExit( + BuiltinSelf( + BuiltinNodeUtils( + BuiltinPersist( + BuiltinMkUuid( + BuiltinMboxClear( + BuiltinLevOps( + BuiltinSleep( + BuiltinMonitors( + BuiltinPini( + BuiltinDebugUtils( + BuiltinMath( + BuiltinStdIo(UserRuntimeZero))))))))))))))))))))))))))) diff --git a/rt/src/UserRuntime.ts b/rt/src/UserRuntime.ts deleted file mode 100644 index 6cffc82..0000000 --- a/rt/src/UserRuntime.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { UserRuntimeZero } from './builtins/UserRuntimeZero' -import { BuiltinStdIo } from './builtins/stdio' -import { BuiltinMath } from './builtins/math' -import { BuiltinDebugUtils } from './builtins/debugutils' -import { BuiltinPini } from './builtins/pini' -import { BuiltinMonitors } from './builtins/monitor' -import { BuiltinSleep } from './builtins/sleep' -import { BuiltinLevOps } from './builtins/levelops' -import { BuiltinMboxClear } from './builtins/mboxclear' -import { BuiltinMkUuid } from './builtins/mkuuid' -import { BuiltinPersist } from './builtins/persist' -import { BuiltinNodeUtils } from './builtins/nodeutil' -import { BuiltinSelf } from './builtins/self' -import { BuiltinExit } from './builtins/exit' -import { BuiltinAdv } from './builtins/adv' -import { BuiltinGetTime } from './builtins/getTime' -import { BuiltinStringToInt } from './builtins/stringToInt' -import { BuiltinToString } from './builtins/toString' -import { BuiltinSend } from './builtins/send' -import { BuiltinSpawn } from './builtins/spawn' -import { BuiltinReceive } from './builtins/receive' -import { BuiltinAttenuate } from './builtins/attenuate' -import { BuiltinRegistry } from './builtins/whereis' -import { BuiltinDeclassify } from './builtins/declassify' -import { BuiltinRaiseTrust } from './builtins/raiseTrust' -import { BuiltinSandbox } from './builtins/sandbox' -import { BuiltinLocalArrays } from './builtins/localarrays' -import { RuntimeAssert } from './builtins/runtimeassert' -import { BuiltinService } from './builtins/service' -import { BuiltinString } from './builtins/string' - -let BuiltSpawnSendReceive = x => BuiltinSpawn(BuiltinSend(BuiltinReceive(x))) - -export const UserRuntime = - BuiltinString ( - BuiltinService ( - RuntimeAssert( - BuiltinLocalArrays( - BuiltinSandbox( - BuiltinRaiseTrust( - BuiltinDeclassify ( - BuiltinRegistry( - BuiltinAttenuate( - BuiltSpawnSendReceive( - BuiltinStringToInt( - BuiltinToString( - BuiltinGetTime( - BuiltinAdv( - BuiltinExit( - BuiltinSelf( - BuiltinNodeUtils( - BuiltinPersist( - BuiltinMkUuid( - BuiltinMboxClear( - BuiltinLevOps( - BuiltinSleep( - BuiltinMonitors( - BuiltinPini( - BuiltinDebugUtils( - BuiltinMath( - BuiltinStdIo(UserRuntimeZero))))))))))))))))))))))))))) diff --git a/rt/src/ValuesUtil.ts b/rt/src/ValuesUtil.mts similarity index 76% rename from rt/src/ValuesUtil.ts rename to rt/src/ValuesUtil.mts index d6c0ed2..6ff1d9b 100644 --- a/rt/src/ValuesUtil.ts +++ b/rt/src/ValuesUtil.mts @@ -1,7 +1,11 @@ -import {listStringRep} from './Lval' -import { RawList } from './RawList' -import { TroupeType } from './TroupeTypes' -import levels from './options' +import {listStringRep} from './Lval.mjs' +import { RawList } from './RawList.mjs' +import { TroupeType } from './TroupeTypes.mjs' +import * as levels from './options.mjs' + + + + export function isListFlagSet (x:any) { return (x.isList == true ) diff --git a/rt/src/builtins/UserRuntimeZero.ts b/rt/src/builtins/UserRuntimeZero.mts similarity index 93% rename from rt/src/builtins/UserRuntimeZero.ts rename to rt/src/builtins/UserRuntimeZero.mts index 1454aef..2af231c 100644 --- a/rt/src/builtins/UserRuntimeZero.ts +++ b/rt/src/builtins/UserRuntimeZero.mts @@ -1,27 +1,26 @@ 'use strict' -import { runtimeEquals } from '../EqualityChecker' -import { isListFlagSet, isTupleFlagSet, mkTuple, mkList } from '../ValuesUtil' -import { LVal, LValCopyAt, LCopyVal } from '../Lval' -import { Nil, Cons, RawList } from '../RawList' -import { loadLibsAsync } from '../loadLibsAsync'; -import options from '../options' -import { BaseFunctionWithExplicitArg, ServiceFunction } from '../BaseFunction' -import { Atom } from '../Atom' -import { assertIsString, assertPairAreNumbers, assertPairAreStringsOrNumbers, assertIsBoolean, assertIsListOrTuple, assertIsNumber, rawAssertIsList} from '../Asserts' -import { __unit } from '../UnitVal' -import { RuntimeInterface } from '../RuntimeInterface'; -import { Record } from '../Record' -import { TroupeType } from '../TroupeTypes' -import { RawClosure } from '../RawClosure' -import __unitbase from '../UnitBase' -import { Thread } from '../Thread' +import { runtimeEquals } from '../EqualityChecker.mjs' +import { isListFlagSet, isTupleFlagSet, mkTuple, mkList } from '../ValuesUtil.mjs' +import { LVal, LValCopyAt, LCopyVal } from '../Lval.mjs' +import { Nil, Cons, RawList } from '../RawList.mjs' +import { loadLibsAsync } from '../loadLibsAsync.mjs'; +import * as levels from '../options.mjs' +import { BaseFunctionWithExplicitArg, ServiceFunction } from '../BaseFunction.mjs' +import { Atom } from '../Atom.mjs' +import { assertIsString, assertPairAreNumbers, assertPairAreStringsOrNumbers, assertIsBoolean, assertIsListOrTuple, assertIsNumber, rawAssertIsList} from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs' +import { RuntimeInterface } from '../RuntimeInterface.mjs'; +import { Record } from '../Record.mjs' +import { TroupeType } from '../TroupeTypes.mjs' +import { RawClosure } from '../RawClosure.mjs' +import { __unitbase } from '../UnitBase.mjs' +import { Thread } from '../Thread.mjs' // import { builtin_sandbox } from './builtins/sandox' export type Constructor = new (...args: any[]) => T; -const levels = options; const {lub, lubs} = levels class RtEnv { diff --git a/rt/src/builtins/adv.ts b/rt/src/builtins/adv.mts similarity index 90% rename from rt/src/builtins/adv.ts rename to rt/src/builtins/adv.mts index b9d1890..1dd9e73 100644 --- a/rt/src/builtins/adv.ts +++ b/rt/src/builtins/adv.mts @@ -1,10 +1,9 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertIsNTuple, assertNormalState } from '../Asserts'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as levels from '../options.mjs' +import { assertIsNTuple, assertNormalState } from '../Asserts.mjs'; +import { __unit } from '../UnitVal.mjs'; -const levels = options; const {lub, flowsTo} = levels export function BuiltinAdv >(Base: TBase) { diff --git a/rt/src/builtins/attenuate.ts b/rt/src/builtins/attenuate.mts similarity index 86% rename from rt/src/builtins/attenuate.ts rename to rt/src/builtins/attenuate.mts index 9323db8..86142ba 100644 --- a/rt/src/builtins/attenuate.ts +++ b/rt/src/builtins/attenuate.mts @@ -1,8 +1,8 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import levels from '../options' -import { Authority } from '../Authority'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel } from '../Asserts'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as levels from '../options.mjs' +import { Authority } from '../Authority.mjs'; +import { assertIsNTuple, assertIsAuthority, assertIsLevel } from '../Asserts.mjs' const {lubs, flowsTo} = levels diff --git a/rt/src/builtins/debugutils.ts b/rt/src/builtins/debugutils.mts similarity index 93% rename from rt/src/builtins/debugutils.ts rename to rt/src/builtins/debugutils.mts index b245f99..f712e7a 100644 --- a/rt/src/builtins/debugutils.ts +++ b/rt/src/builtins/debugutils.mts @@ -1,7 +1,7 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { assertIsString, assertIsNumber, assertIsNTuple } from '../Asserts'; -import { __unit } from '../UnitVal'; -import { TroupeType } from '../TroupeTypes'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { assertIsString, assertIsNumber, assertIsNTuple } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; +import { TroupeType } from '../TroupeTypes.mjs'; export function BuiltinDebugUtils > (Base:TBase) { diff --git a/rt/src/builtins/declassify.ts b/rt/src/builtins/declassify.mts similarity index 92% rename from rt/src/builtins/declassify.ts rename to rt/src/builtins/declassify.mts index b8df6fc..2dea423 100644 --- a/rt/src/builtins/declassify.ts +++ b/rt/src/builtins/declassify.mts @@ -1,8 +1,9 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LCopyVal } from '../Lval'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel } from '../Asserts'; -import { __unit } from '../UnitVal'; -import options, { lubs } from '../options' +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LCopyVal } from '../Lval.mjs'; +import { assertIsNTuple, assertIsAuthority, assertIsLevel } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; +import * as options from '../options.mjs' +let { lubs } = options const levels = options; const { lub, flowsTo } = levels diff --git a/rt/src/builtins/exit.ts b/rt/src/builtins/exit.mts similarity index 84% rename from rt/src/builtins/exit.ts rename to rt/src/builtins/exit.mts index 42b6bc2..9d4cbb5 100644 --- a/rt/src/builtins/exit.ts +++ b/rt/src/builtins/exit.mts @@ -1,8 +1,8 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertNormalState, assertIsNTuple, assertIsAuthority, assertIsNumber, assertIsTopAuthority } from '../Asserts'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as options from '../options.mjs' +import { assertNormalState, assertIsNTuple, assertIsAuthority, assertIsNumber, assertIsTopAuthority } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; const levels = options; const { lub, flowsTo } = levels diff --git a/rt/src/builtins/getTime.ts b/rt/src/builtins/getTime.mts similarity index 86% rename from rt/src/builtins/getTime.ts rename to rt/src/builtins/getTime.mts index 69d4725..79e024e 100644 --- a/rt/src/builtins/getTime.ts +++ b/rt/src/builtins/getTime.mts @@ -1,7 +1,7 @@ 'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import { assertIsUnit, assertNormalState } from '../Asserts'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import { assertIsUnit, assertNormalState } from '../Asserts.mjs' export function BuiltinGetTime>(Base: TBase) { diff --git a/rt/src/builtins/levelops.ts b/rt/src/builtins/levelops.mts similarity index 91% rename from rt/src/builtins/levelops.ts rename to rt/src/builtins/levelops.mts index 21a792b..d293d3f 100644 --- a/rt/src/builtins/levelops.ts +++ b/rt/src/builtins/levelops.mts @@ -1,10 +1,10 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as options from '../options.mjs' const levels = options; const {lub, flowsTo} = levels import { v4 as uuidv4 } from 'uuid' -import { assertIsNTuple, assertIsLevel, assertIsUnit } from '../Asserts'; +import { assertIsNTuple, assertIsLevel, assertIsUnit } from '../Asserts.mjs' export function BuiltinLevOps > (Base:TBase) { diff --git a/rt/src/builtins/localarrays.ts b/rt/src/builtins/localarrays.mts similarity index 91% rename from rt/src/builtins/localarrays.ts rename to rt/src/builtins/localarrays.mts index fa97995..039eaa6 100644 --- a/rt/src/builtins/localarrays.ts +++ b/rt/src/builtins/localarrays.mts @@ -1,10 +1,10 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertIsUnit, assertIsNumber, assertIsNTuple, assertIsLevel, assertIsLocalObject } from '../Asserts'; -import { LocalObject } from '../LocalObject'; -import { __unit } from '../UnitVal'; -let levels, {lub, lubs, flowsTo} = options; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as options from '../options.mjs' +import { assertIsUnit, assertIsNumber, assertIsNTuple, assertIsLevel, assertIsLocalObject } from '../Asserts.mjs' +import { LocalObject } from '../LocalObject.mjs'; +import { __unit } from '../UnitVal.mjs'; +let {lub, flowsTo} = options; diff --git a/rt/src/builtins/math.ts b/rt/src/builtins/math.mts similarity index 84% rename from rt/src/builtins/math.ts rename to rt/src/builtins/math.mts index 690e405..66b51f6 100644 --- a/rt/src/builtins/math.ts +++ b/rt/src/builtins/math.mts @@ -1,8 +1,7 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertIsUnit, assertIsNumber } from '../Asserts'; -const levels = options; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as levels from '../options.mjs' +import { assertIsUnit, assertIsNumber } from '../Asserts.mjs' export function BuiltinMath > (Base:TBase) { diff --git a/rt/src/builtins/mboxclear.ts b/rt/src/builtins/mboxclear.mts similarity index 93% rename from rt/src/builtins/mboxclear.ts rename to rt/src/builtins/mboxclear.mts index e26684f..b231564 100644 --- a/rt/src/builtins/mboxclear.ts +++ b/rt/src/builtins/mboxclear.mts @@ -1,5 +1,5 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { assertIsLevel, assertIsNTuple, assertIsCapability, assertIsAuthority } from '../Asserts'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { assertIsLevel, assertIsNTuple, assertIsCapability, assertIsAuthority } from '../Asserts.mjs' export function BuiltinMboxClear > (Base:TBase) { diff --git a/rt/src/builtins/mkuuid.ts b/rt/src/builtins/mkuuid.mts similarity index 85% rename from rt/src/builtins/mkuuid.ts rename to rt/src/builtins/mkuuid.mts index 5a8b930..00e38d1 100644 --- a/rt/src/builtins/mkuuid.ts +++ b/rt/src/builtins/mkuuid.mts @@ -1,5 +1,5 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { assertIsUnit } from '../Asserts'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { assertIsUnit } from '../Asserts.mjs' export function BuiltinMkUuid > (Base:TBase) { diff --git a/rt/src/builtins/monitor.ts b/rt/src/builtins/monitor.mts similarity index 93% rename from rt/src/builtins/monitor.ts rename to rt/src/builtins/monitor.mts index d9431b5..2daf5d4 100644 --- a/rt/src/builtins/monitor.ts +++ b/rt/src/builtins/monitor.mts @@ -1,6 +1,6 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { assertNormalState, assertIsProcessId, assertIsString } from '../Asserts'; -import { __unit } from '../UnitVal'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { assertNormalState, assertIsProcessId, assertIsString } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; export function BuiltinMonitors > (Base:TBase) { diff --git a/rt/src/builtins/nodeutil.ts b/rt/src/builtins/nodeutil.mts similarity index 80% rename from rt/src/builtins/nodeutil.ts rename to rt/src/builtins/nodeutil.mts index 05f630a..b78a304 100644 --- a/rt/src/builtins/nodeutil.ts +++ b/rt/src/builtins/nodeutil.mts @@ -1,8 +1,6 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertIsProcessId } from '../Asserts'; -const levels = options; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import { assertIsProcessId } from '../Asserts.mjs' /** * Returns a string corresponding to the node identify diff --git a/rt/src/builtins/persist.ts b/rt/src/builtins/persist.mts similarity index 80% rename from rt/src/builtins/persist.ts rename to rt/src/builtins/persist.mts index b5bc6ec..7c99408 100644 --- a/rt/src/builtins/persist.ts +++ b/rt/src/builtins/persist.mts @@ -1,11 +1,10 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -const levels = options; -import {deserialize} from '../deserialize' -import fs from 'fs'; -import { assertIsNTuple, assertIsString } from '../Asserts'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as levels from '../options.mjs' +import {deserialize} from '../deserialize.mjs' +import * as fs from 'node:fs'; +import { assertIsNTuple, assertIsString } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; export function BuiltinPersist>(Base: TBase) { return class extends Base { diff --git a/rt/src/builtins/pini.ts b/rt/src/builtins/pini.mts similarity index 93% rename from rt/src/builtins/pini.ts rename to rt/src/builtins/pini.mts index 301eea5..7466c9b 100644 --- a/rt/src/builtins/pini.ts +++ b/rt/src/builtins/pini.mts @@ -1,7 +1,7 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertNormalState, assertIsAuthority, assertIsCapability, assertIsNTuple, assertIsLevel } from '../Asserts'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as options from '../options.mjs' +import { assertNormalState, assertIsAuthority, assertIsCapability, assertIsNTuple, assertIsLevel } from '../Asserts.mjs' const levels = options; const flowsTo = levels.flowsTo; diff --git a/rt/src/builtins/raiseTrust.ts b/rt/src/builtins/raiseTrust.mts similarity index 87% rename from rt/src/builtins/raiseTrust.ts rename to rt/src/builtins/raiseTrust.mts index fc2ec2f..fddac72 100644 --- a/rt/src/builtins/raiseTrust.ts +++ b/rt/src/builtins/raiseTrust.mts @@ -1,10 +1,10 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LCopyVal } from '../Lval'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel, assertNormalState, assertIsString, assertIsTopAuthority } from '../Asserts'; -import { __unit } from '../UnitVal'; -import options, { lubs } from '../options' -import { __nodeManager } from '../NodeManager'; -import { nodeTrustLevel, _trustMap } from '../TrustManager'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LCopyVal } from '../Lval.mjs'; +import { assertIsNTuple, assertIsAuthority, assertIsLevel, assertNormalState, assertIsString, assertIsTopAuthority } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; +import * as options from '../options.mjs' +import { __nodeManager } from '../NodeManager.mjs'; +import { nodeTrustLevel, _trustMap } from '../TrustManager.mjs'; const levels = options; const { lub, flowsTo } = levels diff --git a/rt/src/builtins/receive.ts b/rt/src/builtins/receive.mts similarity index 95% rename from rt/src/builtins/receive.ts rename to rt/src/builtins/receive.mts index fd53b9c..3ce47e3 100644 --- a/rt/src/builtins/receive.ts +++ b/rt/src/builtins/receive.mts @@ -1,13 +1,13 @@ -import { UserRuntimeZero, Constructor, mkBase, mkService } from './UserRuntimeZero' -import { assertNormalState, assertIsNTuple, assertIsLevel, assertIsList, assertIsAtom, assertIsNumber, assertIsUnit, assertIsFunction } from '../Asserts'; -import { flowsTo, lub, glb, BOT } from '../options'; -import { RuntimeInterface } from '../RuntimeInterface'; -import { ReceiveTaintAction } from '../ReceiveTaintAction'; -import { LVal } from '../Lval'; -import { mkTuple } from '../ValuesUtil'; -import { __unit } from '../UnitVal'; -import SandboxStatus from '../SandboxStatus'; -import { Thread } from '../Thread'; +import { UserRuntimeZero, Constructor, mkBase, mkService } from './UserRuntimeZero.mjs' +import { assertNormalState, assertIsNTuple, assertIsLevel, assertIsList, assertIsAtom, assertIsNumber, assertIsUnit, assertIsFunction } from '../Asserts.mjs' +import { flowsTo, lub, glb, BOT } from '../options.mjs'; +import { RuntimeInterface } from '../RuntimeInterface.mjs'; +import { ReceiveTaintAction } from '../ReceiveTaintAction.mjs'; +import { LVal } from '../Lval.mjs'; +import { mkTuple } from '../ValuesUtil.mjs'; +import { __unit } from '../UnitVal.mjs'; +import SandboxStatus from '../SandboxStatus.mjs'; +import { Thread } from '../Thread.mjs'; diff --git a/rt/src/builtins/runtimeassert.ts b/rt/src/builtins/runtimeassert.mts similarity index 89% rename from rt/src/builtins/runtimeassert.ts rename to rt/src/builtins/runtimeassert.mts index 2967f09..e4f450a 100644 --- a/rt/src/builtins/runtimeassert.ts +++ b/rt/src/builtins/runtimeassert.mts @@ -1,5 +1,5 @@ -import { assertIsFunctionRaw, rawAssertIsBoolean, rawAssertIsList, rawAssertIsNumber, rawAssertIsRecord, rawAssertIsString, rawAssertIsTuple, rawAssertPairsAreStringsOrNumbers, rawAssertIsLevel } from '../Asserts' -import {UserRuntimeZero, Constructor } from './UserRuntimeZero' +import { assertIsFunctionRaw, rawAssertIsBoolean, rawAssertIsList, rawAssertIsNumber, rawAssertIsRecord, rawAssertIsString, rawAssertIsTuple, rawAssertPairsAreStringsOrNumbers, rawAssertIsLevel } from '../Asserts.mjs' +import {UserRuntimeZero, Constructor } from './UserRuntimeZero.mjs' export function RuntimeAssert > (Base:TBase) { diff --git a/rt/src/builtins/sandbox.ts b/rt/src/builtins/sandbox.mts similarity index 89% rename from rt/src/builtins/sandbox.ts rename to rt/src/builtins/sandbox.mts index ce06eac..90d43ab 100644 --- a/rt/src/builtins/sandbox.ts +++ b/rt/src/builtins/sandbox.mts @@ -1,19 +1,20 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal, LValCopyAt } from '../Lval'; -import options from '../options' -import { assertNormalState, assertIsNTuple, assertIsNumber, assertIsFunction } from '../Asserts'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal, LValCopyAt } from '../Lval.mjs'; +import * as options from '../options.mjs' +import { assertNormalState, assertIsNTuple, assertIsNumber, assertIsFunction } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; -const yargs = require ('yargs') +import yargs from 'yargs'; let logLevel = yargs.argv.debugsandbox? 'debug': 'info' -const logger = require('../logger.js').mkLogger('MBX', logLevel); +import { mkLogger } from '../logger.mjs' +const logger = mkLogger('MBX', logLevel); const debug = x => logger.debug(x) -import SandboxStatus from '../SandboxStatus' -import { mkTuple } from '../ValuesUtil'; -import { CALLSIZE, RETOFFSET, Thread } from '../Thread'; -import { RawClosure, SandboxResumption } from '../RawClosure'; -import { RuntimeInterface } from '../RuntimeInterface'; +import SandboxStatus from '../SandboxStatus.mjs' +import { mkTuple } from '../ValuesUtil.mjs'; +import { CALLSIZE, RETOFFSET, Thread } from '../Thread.mjs'; +import { RawClosure, SandboxResumption } from '../RawClosure.mjs'; +import { RuntimeInterface } from '../RuntimeInterface.mjs'; function rt_raisedToLev(x, y) { return new LValCopyAt(x, y) diff --git a/rt/src/builtins/self.ts b/rt/src/builtins/self.mts similarity index 80% rename from rt/src/builtins/self.ts rename to rt/src/builtins/self.mts index 3f49ef4..6b09833 100644 --- a/rt/src/builtins/self.ts +++ b/rt/src/builtins/self.mts @@ -1,7 +1,4 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -const levels = options; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' /** * Returns a string corresponding to the node identify diff --git a/rt/src/builtins/send.ts b/rt/src/builtins/send.mts similarity index 97% rename from rt/src/builtins/send.ts rename to rt/src/builtins/send.mts index 1714a55..699a416 100644 --- a/rt/src/builtins/send.ts +++ b/rt/src/builtins/send.mts @@ -1,5 +1,5 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { assertNormalState, assertIsNTuple, assertIsProcessId } from '../Asserts'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { assertNormalState, assertIsNTuple, assertIsProcessId } from '../Asserts.mjs' export function BuiltinSend>(Base: TBase) { diff --git a/rt/src/builtins/service.ts b/rt/src/builtins/service.mts similarity index 82% rename from rt/src/builtins/service.ts rename to rt/src/builtins/service.mts index 2dca7b9..1ce4a70 100644 --- a/rt/src/builtins/service.ts +++ b/rt/src/builtins/service.mts @@ -1,5 +1,5 @@ -import {UserRuntimeZero, Constructor, mkBase, mkService} from './UserRuntimeZero' -import { __unit } from '../UnitVal' +import {UserRuntimeZero, Constructor, mkBase, mkService} from './UserRuntimeZero.mjs' +import { __unit } from '../UnitVal.mjs' export function BuiltinService > (Base:TBase) { return class extends Base { _servicetest = mkService(() => this.runtime.$service.servicetest(),"servicetest") diff --git a/rt/src/builtins/sleep.ts b/rt/src/builtins/sleep.mts similarity index 78% rename from rt/src/builtins/sleep.ts rename to rt/src/builtins/sleep.mts index e827ca3..0e29825 100644 --- a/rt/src/builtins/sleep.ts +++ b/rt/src/builtins/sleep.mts @@ -1,7 +1,7 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { assertIsNumber } from '../Asserts' -import { __unit } from '../UnitVal' -import { SleepTimeout } from '../Thread' +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { assertIsNumber } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs' +import { SleepTimeout } from '../Thread.mjs' export function BuiltinSleep > (Base:TBase) { return class extends Base { sleep = mkBase((arg) => { diff --git a/rt/src/builtins/spawn.ts b/rt/src/builtins/spawn.mts similarity index 91% rename from rt/src/builtins/spawn.ts rename to rt/src/builtins/spawn.mts index b351af7..66f4136 100644 --- a/rt/src/builtins/spawn.ts +++ b/rt/src/builtins/spawn.mts @@ -1,8 +1,8 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import {lub} from '../options' -import { assertNormalState, assertIsFunction, assertIsNode } from '../Asserts'; -import { __nodeManager } from '../NodeManager'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import {lub} from '../options.mjs' +import { assertNormalState, assertIsFunction, assertIsNode } from '../Asserts.mjs' +import { __nodeManager } from '../NodeManager.mjs'; +import { __unit } from '../UnitVal.mjs'; export function BuiltinSpawn>(Base: TBase) { diff --git a/rt/src/builtins/stdio.ts b/rt/src/builtins/stdio.mts similarity index 93% rename from rt/src/builtins/stdio.ts rename to rt/src/builtins/stdio.mts index 8dcd246..04356e8 100644 --- a/rt/src/builtins/stdio.ts +++ b/rt/src/builtins/stdio.mts @@ -1,15 +1,18 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LocalObject } from '../LocalObject' -import options, { mkLevel } from '../options' -import { assertIsAuthority, assertIsTopAuthority, assertIsNTuple, assertIsLocalObject, assertIsString, assertIsUnit, assertNormalState } from '../Asserts'; -import { __unit } from '../UnitVal'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LocalObject } from '../LocalObject.mjs' +import * as options from '../options.mjs' +import { mkLevel } from '../options.mjs' +import { assertIsAuthority, assertIsTopAuthority, assertIsNTuple, assertIsLocalObject, assertIsString, assertIsUnit, assertNormalState } from '../Asserts.mjs' +import { __unit } from '../UnitVal.mjs'; import yargs from 'yargs' const levels = options; const flowsTo = levels.flowsTo; +import * as _rl from 'node:readline'; -const readline = require('readline').createInterface({ + +const readline = _rl.createInterface({ input: process.stdin, output: process.stdout }) diff --git a/rt/src/builtins/string.ts b/rt/src/builtins/string.mts similarity index 85% rename from rt/src/builtins/string.ts rename to rt/src/builtins/string.mts index 09411f4..5fd002a 100644 --- a/rt/src/builtins/string.ts +++ b/rt/src/builtins/string.mts @@ -1,8 +1,8 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero' -import { LVal } from '../Lval'; -import options from '../options' -import { assertIsUnit, assertIsString, assertIsNTuple, assertIsNumber } from '../Asserts'; -import { lub, lubs } from '../levels/tagsets'; +import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; +import * as options from '../options.mjs' +import { assertIsUnit, assertIsString, assertIsNTuple, assertIsNumber } from '../Asserts.mjs' +import { lub, lubs } from '../levels/tagsets.mjs'; const levels = options; diff --git a/rt/src/builtins/stringToInt.ts b/rt/src/builtins/stringToInt.mts similarity index 89% rename from rt/src/builtins/stringToInt.ts rename to rt/src/builtins/stringToInt.mts index 8e02998..ae75699 100644 --- a/rt/src/builtins/stringToInt.ts +++ b/rt/src/builtins/stringToInt.mts @@ -1,6 +1,6 @@ 'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; export function BuiltinStringToInt>(Base: TBase) { diff --git a/rt/src/builtins/toString.ts b/rt/src/builtins/toString.mts similarity index 95% rename from rt/src/builtins/toString.ts rename to rt/src/builtins/toString.mts index 90c2cbf..f450602 100644 --- a/rt/src/builtins/toString.ts +++ b/rt/src/builtins/toString.mts @@ -1,6 +1,6 @@ 'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import { LVal } from '../Lval'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { LVal } from '../Lval.mjs'; export function BuiltinToString>(Base: TBase) { diff --git a/rt/src/builtins/whereis.ts b/rt/src/builtins/whereis.mts similarity index 86% rename from rt/src/builtins/whereis.ts rename to rt/src/builtins/whereis.mts index 9ef41c5..adabadf 100644 --- a/rt/src/builtins/whereis.ts +++ b/rt/src/builtins/whereis.mts @@ -1,20 +1,22 @@ 'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero' -import levels from '../options' -import { ProcessID } from '../process'; +import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import * as levels from '../options.mjs' +import { ProcessID } from '../process.mjs'; const { lubs, flowsTo } = levels -import {deserialize} from '../deserialize' -import { __nodeManager } from '../NodeManager'; -import { assertNormalState, assertIsNTuple, assertIsString, assertIsProcessId, assertIsAuthority, assertIsTopAuthority, assertIsNode } from '../Asserts'; -import { __unit } from '../UnitVal'; -import { nodeTrustLevel } from '../TrustManager'; +import {deserialize} from '../deserialize.mjs' +import { __nodeManager } from '../NodeManager.mjs'; +import { assertNormalState, assertIsNTuple, assertIsString, assertIsProcessId, assertIsAuthority, assertIsTopAuthority, assertIsNode } from '../Asserts.mjs'; +import { __unit } from '../UnitVal.mjs'; +import { nodeTrustLevel } from '../TrustManager.mjs'; export let __theRegister = {} -import p2p from '../p2p/p2p' -import runId from '../runId'; +import {p2p} from '../p2p/p2p.js' -const yargs = require('yargs'); +// import runId from '../runId.mjs'; + +import yargs from 'yargs'; let logLevel = yargs.argv.debug ? 'debug': 'info' -const logger = require('../logger.js').mkLogger('RTM', logLevel); +import { mkLogger } from '../logger.mjs' +const logger = mkLogger('RTM', logLevel); const debug = x => logger.debug(x) diff --git a/rt/src/deserialize.ts b/rt/src/deserialize.mts similarity index 94% rename from rt/src/deserialize.ts rename to rt/src/deserialize.mts index a76290a..f8cbe43 100644 --- a/rt/src/deserialize.ts +++ b/rt/src/deserialize.mts @@ -1,19 +1,19 @@ "use strict"; -const assert = require('assert'); -const { spawn } = require('child_process') -import * as Ty from './TroupeTypes' -import { LVal } from './Lval'; -import { mkTuple, mkList } from './ValuesUtil'; -import { ProcessID } from './process'; -import { Authority } from './Authority'; -import { Atom } from './Atom'; -import __unitbase from './UnitBase' -import { glb, mkLevel } from './options'; -import { RuntimeInterface } from './RuntimeInterface'; -import { Level } from './Level'; -import { Record } from './Record'; -import { RawClosure } from './RawClosure'; -import levels from './levels/tagsets'; +import { strict as assert } from 'node:assert' +import {spawn} from 'child_process' +import * as Ty from './TroupeTypes.mjs' +import { LVal } from './Lval.mjs'; +import { mkTuple, mkList } from './ValuesUtil.mjs'; +import { ProcessID } from './process.mjs'; +import { Authority } from './Authority.mjs'; +import { Atom } from './Atom.mjs'; +import { __unitbase }from './UnitBase.mjs' +import { glb, mkLevel } from './options.mjs'; +import { RuntimeInterface } from './RuntimeInterface.mjs'; +import { Level } from './Level.mjs'; +import { Record } from './Record.mjs'; +import { RawClosure } from './RawClosure.mjs'; +import * as levels from './levels/tagsets.mjs'; let __compilerOsProcess = null; diff --git a/rt/src/dev/relay.ts b/rt/src/dev/relay.ts index 5a1e253..59c035f 100644 --- a/rt/src/dev/relay.ts +++ b/rt/src/dev/relay.ts @@ -10,7 +10,7 @@ const KadDHT = require ( 'libp2p-kad-dht') const Multiplex = require ( 'libp2p-mplex') const SECIO = require( 'libp2p-secio') const Libp2p = require('libp2p') -import fs from 'fs' +import * as fs from 'node:fs'; import yargs from 'yargs' const PeerId = require("peer-id") const PeerInfo = require ("peer-info") diff --git a/rt/src/levels/singleton.ts b/rt/src/levels/singleton.mts similarity index 66% rename from rt/src/levels/singleton.ts rename to rt/src/levels/singleton.mts index cdc5cc9..59fb8fb 100644 --- a/rt/src/levels/singleton.ts +++ b/rt/src/levels/singleton.mts @@ -1,5 +1,5 @@ -import { Level } from '../Level.js' +import { Level } from '../Level.mjs' class Singleton extends Level { @@ -20,16 +20,16 @@ class Singleton extends Level { let __theLevel = new Singleton(0) -function lub (...ls:Level[]):Level { +export function lub (...ls:Level[]):Level { return __theLevel } -function glb (l1:Level, l2:Level):Level { +export function glb (l1:Level, l2:Level):Level { return __theLevel } -function flowsTo (l1:Level, l2:Level):boolean { +export function flowsTo (l1:Level, l2:Level):boolean { return true; } @@ -42,7 +42,7 @@ function fromString (str2): Level { -function lubs (x) { +export function lubs (x) { return __theLevel } @@ -59,4 +59,6 @@ let levels = { } -export = levels; +export let BOT = __theLevel +export let TOP = __theLevel +export let mkLevel = fromString diff --git a/rt/src/levels/tagsets.ts b/rt/src/levels/tagsets.mts similarity index 88% rename from rt/src/levels/tagsets.ts rename to rt/src/levels/tagsets.mts index 66bcb47..0d89aed 100644 --- a/rt/src/levels/tagsets.ts +++ b/rt/src/levels/tagsets.mts @@ -1,10 +1,9 @@ -const logger = require('../logger.js').mkLogger('TAGSETS'); +import { mkLogger } from '../logger.mjs' +const logger = mkLogger('TAGSETS'); const info = x => logger.info(x) const debug = x => logger.debug(x) -import { create } from 'peer-id'; -import { string } from 'yargs'; -import { Level } from '../Level.js' +import { Level } from '../Level.mjs' function stringRep (T) { @@ -75,7 +74,7 @@ topLevel.isTop = true; -function lub (...ls:Level[]):Level { +export function lub (...ls:Level[]):Level { if (ls.length == 2) { if (ls[0] == ls[1]) { return ls[0] @@ -94,7 +93,7 @@ function lub (...ls:Level[]):Level { } -function glb (l1:Level, l2:Level):Level { +export function glb (l1:Level, l2:Level):Level { if (l1 == topLevel) { return l2; } @@ -113,7 +112,7 @@ function glb (l1:Level, l2:Level):Level { return createTagLevel (s); } -function flowsTo (l1:Level, l2:Level):boolean { +export function flowsTo (l1:Level, l2:Level):boolean { if (l1 == l2) { return true; } @@ -164,7 +163,7 @@ function fromString (str2): Level { -function lubs (x) { +export function lubs (x) { if (x.length == 0) { return levels.BOT; } else { @@ -187,5 +186,8 @@ let levels = { lubs } +export let BOT = botLevel +export let TOP = topLevel +export let mkLevel = fromString -export = levels; +// export default levels \ No newline at end of file diff --git a/rt/src/loadLibs.ts b/rt/src/loadLibs.mts similarity index 96% rename from rt/src/loadLibs.ts rename to rt/src/loadLibs.mts index b347713..9ba0719 100644 --- a/rt/src/loadLibs.ts +++ b/rt/src/loadLibs.mts @@ -1,9 +1,12 @@ /* 2020-05-19: AA This code is deprecated */ 'use strict' -const fs = require('fs'); -const logger = require('./logger.js').mkLogger('lib'); +import * as fs from 'node:fs' + +import { mkLogger } from './logger.mjs' +const logger = mkLogger('lib') + const info = x => logger.info(x) const debug = x => logger.debug(x) diff --git a/rt/src/loadLibsAsync.ts b/rt/src/loadLibsAsync.mts similarity index 93% rename from rt/src/loadLibsAsync.ts rename to rt/src/loadLibsAsync.mts index 6495725..c23d418 100644 --- a/rt/src/loadLibsAsync.ts +++ b/rt/src/loadLibsAsync.mts @@ -1,10 +1,11 @@ 'use strict' -import fs from 'fs' -import levels from './levels/tagsets'; +import * as fs from 'node:fs' +import * as levels from './levels/tagsets.mjs'; const { readFile } = fs.promises +import { mkLogger } from './logger.mjs' +const logger = mkLogger('lib') -const logger = require('./logger.js').mkLogger('lib'); const info = x => logger.info(x) const debug = x => logger.debug(x) diff --git a/rt/src/logger.ts b/rt/src/logger.mts similarity index 90% rename from rt/src/logger.ts rename to rt/src/logger.mts index 3222137..0e14fe0 100644 --- a/rt/src/logger.ts +++ b/rt/src/logger.mts @@ -2,7 +2,8 @@ // this library or this way of doing things, but this still beats console // outputs. -const { createLogger, format, transports } = require('winston'); +import winston_pkg from 'winston'; +const { createLogger, format, transports } = winston_pkg const { combine, timestamp, label, printf } = format; const myFormat = printf(info => { diff --git a/rt/src/options.mts b/rt/src/options.mts new file mode 100644 index 0000000..fd1636b --- /dev/null +++ b/rt/src/options.mts @@ -0,0 +1,3 @@ +// import levels from './levels/tagsets' +// export default levels +export * from './levels/tagsets.mjs' \ No newline at end of file diff --git a/rt/src/options.ts b/rt/src/options.ts deleted file mode 100644 index 134da14..0000000 --- a/rt/src/options.ts +++ /dev/null @@ -1,5 +0,0 @@ -import levels = require ( './levels/tagsets.js'); -// import levels = require ( './levels/singleton.js'); -export = levels - - diff --git a/rt/src/p2p/mkaliases.js b/rt/src/p2p/mkaliases.ts similarity index 67% rename from rt/src/p2p/mkaliases.js rename to rt/src/p2p/mkaliases.ts index ce2b71c..aff4baf 100644 --- a/rt/src/p2p/mkaliases.js +++ b/rt/src/p2p/mkaliases.ts @@ -10,26 +10,33 @@ */ -'use strict' -const fs=require('fs'); -const path=require('path'); -const argv=require('yargs').argv -const files=argv['include']; + +import * as fs from 'node:fs'; +import * as path from 'path'; +import yargs from 'yargs' + +const argv:any =yargs.argv + +const files_args:any = argv['include']; + +const files = Array.isArray (files_args) ? files_args : [files_args] const outfile=argv['outfile'] let aliases = {} let trustmap = [] -for (let i in files) { +for (let i = 0; i < files.length; i ++) { let fname = files[i] - let json = JSON.parse (fs.readFileSync(fname)); + if (typeof(fname) !='string') { + continue; + } + let json = JSON.parse (fs.readFileSync(fname,'utf-8').toString()); let alias = path.basename(fname, ".json") aliases[alias] = json.id if (argv.trustmap) { let level; - if (argv.droptrustprefix) { let j = alias.indexOf(argv.droptrustprefix) ; if (j == 0) { @@ -39,7 +46,6 @@ for (let i in files) { } } trustmap.push ( {id:json.id, level:level}) - } } diff --git a/rt/src/p2p/mkid.ts b/rt/src/p2p/mkid.ts index 42c1fdb..fa264b1 100644 --- a/rt/src/p2p/mkid.ts +++ b/rt/src/p2p/mkid.ts @@ -4,8 +4,9 @@ // prevent an accidental overwrite of key files 'use strict'; -const fs = require('fs') -const fsPromises = require('fs').promises +import * as fs from 'node:fs' +import * as fsPromises from 'node:fs/promises'; +// const fsPromises = require('fs').promises const PeerId = require("peer-id") const args = require('yargs').argv; diff --git a/rt/src/p2p/p2p.ts b/rt/src/p2p/p2p.ts index ba328b4..7981b92 100644 --- a/rt/src/p2p/p2p.ts +++ b/rt/src/p2p/p2p.ts @@ -56,8 +56,6 @@ the libp2p). -'use strict' - // LOGGING AND DEBUGGING let yargs = require('yargs'); @@ -66,8 +64,16 @@ let __port = yargs.argv.port || 0 const _PROTOCOL = "/troupe/1.0.0" +let logger; +(async() => { + let { mkLogger } = await import ('../logger.mjs'); + logger = mkLogger ('p2p', logLevel) +})() + +// const logger = require('../logger.js').mkLogger('p2p',logLevel); + + -const logger = require('../logger.js').mkLogger('p2p',logLevel); const info = x => logger.info(x) const debug = x => logger.debug(x) const error = x => logger.error(x); @@ -95,7 +101,6 @@ const p2pconfig = require('./p2pconfig.js') // const Pushable = require('pull-pushable') import { v4 as uuidv4} from 'uuid' -import { Nil } from '../RawList'; const MessageType = { @@ -729,7 +734,7 @@ function processExpectedNetworkErrors (err, source="source unknown") { } -export default { +export let p2p = { startp2p: startp2p, spawnp2p: (arg1, arg2) => _troupeP2P.spawnp2p(arg1, arg2), sendp2p: (arg1, arg2, arg3) => _troupeP2P.sendp2p(arg1, arg2, arg3), diff --git a/rt/src/p2p/p2pconfig.js b/rt/src/p2p/p2pconfig.js index 9e59819..af1221e 100644 --- a/rt/src/p2p/p2pconfig.js +++ b/rt/src/p2p/p2pconfig.js @@ -1,6 +1,11 @@ 'use strict' const P2PCONFIG_FILE = 'p2pconfig.json' -const logger = require('../logger.js').mkLogger('p2p-config','info'); +let logger; +(async() => { + let { mkLogger } = await import ('../logger.mjs'); + logger = mkLogger ('p2p-config','info'); +})() + const fs = require('fs'); let relays diff --git a/rt/src/process.ts b/rt/src/process.mts similarity index 86% rename from rt/src/process.ts rename to rt/src/process.mts index 0ce5442..b3d294d 100644 --- a/rt/src/process.ts +++ b/rt/src/process.mts @@ -1,6 +1,6 @@ -import { TroupeRawValue } from "./TroupeRawValue"; -import { TroupeType } from "./TroupeTypes"; -import { BOT } from "./options" +import { TroupeRawValue } from "./TroupeRawValue.mjs"; +import { TroupeType } from "./TroupeTypes.mjs"; +import { BOT } from "./options.mjs" export function pid_equals (o1, o2) { let eq = o1.val.pid.toString() == o2.val.pid.toString(); diff --git a/rt/src/runId.ts b/rt/src/runId.mts similarity index 100% rename from rt/src/runId.ts rename to rt/src/runId.mts diff --git a/rt/src/runtimeMonitored.ts b/rt/src/runtimeMonitored.mts similarity index 91% rename from rt/src/runtimeMonitored.ts rename to rt/src/runtimeMonitored.mts index 93b0150..3b34af8 100644 --- a/rt/src/runtimeMonitored.ts +++ b/rt/src/runtimeMonitored.mts @@ -1,40 +1,40 @@ -'use strict' - -import fs from 'fs'; +import * as fs from 'node:fs'; import chalk from 'chalk'; import { v4 as uuidv4 } from 'uuid' import AggregateError from 'aggregate-error'; -import { __unit } from './UnitVal' -import { Authority } from './Authority' -import { Scheduler } from './Scheduler' -import { MailboxProcessor } from './MailboxProcessor' -import { RuntimeInterface } from './RuntimeInterface' -import { LVal, MbVal } from './Lval' -import { ProcessID } from './process'; -import { UserRuntime } from './UserRuntime' -import levels from './options' -import * as DS from './deserialize' -import p2p from './p2p/p2p' -import { closeReadline } from './builtins/stdio'; -import { __theRegister } from './builtins/whereis'; -import { assertIsFunction } from './Asserts' -import runId from './runId' -import { __nodeManager } from './NodeManager' -import { setRuntimeObject } from './SysState'; -import { initTrustMap, nodeTrustLevel, _trustMap } from './TrustManager'; -import { serialize } from './serialize'; -import { Thread } from './Thread'; - -const { Console } = require('node:console') +import { __unit } from './UnitVal.mjs' +import { Authority } from './Authority.mjs' +import { Scheduler } from './Scheduler.mjs' +import { MailboxProcessor } from './MailboxProcessor.mjs' +import { RuntimeInterface } from './RuntimeInterface.mjs' +import { LVal, MbVal } from './Lval.mjs' +import { ProcessID } from './process.mjs'; +import { UserRuntime } from './UserRuntime.mjs' +import * as levels from './options.mjs' +import * as DS from './deserialize.mjs' +import { p2p } from './p2p/p2p.js' +import { closeReadline } from './builtins/stdio.mjs'; +import { __theRegister } from './builtins/whereis.mjs'; +import { assertIsFunction } from './Asserts.mjs' +import runId from './runId.mjs' +import { __nodeManager } from './NodeManager.mjs' +import { setRuntimeObject } from './SysState.mjs'; +import { initTrustMap, nodeTrustLevel, _trustMap } from './TrustManager.mjs'; +import { serialize } from './serialize.mjs'; +import { Thread } from './Thread.mjs'; + +import { Console } from 'node:console' const { flowsTo, lub, glb } = levels -const yargs = require('yargs'); +import yargs from 'yargs' const readFile = fs.promises.readFile const rt_uuid = runId let logLevel = yargs.argv.debug ? 'debug': 'info' -const logger = require('./logger.js').mkLogger('RTM', logLevel); +import { mkLogger } from './logger.mjs' +const logger = mkLogger('RTM', logLevel); + const info = x => logger.info(x) const debug = x => logger.debug(x) const error = x => logger.error(x) @@ -436,7 +436,7 @@ async function loadServiceCode() { async function getNetworkPeerId(rtHandlers) { - const nodeIdFile = yargs.argv.id; + const nodeIdFile = yargs.argv.id as string; if (nodeIdFile) { try { let nodeIdObj = await readFile(nodeIdFile, 'utf-8') diff --git a/rt/src/serialize.ts b/rt/src/serialize.mts similarity index 95% rename from rt/src/serialize.ts rename to rt/src/serialize.mts index 8a120f8..0b45a88 100644 --- a/rt/src/serialize.ts +++ b/rt/src/serialize.mts @@ -10,16 +10,17 @@ */ import assert from 'assert' -import { lub } from './options'; -import * as Ty from './TroupeTypes' -import { LVal } from './Lval'; -import { Level } from './Level'; -import { StopThreadError, ThreadError } from './TroupeError'; -import { getRuntimeObject } from './SysState'; - -const yargs = require('yargs'); +import { lub } from './options.mjs'; +import * as Ty from './TroupeTypes.mjs' +import { LVal } from './Lval.mjs'; +import { Level } from './Level.mjs'; +import { StopThreadError, ThreadError } from './TroupeError.mjs'; +import { getRuntimeObject } from './SysState.mjs'; + +import yargs from 'yargs'; let logLevel = yargs.argv.debug ? 'debug': 'info' -const logger = require('./logger.js').mkLogger('SRL', logLevel); +import { mkLogger } from './logger.mjs' +const logger = mkLogger('SRL', logLevel); const debug = x => logger.debug(x) diff --git a/rt/src/troupe.js b/rt/src/troupe.js deleted file mode 100644 index 4acf1fa..0000000 --- a/rt/src/troupe.js +++ /dev/null @@ -1,20 +0,0 @@ -import {start } from './runtimeMonitored.js' -import { getRuntimeObject } from './SysState.js'; -const path = require('path'); -let yargs = require('yargs'); -let fs = require('fs'); -let p = yargs.argv.f; -if (!path.isAbsolute(p)) { - p = path.normalize ( process.cwd() + "/"+ p ); -} - -if (!fs.existsSync(p)) { - console.error (`Cannot find file ${p}`) - process.exit (1) -} - -let Top = require(p); - -let __userRuntime = getRuntimeObject().__userRuntime -let top = new Top (__userRuntime); -start (top); diff --git a/rt/src/troupe.mts b/rt/src/troupe.mts new file mode 100644 index 0000000..8eb7b1c --- /dev/null +++ b/rt/src/troupe.mts @@ -0,0 +1,24 @@ +import { start } from './runtimeMonitored.mjs'; +import { getRuntimeObject } from './SysState.mjs'; +import path from 'path'; +import yargs from 'yargs' +import fs from 'node:fs' +// let yargs = require('yargs'); +// let fs = require('fs'); +let p:any = yargs.argv.f; +if (!path.isAbsolute(p)) { + p = path.normalize(process.cwd() + "/" + p); +} +if (!fs.existsSync(p)) { + console.error(`Cannot find file ${p}`); + process.exit(1); +} +(async () => { + let d = await import (p); + let Top = d.default + let __userRuntime = (getRuntimeObject() as any).__userRuntime; + let top = new Top(__userRuntime); + start(top); + +}) () + diff --git a/rt/tsconfig.json b/rt/tsconfig.json index 127b38b..c580d1d 100644 --- a/rt/tsconfig.json +++ b/rt/tsconfig.json @@ -2,9 +2,9 @@ "compilerOptions": { "outDir": "./built", "allowJs": true, - "moduleResolution": "node", - "module": "commonjs", - "target": "ES2017", + "moduleResolution": "node16", + "module": "Node16", + "target": "ES2022", "esModuleInterop": true, "incremental": true, @@ -12,5 +12,5 @@ "include": [ "src/**/*" ], - "exclude": ["../../trp-rt/**"] + "exclude": ["../../trp-rt/**", "src/dev/*"] } From 0119ba0f546a00a29eb9214b8d1dc5e6e90f8d7e Mon Sep 17 00:00:00 2001 From: Aslan Askarov Date: Sat, 18 Mar 2023 18:11:50 +0100 Subject: [PATCH 02/22] checkpoint --- network.sh | 2 +- rt/troupe | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/network.sh b/network.sh index 90a37b3..eaf4e27 100755 --- a/network.sh +++ b/network.sh @@ -1,6 +1,6 @@ #!/bin/bash -tmp=`mktemp` +tmp=`mktemp`.js $TROUPE/bin/troupec $1 --output=$tmp diff --git a/rt/troupe b/rt/troupe index 670131d..3002d98 100755 --- a/rt/troupe +++ b/rt/troupe @@ -10,7 +10,7 @@ fi # Locate the troupe.js runtime and check if it is built script_dir=$(dirname $($readlink -f $0)) -troupe_rt="$script_dir/built/troupe.js" +troupe_rt="$script_dir/built/troupe.mjs" if [ ! -f "$troupe_rt" ]; then echo "Could not find Troupe runtime. Try building it using 'make rt'" exit 1 From 21c96a57f70ec1fcdb763dd550f38bdef4c8a598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20N=C3=A4f?= <9679062+lucanaef@users.noreply.github.com> Date: Fri, 14 Apr 2023 07:47:18 +0000 Subject: [PATCH 03/22] Fix typo --- rt/src/builtins/stdio.mts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rt/src/builtins/stdio.mts b/rt/src/builtins/stdio.mts index 04356e8..83be908 100644 --- a/rt/src/builtins/stdio.mts +++ b/rt/src/builtins/stdio.mts @@ -48,7 +48,7 @@ export function BuiltinStdIo>(Base: T } else { this.runtime.$t.threadError (`Not sufficient authority in getStdout\n` + - ` | Provided autohrity level ${arg.val.authorityLevel.stringRep()}\n` + + ` | Provided authority level ${arg.val.authorityLevel.stringRep()}\n` + ` | Required authority level ${__stdio_lev.stringRep()}`) } From 6e7aa3f201b967e09c230edf39a2ea2d1793f16c Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Sat, 3 Jun 2023 12:04:27 +0200 Subject: [PATCH 04/22] Establish first connection between peers --- {patches => old_patches}/libp2p+0.27.2.patch | 0 .../libp2p-tcp+0.14.6.patch | 0 package.json | 33 +-- rt/src/builtins/whereis.mts | 2 +- rt/src/p2p/{p2p.ts => p2p.mts} | 235 ++++++++++++++++-- rt/src/runtimeMonitored.mts | 2 +- 6 files changed, 226 insertions(+), 46 deletions(-) rename {patches => old_patches}/libp2p+0.27.2.patch (100%) rename {patches => old_patches}/libp2p-tcp+0.14.6.patch (100%) rename rt/src/p2p/{p2p.ts => p2p.mts} (78%) diff --git a/patches/libp2p+0.27.2.patch b/old_patches/libp2p+0.27.2.patch similarity index 100% rename from patches/libp2p+0.27.2.patch rename to old_patches/libp2p+0.27.2.patch diff --git a/patches/libp2p-tcp+0.14.6.patch b/old_patches/libp2p-tcp+0.14.6.patch similarity index 100% rename from patches/libp2p-tcp+0.14.6.patch rename to old_patches/libp2p-tcp+0.14.6.patch diff --git a/package.json b/package.json index f1a5177..ed1a943 100644 --- a/package.json +++ b/package.json @@ -14,41 +14,32 @@ "author": "", "license": "ISC", "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/bootstrap": "^8.0.0", + "@libp2p/interface-connection-manager": "^3.0.1", + "@libp2p/kad-dht": "^9.3.4", + "@libp2p/mdns": "^8.0.0", + "@libp2p/mplex": "^8.0.3", + "@libp2p/tcp": "^7.0.1", + "@libp2p/websockets": "^6.0.1", "@nodeutils/defaults-deep": "^1.1.0", "@types/node": "^18.15.3", + "aggregate-error": "^4.0.1", "chalk": "^5.2.0", "find-free-port": "^2.0.0", - "it-length-prefixed": "^3.0.1", - "it-pipe": "^1.1.0", - "it-pushable": "^1.4.0", - "libp2p": "^0.27.4", - "libp2p-bootstrap": "^0.10.4", - "libp2p-kad-dht": "^0.18.6", - "libp2p-mdns": "^0.13.3", - "libp2p-mplex": "^0.9.5", - "libp2p-secio": "^0.12.4", - "libp2p-spdy": "^0.13.3", - "libp2p-tcp": "^0.14.4", - "libp2p-websocket-star": "^0.10.2", - "libp2p-websockets": "^0.13.6", + "libp2p": "^0.45.3", "npm": "^6.14.4", - "p-defer": "^3.0.0", - "p-fifo": "^1.0.0", - "peer-id": "^0.13.11", - "peer-info": "^0.17.5", "postinstall-postinstall": "^2.1.0", "progress": "^2.0.3", - "pull-pushable": "^2.2.0", - "pull-stream": "^3.6.14", "request": "^2.88.2", - "socket.io": "^2.3.0", - "streaming-iterables": "^4.1.2", "update": "^0.7.4", "uuid": "^7.0.2", "winston": "^3.2.1", "yargs": "^15.3.1" }, "devDependencies": { + "@types/ws": "^8.5.4", "@types/yargs": "^15.0.4", "patch-package": "^6.5.1", "postinstall-prepare": "^1.0.1", diff --git a/rt/src/builtins/whereis.mts b/rt/src/builtins/whereis.mts index adabadf..44d74a7 100644 --- a/rt/src/builtins/whereis.mts +++ b/rt/src/builtins/whereis.mts @@ -9,7 +9,7 @@ import { assertNormalState, assertIsNTuple, assertIsString, assertIsProcessId, a import { __unit } from '../UnitVal.mjs'; import { nodeTrustLevel } from '../TrustManager.mjs'; export let __theRegister = {} -import {p2p} from '../p2p/p2p.js' +import {p2p} from '../p2p/p2p.mjs' // import runId from '../runId.mjs'; diff --git a/rt/src/p2p/p2p.ts b/rt/src/p2p/p2p.mts similarity index 78% rename from rt/src/p2p/p2p.ts rename to rt/src/p2p/p2p.mts index 7981b92..896ef8a 100644 --- a/rt/src/p2p/p2p.ts +++ b/rt/src/p2p/p2p.mts @@ -58,7 +58,7 @@ the libp2p). // LOGGING AND DEBUGGING -let yargs = require('yargs'); +import yargs from 'yargs' let logLevel = yargs.argv.debugp2p? 'debug':'info' let __port = yargs.argv.port || 0 @@ -78,10 +78,8 @@ const info = x => logger.info(x) const debug = x => logger.debug(x) const error = x => logger.error(x); -const lp = require('it-length-prefixed') - - +/* // // const pull = require('pull-stream') const pipe = require('it-pipe') @@ -95,6 +93,8 @@ const multiaddr = require('multiaddr') const AggregateError = require('aggregate-error'); const p2pconfig = require('./p2pconfig.js') +*/ + @@ -112,7 +112,7 @@ const MessageType = { WHEREISOK: 5 } - +/* async function obtainPeerId(nodeId) { let id = null; @@ -150,7 +150,7 @@ function TroupeP2P (_rt, _peerInfo) { // GLOBALS - let _node = null; // the current node; initalized once upon start + /* let _node = null; // the current node; initalized once upon start let _nodeTable:IHash = {}; // a table of the form [PeerId ↦ Connection] // This table is mutable: we populate it upon @@ -250,8 +250,6 @@ function TroupeP2P (_rt, _peerInfo) { } } } - - this.spawnp2p = async (id, data) => { const spawnNonce = uuidv4(); @@ -446,7 +444,7 @@ function TroupeP2P (_rt, _peerInfo) { } */ - +/* async function inputHandler(id, input, fromNodeId_) { let fromNodeId = fromNodeId_.toB58String() debug ("-- input handler") @@ -626,7 +624,7 @@ function TroupeP2P (_rt, _peerInfo) { } showNPeers(); */ - return; + /* return; } @@ -634,8 +632,8 @@ function TroupeP2P (_rt, _peerInfo) { debug ("node stopping...") await _node.stop(); debug ("node stopped") - } -} + }*/ +/*} const _HEALTHCHECKPERIOD = 5000 // 2020-02-10; AA; this should be an option @@ -662,11 +660,75 @@ function setupBlockingHealthChecker (period) { f () } +*/ +import type { PeerId } from '@libp2p/interface-peer-id' +import type { ConnectionManager } from '@libp2p/interface-connection-manager' + +import { tcp } from '@libp2p/tcp' +import { webSockets } from '@libp2p/websockets' +import { mplex } from '@libp2p/mplex' +import { yamux } from '@chainsafe/libp2p-yamux' +import { noise } from '@chainsafe/libp2p-noise' +import defaultsDeep from '@nodeutils/defaults-deep' +import { Libp2p, createLibp2p as create } from 'libp2p' +import { createFromJSON, createEd25519PeerId } from '@libp2p/peer-id-factory' +import { bootstrap } from '@libp2p/bootstrap' +import { mdns } from '@libp2p/mdns' +import { pipe } from 'it-pipe' +import * as lp from 'it-length-prefixed' +import map from 'it-map' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' + +import { pushable } from 'it-pushable' + +let bootstrappers = [ + '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', + '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', +] + + +async function createLibp2p (_options) { + const defaults = { + transports: [ + tcp(), + webSockets() + ], + streamMuxers: [ + yamux(), + mplex() + ], + connectionEncryption: [ + noise() + ], + peerDiscovery: [ + /*bootstrap({ + list: bootstrappers + }),*/ + mdns({ + interval: 20e3 + }) + ], + /*dht: kadDHT({ + kBucketSize: 20, + clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) + }),*/ + } + + return create(defaultsDeep(_options, defaults)) +} + + let _troupeP2P = null; -async function startp2p(nodeId, rt) { - // kick off the network initialization by loading the peerid +async function startp2p(nodeId, rt): Promise { + /*// kick off the network initialization by loading the peerid let peerInfo = await obtainPeerId(nodeId); debug ("Peer info created/loaded") _troupeP2P = new TroupeP2P( rt, peerInfo ); @@ -675,10 +737,124 @@ async function startp2p(nodeId, rt) { return peerInfo.id.toB58String() // if (rt) { // rt.networkReady(peerInfo.id.toB58String()); - // } + // }*/ + + let id : PeerId = null + try { + debug ("Creating new pair id...") + id = await createEd25519PeerId(); + debug("Created new pair id"); + } catch (err) { + logger.error("Error creating new peer id"); + throw err; + } + + let nodeListener : Libp2p = await createLibp2p({ + peerId: id, + addresses: { + listen: ['/ip4/0.0.0.0/tcp/0'] + }, + connectionManager : { + maxConnections: Infinity, + minConnections: 0 + } + }) + + _troupeP2P = nodeListener + let connectionManager = (nodeListener as any).components.connectionManager + + await nodeListener.handle('/chat/1.0.0', async ({ stream }) => { + console.log('Handling chat') + /*// Send stdin to the stream + stdinToStream(stream)*/ + // Read the stream and output to console + streamToConsole(stream) + }) + + nodeListener.addEventListener('peer:discovery', async (evt) => { + const peerInfo = evt.detail + console.log('Discovered:', peerInfo.id.toString()) + + const stream = await nodeListener.dialProtocol(peerInfo.id, '/chat/1.0.0') + stdinToStream(stream) + }) + + nodeListener.addEventListener('peer:connect', (evt) => { + const peerId = evt.detail + console.log('Connection established to:', peerId.toString()) + + /*setTimeout(() => { + console.log(connectionManager.getConnections(peerId)[0].streams) + }, 5000)*/ + }) + + //console.log((nodeListener as any).components.connectionManager) + + debug(`id is ${id.toString()}`) + return id +} + +async function sendp2p(id, procId, obj) { + +} + +function setupConnection (peerId, stream) { + let id:string = peerId.toString() + debug(`setupConnection with ${id}`); + const p = pushable() + + pipe (p, /*map (JSON.stringify), lp.encode(),*/ stream, /*lp.decode(), map(JSON.parse),*/ + async (source) => { + try { + for await (const x of source) { + //inputHandler (id, x, peerId) + console.log('Input: ', x) + } + } catch (err) { + debug (`try catch of the source`) + //processExpectedNetworkErrors(err, "setupConnection/pipe"); + throw err; + } + } + ) + stream.p = p; +} + +function stdinToStream(stream) { + // Read utf-8 from stdin + process.stdin.setEncoding('utf8') + pipe( + // Read from stdin (the source) + process.stdin, + // Turn strings into buffers + (source) => map(source, (string) => uint8ArrayFromString(string)), + // Encode with length prefix (so receiving side knows how much data is coming) + (source) => lp.encode(source), + // Write to the stream (the sink) + stream.sink + ) } +function streamToConsole(stream) { + pipe( + // Read from the stream (the source) + stream.source, + // Decode length-prefixed data + (source) => lp.decode(source), + // Turn buffers into strings + (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), + // Sink function + async function (source) { + // For each chunk of data + for await (const msg of source) { + // Output the data as a utf8 string + console.log('> ' + msg.toString().replace('\n', '')) + } + } + ) +} +/* function processExpectedNetworkErrors (err, source="source unknown") { debug (`error source: ${source}`); if (err instanceof AggregateError) { @@ -731,16 +907,29 @@ function processExpectedNetworkErrors (err, source="source unknown") { throw err; } } - } + }*/ export let p2p = { - startp2p: startp2p, - spawnp2p: (arg1, arg2) => _troupeP2P.spawnp2p(arg1, arg2), - sendp2p: (arg1, arg2, arg3) => _troupeP2P.sendp2p(arg1, arg2, arg3), - whereisp2p: (arg1, arg2) => _troupeP2P.whereisp2p (arg1, arg2), - stopp2p: async () =>{ - await _troupeP2P.stop() + startp2p: (arg1, arg2) => { + return startp2p(arg1, arg2) + }, + spawnp2p: (arg1, arg2) => { + throw new Error("Spawn p2p") + }, + //_troupeP2P.spawnp2p(arg1, arg2), + sendp2p: (arg1, arg2, arg3) => { + throw new Error("Send p2p") + }, + //_troupeP2P.sendp2p(arg1, arg2, arg3), + whereisp2p: (arg1, arg2) => { + throw new Error("WhereIs p2p") + }, + //_troupeP2P.whereisp2p (arg1, arg2), + stopp2p: async () => { + return await _troupeP2P.stop() }, - processExpectedNetworkErrors: processExpectedNetworkErrors + processExpectedNetworkErrors: (arg1, arg2) => { + throw new Error("Error p2p") + }, //processExpectedNetworkErrors } diff --git a/rt/src/runtimeMonitored.mts b/rt/src/runtimeMonitored.mts index 3b34af8..6a840f8 100644 --- a/rt/src/runtimeMonitored.mts +++ b/rt/src/runtimeMonitored.mts @@ -12,7 +12,7 @@ import { ProcessID } from './process.mjs'; import { UserRuntime } from './UserRuntime.mjs' import * as levels from './options.mjs' import * as DS from './deserialize.mjs' -import { p2p } from './p2p/p2p.js' +import { p2p } from './p2p/p2p.mjs' import { closeReadline } from './builtins/stdio.mjs'; import { __theRegister } from './builtins/whereis.mjs'; import { assertIsFunction } from './Asserts.mjs' From e832f1a978fd9cd096c949af9a8b7da858bd067c Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Thu, 29 Jun 2023 10:17:32 +0200 Subject: [PATCH 05/22] Make echo example work --- rt/src/p2p/p2p.mts | 337 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 288 insertions(+), 49 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 896ef8a..c176ff3 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -100,7 +100,7 @@ const p2pconfig = require('./p2pconfig.js') // const Pushable = require('pull-pushable') -import { v4 as uuidv4} from 'uuid' +import {v4 as uuidv4} from 'uuid' const MessageType = { @@ -194,7 +194,7 @@ function TroupeP2P (_rt, _peerInfo) { const p = pushable () _nodeTable[id] = p; - pipe (p, map (JSON.stringify), lp.encode(), stream,lp.decode(), map(JSON.parse), + pipe (p, map (JSON.stringify), lp.encode(), stream, lp.decode(), map(JSON.parse), async (source) => { try { for await (const x of source) { @@ -661,7 +661,7 @@ function setupBlockingHealthChecker (period) { } */ -import type { PeerId } from '@libp2p/interface-peer-id' +import { PeerId } from '@libp2p/interface-peer-id' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import { tcp } from '@libp2p/tcp' @@ -672,6 +672,7 @@ import { noise } from '@chainsafe/libp2p-noise' import defaultsDeep from '@nodeutils/defaults-deep' import { Libp2p, createLibp2p as create } from 'libp2p' import { createFromJSON, createEd25519PeerId } from '@libp2p/peer-id-factory' +import { peerIdFromString } from '@libp2p/peer-id' import { bootstrap } from '@libp2p/bootstrap' import { mdns } from '@libp2p/mdns' import { pipe } from 'it-pipe' @@ -679,8 +680,8 @@ import * as lp from 'it-length-prefixed' import map from 'it-map' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - import { pushable } from 'it-pushable' +//import { PeerId } from '@libp2p/interface-peer-id' let bootstrappers = [ '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', @@ -723,9 +724,34 @@ async function createLibp2p (_options) { return create(defaultsDeep(_options, defaults)) } +async function obtainPeerId(nodeId) : Promise { + let id : PeerId = null; + if (nodeId) { + try { + id = await createFromJSON(nodeId); + debug(`Loaded id from file: ${id.toString()}`); + } catch (err) { + logger.error("error creating peer id from json"); + throw err + } + } else { + try { + debug ("Creating new pair id...") + id = await createEd25519PeerId(); + debug("Created new pair id"); + } catch (err) { + logger.error("error creating new peer id"); + throw err; + } + } + /*let _peerInfo = new PeerInfo(id) + _peerInfo.multiaddrs.add(`/ip4/0.0.0.0/tcp/${__port}`); + return _peerInfo;*/ + return id; +} - -let _troupeP2P = null; +let _node : Libp2p = null; +let _rt = null; async function startp2p(nodeId, rt): Promise { /*// kick off the network initialization by loading the peerid @@ -739,15 +765,7 @@ async function startp2p(nodeId, rt): Promise { // rt.networkReady(peerInfo.id.toB58String()); // }*/ - let id : PeerId = null - try { - debug ("Creating new pair id...") - id = await createEd25519PeerId(); - debug("Created new pair id"); - } catch (err) { - logger.error("Error creating new peer id"); - throw err; - } + let id : PeerId = await obtainPeerId(nodeId); let nodeListener : Libp2p = await createLibp2p({ peerId: id, @@ -760,64 +778,171 @@ async function startp2p(nodeId, rt): Promise { } }) - _troupeP2P = nodeListener - let connectionManager = (nodeListener as any).components.connectionManager + _node = nodeListener + _rt = rt + //let connectionManager = (nodeListener as any).components.connectionManager - await nodeListener.handle('/chat/1.0.0', async ({ stream }) => { - console.log('Handling chat') - /*// Send stdin to the stream - stdinToStream(stream)*/ - // Read the stream and output to console - streamToConsole(stream) + await nodeListener.handle(_PROTOCOL, async ({ connection, stream }) => { + //console.log('Handling protocol') + //streamToConsole(stream) + setupConnection(connection.remotePeer, stream) }) nodeListener.addEventListener('peer:discovery', async (evt) => { const peerInfo = evt.detail - console.log('Discovered:', peerInfo.id.toString()) + console.log('Discovered:', peerInfo.id.toString()) // add to PeerStore??? - const stream = await nodeListener.dialProtocol(peerInfo.id, '/chat/1.0.0') - stdinToStream(stream) + /*setTimeout(() => { + console.log('Sending whereIs') + let data = "Hello" + whereisp2p(peerInfo.id, peerInfo.id.toString()) + }, 3000)*/ + + //await dial(peerInfo.id.toString()) + //const stream = await nodeListener.dialProtocol(peerInfo.id, _PROTOCOL) + //setupConnection(peerInfo.id, stream) + //stdinToStream(stream) }) nodeListener.addEventListener('peer:connect', (evt) => { const peerId = evt.detail console.log('Connection established to:', peerId.toString()) - - /*setTimeout(() => { - console.log(connectionManager.getConnections(peerId)[0].streams) - }, 5000)*/ }) - //console.log((nodeListener as any).components.connectionManager) - debug(`id is ${id.toString()}`) return id } -async function sendp2p(id, procId, obj) { +async function sendp2p(id : PeerId, procId, obj) { + debug (`sendp2p`) + + let data = { + messageType: MessageType.SEND, + pid: procId, + message: obj + } + + push_wrap(id, data) +} + +async function push_wrap(id: any, data: any) { + debug (`push_wrap`) + //let peerId = PeerId + let connections = _node.getConnections(id) + let p = null + if(connections.length >= 1) { + let connection = connections[0] + let streams = connection.streams + if(streams.length >= 1) { + let stream = streams[0] + p = (stream as any).p; + } else { + debug("streams array empty") + throw new Error + } + } else { + debug("connections array empty") + let stream = await dial(id.toString()) + debug("dialed to obtain stream") + p = (stream as any).p; + } + debug (`push_wrap; stream obtained`) + + while (true) { + try { + debug (`push_wrap; pushing`) + await p.push (data); + debug (`push_wrap; data pushed into the stream`) + break + } catch (err) { + // the stream we have used is + // no good for whatever reason; + // most likely there are networking + // issues. we report the errors + // and redial + debug (`push wrap error`) + //processExpectedNetworkErrors(err, "push_wrap"); + throw err + } + } } -function setupConnection (peerId, stream) { +function setupConnection(peerId : PeerId, stream) { let id:string = peerId.toString() debug(`setupConnection with ${id}`); - const p = pushable() + const p = pushable({ objectMode : true }) + + pipe (p, + (source) => map(source, (json) => JSON.stringify(json)), + (source) => map(source, (string) => uint8ArrayFromString(string, 'utf8')), + (source) => lp.encode(source), + stream, + (source) => lp.decode(source), + (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), + (source) => map(source, (string) => JSON.parse(string)), + async (source) => { + try { + for await (const x of source) { + //console.log('Input: ', x) + inputHandler (id, x, peerId) + } + } catch (err) { + debug (`try catch of the source`) + //processExpectedNetworkErrors(err, "setupConnection/pipe"); + throw err; + } - pipe (p, /*map (JSON.stringify), lp.encode(),*/ stream, /*lp.decode(), map(JSON.parse),*/ - async (source) => { + debug(`deleting entry for ${id}`); try { - for await (const x of source) { - //inputHandler (id, x, peerId) - console.log('Input: ', x) - } + await _node.hangUp(peerId); } catch (err) { - debug (`try catch of the source`) - //processExpectedNetworkErrors(err, "setupConnection/pipe"); - throw err; + throw err; } - } + reissueUnacknowledged(id) + } ) - stream.p = p; + stream.p = p; // Storing a reference to the pushable on the stream + // We rely on the p2p library to keep track of streams +} + +function dial(id) { + let i = 0; + let timeout = 2000; + return new Promise((resolve, reject) =>{ + async function iterate() { + try { + /*const peerInfo = await getPeerInfoWithRelay(id); + debug ("find peer succeeded"); + debug (`dialing will use the following addresses:`) + peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); + debug (">> -- end of address list -- << ")*/ + let peerId : PeerId = peerIdFromString(id) + debug (`trying to dial ${peerId}, attempt number ${i}`) + const stream = await _node.dialProtocol(peerId, _PROTOCOL) + debug ("dial successful") + setupConnection (peerId, stream); + resolve ( stream ); + } catch ( err ) { + //processExpectedNetworkErrors (err, "dial"); + + // if the error is suppressed we move on to trying 10 times + // with exponential backoff + // 2020-02-10; AA: TODO: this code has a hardcoded constant + if (i <= 10) { + debug (`dial failed, we retry in ${timeout} seconds`) + debug(err) + setTimeout (iterate, timeout); + i ++ ; + timeout *= 2 + } else { + debug (`we are giving up on dialing`) + reject (err); + } + } + } + iterate () + }) } function stdinToStream(stream) { @@ -854,6 +979,120 @@ function streamToConsole(stream) { ) } +async function inputHandler(id, input, fromNodeId_) { + let fromNodeId = fromNodeId_.toString() + debug ("-- input handler") + switch (input.messageType) { + /*case (MessageType.SPAWN): + if (_rt.remoteSpawnOK()) { + debug ("RECEIVED SPAWN") + let x = await _rt.spawnFromRemote (input.message, fromNodeId) + + push_wrap(id, { + messageType: MessageType.SPAWNOK, + spawnNonce: input.spawnNonce, + message: x + }); + break; + } // drop the message otherwise + + case (MessageType.SPAWNOK): + debug ("SPAWN OK") + let _cb = _spawnNonces[input.spawnNonce]; + if (_cb) { + delete _spawnNonces[input.spawnNonce]; // cleanup + _cb(null, input.message); // null means no errors + } else { + // something is fishy; + debug("something is fishy; no matching callback for the nonce"); + } + break;*/ + + case (MessageType.SEND): + debug (`SEND ${fromNodeId}`); + _rt.receiveFromRemote ( + input.pid, + input.message, + fromNodeId + ) + break; + + case (MessageType.WHEREIS): + debug ("p2p whereis incoming request") + let y = await _rt.whereisFromRemote (input.message) + push_wrap(id, { + messageType: MessageType.WHEREISOK, + whereisNonce : input.whereisNonce, + message : y + }); + debug ("p2p whereis replied") + break; + + case (MessageType.WHEREISOK): + let _cbw = _whereisNonces[input.whereisNonce]; + if (_cbw) { + delete _whereisNonces [input.whereisNonce]; + _cbw (null, input.message); + } else { + debug ("cannot find whereis callback") + } + break; + + case (MessageType.TEST): + debug("TEST input"); + debug(input) + break; + + default: + debug (`received data ${input.toString('utf8').replace('\n', '')}`); + break; + } +} + +async function whereisp2p(id, str) { + let whereisNonce = uuidv4() + + function f () { + push_wrap(id, { + messageType: MessageType.WHEREIS, + whereisNonce : whereisNonce, + message : str + }); + } + addUnacknowledged(id, whereisNonce, f); + + return new Promise ( (resolve, reject) => { + _whereisNonces[whereisNonce] = (err, data) => { + if (err) { reject (err) } else { + removeUnacknowledged (id,whereisNonce) + resolve (data) + } + } + debug ("pushing whereis message") + f (); + }) +} + +let _whereisNonces = {}; +let _unacknowledged:any = {} + +function addUnacknowledged (id, uuid, f) { + if (!_unacknowledged[id]){ + _unacknowledged[id] = [] + } + _unacknowledged[id][uuid] = f +} + +function removeUnacknowledged (id, uuid) { + delete _unacknowledged[id][uuid]; +} + +function reissueUnacknowledged (id:string) { + for (let uuid in _unacknowledged[id] ) { + setImmediate(_unacknowledged[id][uuid]) + } +} + /* function processExpectedNetworkErrors (err, source="source unknown") { debug (`error source: ${source}`); @@ -919,15 +1158,15 @@ export let p2p = { }, //_troupeP2P.spawnp2p(arg1, arg2), sendp2p: (arg1, arg2, arg3) => { - throw new Error("Send p2p") + return sendp2p(arg1, arg2, arg3) }, //_troupeP2P.sendp2p(arg1, arg2, arg3), whereisp2p: (arg1, arg2) => { - throw new Error("WhereIs p2p") + return whereisp2p(arg1, arg2) }, //_troupeP2P.whereisp2p (arg1, arg2), stopp2p: async () => { - return await _troupeP2P.stop() + return await _node.stop() }, processExpectedNetworkErrors: (arg1, arg2) => { throw new Error("Error p2p") From c18351146ad815cdb728fd823831b6b047f4360c Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Thu, 29 Jun 2023 11:14:11 +0200 Subject: [PATCH 06/22] Make pingpong example work --- rt/src/p2p/p2p.mts | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index c176ff3..acedb6d 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -783,7 +783,7 @@ async function startp2p(nodeId, rt): Promise { //let connectionManager = (nodeListener as any).components.connectionManager await nodeListener.handle(_PROTOCOL, async ({ connection, stream }) => { - //console.log('Handling protocol') + console.log('Handling protocol') //streamToConsole(stream) setupConnection(connection.remotePeer, stream) }) @@ -862,7 +862,7 @@ async function push_wrap(id: any, data: any) { // issues. we report the errors // and redial debug (`push wrap error`) - //processExpectedNetworkErrors(err, "push_wrap"); + processExpectedNetworkErrors(err, "push_wrap"); throw err } } @@ -889,7 +889,7 @@ function setupConnection(peerId : PeerId, stream) { } } catch (err) { debug (`try catch of the source`) - //processExpectedNetworkErrors(err, "setupConnection/pipe"); + processExpectedNetworkErrors(err, "setupConnection/pipe"); throw err; } @@ -924,7 +924,7 @@ function dial(id) { setupConnection (peerId, stream); resolve ( stream ); } catch ( err ) { - //processExpectedNetworkErrors (err, "dial"); + processExpectedNetworkErrors (err, "dial"); // if the error is suppressed we move on to trying 10 times // with exponential backoff @@ -983,7 +983,7 @@ async function inputHandler(id, input, fromNodeId_) { let fromNodeId = fromNodeId_.toString() debug ("-- input handler") switch (input.messageType) { - /*case (MessageType.SPAWN): + case (MessageType.SPAWN): if (_rt.remoteSpawnOK()) { debug ("RECEIVED SPAWN") let x = await _rt.spawnFromRemote (input.message, fromNodeId) @@ -1006,7 +1006,7 @@ async function inputHandler(id, input, fromNodeId_) { // something is fishy; debug("something is fishy; no matching callback for the nonce"); } - break;*/ + break; case (MessageType.SEND): debug (`SEND ${fromNodeId}`); @@ -1074,7 +1074,22 @@ async function whereisp2p(id, str) { } let _whereisNonces = {}; -let _unacknowledged:any = {} +let _unacknowledged:any = {}; +let _spawnNonces = {}; + +async function spawnp2p(id, data) { + const spawnNonce = uuidv4(); + return new Promise ((resolve, reject) => { + _spawnNonces[spawnNonce] = (err, data) => { + if (err) { reject (err) } else { resolve (data)} + }; + push_wrap(id, { + messageType: MessageType.SPAWN, + spawnNonce: spawnNonce, + message: data + }) + }); +} function addUnacknowledged (id, uuid, f) { if (!_unacknowledged[id]){ @@ -1093,11 +1108,10 @@ function reissueUnacknowledged (id:string) { } } -/* function processExpectedNetworkErrors (err, source="source unknown") { debug (`error source: ${source}`); if (err instanceof AggregateError) { - for (const e of err ) { + for (const e of err.errors ) { processExpectedNetworkErrors (e, source) } } else { @@ -1146,7 +1160,7 @@ function processExpectedNetworkErrors (err, source="source unknown") { throw err; } } - }*/ +} export let p2p = { @@ -1154,21 +1168,18 @@ export let p2p = { return startp2p(arg1, arg2) }, spawnp2p: (arg1, arg2) => { - throw new Error("Spawn p2p") + return spawnp2p(arg1, arg2) }, - //_troupeP2P.spawnp2p(arg1, arg2), sendp2p: (arg1, arg2, arg3) => { return sendp2p(arg1, arg2, arg3) }, - //_troupeP2P.sendp2p(arg1, arg2, arg3), whereisp2p: (arg1, arg2) => { return whereisp2p(arg1, arg2) }, - //_troupeP2P.whereisp2p (arg1, arg2), stopp2p: async () => { return await _node.stop() }, processExpectedNetworkErrors: (arg1, arg2) => { - throw new Error("Error p2p") - }, //processExpectedNetworkErrors + processExpectedNetworkErrors(arg1, arg2) + }, } From 9edbd9839ce33ce4b58b479c62e237f26550afe6 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Fri, 30 Jun 2023 11:31:50 +0200 Subject: [PATCH 07/22] Make parallel example work --- rt/src/p2p/p2p.mts | 188 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 143 insertions(+), 45 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index acedb6d..3a689b2 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -662,7 +662,6 @@ function setupBlockingHealthChecker (period) { */ import { PeerId } from '@libp2p/interface-peer-id' -import type { ConnectionManager } from '@libp2p/interface-connection-manager' import { tcp } from '@libp2p/tcp' import { webSockets } from '@libp2p/websockets' @@ -681,7 +680,6 @@ import map from 'it-map' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { pushable } from 'it-pushable' -//import { PeerId } from '@libp2p/interface-peer-id' let bootstrappers = [ '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', @@ -750,6 +748,30 @@ async function obtainPeerId(nodeId) : Promise { return id; } +const _HEALTHCHECKPERIOD = 5000 // 2020-02-10; AA; this should be an option + +function setupBlockingHealthChecker (period) { + let _lastHealth:number = Date.now() + let _healthCounter = 0; + let health_threshold = Math.max (period * 1.25 , period + 50) + // AA: 2020-02-10; + // The event queue always has a fair bit of latency, so we adjust for + // the minimal expected latency here; the constant of 50 is an + // empirically derived value, but needs to be critically reevaluated + // as the system evolves + + function f() { + let now = Date.now() + // debug (`Health checker running ${now - _lastHealth}, ${new Date()}`) + if (now - _lastHealth > health_threshold) { + debug (`Potential blocking issue: ${_healthCounter} ${now - _lastHealth}`) + } + _lastHealth = now; + setTimeout(f, period); + } + f () +} + let _node : Libp2p = null; let _rt = null; @@ -778,13 +800,13 @@ async function startp2p(nodeId, rt): Promise { } }) + setupBlockingHealthChecker(_HEALTHCHECKPERIOD); + _node = nodeListener _rt = rt - //let connectionManager = (nodeListener as any).components.connectionManager await nodeListener.handle(_PROTOCOL, async ({ connection, stream }) => { - console.log('Handling protocol') - //streamToConsole(stream) + console.log(`Handling protocol, id: ${connection.remotePeer}`) setupConnection(connection.remotePeer, stream) }) @@ -827,8 +849,8 @@ async function sendp2p(id : PeerId, procId, obj) { async function push_wrap(id: any, data: any) { debug (`push_wrap`) - //let peerId = PeerId let connections = _node.getConnections(id) + let needsToDial = true; let p = null if(connections.length >= 1) { let connection = connections[0] @@ -836,12 +858,14 @@ async function push_wrap(id: any, data: any) { if(streams.length >= 1) { let stream = streams[0] p = (stream as any).p; + needsToDial = p == undefined; } else { debug("streams array empty") - throw new Error + throw new Error //AB: What to do then? Can this happen? } - } else { - debug("connections array empty") + } + if(needsToDial) { + debug("needs to dial") let stream = await dial(id.toString()) debug("dialed to obtain stream") p = (stream as any).p; @@ -862,8 +886,7 @@ async function push_wrap(id: any, data: any) { // issues. we report the errors // and redial debug (`push wrap error`) - processExpectedNetworkErrors(err, "push_wrap"); - throw err + processExpectedNetworkErrors(err, "push_wrap"); } } } @@ -885,12 +908,11 @@ function setupConnection(peerId : PeerId, stream) { try { for await (const x of source) { //console.log('Input: ', x) - inputHandler (id, x, peerId) + inputHandler (id, x, peerId) //AB: Something is wonky with the parameters! } } catch (err) { debug (`try catch of the source`) processExpectedNetworkErrors(err, "setupConnection/pipe"); - throw err; } debug(`deleting entry for ${id}`); @@ -904,44 +926,121 @@ function setupConnection(peerId : PeerId, stream) { ) stream.p = p; // Storing a reference to the pushable on the stream // We rely on the p2p library to keep track of streams + debug(`Connection set up with ${id}`); +} + +/*function nPeers( ) { + return _node.getPeers().length } +async function getPeerInfo(id:string) { + const peerId = peerIdFromString(id); + return new Promise ((resolve, reject) => { + let n_attempts = 0; + async function try_find_peer () { + if (_node.peerStore.has(peerId)) { + debug ("peer info is in the store") + resolve (_node.peerStore.get(peerId)) + } else { + try { + debug (`calling peerRouting.findPeer ${peerId}`) + const peerInfo = await _node.peerRouting.findPeer (peerId, {timeout:1000}); + debug ("findPeer returned") + resolve (peerInfo); + } catch (err) { + debug (`try_find_peer exception`) + if (nPeers() > 0 ) { + n_attempts ++ ; + } + + if (err instanceof AggregateError) { + for (let e of err.errors) { + debug (`Find peer error with code: ${e}, ${e.code}`) + } + } else { + debug (`Find peer error: ${err.toString()}`) + throw err; + } + + if (n_attempts > 5) { + debug (`Resolving to empty peer info`) + resolve (new PeerInfo(peerId)) + // reject (err); + } else { + debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) + // addPending (try_find_peer); + setTimeout (try_find_peer, 500) + } + } + } + } + try_find_peer (); + }); +} + +let _relay_id = null; + +async function getPeerInfoWithRelay(id:any) { + let known_nodes = p2pconfig.known_nodes; + for (let ni of known_nodes) { + if (ni.nodeid == id) { + // found a known node! + let pi = new PeerInfo (PeerId.createFromB58String(id)); + pi.multiaddrs.add (multiaddr(`${ni.ip}`)) + debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`) + return pi + } + } + debug ("the node is not known; using relay information") + + let pi:any = await getPeerInfo (id) + if (_relay_id) { + pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) + } + + // for (let i = 0; i < p2pconfig.relays.length; i++ ) { + // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) + // } + return pi +}*/ +//AB: fix! + function dial(id) { let i = 0; let timeout = 2000; return new Promise((resolve, reject) =>{ - async function iterate() { - try { - /*const peerInfo = await getPeerInfoWithRelay(id); - debug ("find peer succeeded"); - debug (`dialing will use the following addresses:`) - peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); - debug (">> -- end of address list -- << ")*/ - let peerId : PeerId = peerIdFromString(id) - debug (`trying to dial ${peerId}, attempt number ${i}`) - const stream = await _node.dialProtocol(peerId, _PROTOCOL) - debug ("dial successful") - setupConnection (peerId, stream); - resolve ( stream ); - } catch ( err ) { - processExpectedNetworkErrors (err, "dial"); - - // if the error is suppressed we move on to trying 10 times - // with exponential backoff - // 2020-02-10; AA: TODO: this code has a hardcoded constant - if (i <= 10) { - debug (`dial failed, we retry in ${timeout} seconds`) - debug(err) - setTimeout (iterate, timeout); - i ++ ; - timeout *= 2 - } else { - debug (`we are giving up on dialing`) - reject (err); - } - } + async function iterate() { + try { + /*const peerInfo = await getPeerInfoWithRelay(id); + debug ("find peer succeeded"); + debug (`dialing will use the following addresses:`) + peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); + debug (">> -- end of address list -- << ")*/ + let peerId : PeerId = peerIdFromString(id) + debug (`trying to dial ${peerId}, attempt number ${i}`) + const stream = await _node.dialProtocol(peerId, _PROTOCOL) + debug ("dial successful") + setupConnection (peerId, stream); + resolve ( stream ); + } catch ( err ) { + processExpectedNetworkErrors (err, "dial"); + + // if the error is suppressed we move on to trying 10 times + // with exponential backoff + // 2020-02-10; AA: TODO: this code has a hardcoded constant + if (i <= 10) { + debug (`dial failed, we retry in ${timeout} seconds`) + debug(err) + setTimeout (iterate, timeout); + i++; + timeout *= 2; + } else { + debug (`we are giving up on dialing`) + reject (err); + } } - iterate () + } + iterate () }) } @@ -1162,7 +1261,6 @@ function processExpectedNetworkErrors (err, source="source unknown") { } } - export let p2p = { startp2p: (arg1, arg2) => { return startp2p(arg1, arg2) From 3731c7894ca6adb60b8de93affee2eefd0d9af12 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Mon, 3 Jul 2023 14:29:31 +0200 Subject: [PATCH 08/22] Convert mkid to ES --- examples/network/echo/Makefile | 2 +- examples/network/parallel/Makefile | 2 +- examples/network/pingpong/Makefile | 6 ++-- relay/Makefile | 2 +- rt/src/p2p/mkid.mts | 49 ++++++++++++++++++++++++++++++ rt/src/p2p/mkid.ts | 47 ---------------------------- 6 files changed, 55 insertions(+), 53 deletions(-) create mode 100644 rt/src/p2p/mkid.mts delete mode 100644 rt/src/p2p/mkid.ts diff --git a/examples/network/echo/Makefile b/examples/network/echo/Makefile index 6018d95..e498e12 100644 --- a/examples/network/echo/Makefile +++ b/examples/network/echo/Makefile @@ -1,4 +1,4 @@ -MKID=node $(TROUPE)/rt/built/p2p/mkid.js +MKID=node $(TROUPE)/rt/built/p2p/mkid.mjs MKALIASES=node $(TROUPE)/rt/built/p2p/mkaliases.js START=$(TROUPE)/network.sh diff --git a/examples/network/parallel/Makefile b/examples/network/parallel/Makefile index e73db5b..67e74f1 100644 --- a/examples/network/parallel/Makefile +++ b/examples/network/parallel/Makefile @@ -1,4 +1,4 @@ -MKID=node $(TROUPE)/rt/built/p2p/mkid.js +MKID=node $(TROUPE)/rt/built/p2p/mkid.mjs MKALIASES=node $(TROUPE)/rt/built/p2p/mkaliases.js START=$(TROUPE)/network.sh diff --git a/examples/network/pingpong/Makefile b/examples/network/pingpong/Makefile index 7c08957..854d45d 100644 --- a/examples/network/pingpong/Makefile +++ b/examples/network/pingpong/Makefile @@ -1,12 +1,12 @@ -MKID=node $(TROUPE)/rt/built/p2p/mkid.js +MKID=node $(TROUPE)/rt/built/p2p/mkid.mjs MKALIASES=node $(TROUPE)/rt/built/p2p/mkaliases.js START=$(TROUPE)/network.sh zero.listener: - $(START) zero.trp --id=ids/pingpong-listener.json --rspawn=true --aliases=aliases.json --stdiolev={} # --debug --debugp2p + $(START) zero.trp --id=ids/pingpong-listener.json --rspawn=true --aliases=aliases.json --stdiolev={} --debug --debugp2p pingpong.dialer: - $(START) p2ppingpong.trp --id=ids/pingpong-dialer.json --aliases=aliases.json # --debug --debugp2p + $(START) p2ppingpong.trp --id=ids/pingpong-dialer.json --aliases=aliases.json --debug --debugp2p create-network-identifiers: mkdir -p ids diff --git a/relay/Makefile b/relay/Makefile index b08b901..bed8798 100644 --- a/relay/Makefile +++ b/relay/Makefile @@ -2,4 +2,4 @@ start-relay: ./troupe-p2p-relay --key=keys/relay.priv generate-relay-key: - node $(TROUPE)/rt/built/p2p/mkid.js --privkeyfile=keys/relay.priv --idfile=keys/relay.id --verbose \ No newline at end of file + node $(TROUPE)/rt/built/p2p/mkid.mjs --privkeyfile=keys/relay.priv --idfile=keys/relay.id --verbose \ No newline at end of file diff --git a/rt/src/p2p/mkid.mts b/rt/src/p2p/mkid.mts new file mode 100644 index 0000000..ce767bc --- /dev/null +++ b/rt/src/p2p/mkid.mts @@ -0,0 +1,49 @@ +// A small utility for creating p2p peer identifiers + +// This utility checks that the files exists in order to +// prevent an accidental overwrite of key files + +'use strict'; +import * as fs from 'node:fs' +import * as fsPromises from 'node:fs/promises'; +// const fsPromises = require('fs').promises +import PeerId from "peer-id"; +//const args = require('yargs').argv; +import pkg from 'yargs' +const {argv} = pkg; + +let outfile = argv.outfile +if (!outfile && ! (argv.privkeyfile && argv.idfile)) { + console.log ("Troupe p2p identifier generator") + console.log ("Usage: node $TROUPE/rt/bulit/p2p/mkid.mjs --outfile=FILENAME | --privkeyfile=FILENAME --idfile=FILENAME [ --verbose]"); + process.exit(1) +} + +async function ensureFileDoesntExist (f) { + if (fs.existsSync (f)) { + console.error ("File already exists", f) + process.exit (1) + } +} + +(async () => { + let id = await PeerId.create(); + const obj = id.toJSON(); + if (argv.verbose) { + console.log("Created key with id:", obj.id); + } + + const s = JSON.stringify(obj); + if (argv.outfile) { + await ensureFileDoesntExist (argv.outfile) + fsPromises.writeFile ((outfile as fs.PathLike), s, 'utf8'); + } + + + if (argv.idfile && argv.privkeyfile) { + await ensureFileDoesntExist (argv.idfile) + await ensureFileDoesntExist (argv.privkeyfile) + fsPromises.writeFile ((argv.idfile as fs.PathLike), obj.id, 'utf8'); + fsPromises.writeFile ((argv.privkeyfile as fs.PathLike), obj.privKey, 'utf8' ); + } +}) (); \ No newline at end of file diff --git a/rt/src/p2p/mkid.ts b/rt/src/p2p/mkid.ts deleted file mode 100644 index fa264b1..0000000 --- a/rt/src/p2p/mkid.ts +++ /dev/null @@ -1,47 +0,0 @@ -// A small utility for creating p2p peer identifiers - -// This utility checks that the files exists in order to -// prevent an accidental overwrite of key files - -'use strict'; -import * as fs from 'node:fs' -import * as fsPromises from 'node:fs/promises'; -// const fsPromises = require('fs').promises -const PeerId = require("peer-id") -const args = require('yargs').argv; - -let outfile = args.outfile -if (!outfile && ! (args.privkeyfile && args.idfile)) { - console.log ("Troupe p2p identifier generator") - console.log ("Usage: node $TROUPE/rt/bulit/p2p/mkid.js --outfile=FILENAME | --privkeyfile=FILENAME --idfile=FILENAME [ --verbose]"); - process.exit(1) -} - -async function ensureFileDoesntExist (f) { - if (fs.existsSync (f)) { - console.error ("File already exists", f) - process.exit (1) - } -} - -(async () => { - let id = await PeerId.create(); - const obj = id.toJSON(); - if (args.verbose) { - console.log("Created key with id:", obj.id); - } - - const s = JSON.stringify(obj); - if (args.outfile) { - await ensureFileDoesntExist (args.outfile) - fsPromises.writeFile (outfile, s, 'utf8'); - } - - - if (args.idfile && args.privkeyfile) { - await ensureFileDoesntExist (args.idfile) - await ensureFileDoesntExist (args.privkeyfile) - fsPromises.writeFile (args.idfile, obj.id, 'utf8'); - fsPromises.writeFile (args.privkeyfile, obj.privKey, 'utf8' ); - } -}) (); \ No newline at end of file From 4b6767b8cf68efb50612e75bd12f36657297dd96 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Tue, 4 Jul 2023 09:49:10 +0200 Subject: [PATCH 09/22] Fix writing ids to file in mkid --- rt/src/p2p/mkid.mts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/rt/src/p2p/mkid.mts b/rt/src/p2p/mkid.mts index ce767bc..daa4abe 100644 --- a/rt/src/p2p/mkid.mts +++ b/rt/src/p2p/mkid.mts @@ -6,9 +6,8 @@ 'use strict'; import * as fs from 'node:fs' import * as fsPromises from 'node:fs/promises'; -// const fsPromises = require('fs').promises -import PeerId from "peer-id"; -//const args = require('yargs').argv; +import { createEd25519PeerId } from '@libp2p/peer-id-factory' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import pkg from 'yargs' const {argv} = pkg; @@ -27,8 +26,13 @@ async function ensureFileDoesntExist (f) { } (async () => { - let id = await PeerId.create(); - const obj = id.toJSON(); + let peerid = await createEd25519PeerId(); + + const obj = { + id : peerid.toString(), + privKey : uint8ArrayToString(peerid.privateKey, 'base64pad'), + pubKey : uint8ArrayToString(peerid.publicKey, 'base64pad') + }; if (argv.verbose) { console.log("Created key with id:", obj.id); } From 3426a36801748720ebb764ab0163d2865fdfc9cb Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Wed, 12 Jul 2023 08:38:14 +0200 Subject: [PATCH 10/22] WIP change relays to use javascript --- relay/Makefile | 1 + relay/relay.mjs | 46 ++++++++ rt/src/p2p/p2p.mts | 260 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 248 insertions(+), 59 deletions(-) create mode 100644 relay/relay.mjs diff --git a/relay/Makefile b/relay/Makefile index bed8798..a9b75d1 100644 --- a/relay/Makefile +++ b/relay/Makefile @@ -2,4 +2,5 @@ start-relay: ./troupe-p2p-relay --key=keys/relay.priv generate-relay-key: + mkdir -p keys node $(TROUPE)/rt/built/p2p/mkid.mjs --privkeyfile=keys/relay.priv --idfile=keys/relay.id --verbose \ No newline at end of file diff --git a/relay/relay.mjs b/relay/relay.mjs new file mode 100644 index 0000000..18f1d7b --- /dev/null +++ b/relay/relay.mjs @@ -0,0 +1,46 @@ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { webSockets } from '@libp2p/websockets' +import { createLibp2p } from 'libp2p' +import { circuitRelayServer } from 'libp2p/circuit-relay' +import { identifyService } from 'libp2p/identify' +import { createFromJSON } from '@libp2p/peer-id-factory' + +async function main () { + const id = await createFromJSON({id : "12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf", + privKey : "CAESQEQ7HBed1HEMpRHdhDmsJOlzHsVNBEWVc7DjEzuQtElv+uET7jQtZlGNKpltf2w4P7UqMdSYm4cYAGzjHcGcSj4="}); + const node = await createLibp2p({ + peerId : id, + addresses: { + listen: ['/ip4/0.0.0.0/tcp/5555/ws'] + // TODO check "What is next?" section + // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] + }, + transports: [ + webSockets() + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + yamux(), + mplex() + ], + services: { + identify: identifyService(), + relay: circuitRelayServer() + } + }) + + await node.handle("/trouperelay/keepalive", async ({ connection, stream }) => { + console.log(`Relay handling protocol, id: ${connection.remotePeer}`) + //setupConnection(connection.remotePeer, stream) + }) + + console.log(`Node started with id ${node.peerId.toString()}`) + console.log('Listening on:') + node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) +} + +main() \ No newline at end of file diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 3a689b2..93c95b5 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -58,7 +58,7 @@ the libp2p). // LOGGING AND DEBUGGING -import yargs from 'yargs' +/*import yargs from 'yargs' let logLevel = yargs.argv.debugp2p? 'debug':'info' let __port = yargs.argv.port || 0 @@ -76,7 +76,7 @@ let logger; const info = x => logger.info(x) const debug = x => logger.debug(x) -const error = x => logger.error(x); +const error = x => logger.error(x);*/ /* @@ -100,7 +100,7 @@ const p2pconfig = require('./p2pconfig.js') // const Pushable = require('pull-pushable') -import {v4 as uuidv4} from 'uuid' +/*import {v4 as uuidv4} from 'uuid' const MessageType = { @@ -110,7 +110,7 @@ const MessageType = { TEST: 3, WHEREIS: 4, WHEREISOK: 5 -} +}*/ /* @@ -661,6 +661,37 @@ function setupBlockingHealthChecker (period) { } */ +// LOGGING AND DEBUGGING + +import yargs from 'yargs' +let logLevel = yargs.argv.debugp2p? 'debug':'info' +let __port = yargs.argv.port || 0 + +const _PROTOCOL = "/troupe/1.0.0" + +let logger; +(async() => { + let { mkLogger } = await import ('../logger.mjs'); + logger = mkLogger ('p2p', logLevel) +})() + +// const logger = require('../logger.js').mkLogger('p2p',logLevel); + +const info = x => logger.info(x) +const debug = x => logger.debug(x) +const error = x => logger.error(x); + +import {v4 as uuidv4} from 'uuid' + +const MessageType = { + SPAWN: 0, + SPAWNOK: 1, + SEND: 2, + TEST: 3, + WHEREIS: 4, + WHEREISOK: 5 +} + import { PeerId } from '@libp2p/interface-peer-id' import { tcp } from '@libp2p/tcp' @@ -680,8 +711,18 @@ import map from 'it-map' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { pushable } from 'it-pushable' +import p2pconfig from './p2pconfig.js'; //AB: ecmascript? +import { multiaddr } from '@multiformats/multiaddr' +import { identifyService } from 'libp2p/identify' +import { circuitRelayTransport } from 'libp2p/circuit-relay' + +//import { secio } from 'libp2p-secio'; //AB: deprecated - find out why it's needed +import pkg from 'libp2p-secio' +import { nodeTrustLevel } from '../TrustManager.mjs'; +const {secio} = pkg; -let bootstrappers = [ + +let bootstrappers = [ //AB: bootstrap known_nodes from config?? Make findNode easier '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', @@ -696,23 +737,29 @@ async function createLibp2p (_options) { const defaults = { transports: [ tcp(), - webSockets() + webSockets(), + circuitRelayTransport({ + discoverRelays: 2 //AB: what to set this to? + }) ], streamMuxers: [ yamux(), mplex() ], connectionEncryption: [ - noise() + noise(), ], peerDiscovery: [ /*bootstrap({ list: bootstrappers }),*/ - mdns({ + /*mdns({ interval: 20e3 - }) + })*/ ], + services: { + identify: identifyService() + } /*dht: kadDHT({ kBucketSize: 20, clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) @@ -743,7 +790,7 @@ async function obtainPeerId(nodeId) : Promise { } } /*let _peerInfo = new PeerInfo(id) - _peerInfo.multiaddrs.add(`/ip4/0.0.0.0/tcp/${__port}`); + _peerInfo.multiaddrs.add(`/ip4/0.0.0.0/tcp/${__port}`); //AB: do this??? already in adresses, possibly return _peerInfo;*/ return id; } @@ -789,48 +836,58 @@ async function startp2p(nodeId, rt): Promise { let id : PeerId = await obtainPeerId(nodeId); - let nodeListener : Libp2p = await createLibp2p({ - peerId: id, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - connectionManager : { - maxConnections: Infinity, - minConnections: 0 - } - }) - + try { + let nodeListener : Libp2p = await createLibp2p({ + peerId: id, + addresses: { + listen: ['/ip4/0.0.0.0/tcp/0'] + }, + connectionManager : { + maxConnections: Infinity, + minConnections: 0 + } + }) + + _node = nodeListener + _rt = rt + } catch (err) { + debug(`Something wrong while creating Libp2p node: ${err}`) + throw err + } + setupBlockingHealthChecker(_HEALTHCHECKPERIOD); - - _node = nodeListener - _rt = rt - - await nodeListener.handle(_PROTOCOL, async ({ connection, stream }) => { - console.log(`Handling protocol, id: ${connection.remotePeer}`) + + await _node.handle(_PROTOCOL, async ({ connection, stream }) => { + debug(`Handling protocol, id: ${connection.remotePeer}`) setupConnection(connection.remotePeer, stream) }) - nodeListener.addEventListener('peer:discovery', async (evt) => { + _node.addEventListener('peer:discovery', async (evt) => { const peerInfo = evt.detail - console.log('Discovered:', peerInfo.id.toString()) // add to PeerStore??? - - /*setTimeout(() => { - console.log('Sending whereIs') - let data = "Hello" - whereisp2p(peerInfo.id, peerInfo.id.toString()) - }, 3000)*/ - - //await dial(peerInfo.id.toString()) - //const stream = await nodeListener.dialProtocol(peerInfo.id, _PROTOCOL) - //setupConnection(peerInfo.id, stream) - //stdinToStream(stream) + debug(`Discovered: ${peerInfo.id.toString()}`) // add to PeerStore??? }) - nodeListener.addEventListener('peer:connect', (evt) => { + _node.addEventListener('peer:connect', (evt) => { const peerId = evt.detail - console.log('Connection established to:', peerId.toString()) + debug(`Connection established to: ${peerId.toString()}`) }) + _node.addEventListener('peer:disconnect', (evt) => { + let id = evt.detail + debug (`-- disconnect: ${id}`) + if (_relayTable[id.toString()]) { + debug (`deleting relay table entry`) + delete _relayTable[id.toString()] + } + }) + + debug("p2p node started") + + /*for (let relay_addr of p2pconfig.relays ) { + keepAliveRelay(relay_addr); + }*/ + keepAliveRelay("/ip4/127.0.0.1/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf") + debug(`id is ${id.toString()}`) return id } @@ -853,7 +910,7 @@ async function push_wrap(id: any, data: any) { let needsToDial = true; let p = null if(connections.length >= 1) { - let connection = connections[0] + let connection = connections[0] //AB: check all connections let streams = connection.streams if(streams.length >= 1) { let stream = streams[0] @@ -929,24 +986,35 @@ function setupConnection(peerId : PeerId, stream) { debug(`Connection set up with ${id}`); } -/*function nPeers( ) { +function nPeers( ) { return _node.getPeers().length } -async function getPeerInfo(id:string) { +async function getPeerInfo(id:string) : Promise{ const peerId = peerIdFromString(id); return new Promise ((resolve, reject) => { let n_attempts = 0; async function try_find_peer () { - if (_node.peerStore.has(peerId)) { + if (await _node.peerStore.has(peerId)) { debug ("peer info is in the store") - resolve (_node.peerStore.get(peerId)) + try { + let foundPeer = await _node.peerStore.get(peerId) + resolve (foundPeer.id) + } catch (err) { + debug(`Error in getPeerInfo: ${err}`) + throw err + } } else { try { debug (`calling peerRouting.findPeer ${peerId}`) - const peerInfo = await _node.peerRouting.findPeer (peerId, {timeout:1000}); + const peerInfo = await _node.peerRouting.findPeer (peerId, {signal : AbortSignal.timeout(1000)}); debug ("findPeer returned") - resolve (peerInfo); + await _node.peerStore.patch(peerInfo.id, { + multiaddrs: + peerInfo.multiaddrs + }) //AB: necessary?? + debug("added multiaddr to store") + resolve (peerInfo.id); } catch (err) { debug (`try_find_peer exception`) if (nPeers() > 0 ) { @@ -959,12 +1027,12 @@ async function getPeerInfo(id:string) { } } else { debug (`Find peer error: ${err.toString()}`) - throw err; + //throw err; } if (n_attempts > 5) { debug (`Resolving to empty peer info`) - resolve (new PeerInfo(peerId)) + resolve (peerId) // reject (err); } else { debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) @@ -978,32 +1046,106 @@ async function getPeerInfo(id:string) { }); } +export interface IHash { + [details: string] : any; +} //AB: use in-built functionality instead + let _relay_id = null; +let _KEEPALIVE = 5000 //AB: can tag peers with "Keep_alive" in the peerstore +let _keepAliveCounter = 0; +let _relayTable:IHash = {} + +async function dialRelay (relay_addr) { + debug (`dialing relay ${relay_addr}`) + let id = relay_addr.split('/').pop(); + const relayId = peerIdFromString(id) + await _node.peerStore.patch(relayId, { + multiaddrs: [ + multiaddr(`${relay_addr}`) + ] + }) + await _node.peerStore.merge(relayId, { + tags : { + 'keep-alive' : {} + } + }); + debug (`Added relay address`) + const conn = await _node.dial(relayId); + debug (`Got relay connection`) + const stream = await _node.dialProtocol (relayId, "/trouperelay/keepalive") + debug (`Got relay stream`) + const peerId = conn.remotePeer + _relay_id = peerId.toString() + debug (`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`) + const p = pushable({ objectMode : true }) + + pipe (stream.source, + async (source: any) => { + let ss = "" + for await (const msg of source ) { + debug (`~~ relay says:${msg.toString().trim()}`) + } + }) + pipe (p, + (stream.sink as any)); + + _relayTable[id] = p; + return p; +} + +async function keepAliveRelay (relay_addr:string) { + let id = relay_addr.split('/').pop(); + debug (`relay id is ${id}`) + let timeout = _KEEPALIVE; + async function f () { + try { + let p = _relayTable[id] ? _relayTable[id] : await dialRelay (relay_addr) + p.push (`keep alive request ${_keepAliveCounter++}\n`) + timeout = _KEEPALIVE + } catch (err ) { + timeout = timeout < 600e3 ? timeout * 2 : timeout // exponential backoff with 10 min limit + processExpectedNetworkErrors(err, "relay") + debug (`~~ error reaching the relay server; we will retry again in ${timeout/1000} seconds`) + } + setTimeout(f,timeout) + } + f () + } + async function getPeerInfoWithRelay(id:any) { let known_nodes = p2pconfig.known_nodes; for (let ni of known_nodes) { if (ni.nodeid == id) { // found a known node! - let pi = new PeerInfo (PeerId.createFromB58String(id)); - pi.multiaddrs.add (multiaddr(`${ni.ip}`)) + let pi = peerIdFromString(id); + await _node.peerStore.patch(pi, { + multiaddrs: [ + multiaddr(`${ni.ip}`) + ] + }) + //pi.multiaddrs.add (multiaddr(`${ni.ip}`)) debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`) return pi } } debug ("the node is not known; using relay information") - let pi:any = await getPeerInfo (id) + let pi = await getPeerInfo(id) if (_relay_id) { - pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) + //pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) + await _node.peerStore.patch(pi, { + multiaddrs: [ + multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`) + ] + }) } // for (let i = 0; i < p2pconfig.relays.length; i++ ) { // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) // } return pi -}*/ -//AB: fix! +} function dial(id) { let i = 0; @@ -1016,7 +1158,7 @@ function dial(id) { debug (`dialing will use the following addresses:`) peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); debug (">> -- end of address list -- << ")*/ - let peerId : PeerId = peerIdFromString(id) + let peerId : PeerId = await getPeerInfoWithRelay(id) debug (`trying to dial ${peerId}, attempt number ${i}`) const stream = await _node.dialProtocol(peerId, _PROTOCOL) debug ("dial successful") @@ -1153,7 +1295,7 @@ async function whereisp2p(id, str) { function f () { push_wrap(id, { - messageType: MessageType.WHEREIS, + messageType : MessageType.WHEREIS, whereisNonce : whereisNonce, message : str }); From 2d6b09d8430710b989a61f6651529a6b7ba2de73 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Wed, 12 Jul 2023 15:26:50 +0200 Subject: [PATCH 11/22] WIP use javascript for relays --- relay/relay.mjs | 11 ++++++++++- rt/src/p2p/p2p.mts | 35 ++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/relay/relay.mjs b/relay/relay.mjs index 18f1d7b..6cb7844 100644 --- a/relay/relay.mjs +++ b/relay/relay.mjs @@ -27,9 +27,18 @@ async function main () { yamux(), mplex() ], - services: { + /*services: { identify: identifyService(), relay: circuitRelayServer() + }*/ + relay: { + enabled: true, + hop: { + enabled: true + }, + advertise: { + enabled: true, + } } }) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 93c95b5..1a334ac 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -716,11 +716,6 @@ import { multiaddr } from '@multiformats/multiaddr' import { identifyService } from 'libp2p/identify' import { circuitRelayTransport } from 'libp2p/circuit-relay' -//import { secio } from 'libp2p-secio'; //AB: deprecated - find out why it's needed -import pkg from 'libp2p-secio' -import { nodeTrustLevel } from '../TrustManager.mjs'; -const {secio} = pkg; - let bootstrappers = [ //AB: bootstrap known_nodes from config?? Make findNode easier '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', @@ -738,9 +733,10 @@ async function createLibp2p (_options) { transports: [ tcp(), webSockets(), - circuitRelayTransport({ - discoverRelays: 2 //AB: what to set this to? - }) + /*circuitRelayTransport({ + discoverRelays: 2, //AB: what to set this to? + reservationConcurrency : 2, + })*/ ], streamMuxers: [ yamux(), @@ -757,9 +753,16 @@ async function createLibp2p (_options) { interval: 20e3 })*/ ], - services: { + /*services: { identify: identifyService() - } + },*/ + relay: { + enabled: true, + autoRelay: { + enabled: true, + maxListeners: Infinity + } + }, /*dht: kadDHT({ kBucketSize: 20, clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) @@ -879,14 +882,20 @@ async function startp2p(nodeId, rt): Promise { debug (`deleting relay table entry`) delete _relayTable[id.toString()] } - }) + }) + + _node.addEventListener('self:peer:update', (evt) => { + // Updated self multiaddrs? + debug(`Advertising with following addresses:`) + _node.getMultiaddrs().forEach((ma) => debug(ma.toString())) + }) debug("p2p node started") /*for (let relay_addr of p2pconfig.relays ) { keepAliveRelay(relay_addr); }*/ - keepAliveRelay("/ip4/127.0.0.1/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf") + keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf") debug(`id is ${id.toString()}`) return id @@ -1037,7 +1046,7 @@ async function getPeerInfo(id:string) : Promise{ } else { debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) // addPending (try_find_peer); - setTimeout (try_find_peer, 500) + setTimeout (try_find_peer, 5000) } } } From a8e916b4b9da86bc59b77ea293b47e60fe8b3f74 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Mon, 17 Jul 2023 11:09:21 +0200 Subject: [PATCH 12/22] Make connecting to relays work --- relay/relay.mjs | 12 ++++++------ rt/src/p2p/p2p.mts | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/relay/relay.mjs b/relay/relay.mjs index 6cb7844..a4d717e 100644 --- a/relay/relay.mjs +++ b/relay/relay.mjs @@ -13,9 +13,9 @@ async function main () { const node = await createLibp2p({ peerId : id, addresses: { - listen: ['/ip4/0.0.0.0/tcp/5555/ws'] + listen: ['/ip4/0.0.0.0/tcp/5555/ws'], // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] + announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] }, transports: [ webSockets() @@ -27,11 +27,11 @@ async function main () { yamux(), mplex() ], - /*services: { + services: { identify: identifyService(), relay: circuitRelayServer() - }*/ - relay: { + } + /*relay: { enabled: true, hop: { enabled: true @@ -39,7 +39,7 @@ async function main () { advertise: { enabled: true, } - } + }*/ }) await node.handle("/trouperelay/keepalive", async ({ connection, stream }) => { diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 1a334ac..0342e13 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -733,10 +733,10 @@ async function createLibp2p (_options) { transports: [ tcp(), webSockets(), - /*circuitRelayTransport({ + circuitRelayTransport({ discoverRelays: 2, //AB: what to set this to? reservationConcurrency : 2, - })*/ + }) ], streamMuxers: [ yamux(), @@ -753,9 +753,9 @@ async function createLibp2p (_options) { interval: 20e3 })*/ ], - /*services: { + services: { identify: identifyService() - },*/ + }, relay: { enabled: true, autoRelay: { @@ -1046,7 +1046,7 @@ async function getPeerInfo(id:string) : Promise{ } else { debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) // addPending (try_find_peer); - setTimeout (try_find_peer, 5000) + setTimeout (try_find_peer, 500) } } } From 83d14c74c348301494702c91a9a229ae43df43b2 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Tue, 18 Jul 2023 10:25:58 +0200 Subject: [PATCH 13/22] Fix relays breaking connection after a short time --- package.json | 1 + relay/relay.mjs | 21 +++++++-------------- rt/src/p2p/p2p.mts | 17 +++++------------ 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index ed1a943..cdaebd5 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@libp2p/kad-dht": "^9.3.4", "@libp2p/mdns": "^8.0.0", "@libp2p/mplex": "^8.0.3", + "@libp2p/peer-store": "^8.2.1", "@libp2p/tcp": "^7.0.1", "@libp2p/websockets": "^6.0.1", "@nodeutils/defaults-deep": "^1.1.0", diff --git a/relay/relay.mjs b/relay/relay.mjs index a4d717e..ade14f7 100644 --- a/relay/relay.mjs +++ b/relay/relay.mjs @@ -13,9 +13,7 @@ async function main () { const node = await createLibp2p({ peerId : id, addresses: { - listen: ['/ip4/0.0.0.0/tcp/5555/ws'], - // TODO check "What is next?" section - announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] + listen: ['/ip4/0.0.0.0/tcp/5555/ws'] }, transports: [ webSockets() @@ -29,22 +27,17 @@ async function main () { ], services: { identify: identifyService(), - relay: circuitRelayServer() + relay: circuitRelayServer({ // makes the node function as a relay server + reservations: { + defaultDurationLimit: 2147483647, // the default maximum amount of time a relayed connection can be open for + defaultDataLimit: BigInt(4294967295), // the default maximum number of bytes that can be transferred over a relayed connection + } + }), //AB: find out which settings to use to not cut off connections } - /*relay: { - enabled: true, - hop: { - enabled: true - }, - advertise: { - enabled: true, - } - }*/ }) await node.handle("/trouperelay/keepalive", async ({ connection, stream }) => { console.log(`Relay handling protocol, id: ${connection.remotePeer}`) - //setupConnection(connection.remotePeer, stream) }) console.log(`Node started with id ${node.peerId.toString()}`) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 0342e13..f700527 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -715,7 +715,7 @@ import p2pconfig from './p2pconfig.js'; //AB: ecmascript? import { multiaddr } from '@multiformats/multiaddr' import { identifyService } from 'libp2p/identify' import { circuitRelayTransport } from 'libp2p/circuit-relay' - +import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags' let bootstrappers = [ //AB: bootstrap known_nodes from config?? Make findNode easier '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', @@ -756,13 +756,6 @@ async function createLibp2p (_options) { services: { identify: identifyService() }, - relay: { - enabled: true, - autoRelay: { - enabled: true, - maxListeners: Infinity - } - }, /*dht: kadDHT({ kBucketSize: 20, clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) @@ -1075,10 +1068,10 @@ async function dialRelay (relay_addr) { ] }) await _node.peerStore.merge(relayId, { - tags : { - 'keep-alive' : {} + tags: { + [KEEP_ALIVE]: {} } - }); + }) debug (`Added relay address`) const conn = await _node.dial(relayId); debug (`Got relay connection`) @@ -1141,7 +1134,7 @@ async function getPeerInfoWithRelay(id:any) { debug ("the node is not known; using relay information") let pi = await getPeerInfo(id) - if (_relay_id) { + if (_relay_id) { //AB: use all relays as below! //pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) await _node.peerStore.patch(pi, { multiaddrs: [ From 705cdabbf8a451b31f21c65095906a560070a673 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Wed, 19 Jul 2023 09:58:34 +0200 Subject: [PATCH 14/22] Refactor p2p.mts --- rt/src/p2p/libp2p-bundle.js | 2 +- rt/src/p2p/p2p.mts | 1630 ++++++-------------- rt/src/p2p/{p2pconfig.js => p2pconfig.mjs} | 8 +- 3 files changed, 504 insertions(+), 1136 deletions(-) rename rt/src/p2p/{p2pconfig.js => p2pconfig.mjs} (92%) diff --git a/rt/src/p2p/libp2p-bundle.js b/rt/src/p2p/libp2p-bundle.js index f0fa26d..7eb1c77 100644 --- a/rt/src/p2p/libp2p-bundle.js +++ b/rt/src/p2p/libp2p-bundle.js @@ -10,7 +10,7 @@ const Multiplex = require('libp2p-mplex') const SECIO = require('libp2p-secio') const libp2p = require('libp2p') const defaultsDeep = require('@nodeutils/defaults-deep') -const p2pconfig = require('./p2pconfig.js') +const p2pconfig = require('./p2pconfig.mjs').default const bootstrapers = [ // TODO: 2020-02-10: check whether this list needs updating // and ideally make this a configurable option; AA diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index f700527..aa41042 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -53,56 +53,56 @@ the libp2p). */ - - +// IMPORTS + +import { PeerId } from '@libp2p/interface-peer-id'; +import yargs from 'yargs'; +import { tcp } from '@libp2p/tcp'; +import { webSockets } from '@libp2p/websockets'; +import { mplex } from '@libp2p/mplex'; +import { yamux } from '@chainsafe/libp2p-yamux'; +import { noise } from '@chainsafe/libp2p-noise'; +import defaultsDeep from '@nodeutils/defaults-deep'; +import { Libp2p, createLibp2p as create } from 'libp2p'; +import { createFromJSON, createEd25519PeerId } from '@libp2p/peer-id-factory'; +import { peerIdFromString } from '@libp2p/peer-id'; +import { bootstrap } from '@libp2p/bootstrap'; +import { mdns } from '@libp2p/mdns'; +import { pipe } from 'it-pipe'; +import * as lp from 'it-length-prefixed'; +import map from 'it-map'; +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'; +import { toString as uint8ArrayToString } from 'uint8arrays/to-string'; +import { pushable } from 'it-pushable'; +import p2pconfig from './p2pconfig.mjs'; +import { multiaddr } from '@multiformats/multiaddr'; +import { identifyService } from 'libp2p/identify'; +import { circuitRelayTransport } from 'libp2p/circuit-relay'; +import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'; +import { Logger } from 'winston'; +import {v4 as uuidv4} from 'uuid'; // LOGGING AND DEBUGGING -/*import yargs from 'yargs' -let logLevel = yargs.argv.debugp2p? 'debug':'info' -let __port = yargs.argv.port || 0 +let logLevel = yargs.argv.debugp2p? 'debug':'info'; +let __port = yargs.argv.port || 0; -const _PROTOCOL = "/troupe/1.0.0" - -let logger; +let logger: Logger; (async() => { - let { mkLogger } = await import ('../logger.mjs'); - logger = mkLogger ('p2p', logLevel) + let { mkLogger } = await import ('../logger.mjs'); + logger = mkLogger ('p2p', logLevel); })() -// const logger = require('../logger.js').mkLogger('p2p',logLevel); - - - -const info = x => logger.info(x) -const debug = x => logger.debug(x) -const error = x => logger.error(x);*/ - - -/* -// -// const pull = require('pull-stream') -const pipe = require('it-pipe') -const pushable = require ('./Pushable.js') -import { map } from 'streaming-iterables' - -const PeerId = require("peer-id") -const PeerInfo = require("peer-info") -const Libp2p = require("./libp2p-bundle") -const multiaddr = require('multiaddr') -const AggregateError = require('aggregate-error'); -const p2pconfig = require('./p2pconfig.js') - -*/ - - - - -// const Pushable = require('pull-pushable') - -/*import {v4 as uuidv4} from 'uuid' +const info = x => logger.info(x); +const debug = x => logger.debug(x); +const error = x => logger.error(x); +// CONSTANTS +const _PROTOCOL = "/troupe/1.0.0"; +const _RELAY_PROTOCOL = "/trouperelay/keepalive"; +const _HEALTHCHECKPERIOD = 5000; // 2020-02-10; AA; this should be an option +const _KEEPALIVE = 5000; const MessageType = { SPAWN: 0, SPAWNOK: 1, @@ -110,625 +110,90 @@ const MessageType = { TEST: 3, WHEREIS: 4, WHEREISOK: 5 -}*/ - -/* - -async function obtainPeerId(nodeId) { - let id = null; - if (nodeId) { - try { - id = await PeerId.createFromJSON(nodeId); - debug(`Loaded id from file: ${id.toB58String()}`); - } catch (err ) { - logger.error("error creating peer id from json"); - throw err - } - } else { - try { - debug ("Creating new pair id...") - id = await PeerId.create(); - debug("Created new pair id"); - } catch (err) { - logger.error("error creating new peer id"); - throw err; - } - } - let _peerInfo = new PeerInfo(id) - _peerInfo.multiaddrs.add(`/ip4/0.0.0.0/tcp/${__port}`); - return _peerInfo; -} - - -export interface IHash { - [details: string] : any; -} - - - -function TroupeP2P (_rt, _peerInfo) { - // GLOBALS - - - /* let _node = null; // the current node; initalized once upon start - - let _nodeTable:IHash = {}; // a table of the form [PeerId ↦ Connection] - // This table is mutable: we populate it upon - // discover of a node (either via dial or - // handle), and remove entries upon - // disconnects. - - - let _spawnNonces = {}; // a table of the form [Nonce ↦ Stream]. - // This table is mutable: we populate it upon - // issing a SPAWN to a remote node, and remove - // entries from it upon receiving a successful - // SPAWNOK mesasge that matches the nonce. - - let _whereisNonces = {}; - - let _unacknowledged:any = {} - - function addUnacknowledged (id, uuid, f) { - if (!_unacknowledged[id]){ - _unacknowledged[id] = [] - } - _unacknowledged[id][uuid] = f - } - - function removeUnacknowledged (id, uuid) { - delete _unacknowledged[id][uuid]; - } - - - function reissueUnacknowledged (id:string) { - for (let uuid in _unacknowledged[id] ) { - setImmediate(_unacknowledged[id][uuid]) - } - } - - function setupConnection (peerId, stream) { - let id:string = peerId.toB58String() - debug(`setupConnection with ${id}`); - _node.connectionManager.setPeerValue (peerId, 1); - const p = pushable () - _nodeTable[id] = p; - - pipe (p, map (JSON.stringify), lp.encode(), stream, lp.decode(), map(JSON.parse), - async (source) => { - try { - for await (const x of source) { - inputHandler (id, x, peerId) - } - } catch (err) { - debug (`try catch of the source`) - processExpectedNetworkErrors(err, "setupConnection/pipe"); - } - - debug(`deleting entry for ${id}`); - try { - await _node.hangUp (peerId); // hanging up; will it cause an exception?? - } catch (err) { - - } - delete _nodeTable[id]; - reissueUnacknowledged (id) - } - ) - } - - - - - async function push_wrap (id:any, data:any) { - - while (true) { - try { - debug (`push_wrap`) - - if (!_nodeTable[id]) { - debug (`no stream cached for ${id}; redialing}`) - await dial (id); - } else { - debug (`cached stream is available; we reuse it`) - } - - let p = _nodeTable[id]; - - debug (`push_wrap; stream obtained`) - await p.push (data); - debug (`push_wrap; data pushed into the stream`) - break - } catch (err) { - // the stream we have used is - // no good for whatever reason; - // most likely there are networking - // issues. we report the errors - // and redial - debug (`push wrap error`) - processExpectedNetworkErrors(err, "push_wrap"); - } - } - } - - this.spawnp2p = async (id, data) => { - const spawnNonce = uuidv4(); - return new Promise ((resolve, reject) => { - _spawnNonces[spawnNonce] = (err, data) => { - if (err) { reject (err) } else { resolve (data)} - }; - push_wrap(id, { - messageType: MessageType.SPAWN, - spawnNonce: spawnNonce, - message: data - }) - }); - } - - - this.whereisp2p = async (id, str) => { - - let whereisNonce = uuidv4() - - function f () { - push_wrap(id, { - messageType: MessageType.WHEREIS, - whereisNonce : whereisNonce, - message : str - }); - } - addUnacknowledged(id, whereisNonce,f); - - return new Promise ( (resolve, reject) => { - _whereisNonces[whereisNonce] = (err, data) => { - if (err) { reject (err) } else { - removeUnacknowledged (id,whereisNonce) - resolve (data) - } - } - debug ("pushing whereis message") - f (); - }) - } - - this.sendp2p = async (id, procId, obj) => { - // let p = await getNodePushStream(id); - push_wrap(id, { - messageType: MessageType.SEND, - pid: procId, - message: obj - }); - } - - - let __networkPending = []; - - function tryPending() { - if (__networkPending.length > 0 ) { - let n = __networkPending.length; - debug (`####### Connect trigger: try Pending. There are ${n} pending commands`); - for ( let i = 0; i < n; i++) { - // debug (`discovery trigger ${key}`) - let t = __networkPending.shift (); - t () ; - } - } - } - - function addPending (t) { - __networkPending.push (t); - } - - - - async function getPeerInfo(id:string) { - const peerId = PeerId.createFromB58String(id); - return new Promise ((resolve, reject) => { - let n_attempts = 0; - async function try_find_peer () { - if (_node.peerStore.has(peerId)) { - debug ("peer info is in the store") - resolve (_node.peerStore.get(peerId)) - } else { - try { - debug (`calling peerRouting.findPeer ${peerId}`) - const peerInfo = await _node.peerRouting.findPeer (peerId, {timeout:1000}); - debug ("findPeer returned") - resolve (peerInfo); - } catch (err) { - debug (`try_find_peer exception`) - if (nPeers() > 0 ) { - n_attempts ++ ; - } - - if (err instanceof AggregateError) { - for (let e of err) { - debug (`Find peer error with code: ${e}, ${e.code}`) - } - } else { - debug (`Find peer error: ${err.toString()}`) - throw err; - } - - if (n_attempts > 5) { - debug (`Resolving to empty peer info`) - resolve (new PeerInfo(peerId)) - // reject (err); - } else { - debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) - // addPending (try_find_peer); - setTimeout (try_find_peer, 500) - } - } - } - } - try_find_peer (); - }); - } - - let _relay_id = null; - - async function getPeerInfoWithRelay(id:any) { - let known_nodes = p2pconfig.known_nodes; - for (let ni of known_nodes) { - if (ni.nodeid == id) { - // found a known node! - let pi = new PeerInfo (PeerId.createFromB58String(id)); - pi.multiaddrs.add (multiaddr(`${ni.ip}`)) - debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`) - return pi - } - } - debug ("the node is not known; using relay information") - - let pi:any = await getPeerInfo (id) - if (_relay_id) { - pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) - } - - // for (let i = 0; i < p2pconfig.relays.length; i++ ) { - // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) - // } - return pi - } - - function dial (id) { - let i = 0; - let timeout = 2000; - return new Promise((resolve, reject) =>{ - async function iterate() { - try { - const peerInfo = await getPeerInfoWithRelay(id); - debug ("find peer succeeded"); - debug (`dialing will use the following addresses:`) - peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); - debug (">> -- end of address list -- << ") - debug (`trying to dial, attempt number ${i}`) - const { stream } = await _node.dialProtocol(peerInfo, _PROTOCOL) - debug ("dial successful") - setupConnection (peerInfo.id, stream); - resolve ( stream ); - } catch ( err ) { - processExpectedNetworkErrors (err, "dial"); - // if the error is suppressed we move on to trying 10 times - // with exponential backoff - // 2020-02-10; AA: TODO: this code has a hardcoded constant - if (i <= 10) { - debug (`dial failed, we retry in ${timeout} seconds`) - setTimeout (iterate, timeout); - i ++ ; - timeout *= 2 - } else { - debug (`we are giving up on dialing`) - reject (err); - } - } - } - iterate () - }) - } - - - - - - - /* - async function getNodePushStream (id:string) { - if (!_nodeTable[id]) { - debug (`no stream cached for ${id}; redialing}`) - await dial (id); - } - - return _nodeTable[id]; - } - */ - -/* - async function inputHandler(id, input, fromNodeId_) { - let fromNodeId = fromNodeId_.toB58String() - debug ("-- input handler") - switch (input.messageType) { - case (MessageType.SPAWN): - if (_rt.remoteSpawnOK()) { - debug ("RECEIVED SPAWN") - let x = await _rt.spawnFromRemote (input.message, fromNodeId) - - push_wrap(id, { - messageType: MessageType.SPAWNOK, - spawnNonce: input.spawnNonce, - message: x - }); - break; - } // drop the message otherwise - - case (MessageType.SPAWNOK): - debug ("SPAWN OK") - let _cb = _spawnNonces[input.spawnNonce]; - if (_cb) { - delete _spawnNonces[input.spawnNonce]; // cleanup - _cb(null, input.message); // null means no errors - } else { - // something is fishy; - debug("something is fishy; no matching callback for the nonce"); - } - break; - - case (MessageType.SEND): - debug (`SEND ${fromNodeId_.toB58String()}`); - _rt.receiveFromRemote ( - input.pid, - input.message, - fromNodeId - ) - break; - - case (MessageType.WHEREIS): - debug ("p2p whereis incoming request") - let y = await _rt.whereisFromRemote (input.message) - push_wrap(id, { - messageType: MessageType.WHEREISOK, - whereisNonce : input.whereisNonce, - message : y - }); - debug ("p2p whereis replied") - break; - - case (MessageType.WHEREISOK): - let _cbw = _whereisNonces[input.whereisNonce]; - if (_cbw) { - delete _whereisNonces [input.whereisNonce]; - _cbw (null, input.message); - } else { - debug ("cannot find whereis callback") - } - break; - - case (MessageType.TEST): - debug("TEST input"); - break; - - default: - debug (`received data ${input.toString('utf8').replace('\n', '')}`); - break; - } - } +}; +// SET-UP +let _node : Libp2p = null; +let _rt = null; - let _KEEPALIVE = 5000 - let _keepAliveCounter = 0; - let _relayTable:IHash = {} - - async function dialRelay (relay_addr) { - debug (`dialing relay ${relay_addr}`) - const conn = await _node.dial(relay_addr); - const {stream} = await _node.dialProtocol (relay_addr, "/trouperelay/keepalive") - const peerId = conn.remotePeer - _relay_id = peerId.toB58String() - debug (`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`) - const p = pushable() - - pipe (stream.source, - async (source: any) => { - let ss = "" - for await (const msg of source ) { - debug (`~~ relay says:${msg.toString().trim()}`) - } - }) - pipe (p, stream.sink); - let id = relay_addr.split('/').pop(); - _relayTable[id] = p ; - return p; - } - - async function keepAliveRelay (relay_addr:string) { - let id = relay_addr.split('/').pop(); - debug (`relay id is ${id}`) - let timeout = _KEEPALIVE; - async function f () { - try { - let p = _relayTable[id] ? _relayTable[id] : await dialRelay (relay_addr) - p.push (`keep alive request ${_keepAliveCounter++}\n`) - timeout = _KEEPALIVE - } catch (err ) { - timeout = timeout < 600e3 ? timeout * 2 : timeout // exponential backoff with 10 min limit - processExpectedNetworkErrors(err, "relay") - debug (`~~ error reaching the relay server; we will retry again in ${timeout/1000} seconds`) - } - setTimeout(f,timeout) - } - f () +let bootstrappers = [ + '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', + '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', +]; +let bootstrappers2 = p2pconfig.known_nodes.map((obj) => `${obj.ip}/${obj.nodeid}`); //AB: bootstrap known_nodes from config?? Make findNode easier + +async function startp2p(nodeId, rt: any): Promise { + let id : PeerId = await obtainPeerId(nodeId); + + try { + let nodeListener: Libp2p = await createLibp2p({ + peerId: id, + addresses: { + listen: [`/ip4/0.0.0.0/tcp/${__port}`] + }, + connectionManager : { + maxConnections: Infinity, + minConnections: 0 //What are good numbers here? } - - - - - function onPeerDiscovery (peer) { - debug(`discovered: ${peer.id.toB58String()}`) - } - - function nPeers( ) { - return _node.metrics.peers.length - } - - this.startNode = async () => { - debug(`Starting p2p node ${_peerInfo.id.toB58String()}`) - _node = new Libp2p ( - { peerInfo: _peerInfo} - ); - debug("Node created") - - _node.on('peer:discovery', onPeerDiscovery ); - - _node.on('error', (err) => { - error (`Error in p2p: ${err}`); - }) - - _node.on ('peer:connect', (peerInfo)=>{ - tryPending (); - let idStr = peerInfo.id.toB58String(); - debug (`++ connect: ${idStr} ${nPeers()}` ); - }) - - _node.on('peer:disconnect', (peerInfo) => { - let id = peerInfo.id.toB58String(); - debug (`-- disconnect: ${id}`) - if (_nodeTable[id]) { - debug (`deleting node table entry for ${id}`) - delete _nodeTable[id] - } - if (_relayTable[id]) { - debug (`deleting relay table entry`) - delete _relayTable[id] - } - }) - - await _node.handle(_PROTOCOL, async ({ connection, stream }) => { - setupConnection (connection.remotePeer, stream) - } - ) - - await _node.start (); - debug("p2p node started") - for (let relay_addr of p2pconfig.relays ) { - keepAliveRelay(relay_addr); - } - - /* - function showNPeers () { - if (logLevel == 'debug') { - debug(`--------- n peers: ${nPeers()}`); - setTimeout(showNPeers, 5000); - } - } - showNPeers(); - */ - /* return; - } - - - this.stop = async () => { - debug ("node stopping...") - await _node.stop(); - debug ("node stopped") - }*/ -/*} - - -const _HEALTHCHECKPERIOD = 5000 // 2020-02-10; AA; this should be an option - -function setupBlockingHealthChecker (period) { - let _lastHealth:number = Date.now() - let _healthCounter = 0; - let health_threshold = Math.max (period * 1.25 , period + 50) - // AA: 2020-02-10; - // The event queue always has a fair bit of latency, so we adjust for - // the minimal expected latency here; the constant of 50 is an - // empirically derived value, but needs to be critically reevaluated - // as the system evolves - - function f() { - let now = Date.now() - // debug (`Health checker running ${now - _lastHealth}, ${new Date()}`) - if (now - _lastHealth > health_threshold) { - debug (`Potential blocking issue: ${_healthCounter} ${now - _lastHealth}`) - } - _lastHealth = now; - setTimeout(f, period); - } - f () -} + }); + + _node = nodeListener; + _rt = rt; -*/ -// LOGGING AND DEBUGGING + } catch (err) { + error(`Something wrong while creating Libp2p node: ${err}`); + throw err; + } + + await _node.handle(_PROTOCOL, async ({ connection, stream }) => { + debug(`Handling protocol dial from id: ${connection.remotePeer}`); + setupConnection(connection.remotePeer, stream); + }); -import yargs from 'yargs' -let logLevel = yargs.argv.debugp2p? 'debug':'info' -let __port = yargs.argv.port || 0 + _node.addEventListener('peer:discovery', async (evt) => { + const peerInfo = evt.detail; + debug(`Discovered: ${peerInfo.id.toString()}`); + }); -const _PROTOCOL = "/troupe/1.0.0" + _node.addEventListener('peer:connect', (evt) => { + const peerId = evt.detail; + debug(`Connection established to: ${peerId.toString()}`); + }); -let logger; -(async() => { - let { mkLogger } = await import ('../logger.mjs'); - logger = mkLogger ('p2p', logLevel) -})() + _node.addEventListener('peer:disconnect', (evt) => { + let id = evt.detail; + debug (`-- disconnect: ${id}`); + if (_relayTable[id.toString()]) { + debug (`deleting relay table entry`); + delete _relayTable[id.toString()]; + } + }); + + _node.addEventListener('self:peer:update', (_) => { + debug(`Advertising with following addresses:`); + _node.getMultiaddrs().forEach(m => debug(m.toString())); + }) -// const logger = require('../logger.js').mkLogger('p2p',logLevel); + debug("p2p node started"); + debug(`id is ${id.toString()}`); -const info = x => logger.info(x) -const debug = x => logger.debug(x) -const error = x => logger.error(x); + setupBlockingHealthChecker(_HEALTHCHECKPERIOD); -import {v4 as uuidv4} from 'uuid' + /*for (let relay_addr of p2pconfig.relays ) { //AB: update relay addresses in p2pconfig + keepAliveRelay(relay_addr); + }*/ //AB: update relay addresses in p2pconfig + keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); -const MessageType = { - SPAWN: 0, - SPAWNOK: 1, - SEND: 2, - TEST: 3, - WHEREIS: 4, - WHEREISOK: 5 + return id; } -import { PeerId } from '@libp2p/interface-peer-id' - -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' -import defaultsDeep from '@nodeutils/defaults-deep' -import { Libp2p, createLibp2p as create } from 'libp2p' -import { createFromJSON, createEd25519PeerId } from '@libp2p/peer-id-factory' -import { peerIdFromString } from '@libp2p/peer-id' -import { bootstrap } from '@libp2p/bootstrap' -import { mdns } from '@libp2p/mdns' -import { pipe } from 'it-pipe' -import * as lp from 'it-length-prefixed' -import map from 'it-map' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { pushable } from 'it-pushable' -import p2pconfig from './p2pconfig.js'; //AB: ecmascript? -import { multiaddr } from '@multiformats/multiaddr' -import { identifyService } from 'libp2p/identify' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags' - -let bootstrappers = [ //AB: bootstrap known_nodes from config?? Make findNode easier - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', - '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', -] - - -async function createLibp2p (_options) { +async function createLibp2p(_options) { const defaults = { transports: [ tcp(), @@ -748,7 +213,7 @@ async function createLibp2p (_options) { peerDiscovery: [ /*bootstrap({ list: bootstrappers - }),*/ + }),*/ //AB: should we use bootstrappers? /*mdns({ interval: 20e3 })*/ @@ -759,218 +224,189 @@ async function createLibp2p (_options) { /*dht: kadDHT({ kBucketSize: 20, clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) - }),*/ - } + }),*/ //AB: use this or not? + }; - return create(defaultsDeep(_options, defaults)) + return create(defaultsDeep(_options, defaults)); } -async function obtainPeerId(nodeId) : Promise { +async function obtainPeerId(nodeId): Promise { let id : PeerId = null; - if (nodeId) { + if(nodeId) { try { id = await createFromJSON(nodeId); debug(`Loaded id from file: ${id.toString()}`); } catch (err) { - logger.error("error creating peer id from json"); - throw err + error("Error creating peer id from json"); + throw err; } } else { try { - debug ("Creating new pair id...") + debug("Creating new peer id..."); id = await createEd25519PeerId(); - debug("Created new pair id"); + debug("Created new peer id"); } catch (err) { - logger.error("error creating new peer id"); + error("Error creating new peer id"); throw err; } } - /*let _peerInfo = new PeerInfo(id) - _peerInfo.multiaddrs.add(`/ip4/0.0.0.0/tcp/${__port}`); //AB: do this??? already in adresses, possibly - return _peerInfo;*/ + return id; } -const _HEALTHCHECKPERIOD = 5000 // 2020-02-10; AA; this should be an option - -function setupBlockingHealthChecker (period) { - let _lastHealth:number = Date.now() - let _healthCounter = 0; - let health_threshold = Math.max (period * 1.25 , period + 50) - // AA: 2020-02-10; - // The event queue always has a fair bit of latency, so we adjust for - // the minimal expected latency here; the constant of 50 is an - // empirically derived value, but needs to be critically reevaluated - // as the system evolves +// DIAL - function f() { - let now = Date.now() - // debug (`Health checker running ${now - _lastHealth}, ${new Date()}`) - if (now - _lastHealth > health_threshold) { - debug (`Potential blocking issue: ${_healthCounter} ${now - _lastHealth}`) - } - _lastHealth = now; - setTimeout(f, period); - } - f () -} +function dial(id) { + let i = 0; + let timeout = 2000; + return new Promise((resolve, reject) => { + async function iterate() { + try { + let peerId : PeerId = await getPeerInfoWithRelay(id); -let _node : Libp2p = null; -let _rt = null; + debug (`trying to dial ${peerId}, attempt number ${i}`); + const stream = await _node.dialProtocol(peerId, _PROTOCOL); + debug ("dial successful"); -async function startp2p(nodeId, rt): Promise { - /*// kick off the network initialization by loading the peerid - let peerInfo = await obtainPeerId(nodeId); - debug ("Peer info created/loaded") - _troupeP2P = new TroupeP2P( rt, peerInfo ); - setupBlockingHealthChecker (_HEALTHCHECKPERIOD) - await _troupeP2P.startNode (); - return peerInfo.id.toB58String() - // if (rt) { - // rt.networkReady(peerInfo.id.toB58String()); - // }*/ + setupConnection (peerId, stream); - let id : PeerId = await obtainPeerId(nodeId); + resolve(stream); + } catch (err) { + processExpectedNetworkErrors (err, "dial"); - try { - let nodeListener : Libp2p = await createLibp2p({ - peerId: id, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - connectionManager : { - maxConnections: Infinity, - minConnections: 0 - } - }) - - _node = nodeListener - _rt = rt - } catch (err) { - debug(`Something wrong while creating Libp2p node: ${err}`) - throw err + // if the error is suppressed we move on to trying 10 times with exponential backoff + // 2020-02-10; AA: TODO: this code has a hardcoded constant + if(i <= 10) { + debug (`dial failed, we retry in ${timeout} seconds`); + error(err); + setTimeout(iterate, timeout); + i++; + timeout *= 2; + } else { + debug (`we are giving up on dialing`); + error(err); + reject(err); + } + } } - - setupBlockingHealthChecker(_HEALTHCHECKPERIOD); - - await _node.handle(_PROTOCOL, async ({ connection, stream }) => { - debug(`Handling protocol, id: ${connection.remotePeer}`) - setupConnection(connection.remotePeer, stream) - }) - - _node.addEventListener('peer:discovery', async (evt) => { - const peerInfo = evt.detail - debug(`Discovered: ${peerInfo.id.toString()}`) // add to PeerStore??? - }) - - _node.addEventListener('peer:connect', (evt) => { - const peerId = evt.detail - debug(`Connection established to: ${peerId.toString()}`) - }) - - _node.addEventListener('peer:disconnect', (evt) => { - let id = evt.detail - debug (`-- disconnect: ${id}`) - if (_relayTable[id.toString()]) { - debug (`deleting relay table entry`) - delete _relayTable[id.toString()] - } - }) - - _node.addEventListener('self:peer:update', (evt) => { - // Updated self multiaddrs? - debug(`Advertising with following addresses:`) - _node.getMultiaddrs().forEach((ma) => debug(ma.toString())) - }) - - debug("p2p node started") - - /*for (let relay_addr of p2pconfig.relays ) { - keepAliveRelay(relay_addr); - }*/ - keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf") - - debug(`id is ${id.toString()}`) - return id + iterate(); + }); } -async function sendp2p(id : PeerId, procId, obj) { - debug (`sendp2p`) +async function getPeerInfoWithRelay(id:any) { + let known_nodes = p2pconfig.known_nodes; + for(let ni of known_nodes) { + if(ni.nodeid == id) { + // found a known node! + let pi = peerIdFromString(id); + await _node.peerStore.patch(pi, { + multiaddrs: [ + multiaddr(`${ni.ip}`) + ] + }); + debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`); + return pi; + } + } - let data = { - messageType: MessageType.SEND, - pid: procId, - message: obj + debug("the node is not known; using relay information"); + let pi = await getPeerInfo(id); + + if(_relay_id) { //AB: use all relays as below! + await _node.peerStore.patch(pi, { + multiaddrs: [ + multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`) + ] + }); } - push_wrap(id, data) + // for (let i = 0; i < p2pconfig.relays.length; i++ ) { + // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) + // } + return pi; } -async function push_wrap(id: any, data: any) { - debug (`push_wrap`) - let connections = _node.getConnections(id) - let needsToDial = true; - let p = null - if(connections.length >= 1) { - let connection = connections[0] //AB: check all connections - let streams = connection.streams - if(streams.length >= 1) { - let stream = streams[0] - p = (stream as any).p; - needsToDial = p == undefined; - } else { - debug("streams array empty") - throw new Error //AB: What to do then? Can this happen? +async function getPeerInfo(id:string) : Promise{ + const peerId = peerIdFromString(id); + + return new Promise ((resolve, reject) => { + let n_attempts = 0; + async function try_find_peer() { + if(await _node.peerStore.has(peerId)) { + debug("peer info is in the store"); + try { + let foundPeer = await _node.peerStore.get(peerId); + resolve(foundPeer.id); + } catch (err) { + error(`Error in getPeerInfo / peerStore.get: ${err}`); + throw err; + } + } else { + try { + debug(`calling peerRouting.findPeer ${peerId}`); + const peerInfo = await _node.peerRouting.findPeer(peerId, {signal : AbortSignal.timeout(1000)}); + debug ("findPeer returned"); + await _node.peerStore.patch(peerInfo.id, { + multiaddrs: + peerInfo.multiaddrs + }); //AB: necessary?? + debug("added multiaddr to store"); + resolve (peerInfo.id); + } catch (err) { + debug(`try_find_peer exception`); + + if(nPeers() > 0) { //AB: why only when nPeers > 0? + n_attempts++; + } + + if(err instanceof AggregateError) { + for(let e of err.errors) { + debug(`Find peer error with code: ${e}, ${e.code}`); + } + } else { + debug(`Find peer error: ${err.toString()}`); + } + + if(n_attempts > 5) { + debug(`Resolving to empty peer info`); + resolve(peerId); + } else { + debug(`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`); + setTimeout(try_find_peer, 500); + } + } + } } - } - if(needsToDial) { - debug("needs to dial") - let stream = await dial(id.toString()) - debug("dialed to obtain stream") - p = (stream as any).p; - } - - debug (`push_wrap; stream obtained`) + try_find_peer(); + }); +} - while (true) { - try { - debug (`push_wrap; pushing`) - await p.push (data); - debug (`push_wrap; data pushed into the stream`) - break - } catch (err) { - // the stream we have used is - // no good for whatever reason; - // most likely there are networking - // issues. we report the errors - // and redial - debug (`push wrap error`) - processExpectedNetworkErrors(err, "push_wrap"); - } - } +function nPeers() { + return _node.getPeers().length; } -function setupConnection(peerId : PeerId, stream) { - let id:string = peerId.toString() +// CONNECTION SET-UP + +function setupConnection(peerId : PeerId, stream): void { + let id: string = peerId.toString(); debug(`setupConnection with ${id}`); - const p = pushable({ objectMode : true }) + const p = pushable({ objectMode : true }); pipe (p, (source) => map(source, (json) => JSON.stringify(json)), - (source) => map(source, (string) => uint8ArrayFromString(string, 'utf8')), + (source) => map(source, (string : string) => uint8ArrayFromString(string, 'utf8')), (source) => lp.encode(source), stream, (source) => lp.decode(source), (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), - (source) => map(source, (string) => JSON.parse(string)), + (source) => map(source, (string : string) => JSON.parse(string)), async (source) => { try { for await (const x of source) { - //console.log('Input: ', x) - inputHandler (id, x, peerId) //AB: Something is wonky with the parameters! + inputHandler(id, x, peerId); //AB: Something is wonky with the parameters! } } catch (err) { - debug (`try catch of the source`) + error(`error in pipe`); processExpectedNetworkErrors(err, "setupConnection/pipe"); } @@ -978,117 +414,148 @@ function setupConnection(peerId : PeerId, stream) { try { await _node.hangUp(peerId); } catch (err) { - throw err; + error(`error while hanging up pipe`); + processExpectedNetworkErrors(err, "setupConnection/hang-up"); } - reissueUnacknowledged(id) + reissueUnacknowledged(id); } - ) + ); + stream.p = p; // Storing a reference to the pushable on the stream // We rely on the p2p library to keep track of streams debug(`Connection set up with ${id}`); } -function nPeers( ) { - return _node.getPeers().length -} - -async function getPeerInfo(id:string) : Promise{ - const peerId = peerIdFromString(id); - return new Promise ((resolve, reject) => { - let n_attempts = 0; - async function try_find_peer () { - if (await _node.peerStore.has(peerId)) { - debug ("peer info is in the store") - try { - let foundPeer = await _node.peerStore.get(peerId) - resolve (foundPeer.id) - } catch (err) { - debug(`Error in getPeerInfo: ${err}`) - throw err - } - } else { - try { - debug (`calling peerRouting.findPeer ${peerId}`) - const peerInfo = await _node.peerRouting.findPeer (peerId, {signal : AbortSignal.timeout(1000)}); - debug ("findPeer returned") - await _node.peerStore.patch(peerInfo.id, { - multiaddrs: - peerInfo.multiaddrs - }) //AB: necessary?? - debug("added multiaddr to store") - resolve (peerInfo.id); - } catch (err) { - debug (`try_find_peer exception`) - if (nPeers() > 0 ) { - n_attempts ++ ; - } - - if (err instanceof AggregateError) { - for (let e of err.errors) { - debug (`Find peer error with code: ${e}, ${e.code}`) - } - } else { - debug (`Find peer error: ${err.toString()}`) - //throw err; - } - - if (n_attempts > 5) { - debug (`Resolving to empty peer info`) - resolve (peerId) - // reject (err); - } else { - debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) - // addPending (try_find_peer); - setTimeout (try_find_peer, 500) - } - } - } +async function inputHandler(id, input, fromNodeId_) { //AB: fix parameters!!! + let fromNodeId = fromNodeId_.toString(); + debug ("-- input handler"); + switch (input.messageType) { + case (MessageType.SPAWN): + if(_rt.remoteSpawnOK()) { + debug("RECEIVED SPAWN"); + + let x = await _rt.spawnFromRemote(input.message, fromNodeId); + push_wrap(id, { + messageType: MessageType.SPAWNOK, + spawnNonce: input.spawnNonce, + message: x + }); + } // drop the message otherwise + break; + + case (MessageType.SPAWNOK): + debug ("SPAWN OK"); + let _cb = _spawnNonces[input.spawnNonce]; + if(_cb) { + delete _spawnNonces[input.spawnNonce]; // cleanup + _cb(null, input.message); // null means no errors + } else { + error("cannot find spawn callback"); } - try_find_peer (); - }); + break; + + case (MessageType.SEND): + debug (`SEND from ${fromNodeId}`); + _rt.receiveFromRemote( + input.pid, + input.message, + fromNodeId + ); + break; + + case (MessageType.WHEREIS): + debug("p2p whereis incoming request"); + let y = await _rt.whereisFromRemote(input.message); + push_wrap(id, { + messageType: MessageType.WHEREISOK, + whereisNonce : input.whereisNonce, + message : y + }); + debug("p2p whereis replied"); + break; + + case (MessageType.WHEREISOK): + let _cbw = _whereisNonces[input.whereisNonce]; + if(_cbw) { + delete _whereisNonces [input.whereisNonce]; // cleanup + _cbw (null, input.message); // null means no errors + } else { + error("cannot find whereis callback"); + } + break; + + case (MessageType.TEST): + debug("TEST input"); + debug(input); + break; + + default: + debug(`received data ${input.toString('utf8').replace('\n', '')}`); + break; + } } +// RELAY + export interface IHash { [details: string] : any; -} //AB: use in-built functionality instead +} let _relay_id = null; -let _KEEPALIVE = 5000 //AB: can tag peers with "Keep_alive" in the peerstore -let _keepAliveCounter = 0; -let _relayTable:IHash = {} +//AB: only one counter?? And only one id?? +let _keepAliveCounter = 0; //AB: can tag peers with "Keep_alive" in the peerstore (does it work?) +let _relayTable: IHash = {}; //AB: use in-built functionality instead? + +async function keepAliveRelay(relay_addr:string) { + let id = relay_addr.split('/').pop(); + debug(`relay id is ${id}`); + let timeout = _KEEPALIVE; + async function f() { + try { + let p = _relayTable[id] ? _relayTable[id] : await dialRelay(relay_addr); + p.push(`keep alive request ${_keepAliveCounter++}\n`); //AB: why do we do this??? + timeout = _KEEPALIVE; + } catch (err) { + timeout = timeout < 600e3 ? timeout * 2 : timeout // exponential backoff with 10 min limit + processExpectedNetworkErrors(err, "relay"); + error(`~~ error reaching the relay server; we will retry again in ${timeout/1000} seconds`); + } + setTimeout(f, timeout); + } + f(); +} -async function dialRelay (relay_addr) { - debug (`dialing relay ${relay_addr}`) +async function dialRelay(relay_addr) { + debug(`dialing relay ${relay_addr}`); let id = relay_addr.split('/').pop(); - const relayId = peerIdFromString(id) + const relayId = peerIdFromString(id); + await _node.peerStore.patch(relayId, { multiaddrs: [ multiaddr(`${relay_addr}`) - ] - }) - await _node.peerStore.merge(relayId, { + ], tags: { [KEEP_ALIVE]: {} } - }) - debug (`Added relay address`) - const conn = await _node.dial(relayId); - debug (`Got relay connection`) - const stream = await _node.dialProtocol (relayId, "/trouperelay/keepalive") - debug (`Got relay stream`) - const peerId = conn.remotePeer - _relay_id = peerId.toString() - debug (`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`) - const p = pushable({ objectMode : true }) + }); + + debug (`Added relay address`); + const conn = await _node.dial(relayId); //AB: necessary?? + debug (`Got relay connection`); + const stream = await _node.dialProtocol(relayId, _RELAY_PROTOCOL); + debug (`Got relay stream`); + const peerId = conn.remotePeer; + _relay_id = peerId.toString(); + debug(`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`); + const p = pushable({ objectMode : true }); pipe (stream.source, async (source: any) => { - let ss = "" - for await (const msg of source ) { - debug (`~~ relay says:${msg.toString().trim()}`) + for await (const msg of source) { + debug(`~~ relay says:${msg.toString().trim()}`); } - }) + }); pipe (p, (stream.sink as any)); @@ -1096,262 +563,161 @@ async function dialRelay (relay_addr) { return p; } -async function keepAliveRelay (relay_addr:string) { - let id = relay_addr.split('/').pop(); - debug (`relay id is ${id}`) - let timeout = _KEEPALIVE; - async function f () { - try { - let p = _relayTable[id] ? _relayTable[id] : await dialRelay (relay_addr) - p.push (`keep alive request ${_keepAliveCounter++}\n`) - timeout = _KEEPALIVE - } catch (err ) { - timeout = timeout < 600e3 ? timeout * 2 : timeout // exponential backoff with 10 min limit - processExpectedNetworkErrors(err, "relay") - debug (`~~ error reaching the relay server; we will retry again in ${timeout/1000} seconds`) - } - setTimeout(f,timeout) - } - f () - } +// SEND -async function getPeerInfoWithRelay(id:any) { - let known_nodes = p2pconfig.known_nodes; - for (let ni of known_nodes) { - if (ni.nodeid == id) { - // found a known node! - let pi = peerIdFromString(id); - await _node.peerStore.patch(pi, { - multiaddrs: [ - multiaddr(`${ni.ip}`) - ] - }) - //pi.multiaddrs.add (multiaddr(`${ni.ip}`)) - debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`) - return pi - } - } - debug ("the node is not known; using relay information") - - let pi = await getPeerInfo(id) - if (_relay_id) { //AB: use all relays as below! - //pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`)) - await _node.peerStore.patch(pi, { - multiaddrs: [ - multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`) - ] - }) - } +async function sendp2p(id : PeerId, procId, obj) { + debug(`sendp2p`); + + let data = { + messageType: MessageType.SEND, + pid: procId, + message: obj + }; - // for (let i = 0; i < p2pconfig.relays.length; i++ ) { - // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) - // } - return pi + push_wrap(id, data); } -function dial(id) { - let i = 0; - let timeout = 2000; - return new Promise((resolve, reject) =>{ - async function iterate() { - try { - /*const peerInfo = await getPeerInfoWithRelay(id); - debug ("find peer succeeded"); - debug (`dialing will use the following addresses:`) - peerInfo.multiaddrs.forEach( m => {debug (m.toString() ) }); - debug (">> -- end of address list -- << ")*/ - let peerId : PeerId = await getPeerInfoWithRelay(id) - debug (`trying to dial ${peerId}, attempt number ${i}`) - const stream = await _node.dialProtocol(peerId, _PROTOCOL) - debug ("dial successful") - setupConnection (peerId, stream); - resolve ( stream ); - } catch ( err ) { - processExpectedNetworkErrors (err, "dial"); +async function push_wrap(id: any, data: any) { + debug(`push_wrap`); + let connections = _node.getConnections(id); + let needsToDial = true; + let p = null; - // if the error is suppressed we move on to trying 10 times - // with exponential backoff - // 2020-02-10; AA: TODO: this code has a hardcoded constant - if (i <= 10) { - debug (`dial failed, we retry in ${timeout} seconds`) - debug(err) - setTimeout (iterate, timeout); - i++; - timeout *= 2; - } else { - debug (`we are giving up on dialing`) - reject (err); - } - } + if(connections.length >= 1) { + let connection = connections[0]; //AB: check all connections + let streams = connection.streams; + if(streams.length >= 1) { + let stream = streams[0]; + p = (stream as any).p; + needsToDial = p == undefined; + } else { + error("streams array empty"); + throw new Error //AB: What to do then? Can this happen? } - iterate () - }) -} + } + if(needsToDial) { + debug("needs to dial"); + let stream = await dial(id.toString()); + debug("dialed to obtain stream"); + p = (stream as any).p; + } + + debug (`push_wrap; stream obtained`); -function stdinToStream(stream) { - // Read utf-8 from stdin - process.stdin.setEncoding('utf8') - pipe( - // Read from stdin (the source) - process.stdin, - // Turn strings into buffers - (source) => map(source, (string) => uint8ArrayFromString(string)), - // Encode with length prefix (so receiving side knows how much data is coming) - (source) => lp.encode(source), - // Write to the stream (the sink) - stream.sink - ) + while (true) { + try { + debug(`push_wrap; pushing`); + await p.push(data); + debug(`push_wrap; data pushed into the stream`); + break; + } catch (err) { + // the stream we have used is + // no good for whatever reason; + // most likely there are networking + // issues. we report the errors + // and redial + error(`push wrap error`); + processExpectedNetworkErrors(err, "push_wrap"); + } + } } -function streamToConsole(stream) { - pipe( - // Read from the stream (the source) - stream.source, - // Decode length-prefixed data - (source) => lp.decode(source), - // Turn buffers into strings - (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), - // Sink function - async function (source) { - // For each chunk of data - for await (const msg of source) { - // Output the data as a utf8 string - console.log('> ' + msg.toString().replace('\n', '')) - } - } - ) -} +// WHEREIS / SPAWN -async function inputHandler(id, input, fromNodeId_) { - let fromNodeId = fromNodeId_.toString() - debug ("-- input handler") - switch (input.messageType) { - case (MessageType.SPAWN): - if (_rt.remoteSpawnOK()) { - debug ("RECEIVED SPAWN") - let x = await _rt.spawnFromRemote (input.message, fromNodeId) - - push_wrap(id, { - messageType: MessageType.SPAWNOK, - spawnNonce: input.spawnNonce, - message: x - }); - break; - } // drop the message otherwise - - case (MessageType.SPAWNOK): - debug ("SPAWN OK") - let _cb = _spawnNonces[input.spawnNonce]; - if (_cb) { - delete _spawnNonces[input.spawnNonce]; // cleanup - _cb(null, input.message); // null means no errors - } else { - // something is fishy; - debug("something is fishy; no matching callback for the nonce"); - } - break; - - case (MessageType.SEND): - debug (`SEND ${fromNodeId}`); - _rt.receiveFromRemote ( - input.pid, - input.message, - fromNodeId - ) - break; - - case (MessageType.WHEREIS): - debug ("p2p whereis incoming request") - let y = await _rt.whereisFromRemote (input.message) - push_wrap(id, { - messageType: MessageType.WHEREISOK, - whereisNonce : input.whereisNonce, - message : y - }); - debug ("p2p whereis replied") - break; - - case (MessageType.WHEREISOK): - let _cbw = _whereisNonces[input.whereisNonce]; - if (_cbw) { - delete _whereisNonces [input.whereisNonce]; - _cbw (null, input.message); - } else { - debug ("cannot find whereis callback") - } - break; - - case (MessageType.TEST): - debug("TEST input"); - debug(input) - break; - - default: - debug (`received data ${input.toString('utf8').replace('\n', '')}`); - break; - } -} +let _whereisNonces = {}; +let _unacknowledged:any = {}; async function whereisp2p(id, str) { - let whereisNonce = uuidv4() + let whereisNonce = uuidv4(); - function f () { + function f() { push_wrap(id, { messageType : MessageType.WHEREIS, whereisNonce : whereisNonce, message : str - }); + }); } addUnacknowledged(id, whereisNonce, f); - return new Promise ( (resolve, reject) => { + return new Promise((resolve, reject) => { _whereisNonces[whereisNonce] = (err, data) => { - if (err) { reject (err) } else { - removeUnacknowledged (id,whereisNonce) - resolve (data) + if(err) { + reject(err); + } else { + removeUnacknowledged(id, whereisNonce); + resolve(data); } } - debug ("pushing whereis message") - f (); - }) + debug("pushing whereis message"); + f(); + }); +} + +function addUnacknowledged(id, uuid, f) { + if(!_unacknowledged[id]) { + _unacknowledged[id] = []; + } + _unacknowledged[id][uuid] = f; +} + +function removeUnacknowledged(id, uuid) { + delete _unacknowledged[id][uuid]; +} + +function reissueUnacknowledged(id:string) { + for (let uuid in _unacknowledged[id]) { + setImmediate(_unacknowledged[id][uuid]); + } } -let _whereisNonces = {}; -let _unacknowledged:any = {}; let _spawnNonces = {}; async function spawnp2p(id, data) { const spawnNonce = uuidv4(); + return new Promise ((resolve, reject) => { - _spawnNonces[spawnNonce] = (err, data) => { - if (err) { reject (err) } else { resolve (data)} - }; - push_wrap(id, { - messageType: MessageType.SPAWN, - spawnNonce: spawnNonce, - message: data - }) + _spawnNonces[spawnNonce] = (err, data) => { + if(err) { + reject(err); + } else { + resolve(data); + } + }; + push_wrap(id, { + messageType: MessageType.SPAWN, + spawnNonce: spawnNonce, + message: data + }); }); } -function addUnacknowledged (id, uuid, f) { - if (!_unacknowledged[id]){ - _unacknowledged[id] = [] - } - _unacknowledged[id][uuid] = f -} +// HEALTH CHECK -function removeUnacknowledged (id, uuid) { - delete _unacknowledged[id][uuid]; -} +function setupBlockingHealthChecker(period) { + let _lastHealth:number = Date.now() + let _healthCounter = 0; + let health_threshold = Math.max (period * 1.25 , period + 50) + // AA: 2020-02-10; + // The event queue always has a fair bit of latency, so we adjust for + // the minimal expected latency here; the constant of 50 is an + // empirically derived value, but needs to be critically reevaluated + // as the system evolves -function reissueUnacknowledged (id:string) { - for (let uuid in _unacknowledged[id] ) { - setImmediate(_unacknowledged[id][uuid]) - } + function f() { + let now = Date.now() + // debug (`Health checker running ${now - _lastHealth}, ${new Date()}`) + if (now - _lastHealth > health_threshold) { + debug (`Potential blocking issue: ${_healthCounter} ${now - _lastHealth}`) + } + _lastHealth = now; + setTimeout(f, period); + } + f () } -function processExpectedNetworkErrors (err, source="source unknown") { +// ERROR HANDLING + +function processExpectedNetworkErrors(err, source="source unknown") { debug (`error source: ${source}`); if (err instanceof AggregateError) { for (const e of err.errors ) { @@ -1405,23 +771,25 @@ function processExpectedNetworkErrors (err, source="source unknown") { } } +// INTERFACE + export let p2p = { - startp2p: (arg1, arg2) => { - return startp2p(arg1, arg2) - }, - spawnp2p: (arg1, arg2) => { - return spawnp2p(arg1, arg2) - }, - sendp2p: (arg1, arg2, arg3) => { - return sendp2p(arg1, arg2, arg3) - }, - whereisp2p: (arg1, arg2) => { - return whereisp2p(arg1, arg2) - }, - stopp2p: async () => { - return await _node.stop() - }, - processExpectedNetworkErrors: (arg1, arg2) => { - processExpectedNetworkErrors(arg1, arg2) - }, + startp2p: (arg1, arg2) => { + return startp2p(arg1, arg2) + }, + spawnp2p: (arg1, arg2) => { + return spawnp2p(arg1, arg2) + }, + sendp2p: (arg1, arg2, arg3) => { + return sendp2p(arg1, arg2, arg3) + }, + whereisp2p: (arg1, arg2) => { + return whereisp2p(arg1, arg2) + }, + stopp2p: async () => { + return await _node.stop() + }, + processExpectedNetworkErrors: (arg1, arg2) => { + return processExpectedNetworkErrors(arg1, arg2) + }, } diff --git a/rt/src/p2p/p2pconfig.js b/rt/src/p2p/p2pconfig.mjs similarity index 92% rename from rt/src/p2p/p2pconfig.js rename to rt/src/p2p/p2pconfig.mjs index af1221e..fd93ee5 100644 --- a/rt/src/p2p/p2pconfig.js +++ b/rt/src/p2p/p2pconfig.mjs @@ -6,7 +6,7 @@ let logger; logger = mkLogger ('p2p-config','info'); })() -const fs = require('fs'); +import { existsSync, readFileSync } from 'fs'; let relays let default_relays = @@ -31,9 +31,9 @@ let known_nodes = [ ] -if (fs.existsSync(P2PCONFIG_FILE)) { +if (existsSync(P2PCONFIG_FILE)) { try { - let s = fs.readFileSync(P2PCONFIG_FILE) + let s = readFileSync(P2PCONFIG_FILE) let o = JSON.parse (s); console.log (o.relays) if (o.relays) { @@ -49,4 +49,4 @@ if (fs.existsSync(P2PCONFIG_FILE)) { relays = default_relays } -module.exports = { relays, known_nodes } +export default { relays, known_nodes } From e2fd681352dd24fb7e62a2b105f6e08f90286229 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Wed, 19 Jul 2023 11:19:22 +0200 Subject: [PATCH 15/22] Refactor inputHandler and push_wrap --- rt/src/p2p/p2p.mts | 103 ++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index aa41042..75b5515 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -53,6 +53,13 @@ the libp2p). */ +// AB: TODO: +// - relay pushables?? +// - connection / stream / needsToDial +// - comments +// - discuss w/ Aslan +// - types... :( + // IMPORTS import { PeerId } from '@libp2p/interface-peer-id'; @@ -139,7 +146,7 @@ async function startp2p(nodeId, rt: any): Promise { }, connectionManager : { maxConnections: Infinity, - minConnections: 0 //What are good numbers here? + minConnections: 0 //AB: What are good numbers here? } }); @@ -188,7 +195,7 @@ async function startp2p(nodeId, rt: any): Promise { /*for (let relay_addr of p2pconfig.relays ) { //AB: update relay addresses in p2pconfig keepAliveRelay(relay_addr); }*/ //AB: update relay addresses in p2pconfig - keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); + //keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); return id; } @@ -214,9 +221,9 @@ async function createLibp2p(_options) { /*bootstrap({ list: bootstrappers }),*/ //AB: should we use bootstrappers? - /*mdns({ + mdns({ interval: 20e3 - })*/ + }) ], services: { identify: identifyService() @@ -326,7 +333,7 @@ async function getPeerInfoWithRelay(id:any) { return pi; } -async function getPeerInfo(id:string) : Promise{ +async function getPeerInfo(id:string) : Promise { const peerId = peerIdFromString(id); return new Promise ((resolve, reject) => { @@ -346,11 +353,13 @@ async function getPeerInfo(id:string) : Promise{ debug(`calling peerRouting.findPeer ${peerId}`); const peerInfo = await _node.peerRouting.findPeer(peerId, {signal : AbortSignal.timeout(1000)}); debug ("findPeer returned"); + await _node.peerStore.patch(peerInfo.id, { multiaddrs: peerInfo.multiaddrs - }); //AB: necessary?? + }); debug("added multiaddr to store"); + resolve (peerInfo.id); } catch (err) { debug(`try_find_peer exception`); @@ -403,7 +412,7 @@ function setupConnection(peerId : PeerId, stream): void { async (source) => { try { for await (const x of source) { - inputHandler(id, x, peerId); //AB: Something is wonky with the parameters! + inputHandler(id, x); } } catch (err) { error(`error in pipe`); @@ -426,15 +435,14 @@ function setupConnection(peerId : PeerId, stream): void { debug(`Connection set up with ${id}`); } -async function inputHandler(id, input, fromNodeId_) { //AB: fix parameters!!! - let fromNodeId = fromNodeId_.toString(); +async function inputHandler(id, input) { debug ("-- input handler"); switch (input.messageType) { case (MessageType.SPAWN): if(_rt.remoteSpawnOK()) { debug("RECEIVED SPAWN"); - let x = await _rt.spawnFromRemote(input.message, fromNodeId); + let x = await _rt.spawnFromRemote(input.message, id); push_wrap(id, { messageType: MessageType.SPAWNOK, spawnNonce: input.spawnNonce, @@ -455,11 +463,11 @@ async function inputHandler(id, input, fromNodeId_) { //AB: fix parameters!!! break; case (MessageType.SEND): - debug (`SEND from ${fromNodeId}`); + debug (`SEND from ${id}`); _rt.receiveFromRemote( input.pid, input.message, - fromNodeId + id ); break; @@ -507,7 +515,7 @@ let _relay_id = null; let _keepAliveCounter = 0; //AB: can tag peers with "Keep_alive" in the peerstore (does it work?) let _relayTable: IHash = {}; //AB: use in-built functionality instead? -async function keepAliveRelay(relay_addr:string) { +async function keepAliveRelay(relay_addr: string) { let id = relay_addr.split('/').pop(); debug(`relay id is ${id}`); let timeout = _KEEPALIVE; @@ -540,11 +548,11 @@ async function dialRelay(relay_addr) { } }); - debug (`Added relay address`); + debug(`Added relay address`); const conn = await _node.dial(relayId); //AB: necessary?? - debug (`Got relay connection`); + debug(`Got relay connection`); const stream = await _node.dialProtocol(relayId, _RELAY_PROTOCOL); - debug (`Got relay stream`); + debug(`Got relay stream`); const peerId = conn.remotePeer; _relay_id = peerId.toString(); debug(`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`); @@ -578,47 +586,44 @@ async function sendp2p(id : PeerId, procId, obj) { } async function push_wrap(id: any, data: any) { - debug(`push_wrap`); - let connections = _node.getConnections(id); - let needsToDial = true; - let p = null; - - if(connections.length >= 1) { - let connection = connections[0]; //AB: check all connections - let streams = connection.streams; - if(streams.length >= 1) { - let stream = streams[0]; - p = (stream as any).p; - needsToDial = p == undefined; - } else { - error("streams array empty"); - throw new Error //AB: What to do then? Can this happen? + while (true) { + debug(`push_wrap`); + let connections = _node.getConnections(id); + let needsToDial = true; + let p = null; + + break_loop: + for(const connection of connections) { + let streams = connection.streams; + for(const stream of streams) { + p = (stream as any).p; + needsToDial = p == undefined; + + if(!needsToDial) { + break break_loop; + } + } } - } - if(needsToDial) { - debug("needs to dial"); - let stream = await dial(id.toString()); - debug("dialed to obtain stream"); - p = (stream as any).p; - } - - debug (`push_wrap; stream obtained`); - while (true) { try { - debug(`push_wrap; pushing`); + if(needsToDial) { + debug("needs to dial"); + let stream = await dial(id.toString()); + debug("dialed to obtain stream"); + p = (stream as any).p; + } + + debug (`push_wrap; stream obtained; pushing`); await p.push(data); debug(`push_wrap; data pushed into the stream`); break; } catch (err) { - // the stream we have used is - // no good for whatever reason; - // most likely there are networking - // issues. we report the errors - // and redial + // the stream we have used is no good for whatever reason; + // most likely there are networking issues. + // we report the errors and redial error(`push wrap error`); processExpectedNetworkErrors(err, "push_wrap"); - } + } } } @@ -763,7 +768,7 @@ function processExpectedNetworkErrors(err, source="source unknown") { default: error (`Unhandled error case with error code ${err.code}`) throw err; - } + } } else { error (`Unhandled general error case ${err}`) throw err; From 79377ec30dfa9e7bb7fdf020a73abb156cafb7a1 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Thu, 20 Jul 2023 12:09:48 +0200 Subject: [PATCH 16/22] Refactor and comment everything --- rt/src/p2p/p2p.mts | 665 ++++++++++++++++++++++++++++----------------- 1 file changed, 421 insertions(+), 244 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 75b5515..0376593 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -1,13 +1,18 @@ /* -The p2p runtime maintains a lookup table that maps each PeerId that we see to a -Publishable object. We populate this table upon the following events: +The p2p runtime uses a Libp2p node to keep track of peers and connections. +A Publishable object is added to each stream to be used for sending messages. + +A Publishable object is created in the following instances: 1. When we initate a connection to a node upon the first time, via node.dialProtocol because we are about to send a message (spawn or send) to that PeerId. -2. When we receive a connection from some other in the callback passed to the +2. If we try to send a message and all open streams do not have a Publishable + object that can be used. + +3. When we receive a connection from some other in the callback passed to the node.handle. In this case it is just some other node that wants to connect to us and we are going to "cache" the connection. @@ -24,11 +29,11 @@ Additionally, we pipe the connection to a drain sink that does the following: the publishable object from the lookup table. This should ensure that if we we want to communicate with that node later, we will dialing to that node. -The messages themselves can be one of the three forms: +The messages themselves can be one of the six forms: 1. SPAWN -- spawning on a remote node -2. SPAWNOK -- reply to the spawn (we did not have an analogue of this in express +2. SPAWNOK -- reply to the SPAWN (we did not have an analogue of this in express runtime because express was giving up the possibility of sending response to a given request, here we are doing it manually by maintaining a spawnNonce map). @@ -37,14 +42,9 @@ The messages themselves can be one of the three forms: 4. TEST -- for testing/development purposes -Note that libp2p already implements stream multiplexing and we could -have avoided maintaining these tables and use the built-in -multiplexing instead but +5. WHEREIS -- asking for the address of a certain peer id - (a) it appears to be slower than our custom-build mapping, and - - (b) keeping track of each connection should allow to implement - process linking. +6. WHEREISOK -- reply to the WHEREIS Note on the code below: the code below uses the libp2p framework, and is partially grown out of the Chat example in that framework (to make sense of the @@ -54,9 +54,6 @@ the libp2p). */ // AB: TODO: -// - relay pushables?? -// - connection / stream / needsToDial -// - comments // - discuss w/ Aslan // - types... :( @@ -106,23 +103,23 @@ const error = x => logger.error(x); // CONSTANTS -const _PROTOCOL = "/troupe/1.0.0"; -const _RELAY_PROTOCOL = "/trouperelay/keepalive"; -const _HEALTHCHECKPERIOD = 5000; // 2020-02-10; AA; this should be an option -const _KEEPALIVE = 5000; +const _PROTOCOL = "/troupe/1.0.0"; // Protocol for peers to talk to each other +const _RELAY_PROTOCOL = "/trouperelay/keepalive"; // Protocol for peers to talk to relays +const _HEALTHCHECKPERIOD = 5000; // How often the health check happens 2020-02-10; AA; this should be an option +const _KEEPALIVE = 5000; // Time-out for keep-alive messages to relay const MessageType = { - SPAWN: 0, - SPAWNOK: 1, - SEND: 2, - TEST: 3, - WHEREIS: 4, - WHEREISOK: 5 + SPAWN: 0, + SPAWNOK: 1, + SEND: 2, + TEST: 3, + WHEREIS: 4, + WHEREISOK: 5 }; // SET-UP -let _node : Libp2p = null; -let _rt = null; +let _node: Libp2p = null; // The libp2p node this peer uses +let _rt = null; // The runtime object let bootstrappers = [ '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', @@ -133,11 +130,19 @@ let bootstrappers = [ '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', ]; -let bootstrappers2 = p2pconfig.known_nodes.map((obj) => `${obj.ip}/${obj.nodeid}`); //AB: bootstrap known_nodes from config?? Make findNode easier - -async function startp2p(nodeId, rt: any): Promise { +let bootstrappers2 = p2pconfig.known_nodes.map((obj) => `${obj.ip}/${obj.nodeid}`); +//AB: bootstrap known_nodes from config?? Make findNode easier + +/** + * Start the libp2p node that this peer will use. + * Also sets up the event queue block checker and + * the connections to relays. + */ +async function startp2p(nodeId, rt: any): Promise { + // Load or create a peer id let id : PeerId = await obtainPeerId(nodeId); + // Create the libp2p node try { let nodeListener: Libp2p = await createLibp2p({ peerId: id, @@ -150,6 +155,7 @@ async function startp2p(nodeId, rt: any): Promise { } }); + // Save the libp2p node and runtime objects _node = nodeListener; _rt = rt; @@ -158,48 +164,59 @@ async function startp2p(nodeId, rt: any): Promise { throw err; } + // When a peer dials using the Troupe protocol handle the connection await _node.handle(_PROTOCOL, async ({ connection, stream }) => { debug(`Handling protocol dial from id: ${connection.remotePeer}`); setupConnection(connection.remotePeer, stream); }); + // When a node is discovered report it on the debug logger _node.addEventListener('peer:discovery', async (evt) => { const peerInfo = evt.detail; debug(`Discovered: ${peerInfo.id.toString()}`); }); + // When a node is connected to report it on the debug logger _node.addEventListener('peer:connect', (evt) => { const peerId = evt.detail; debug(`Connection established to: ${peerId.toString()}`); }); + // When a node is disconnected from report it on the debug logger + // If it is a relay, delete it from the relay table _node.addEventListener('peer:disconnect', (evt) => { let id = evt.detail; - debug (`-- disconnect: ${id}`); + debug (`Disconnect from ${id}`); if (_relayTable[id.toString()]) { - debug (`deleting relay table entry`); + debug (`Deleting relay table entry`); delete _relayTable[id.toString()]; } }); + // When new addresses are added report it on the debug logger _node.addEventListener('self:peer:update', (_) => { debug(`Advertising with following addresses:`); _node.getMultiaddrs().forEach(m => debug(m.toString())); }) - debug("p2p node started"); - debug(`id is ${id.toString()}`); + debug("Libp2p node started"); + debug(`This node's id is ${id.toString()}`); + // Set-up checking if the event queue is blocked setupBlockingHealthChecker(_HEALTHCHECKPERIOD); /*for (let relay_addr of p2pconfig.relays ) { //AB: update relay addresses in p2pconfig keepAliveRelay(relay_addr); - }*/ //AB: update relay addresses in p2pconfig - //keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); + }*/ //AB: update relay addresses in p2pconfig + // Make sure relays are dialed and the connections are kept live + keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); return id; } +/** + * Create the libp2p node that this peer will use. + */ async function createLibp2p(_options) { const defaults = { transports: [ @@ -221,9 +238,9 @@ async function createLibp2p(_options) { /*bootstrap({ list: bootstrappers }),*/ //AB: should we use bootstrappers? - mdns({ + /*mdns({ interval: 20e3 - }) + })*/ ], services: { identify: identifyService() @@ -237,23 +254,30 @@ async function createLibp2p(_options) { return create(defaultsDeep(_options, defaults)); } +/** + * Obtain this node's peer id. + * Create it from a JSON object if possible, + * otherwise generate a fresh one. + */ async function obtainPeerId(nodeId): Promise { - let id : PeerId = null; + let id: PeerId = null; if(nodeId) { + // Load the id from a JSON file if possible try { id = await createFromJSON(nodeId); debug(`Loaded id from file: ${id.toString()}`); } catch (err) { - error("Error creating peer id from json"); + error(`Error creating peer id from json: ${err}`); throw err; } } else { + // Otherwise create a fresh id try { debug("Creating new peer id..."); id = await createEd25519PeerId(); debug("Created new peer id"); } catch (err) { - error("Error creating new peer id"); + error(`Error creating new peer id: ${err}`); throw err; } } @@ -263,19 +287,27 @@ async function obtainPeerId(nodeId): Promise { // DIAL -function dial(id) { +/** + * Dial the node `id` using the Troupe protocol. + * First find addresses to use, then attempt to dial. + * Give up if more than 10 attempts have failed. + */ +function dial(id: PeerId) { let i = 0; let timeout = 2000; return new Promise((resolve, reject) => { - async function iterate() { + async function tryDialing() { try { - let peerId : PeerId = await getPeerInfoWithRelay(id); + // Add addresses to the peerStore + await getPeerInfo(id); - debug (`trying to dial ${peerId}, attempt number ${i}`); - const stream = await _node.dialProtocol(peerId, _PROTOCOL); - debug ("dial successful"); + // Dial using the Troupe protocol + debug(`Trying to dial ${id}, attempt number ${i}`); + const stream = await _node.dialProtocol(id, _PROTOCOL); + debug("Dial successful"); - setupConnection (peerId, stream); + // Handle inputs and outputs + setupConnection (id, stream); resolve(stream); } catch (err) { @@ -284,123 +316,153 @@ function dial(id) { // if the error is suppressed we move on to trying 10 times with exponential backoff // 2020-02-10; AA: TODO: this code has a hardcoded constant if(i <= 10) { - debug (`dial failed, we retry in ${timeout} seconds`); - error(err); - setTimeout(iterate, timeout); + debug(`Dial failed, we retry in ${timeout/1000} seconds`); + debug(err); + setTimeout(tryDialing, timeout); i++; timeout *= 2; } else { - debug (`we are giving up on dialing`); - error(err); + error(`Giving up on dialing ${id}: ${err}`); reject(err); } } } - iterate(); + tryDialing(); }); } -async function getPeerInfoWithRelay(id:any) { - let known_nodes = p2pconfig.known_nodes; - for(let ni of known_nodes) { - if(ni.nodeid == id) { - // found a known node! - let pi = peerIdFromString(id); - await _node.peerStore.patch(pi, { +/** + * Tries to find an address to use for a node. + * Checks the known nodes from p2pconfig, the peerStore, + * peerRouting and using a relay. + */ +async function getPeerInfo(id: PeerId): Promise { + let knownNodes = p2pconfig.known_nodes; + debug(`Checking whether node is already known`); + + // Check whether the node is known in p2pconfig + for(let ni of knownNodes) { + if(ni.nodeid == id.toString()) { + // Found a known node! + await _node.peerStore.merge(id, { multiaddrs: [ multiaddr(`${ni.ip}`) ] }); - debug(`node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`); - return pi; + debug(`Node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`); + return; } } + + let needsToFind = true; - debug("the node is not known; using relay information"); - let pi = await getPeerInfo(id); + // Check whether the node is known from previously + // and has an address + if(await _node.peerStore.has(id)) { + try { + let foundPeer = await _node.peerStore.get(id); + if(foundPeer.addresses.length != 0) { + debug("Peer info is in the store"); + needsToFind = false; + } + } catch (err) { + error(`Error in getPeerInfo / peerStore.get: ${err}`); + throw err; + } + } - if(_relay_id) { //AB: use all relays as below! - await _node.peerStore.patch(pi, { + if(needsToFind) { + // The node is not known or has no address + debug("The node is not known; using peerRouting"); + await getPeerInfoWithPeerRouting(id); + } + + if(_relayId) { //AB: use all relays as below! + // Try to contact the node through a relay + await _node.peerStore.merge(id, { multiaddrs: [ - multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id}`) + multiaddr(`/p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`) ] }); } - // for (let i = 0; i < p2pconfig.relays.length; i++ ) { // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) // } - return pi; } -async function getPeerInfo(id:string) : Promise { - const peerId = peerIdFromString(id); - - return new Promise ((resolve, reject) => { +/** + * Tries to find an address to use for a node through peerRouting. + * Tries 6 times, then gives up. + */ +async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { + return new Promise ((resolve, _) => { let n_attempts = 0; - async function try_find_peer() { - if(await _node.peerStore.has(peerId)) { - debug("peer info is in the store"); - try { - let foundPeer = await _node.peerStore.get(peerId); - resolve(foundPeer.id); - } catch (err) { - error(`Error in getPeerInfo / peerStore.get: ${err}`); - throw err; - } - } else { - try { - debug(`calling peerRouting.findPeer ${peerId}`); - const peerInfo = await _node.peerRouting.findPeer(peerId, {signal : AbortSignal.timeout(1000)}); - debug ("findPeer returned"); - - await _node.peerStore.patch(peerInfo.id, { - multiaddrs: - peerInfo.multiaddrs - }); - debug("added multiaddr to store"); - - resolve (peerInfo.id); - } catch (err) { - debug(`try_find_peer exception`); - - if(nPeers() > 0) { //AB: why only when nPeers > 0? - n_attempts++; - } + async function tryFindPeer() { + try { + // Try to find the node, but only spend 1 second on it + debug(`Calling peerRouting.findPeer ${id}`); + const peerInfo = await _node.peerRouting.findPeer(id, {signal : AbortSignal.timeout(1000)}); + debug ("findPeer returned"); + + // Add the found address + await _node.peerStore.merge(id, { + multiaddrs: + peerInfo.multiaddrs + }); + debug("Added multiaddr to store"); - if(err instanceof AggregateError) { - for(let e of err.errors) { - debug(`Find peer error with code: ${e}, ${e.code}`); - } - } else { - debug(`Find peer error: ${err.toString()}`); - } + resolve(); + } catch (err) { + debug(`tryFindPeer exception`); - if(n_attempts > 5) { - debug(`Resolving to empty peer info`); - resolve(peerId); - } else { - debug(`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`); - setTimeout(try_find_peer, 500); + if(err instanceof AggregateError) { + for(let e of err.errors) { + debug(`Find peer error with code: ${e}, ${e.code}`); } + } else { + debug(`Find peer error: ${err.toString()}`); + } + + // Increase the attempts + //AB: why only when nPeers > 0? + if(nPeers() > 0) { + n_attempts++; + } + // Try 6 times and then give up + if(n_attempts > 5) { + debug(`Giving up on peerRouting`); + resolve(); + } else { + debug(`tryFindPeer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`); + setTimeout(tryFindPeer, 500); } } } - try_find_peer(); - }); + tryFindPeer(); + }); } -function nPeers() { +/** + * Returns how many peers we have a connection to. + */ +function nPeers(): number { return _node.getPeers().length; } // CONNECTION SET-UP -function setupConnection(peerId : PeerId, stream): void { +/** + * Sets up the connection with a new peer with `peerId`. + * Ensures that messages that are sent and + * received are marshalled correctly and + * passes any input to the input handler. + */ +function setupConnection(peerId: PeerId, stream): void { let id: string = peerId.toString(); debug(`setupConnection with ${id}`); const p = pushable({ objectMode : true }); + // Setup the pipe to send and receive messages pipe (p, (source) => map(source, (json) => JSON.stringify(json)), (source) => map(source, (string : string) => uint8ArrayFromString(string, 'utf8')), @@ -411,21 +473,22 @@ function setupConnection(peerId : PeerId, stream): void { (source) => map(source, (string : string) => JSON.parse(string)), async (source) => { try { - for await (const x of source) { - inputHandler(id, x); + for await (const message of source) { + // Send any input to the input handler + inputHandler(id, message); } } catch (err) { - error(`error in pipe`); processExpectedNetworkErrors(err, "setupConnection/pipe"); } - debug(`deleting entry for ${id}`); + // Hangs up when the connection closes + debug(`Hanging up connection to ${id}`); try { await _node.hangUp(peerId); } catch (err) { - error(`error while hanging up pipe`); processExpectedNetworkErrors(err, "setupConnection/hang-up"); } + // Resends any unacknowledged WHEREIS requests for this peer reissueUnacknowledged(id); } ); @@ -435,35 +498,54 @@ function setupConnection(peerId : PeerId, stream): void { debug(`Connection set up with ${id}`); } +/** + * Handles the different input types + * - SPAWN: Checks whether remote spawn are allowed, + * informs the runtime and replies SPAWNOK. + * - SPAWNOK: Gives the message to the call-back. + * - SEND: Passes the message to the runtime. + * - WHEREIS: Asks the runtime where the peer is, + * and replies with WHEREISOK. + * - WHEREISOK: Gives the message to the call-back. + * - TEST / other: Writes the input on the debug logger. + */ async function inputHandler(id, input) { - debug ("-- input handler"); + debug("Input handler"); switch (input.messageType) { case (MessageType.SPAWN): + // Check if spawning is allowed if(_rt.remoteSpawnOK()) { - debug("RECEIVED SPAWN"); + debug("Received SPAWN"); - let x = await _rt.spawnFromRemote(input.message, id); - push_wrap(id, { + // Inform the runtime + let runtimeAnswer = await _rt.spawnFromRemote(input.message, id); + + // Reply with SPAWNOK + pushWrap(id, { messageType: MessageType.SPAWNOK, spawnNonce: input.spawnNonce, - message: x + message: runtimeAnswer }); - } // drop the message otherwise + debug("SPAWN replied"); + } // Drop the message otherwise break; case (MessageType.SPAWNOK): - debug ("SPAWN OK"); + debug ("Received SPAWN OK"); + // Find the call-back and give the message + // Otherwise report an error let _cb = _spawnNonces[input.spawnNonce]; if(_cb) { - delete _spawnNonces[input.spawnNonce]; // cleanup + delete _spawnNonces[input.spawnNonce]; // Clean-up _cb(null, input.message); // null means no errors } else { - error("cannot find spawn callback"); + error("Cannot find SPAWN callback"); } break; case (MessageType.SEND): - debug (`SEND from ${id}`); + debug (`Received SEND from ${id}`); + // Pass the message to the runtime _rt.receiveFromRemote( input.pid, input.message, @@ -472,28 +554,35 @@ async function inputHandler(id, input) { break; case (MessageType.WHEREIS): - debug("p2p whereis incoming request"); - let y = await _rt.whereisFromRemote(input.message); - push_wrap(id, { + debug("Received WHEREIS"); + // Get the runtime to find the peer + let runtimeAnswer = await _rt.whereisFromRemote(input.message); + + // Reply with WHEREISOK + pushWrap(id, { messageType: MessageType.WHEREISOK, whereisNonce : input.whereisNonce, - message : y + message : runtimeAnswer }); - debug("p2p whereis replied"); + + debug("WHEREIS replied"); break; - case (MessageType.WHEREISOK): + case (MessageType.WHEREISOK): + debug("Received WHEREISOK"); + // Find the call-back and give the message + // Otherwise report an error let _cbw = _whereisNonces[input.whereisNonce]; if(_cbw) { - delete _whereisNonces [input.whereisNonce]; // cleanup - _cbw (null, input.message); // null means no errors + delete _whereisNonces [input.whereisNonce]; // Clean-up + _cbw(null, input.message); // null means no errors } else { - error("cannot find whereis callback"); + error("Cannot find WHEREIS callback"); } break; case (MessageType.TEST): - debug("TEST input"); + debug("Received TEST"); debug(input); break; @@ -509,71 +598,92 @@ export interface IHash { [details: string] : any; } -let _relay_id = null; - //AB: only one counter?? And only one id?? -let _keepAliveCounter = 0; //AB: can tag peers with "Keep_alive" in the peerstore (does it work?) +let _relayId = null; +let _keepAliveCounter = 0; let _relayTable: IHash = {}; //AB: use in-built functionality instead? -async function keepAliveRelay(relay_addr: string) { - let id = relay_addr.split('/').pop(); - debug(`relay id is ${id}`); +/** + * Send keep-alive messages to a relay at `relayAddr`. + * If a message fails, do an exponential backoff + * on the timeout for new tries. + */ +async function keepAliveRelay(relayAddr: string) { + let id = relayAddr.split('/').pop(); + debug(`Relay id is ${id}`); + let timeout = _KEEPALIVE; - async function f() { - try { - let p = _relayTable[id] ? _relayTable[id] : await dialRelay(relay_addr); - p.push(`keep alive request ${_keepAliveCounter++}\n`); //AB: why do we do this??? + async function keepAlive() { + try { + // Push a keep-alive message to the relay. + // If a pushable is not available, dial the relay. + let p = _relayTable[id] ? _relayTable[id] : await dialRelay(relayAddr); + p.push(`Keep alive request ${_keepAliveCounter++}\n`); //AB: why do we do this? What should the result be? + // Reset the timeout once we are connected to the relay. timeout = _KEEPALIVE; } catch (err) { - timeout = timeout < 600e3 ? timeout * 2 : timeout // exponential backoff with 10 min limit + // Exponential backoff with 10 min limit. + timeout = timeout < 600e3 ? timeout * 2 : timeout processExpectedNetworkErrors(err, "relay"); - error(`~~ error reaching the relay server; we will retry again in ${timeout/1000} seconds`); + debug(`Error reaching the relay server; we will retry again in ${timeout/1000} seconds`); } - setTimeout(f, timeout); + setTimeout(keepAlive, timeout); } - f(); + keepAlive(); } -async function dialRelay(relay_addr) { - debug(`dialing relay ${relay_addr}`); - let id = relay_addr.split('/').pop(); - const relayId = peerIdFromString(id); - - await _node.peerStore.patch(relayId, { +/** + * Dials the relay at `relayAddr` + * and returns the pushable for the relay. + * Also tags the relay with "keep alive" in the peerStore. + */ +async function dialRelay(relayAddr: string) { + debug(`Dialing relay at ${relayAddr}`); + let id = relayAddr.split('/').pop(); + const relayId: PeerId = peerIdFromString(id); + + // Add the address to the peerStore + // Tag the relay with "keep alive" + await _node.peerStore.merge(relayId, { multiaddrs: [ - multiaddr(`${relay_addr}`) + multiaddr(`${relayAddr}`) ], tags: { [KEEP_ALIVE]: {} } }); + // Dial the relay debug(`Added relay address`); - const conn = await _node.dial(relayId); //AB: necessary?? - debug(`Got relay connection`); const stream = await _node.dialProtocol(relayId, _RELAY_PROTOCOL); debug(`Got relay stream`); - const peerId = conn.remotePeer; - _relay_id = peerId.toString(); - debug(`~~ relay dialed, keep alive counter is ${_keepAliveCounter++}`); + _relayId = id; + debug(`Relay dialed, keep alive counter is ${_keepAliveCounter++}`); + const p = pushable({ objectMode : true }); - + // Set up receiving messages from the relay pipe (stream.source, async (source: any) => { for await (const msg of source) { - debug(`~~ relay says:${msg.toString().trim()}`); + debug(`Relay says:${msg.toString().trim()}`); } }); + // Set up sending messages to the relay pipe (p, (stream.sink as any)); + // Save and return the pushable _relayTable[id] = p; return p; } // SEND -async function sendp2p(id : PeerId, procId, obj) { +/** + * Handles a send request to peer `id`. + * Just pushes a SEND message. + */ +async function sendp2p(id: string, procId, obj) { debug(`sendp2p`); let data = { @@ -582,22 +692,33 @@ async function sendp2p(id : PeerId, procId, obj) { message: obj }; - push_wrap(id, data); + let peerId = peerIdFromString(id); + debug("Pushing SEND message"); + pushWrap(peerId, data); } -async function push_wrap(id: any, data: any) { - while (true) { - debug(`push_wrap`); +/** + * Pushes `data` to a connection with `id`. + * First finds a pushable on a connection with `id`. + * Id this does not exists, dials `id`. + * Then pushes the data. + * Continues until the data is successfully pushed. + */ +async function pushWrap(id: PeerId, data: any) { + while(true) { + debug(`push wrap`); let connections = _node.getConnections(id); let needsToDial = true; let p = null; + // Runs through all existing connections with the peer + // and checks whether their streams have a pushable break_loop: for(const connection of connections) { let streams = connection.streams; for(const stream of streams) { p = (stream as any).p; - needsToDial = p == undefined; + needsToDial = (p == undefined); if(!needsToDial) { break break_loop; @@ -606,89 +727,129 @@ async function push_wrap(id: any, data: any) { } try { + // If no pushable was found, dial the peer if(needsToDial) { - debug("needs to dial"); - let stream = await dial(id.toString()); - debug("dialed to obtain stream"); + debug("Needs to dial"); + let stream = await dial(id); + debug("Dialed to obtain stream"); p = (stream as any).p; } - debug (`push_wrap; stream obtained; pushing`); + // A pushable has been found, data can be pushed + debug (`Push wrap; stream obtained; pushing`); await p.push(data); - debug(`push_wrap; data pushed into the stream`); + debug(`Push wrap; data pushed into the stream`); break; } catch (err) { - // the stream we have used is no good for whatever reason; + // The pushable we have used is no good for whatever reason; // most likely there are networking issues. - // we report the errors and redial - error(`push wrap error`); - processExpectedNetworkErrors(err, "push_wrap"); + // We report the errors and redial + processExpectedNetworkErrors(err, "push wrap"); } } } // WHEREIS / SPAWN -let _whereisNonces = {}; -let _unacknowledged:any = {}; +let _whereisNonces = {}; // Stores call-backs for WHEREIS requests +let _unacknowledged: any = {}; // Keeps track of unacknowledged WHEREIS requests + +/** + * Handles a where-is request of peer `id`. + * Creates a nonce which gives the result in the where-is table. + * Also sets the request as unacknowledged. + * Then pushes a WHEREIS message. + */ +async function whereisp2p(id: string, data: any) { + debug("whereisp2p"); -async function whereisp2p(id, str) { + // Create a nonce let whereisNonce = uuidv4(); - function f() { - push_wrap(id, { + function sendMessage() { + let peerId = peerIdFromString(id); + pushWrap(peerId, { messageType : MessageType.WHEREIS, whereisNonce : whereisNonce, - message : str + message : data }); } - addUnacknowledged(id, whereisNonce, f); + // Set the request as unacknowledged + addUnacknowledged(id.toString(), whereisNonce, sendMessage); - return new Promise((resolve, reject) => { - _whereisNonces[whereisNonce] = (err, data) => { + return new Promise((resolve, reject) => { + // Return the error or result when an answer comes in + _whereisNonces[whereisNonce] = (err, result) => { if(err) { reject(err); - } else { - removeUnacknowledged(id, whereisNonce); - resolve(data); + } else { + // Only remoce the unacknowledged status if the request succeeds + removeUnacknowledged(id.toString(), whereisNonce); + resolve(result); } } - debug("pushing whereis message"); - f(); + + // Push the WHEREIS message + debug("Pushing WHEREIS message"); + sendMessage(); }); } -function addUnacknowledged(id, uuid, f) { +/** + * Add the function `f` as unacknowledged + * WHEREIS request for `id` with nonce `uuid`. + */ +function addUnacknowledged(id: string, uuid, f) { if(!_unacknowledged[id]) { _unacknowledged[id] = []; } _unacknowledged[id][uuid] = f; } -function removeUnacknowledged(id, uuid) { +/** + * Remove the unacknowledged WHEREIS request for + * `id` with nonce `uuid`. + */ +function removeUnacknowledged(id: string, uuid) { delete _unacknowledged[id][uuid]; } -function reissueUnacknowledged(id:string) { - for (let uuid in _unacknowledged[id]) { +/** + * Rerun all unacknowledged WHEREIS requests for `id`. + */ +function reissueUnacknowledged(id: string) { + for(let uuid in _unacknowledged[id]) { setImmediate(_unacknowledged[id][uuid]); } } -let _spawnNonces = {}; +let _spawnNonces = {}; // Stores call-backs for SPAWN requests -async function spawnp2p(id, data) { +/** + * Handles a spawn request at peer `id`. + * Creates a nonce which gives the result in the spawn table. + * Then pushes a SPAWN message to the receiving peer. + */ +async function spawnp2p(id: string, data: any) { //AB: why not use "unanknowledged" like for WHEREIS? + debug("spawnp2p"); + + // Create a nonce const spawnNonce = uuidv4(); return new Promise ((resolve, reject) => { - _spawnNonces[spawnNonce] = (err, data) => { + // Return the error or result when an answer comes in + _spawnNonces[spawnNonce] = (err, result) => { if(err) { reject(err); } else { - resolve(data); + resolve(result); } }; - push_wrap(id, { + + // Push the SPAWN message + debug("Pushing SPAWN message"); + let peerId = peerIdFromString(id); + pushWrap(peerId, { messageType: MessageType.SPAWN, spawnNonce: spawnNonce, message: data @@ -698,80 +859,96 @@ async function spawnp2p(id, data) { // HEALTH CHECK -function setupBlockingHealthChecker(period) { - let _lastHealth:number = Date.now() - let _healthCounter = 0; - let health_threshold = Math.max (period * 1.25 , period + 50) +/** + * Checks that the event queue does not get blocked. + * The check is scheduled to run in `period` millisecond intervals. + * If it takes much longer than that before the check runs, + * this is reported, since it indicates blocking. + */ +function setupBlockingHealthChecker(period: number) { + let lastHealth: number = Date.now(); + let healthCounter = 0; + let healthThreshold = Math.max(period * 1.25 , period + 50); // AA: 2020-02-10; // The event queue always has a fair bit of latency, so we adjust for // the minimal expected latency here; the constant of 50 is an // empirically derived value, but needs to be critically reevaluated // as the system evolves - function f() { - let now = Date.now() - // debug (`Health checker running ${now - _lastHealth}, ${new Date()}`) - if (now - _lastHealth > health_threshold) { - debug (`Potential blocking issue: ${_healthCounter} ${now - _lastHealth}`) - } - _lastHealth = now; - setTimeout(f, period); - } - f () + function checkBlocking() { + let now = Date.now() + // check and report if it has been too long since the last health check + // this could indicate that something is the event queue + if(now - lastHealth > healthThreshold) { + debug(`Potential blocking issue`); + debug(`Health check ${healthCounter} took this long ${now - lastHealth}`); + } + lastHealth = now; + healthCounter++; + + // Run the check periodically + setTimeout(checkBlocking, period); + } + checkBlocking(); } // ERROR HANDLING -function processExpectedNetworkErrors(err, source="source unknown") { - debug (`error source: ${source}`); - if (err instanceof AggregateError) { - for (const e of err.errors ) { +/** + * Breaks down aggregate errors to their components. + * Any known errors are reported. + * Any unknown errors are reported and thrown. + */ +function processExpectedNetworkErrors(err, source="unknown") { + debug(`Error source: ${source}`); + if(err instanceof AggregateError) { + for(const e of err.errors ) { processExpectedNetworkErrors (e, source) } } else { - if (err.code) { + if(err.code) { switch (err.code) { case 'ENETUNREACH': - error (`${err.toString()}`) + debug(`${err.toString()}`) break; case 'ENOTFOUND': - error (`${err.toString()}`) + debug(`${err.toString()}`) break; case 'ECONNRESET': - error (`${err.toString()}`) + debug(`${err.toString()}`) break; case 'ERR_TRANSPORT_DIAL_FAILED': - error (`${err.toString()}`) + debug(`${err.toString()}`) break; case 'ABORT_ERR': - error (`${err.toString()}`) + debug(`${err.toString()}`) break; case 'ECONNREFUSED': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; case 'ERR_HOP_REQUEST_FAILED': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; case 'ERR_NO_DIAL_MULTIADDRS': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; case 'ERR_ENCRYPTION_FAILED': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; case 'ERR_NO_VALID_ADDRESSES': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; case 'ERR_MPLEX_STREAM_RESET': - error ((`${err.toString()}`)) + debug(`${err.toString()}`) break; default: - error (`Unhandled error case with error code ${err.code}`) + error(`Unhandled error case with error code ${err.code}`) throw err; } } else { - error (`Unhandled general error case ${err}`) - throw err; + error(`Unhandled general error case ${err}`) + throw err; } } } From f24589d0c9742dd882beebfe2f3564e938064053 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Fri, 21 Jul 2023 10:54:05 +0200 Subject: [PATCH 17/22] Add kad-DHT routing --- relay/relay.mjs | 56 ++++- rt/src/p2p/p2p.mts | 435 ++++++++++++++++++++++----------------- rt/src/p2p/p2pconfig.mjs | 4 +- 3 files changed, 297 insertions(+), 198 deletions(-) diff --git a/relay/relay.mjs b/relay/relay.mjs index ade14f7..7a6695f 100644 --- a/relay/relay.mjs +++ b/relay/relay.mjs @@ -6,8 +6,13 @@ import { createLibp2p } from 'libp2p' import { circuitRelayServer } from 'libp2p/circuit-relay' import { identifyService } from 'libp2p/identify' import { createFromJSON } from '@libp2p/peer-id-factory' +import { pipe } from 'it-pipe'; +import * as lp from 'it-length-prefixed' +import map from 'it-map' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' async function main () { + // TODO: change this to the actual relay const id = await createFromJSON({id : "12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf", privKey : "CAESQEQ7HBed1HEMpRHdhDmsJOlzHsVNBEWVc7DjEzuQtElv+uET7jQtZlGNKpltf2w4P7UqMdSYm4cYAGzjHcGcSj4="}); const node = await createLibp2p({ @@ -28,21 +33,56 @@ async function main () { services: { identify: identifyService(), relay: circuitRelayServer({ // makes the node function as a relay server + /* + The limits are set intentionally very high to avoid the relay cutting off + the connection. This can seemingly not be disabled in any other way. + (See: https://github.com/libp2p/specs/blob/f5c5829ef9753ef8b8a15d36725c59f0e9af897e/relay/circuit-v2.md?plain=1#L71) + There is also no way to distinguish whether the relay cut off the connection + because of a time/data limit or the other party cut off the connection. Therefore, + it is impossible to know whether to re-establish the connection or not. + + Two alternatives to giving large limits were considered. + - The good solution + Implement the connections being intentionally broken by the peers involved + before the relay reaches either limit. This would entail both timing and + counting all the bytes sent on each relayed connection. This was rejected + for being too time consuming, since the relay code might change soon anyway. + + - The hacky solution + Use a version of libp2p where the code for breaking a connection is removed. + This was rejected to allow for easier upgrading of the libp2p library. + */ reservations: { - defaultDurationLimit: 2147483647, // the default maximum amount of time a relayed connection can be open for - defaultDataLimit: BigInt(4294967295), // the default maximum number of bytes that can be transferred over a relayed connection + defaultDurationLimit: 2147483647, + defaultDataLimit: BigInt(4294967295), } - }), //AB: find out which settings to use to not cut off connections + }), } - }) + }); await node.handle("/trouperelay/keepalive", async ({ connection, stream }) => { - console.log(`Relay handling protocol, id: ${connection.remotePeer}`) + let id = connection.remotePeer; + console.log(`Relay handling protocol, id: ${id}`); + streamToConsole(stream, id); }) - console.log(`Node started with id ${node.peerId.toString()}`) - console.log('Listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) + console.log(`Relay node started with id ${node.peerId.toString()}`); + console.log('Listening on:'); + node.getMultiaddrs().forEach((ma) => console.log(ma.toString())); +} + +function streamToConsole (stream, id) { + console.log(`Handling keep-alives from ${id}`); + pipe( + stream.source, + (source) => lp.decode(source), + (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), + async function (source) { + for await (const msg of source) { + console.log(`Keep alive message from ${id}: ${msg.toString()}`); + } + } + ); } main() \ No newline at end of file diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 0376593..3254624 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -53,10 +53,6 @@ the libp2p). */ -// AB: TODO: -// - discuss w/ Aslan -// - types... :( - // IMPORTS import { PeerId } from '@libp2p/interface-peer-id'; @@ -85,6 +81,7 @@ import { circuitRelayTransport } from 'libp2p/circuit-relay'; import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'; import { Logger } from 'winston'; import {v4 as uuidv4} from 'uuid'; +import { kadDHT } from '@libp2p/kad-dht'; // LOGGING AND DEBUGGING @@ -121,7 +118,7 @@ const MessageType = { let _node: Libp2p = null; // The libp2p node this peer uses let _rt = null; // The runtime object -let bootstrappers = [ +let bootstrappers = [ // libp2p bootstrap nodes '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', @@ -130,8 +127,6 @@ let bootstrappers = [ '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', ]; -let bootstrappers2 = p2pconfig.known_nodes.map((obj) => `${obj.ip}/${obj.nodeid}`); -//AB: bootstrap known_nodes from config?? Make findNode easier /** * Start the libp2p node that this peer will use. @@ -146,14 +141,9 @@ async function startp2p(nodeId, rt: any): Promise { try { let nodeListener: Libp2p = await createLibp2p({ peerId: id, - addresses: { - listen: [`/ip4/0.0.0.0/tcp/${__port}`] - }, - connectionManager : { - maxConnections: Infinity, - minConnections: 0 //AB: What are good numbers here? - } }); + + await nodeListener.start(); // Save the libp2p node and runtime objects _node = nodeListener; @@ -164,40 +154,38 @@ async function startp2p(nodeId, rt: any): Promise { throw err; } - // When a peer dials using the Troupe protocol handle the connection + // When a peer dials using the Troupe protocol, handle the connection await _node.handle(_PROTOCOL, async ({ connection, stream }) => { debug(`Handling protocol dial from id: ${connection.remotePeer}`); setupConnection(connection.remotePeer, stream); }); - // When a node is discovered report it on the debug logger + // When a node is discovered, save the address and report it on the debug logger _node.addEventListener('peer:discovery', async (evt) => { const peerInfo = evt.detail; + await _node.peerStore.patch(peerInfo.id, { + multiaddrs: peerInfo.multiaddrs + }); debug(`Discovered: ${peerInfo.id.toString()}`); }); - // When a node is connected to report it on the debug logger + // When a node is connected to, report it on the debug logger _node.addEventListener('peer:connect', (evt) => { const peerId = evt.detail; debug(`Connection established to: ${peerId.toString()}`); }); - // When a node is disconnected from report it on the debug logger - // If it is a relay, delete it from the relay table + // When a node is disconnected from, report it on the debug logger _node.addEventListener('peer:disconnect', (evt) => { let id = evt.detail; - debug (`Disconnect from ${id}`); - if (_relayTable[id.toString()]) { - debug (`Deleting relay table entry`); - delete _relayTable[id.toString()]; - } + debug(`Disconnect from ${id}`); }); // When new addresses are added report it on the debug logger _node.addEventListener('self:peer:update', (_) => { debug(`Advertising with following addresses:`); _node.getMultiaddrs().forEach(m => debug(m.toString())); - }) + }); debug("Libp2p node started"); debug(`This node's id is ${id.toString()}`); @@ -205,11 +193,9 @@ async function startp2p(nodeId, rt: any): Promise { // Set-up checking if the event queue is blocked setupBlockingHealthChecker(_HEALTHCHECKPERIOD); - /*for (let relay_addr of p2pconfig.relays ) { //AB: update relay addresses in p2pconfig - keepAliveRelay(relay_addr); - }*/ //AB: update relay addresses in p2pconfig - // Make sure relays are dialed and the connections are kept live - keepAliveRelay("/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"); + // Make sure the relay is dialed and the connections are kept live + // To use more than one relay, make sure to dial them all + keepAliveRelay(p2pconfig.relays[0]); return id; } @@ -219,12 +205,18 @@ async function startp2p(nodeId, rt: any): Promise { */ async function createLibp2p(_options) { const defaults = { + addresses: { + listen: [`/ip4/0.0.0.0/tcp/${__port}`] + }, + connectionManager : { + minConnections: 1, + maxConnections: Infinity, + }, transports: [ tcp(), webSockets(), circuitRelayTransport({ - discoverRelays: 2, //AB: what to set this to? - reservationConcurrency : 2, + discoverRelays: 1, }) ], streamMuxers: [ @@ -235,20 +227,16 @@ async function createLibp2p(_options) { noise(), ], peerDiscovery: [ - /*bootstrap({ + bootstrap({ list: bootstrappers - }),*/ //AB: should we use bootstrappers? - /*mdns({ - interval: 20e3 - })*/ + }), + mdns(), ], services: { - identify: identifyService() + dht: kadDHT(), + identify: identifyService(), }, - /*dht: kadDHT({ - kBucketSize: 20, - clientMode: true // Whether to run the WAN DHT in client or server mode (default: client mode) - }),*/ //AB: use this or not? + }; return create(defaultsDeep(_options, defaults)); @@ -292,7 +280,7 @@ async function obtainPeerId(nodeId): Promise { * First find addresses to use, then attempt to dial. * Give up if more than 10 attempts have failed. */ -function dial(id: PeerId) { +function dial(id: PeerId) { let i = 0; let timeout = 2000; return new Promise((resolve, reject) => { @@ -307,7 +295,7 @@ function dial(id: PeerId) { debug("Dial successful"); // Handle inputs and outputs - setupConnection (id, stream); + setupConnection(id, stream); resolve(stream); } catch (err) { @@ -332,7 +320,7 @@ function dial(id: PeerId) { } /** - * Tries to find an address to use for a node. + * Tries to find and add addresses to use for a node. * Checks the known nodes from p2pconfig, the peerStore, * peerRouting and using a relay. */ @@ -354,7 +342,7 @@ async function getPeerInfo(id: PeerId): Promise { } } - let needsToFind = true; + let usePeerRouting = true; // Check whether the node is known from previously // and has an address @@ -363,7 +351,7 @@ async function getPeerInfo(id: PeerId): Promise { let foundPeer = await _node.peerStore.get(id); if(foundPeer.addresses.length != 0) { debug("Peer info is in the store"); - needsToFind = false; + usePeerRouting = false; } } catch (err) { error(`Error in getPeerInfo / peerStore.get: ${err}`); @@ -371,28 +359,26 @@ async function getPeerInfo(id: PeerId): Promise { } } - if(needsToFind) { + if(usePeerRouting) { // The node is not known or has no address debug("The node is not known; using peerRouting"); await getPeerInfoWithPeerRouting(id); } - if(_relayId) { //AB: use all relays as below! + if(_relayId) { // Try to contact the node through a relay + // To use several relays, cycle through them and add them all await _node.peerStore.merge(id, { multiaddrs: [ multiaddr(`/p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`) ] }); } - // for (let i = 0; i < p2pconfig.relays.length; i++ ) { - // pi.multiaddrs.add( multiaddr(`${p2pconfig.relays[i]}/p2p-circuit/p2p/${id}`)) - // } } /** - * Tries to find an address to use for a node through peerRouting. - * Tries 6 times, then gives up. + * Tries to find an address to use for a node through + * peerRouting. Tries six times, then gives up. */ async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { return new Promise ((resolve, _) => { @@ -401,8 +387,8 @@ async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { try { // Try to find the node, but only spend 1 second on it debug(`Calling peerRouting.findPeer ${id}`); - const peerInfo = await _node.peerRouting.findPeer(id, {signal : AbortSignal.timeout(1000)}); - debug ("findPeer returned"); + const peerInfo = await _node.peerRouting.findPeer(id, {signal : AbortSignal.timeout(2000)}); + debug("findPeer returned"); // Add the found address await _node.peerStore.merge(id, { @@ -423,12 +409,12 @@ async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { debug(`Find peer error: ${err.toString()}`); } - // Increase the attempts - //AB: why only when nPeers > 0? + // Increase the attempts used + // Only if the node is connected to the network if(nPeers() > 0) { n_attempts++; } - // Try 6 times and then give up + // Try six times and then give up if(n_attempts > 5) { debug(`Giving up on peerRouting`); resolve(); @@ -457,7 +443,7 @@ function nPeers(): number { * received are marshalled correctly and * passes any input to the input handler. */ -function setupConnection(peerId: PeerId, stream): void { +function setupConnection(peerId: PeerId, stream): void { let id: string = peerId.toString(); debug(`setupConnection with ${id}`); const p = pushable({ objectMode : true }); @@ -488,7 +474,8 @@ function setupConnection(peerId: PeerId, stream): void { } catch (err) { processExpectedNetworkErrors(err, "setupConnection/hang-up"); } - // Resends any unacknowledged WHEREIS requests for this peer + + // Resends any unacknowledged WHEREIS and SPAWN requests for this peer reissueUnacknowledged(id); } ); @@ -514,9 +501,25 @@ async function inputHandler(id, input) { switch (input.messageType) { case (MessageType.SPAWN): // Check if spawning is allowed + // Drop the message otherwise if(_rt.remoteSpawnOK()) { debug("Received SPAWN"); - + + if(receivedSpawnNonces[input.spawnNonce]) { + // This is an already seen spawn request. + // Look up the reply and resend without spawning again + debug("This spawn was already received; replying again without spawning"); + let cachedAnswer = receivedSpawnNonces[input.spawnNonce]; + + // Reply with SPAWNOK and return + pushWrap(id, { + messageType: MessageType.SPAWNOK, + spawnNonce: input.spawnNonce, + message: cachedAnswer + }); + return; + } + // Inform the runtime let runtimeAnswer = await _rt.spawnFromRemote(input.message, id); @@ -527,11 +530,19 @@ async function inputHandler(id, input) { message: runtimeAnswer }); debug("SPAWN replied"); - } // Drop the message otherwise + + // Save the nonce and the answer for 10 minutes + // in case we get the same request again + receivedSpawnNonces[input.spawnNonce] = runtimeAnswer; + function deleteSpawnNonce() { + delete receivedSpawnNonces[input.spawnNonce]; + } + setTimeout(deleteSpawnNonce, 600000); + } break; case (MessageType.SPAWNOK): - debug ("Received SPAWN OK"); + debug("Received SPAWN OK"); // Find the call-back and give the message // Otherwise report an error let _cb = _spawnNonces[input.spawnNonce]; @@ -544,7 +555,7 @@ async function inputHandler(id, input) { break; case (MessageType.SEND): - debug (`Received SEND from ${id}`); + debug(`Received SEND from ${id}`); // Pass the message to the runtime _rt.receiveFromRemote( input.pid, @@ -594,14 +605,9 @@ async function inputHandler(id, input) { // RELAY -export interface IHash { - [details: string] : any; -} - -//AB: only one counter?? And only one id?? -let _relayId = null; -let _keepAliveCounter = 0; -let _relayTable: IHash = {}; //AB: use in-built functionality instead? +let _relayId = null; // The id for the relay +let _keepAliveCounter = 0; // The number of times "keep-alive" has been sent to the relay +// To use more than one relay, these should be kept in a table /** * Send keep-alive messages to a relay at `relayAddr`. @@ -616,14 +622,26 @@ async function keepAliveRelay(relayAddr: string) { async function keepAlive() { try { // Push a keep-alive message to the relay. - // If a pushable is not available, dial the relay. - let p = _relayTable[id] ? _relayTable[id] : await dialRelay(relayAddr); - p.push(`Keep alive request ${_keepAliveCounter++}\n`); //AB: why do we do this? What should the result be? - // Reset the timeout once we are connected to the relay. - timeout = _KEEPALIVE; + debug(`Get a pushable for relay: ${id}`); + let peerId = peerIdFromString(id); + let p = await getPushable(peerId, relayAddr); + + // If getPushable fails the pushable may be null + if(p) { + debug(`Pushing keep alive request to ${_relayId}`); + p.push(`Keep alive request ${_keepAliveCounter++}`); + + // Reset the timeout once we are connected to the relay. + timeout = _KEEPALIVE; + } else { + // If there is no pushable, increase the timeout + timeout = timeout < 600e3 ? timeout * 2 : timeout; + debug(`Pushable found was null; we will retry again in ${timeout/1000} seconds`); + } + } catch (err) { // Exponential backoff with 10 min limit. - timeout = timeout < 600e3 ? timeout * 2 : timeout + timeout = timeout < 600e3 ? timeout * 2 : timeout; processExpectedNetworkErrors(err, "relay"); debug(`Error reaching the relay server; we will retry again in ${timeout/1000} seconds`); } @@ -638,43 +656,43 @@ async function keepAliveRelay(relayAddr: string) { * Also tags the relay with "keep alive" in the peerStore. */ async function dialRelay(relayAddr: string) { - debug(`Dialing relay at ${relayAddr}`); - let id = relayAddr.split('/').pop(); - const relayId: PeerId = peerIdFromString(id); - - // Add the address to the peerStore - // Tag the relay with "keep alive" - await _node.peerStore.merge(relayId, { - multiaddrs: [ - multiaddr(`${relayAddr}`) - ], - tags: { - [KEEP_ALIVE]: {} - } - }); + try { + debug(`Dialing relay at ${relayAddr}`); + let id = relayAddr.split('/').pop(); + const relayId: PeerId = peerIdFromString(id); - // Dial the relay - debug(`Added relay address`); - const stream = await _node.dialProtocol(relayId, _RELAY_PROTOCOL); - debug(`Got relay stream`); - _relayId = id; - debug(`Relay dialed, keep alive counter is ${_keepAliveCounter++}`); + // Add the address to the peerStore + // Tag the relay with "keep alive" + await _node.peerStore.merge(relayId, { + multiaddrs: [ + multiaddr(`${relayAddr}`) + ], + tags: { + [KEEP_ALIVE]: {} + } + }); - const p = pushable({ objectMode : true }); - // Set up receiving messages from the relay - pipe (stream.source, - async (source: any) => { - for await (const msg of source) { - debug(`Relay says:${msg.toString().trim()}`); - } - }); - // Set up sending messages to the relay - pipe (p, - (stream.sink as any)); - - // Save and return the pushable - _relayTable[id] = p; - return p; + // Dial the relay + debug(`Added relay address`); + const stream = await _node.dialProtocol(relayId, _RELAY_PROTOCOL); + debug(`Got relay stream`); + _relayId = id; + debug(`Relay dialed, keep alive counter is ${_keepAliveCounter++}`); + + // Set up sending messages to the relay + const p = pushable({ objectMode : true }); + pipe (p, + (source) => map(source, (string: string) => uint8ArrayFromString(string)), + (source) => lp.encode(source), + stream.sink); + + // Save the pushable and return the stream + (stream as any).p = p; // Storing a reference to the pushable on the stream + // We rely on the p2p library to keep track of streams + return stream; + } catch (err) { + processExpectedNetworkErrors (err, "dial relay"); + } } // SEND @@ -699,60 +717,88 @@ async function sendp2p(id: string, procId, obj) { /** * Pushes `data` to a connection with `id`. - * First finds a pushable on a connection with `id`. - * Id this does not exists, dials `id`. - * Then pushes the data. + * First finds a pushable on a connection with + * `id`, then pushes the data. * Continues until the data is successfully pushed. */ async function pushWrap(id: PeerId, data: any) { while(true) { - debug(`push wrap`); - let connections = _node.getConnections(id); - let needsToDial = true; - let p = null; - - // Runs through all existing connections with the peer - // and checks whether their streams have a pushable - break_loop: - for(const connection of connections) { - let streams = connection.streams; - for(const stream of streams) { - p = (stream as any).p; - needsToDial = (p == undefined); - - if(!needsToDial) { - break break_loop; - } - } - } - + debug(`pushWrap`); + let p = await getPushable(id); + try { - // If no pushable was found, dial the peer - if(needsToDial) { - debug("Needs to dial"); - let stream = await dial(id); - debug("Dialed to obtain stream"); - p = (stream as any).p; + if(p) { + // A pushable has been found, data can be pushed + debug(`Stream obtained; pushing`); + await p.push(data); + debug(`Data pushed into the stream`); + break; + } else { + debug("Pushable found was null; re-trying"); } - - // A pushable has been found, data can be pushed - debug (`Push wrap; stream obtained; pushing`); - await p.push(data); - debug(`Push wrap; data pushed into the stream`); - break; } catch (err) { // The pushable we have used is no good for whatever reason; // most likely there are networking issues. // We report the errors and redial - processExpectedNetworkErrors(err, "push wrap"); + processExpectedNetworkErrors(err, "pushWrap"); + } + } +} + +/** + * Finds a pushable to node `id` by checking all + * existing connections with the node. If no + * existing pushable is found, then dials the node. + */ +async function getPushable(id: PeerId, relayAddr=null) { + debug("getPushable"); + let connections = _node.getConnections(id); + let needsToDial = true; + let p = null; + + // Runs through all existing connections with the peer + // and checks whether their streams have a pushable + for(const connection of connections) { + let streams = connection.streams; + for(const stream of streams) { + p = (stream as any).p; + needsToDial = (p == undefined); + + if(!needsToDial) { + debug("Found existing pushable"); + return p; + } + } + } + + // If no pushable was found, dial the peer + if(needsToDial) { + debug("Needs to dial"); + let stream = null; + if(relayAddr) { + stream = await dialRelay(relayAddr); + } else { + stream = await dial(id); + } + // If the dial fails, the stream is null + if(stream) { + debug("Dialed to obtain stream"); + p = (stream as any).p; + } else { + debug("Could not obtain stream through dial"); } } + + return p; } // WHEREIS / SPAWN let _whereisNonces = {}; // Stores call-backs for WHEREIS requests -let _unacknowledged: any = {}; // Keeps track of unacknowledged WHEREIS requests +let _spawnNonces = {}; // Stores call-backs for SPAWN requests +let receivedSpawnNonces = {}; // Stores received SPAWN nonces and the runtime answer for their reply + // These are stored for 10 minutes in case the SPAWNOK disappeared +let _unacknowledged: any = {}; // Keeps track of unacknowledged WHEREIS and SPAWN requests /** * Handles a where-is request of peer `id`. @@ -774,7 +820,8 @@ async function whereisp2p(id: string, data: any) { message : data }); } - // Set the request as unacknowledged + + // Set the WHEREIS request as unacknowledged addUnacknowledged(id.toString(), whereisNonce, sendMessage); return new Promise((resolve, reject) => { @@ -783,7 +830,7 @@ async function whereisp2p(id: string, data: any) { if(err) { reject(err); } else { - // Only remoce the unacknowledged status if the request succeeds + // Only remove the unacknowledged status if the request succeeds removeUnacknowledged(id.toString(), whereisNonce); resolve(result); } @@ -795,6 +842,47 @@ async function whereisp2p(id: string, data: any) { }); } +/** + * Handles a spawn request at peer `id`. + * Creates a nonce which gives the result in the spawn table. + * Then pushes a SPAWN message to the receiving peer. + */ +async function spawnp2p(id: string, data: any) { + debug("spawnp2p"); + + // Create a nonce + const spawnNonce = uuidv4(); + + function sendMessage() { + let peerId = peerIdFromString(id); + pushWrap(peerId, { + messageType : MessageType.SPAWN, + spawnNonce : spawnNonce, + message : data + }); + } + + // Set the SPAWN request as unacknowledged + addUnacknowledged(id.toString(), spawnNonce, sendMessage); + + return new Promise ((resolve, reject) => { + // Return the error or result when an answer comes in + _spawnNonces[spawnNonce] = (err, result) => { + if(err) { + reject(err); + } else { + // Only remove the unacknowledged status if the request succeeds + removeUnacknowledged(id.toString(), spawnNonce); + resolve(result); + } + }; + + // Push the SPAWN message + debug("Pushing SPAWN message"); + sendMessage(); + }); +} + /** * Add the function `f` as unacknowledged * WHEREIS request for `id` with nonce `uuid`. @@ -823,40 +911,6 @@ function reissueUnacknowledged(id: string) { } } -let _spawnNonces = {}; // Stores call-backs for SPAWN requests - -/** - * Handles a spawn request at peer `id`. - * Creates a nonce which gives the result in the spawn table. - * Then pushes a SPAWN message to the receiving peer. - */ -async function spawnp2p(id: string, data: any) { //AB: why not use "unanknowledged" like for WHEREIS? - debug("spawnp2p"); - - // Create a nonce - const spawnNonce = uuidv4(); - - return new Promise ((resolve, reject) => { - // Return the error or result when an answer comes in - _spawnNonces[spawnNonce] = (err, result) => { - if(err) { - reject(err); - } else { - resolve(result); - } - }; - - // Push the SPAWN message - debug("Pushing SPAWN message"); - let peerId = peerIdFromString(id); - pushWrap(peerId, { - messageType: MessageType.SPAWN, - spawnNonce: spawnNonce, - message: data - }); - }); -} - // HEALTH CHECK /** @@ -937,10 +991,13 @@ function processExpectedNetworkErrors(err, source="unknown") { break; case 'ERR_NO_VALID_ADDRESSES': debug(`${err.toString()}`) - break; + break; case 'ERR_MPLEX_STREAM_RESET': debug(`${err.toString()}`) - break; + break; + case 'ERR_TIMEOUT': + debug(`${err.toString()}`); + break; default: error(`Unhandled error case with error code ${err.code}`) diff --git a/rt/src/p2p/p2pconfig.mjs b/rt/src/p2p/p2pconfig.mjs index fd93ee5..63be3ba 100644 --- a/rt/src/p2p/p2pconfig.mjs +++ b/rt/src/p2p/p2pconfig.mjs @@ -9,10 +9,12 @@ let logger; import { existsSync, readFileSync } from 'fs'; let relays + +// TODO: change the relay address to be the actual address let default_relays = // ["/dns4/relay.troupe-lang.net/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe"] // TODO: dns resolution of the relay has stopped working - ["/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe"] + ["/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"] let known_nodes = [ {nodeid:"QmXfj4ysaS4pARJU5uUP59B47aCQP6X6FH6cm5otLhcMPa", ip: "/ip4/134.209.90.7/tcp/6789"}, From 785ed07c41f8c253ff169e56df8b4153fc348491 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Fri, 21 Jul 2023 11:02:25 +0200 Subject: [PATCH 18/22] Remove old relay files --- relay/Makefile | 2 +- relay/go.mod | 15 - relay/go.sum | 1292 ----------------------------------------------- relay/main.go | 189 ------- relay/relay.mjs | 30 +- 5 files changed, 17 insertions(+), 1511 deletions(-) delete mode 100644 relay/go.mod delete mode 100644 relay/go.sum delete mode 100644 relay/main.go diff --git a/relay/Makefile b/relay/Makefile index a9b75d1..cc44db9 100644 --- a/relay/Makefile +++ b/relay/Makefile @@ -1,5 +1,5 @@ start-relay: - ./troupe-p2p-relay --key=keys/relay.priv + node relay.mjs generate-relay-key: mkdir -p keys diff --git a/relay/go.mod b/relay/go.mod deleted file mode 100644 index ae2af55..0000000 --- a/relay/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module troupe-p2p-relay - -require ( - github.com/ipfs/go-log v1.0.5 - github.com/libp2p/go-libp2p v0.18.0 - github.com/libp2p/go-libp2p-circuit v0.6.0 - github.com/libp2p/go-libp2p-connmgr v0.2.1 - github.com/libp2p/go-libp2p-core v0.14.0 - github.com/libp2p/go-libp2p-mplex v0.6.0 - github.com/libp2p/go-libp2p-secio v0.2.1 - github.com/libp2p/go-libp2p-swarm v0.10.2 - github.com/multiformats/go-multiaddr v0.5.0 -) - -go 1.13 diff --git a/relay/go.sum b/relay/go.sum deleted file mode 100644 index bb7530f..0000000 --- a/relay/go.sum +++ /dev/null @@ -1,1292 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= -github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= -github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= -github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= -github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= -github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= -github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= -github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= -github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= -github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= -github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= -github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= -github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= -github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= -github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= -github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= -github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= -github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-libp2p v0.18.0 h1:moKKKG875KNGsCjZxTIFB75ihHiVjFeWg5I4aR1pDLk= -github.com/libp2p/go-libp2p v0.18.0/go.mod h1:+veaZ9z1SZQhmc5PW78jvnnxZ89Mgvmh4cggO11ETmw= -github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= -github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= -github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= -github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= -github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= -github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= -github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= -github.com/libp2p/go-libp2p-connmgr v0.2.1 h1:1ed0HFhCb39sIMK7QYgRBW0vibBBqFQMs4xt9a9AalY= -github.com/libp2p/go-libp2p-connmgr v0.2.1/go.mod h1:JReKEFcgzSHKT9lL3rhYcUtXBs9uMIiMKJGM1tl3xJE= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= -github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= -github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= -github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= -github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= -github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= -github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= -github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= -github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.14.0 h1:0kYSgiK/D7Eo28GTuRXo5YHsWwAisVpFCqCVPUd/vJs= -github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= -github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= -github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= -github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= -github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= -github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= -github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= -github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= -github.com/libp2p/go-libp2p-peerstore v0.4.0/go.mod h1:rDJUFyzEWPpXpEwywkcTYYzDHlwza8riYMaUzaN6hX0= -github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= -github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= -github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= -github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= -github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= -github.com/libp2p/go-libp2p-quic-transport v0.16.1 h1:N/XqYXHurphPLDfXYhll8NyqzdZYQqAF4GIr7+SmLV8= -github.com/libp2p/go-libp2p-quic-transport v0.16.1/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= -github.com/libp2p/go-libp2p-resource-manager v0.1.5 h1:7J6t9KLFS0MxXDTfqA6rwfVCZl/yLQnXW5LpZjHAANI= -github.com/libp2p/go-libp2p-resource-manager v0.1.5/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA= -github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= -github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= -github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= -github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= -github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= -github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= -github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= -github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= -github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= -github.com/libp2p/go-libp2p-testing v0.8.0 h1:/te8SOIyj5sGH5Jr1Uoo+qYB00aK8O4+yHGzLgfE3kc= -github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= -github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= -github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= -github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= -github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= -github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= -github.com/libp2p/go-libp2p-transport-upgrader v0.7.1 h1:MSMe+tUfxpC9GArTz7a4G5zQKQgGh00Vio87d3j3xIg= -github.com/libp2p/go-libp2p-transport-upgrader v0.7.1/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= -github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= -github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= -github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= -github.com/libp2p/go-libp2p-yamux v0.8.2 h1:6GKWntresp0TFxMP/oSoH96nV8XKJRdynXsdp43dn0Y= -github.com/libp2p/go-libp2p-yamux v0.8.2/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= -github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= -github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= -github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= -github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= -github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= -github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= -github.com/libp2p/go-msgio v0.1.0/go.mod h1:eNlv2vy9V2X/kNldcZ+SShFE++o2Yjxwx6RAYsmgJnE= -github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= -github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= -github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= -github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= -github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= -github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= -github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= -github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= -github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= -github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= -github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= -github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= -github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= -github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= -github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= -github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= -github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= -github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= -github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= -github.com/libp2p/go-yamux/v3 v3.0.2 h1:LW0q5+A1Wy0npEsPJP9wmare2NH4ohNluN5EWVwv2mE= -github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= -github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= -github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= -github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= -github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= -github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= -github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= -github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= -github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= -github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= -github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= -github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= -github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= -github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= -github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= -github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= -github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= -github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= -github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= -github.com/raulk/go-watchdog v1.2.0 h1:konN75pw2BMmZ+AfuAm5rtFsWcJpKF3m02rKituuXNo= -github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= -github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= -github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= -github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ= -golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= -gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/relay/main.go b/relay/main.go deleted file mode 100644 index 6b01468..0000000 --- a/relay/main.go +++ /dev/null @@ -1,189 +0,0 @@ -package main - -import ( - "bufio" - "context" - "flag" - "fmt" - "io/ioutil" - "log" - "time" - - golog "github.com/ipfs/go-log" - "github.com/libp2p/go-libp2p" - connmgr "github.com/libp2p/go-libp2p-connmgr" - "github.com/libp2p/go-libp2p-core/crypto" - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - - // dht "github.com/libp2p/go-libp2p-kad-dht" - // "github.com/libp2p/go-libp2p-core/host" - // routing "github.com/libp2p/go-libp2p-routing" - - mplex "github.com/libp2p/go-libp2p-mplex" - secio "github.com/libp2p/go-libp2p-secio" - "github.com/multiformats/go-multiaddr" - - circuit "github.com/libp2p/go-libp2p-circuit" - swarm "github.com/libp2p/go-libp2p-swarm" - ma "github.com/multiformats/go-multiaddr" -) - -func main() { - golog.SetLogLevel("*", "info") - keyfile := flag.String("key", "", "key file") - flag.Parse() - - // Create three libp2p hosts, enable relay client capabilities on all - // of them. - - // Tell the host to monitor for relays. - h1, err := libp2p.New(context.Background(), libp2p.EnableRelay(circuit.OptDiscovery)) - if err != nil { - panic(err) - } - var prvKey crypto.PrivKey - // Tell the host to relay connections for other peers (The ability to *use* - // a relay vs the ability to *be* a relay) - if *keyfile == "" { - // panic(errors.New("no keyfile provided")) - prvKey, _, err = crypto.GenerateKeyPair(crypto.RSA, 2048) - } else { - var decoded []byte - pubBytes, err := ioutil.ReadFile(*keyfile) - if err != nil { - panic(err) - } - text := string(pubBytes) - decoded, err = crypto.ConfigDecodeKey(text) - if err != nil { - panic(err) - } - prvKey, err = crypto.UnmarshalPrivateKey(decoded) - if err != nil { - panic(err) - } - } - - sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", 5555)) - - // var idht *dht.IpfsDHT - ctx := context.Background() - h2, err := libp2p.New(ctx, - libp2p.Identity(prvKey), - libp2p.ListenAddrs(sourceMultiAddr), - libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), - // support secio connections - libp2p.Security(secio.ID, secio.New), - // support any other default transports (TCP) - libp2p.DefaultTransports, - // Let this host use the DHT to find other hosts - /* - libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) { - idht, err = dht.New(ctx, h) - return idht, err - }), - */ - libp2p.EnableRelay(circuit.OptHop), - libp2p.ConnectionManager(connmgr.NewConnManager(30, 100, time.Microsecond*5000)), - // libp2p.EnableAutoRelay() - ) - if err != nil { - panic(err) - } - - h2.SetStreamHandler("/trouperelay/keepalive", func(s network.Stream) { - fmt.Printf("Got a new stream keepalive stream!\n") - go handleKeepAlive(s) - - }) - - // Zero out the listen addresses for the host, so it can only communicate - // via p2p-circuit for our example - - h3, err := libp2p.New(context.Background(), libp2p.ListenAddrs(), libp2p.EnableRelay()) - if err != nil { - panic(err) - } - - h2info := peer.AddrInfo{ - ID: h2.ID(), - Addrs: h2.Addrs(), - } - - // Connect both h1 and h3 to h2, but not to each other - if err := h1.Connect(context.Background(), h2info); err != nil { - panic(err) - } - if err := h3.Connect(context.Background(), h2info); err != nil { - panic(err) - } - - // Now, to test things, let's set up a protocol handler on h3 - h3.SetStreamHandler("/cats", func(s network.Stream) { - fmt.Println("Meow! It worked!") - s.Close() - }) - - _, err = h1.NewStream(context.Background(), h3.ID(), "/cats") - if err == nil { - fmt.Println("Didnt actually expect to get a stream here. What happened?") - return - } - fmt.Println("Okay, no connection from h1 to h3: ", err) - fmt.Println("Just as we suspected") - - // Creates a relay address - relayaddr, err := ma.NewMultiaddr("/p2p-circuit/p2p/" + h3.ID().Pretty()) - if err != nil { - panic(err) - } - - // Since we just tried and failed to dial, the dialer system will, by default - // prevent us from redialing again so quickly. Since we know what we're doing, we - // can use this ugly hack (it's on our TODO list to make it a little cleaner) - // to tell the dialer "no, its okay, let's try this again" - h1.Network().(*swarm.Swarm).Backoff().Clear(h3.ID()) - - h3relayInfo := peer.AddrInfo{ - ID: h3.ID(), - Addrs: []ma.Multiaddr{relayaddr}, - } - if err := h1.Connect(context.Background(), h3relayInfo); err != nil { - panic(err) - } - - // Woohoo! we're connected! - s, err := h1.NewStream(context.Background(), h3.ID(), "/cats") - if err != nil { - fmt.Println("huh, this should have worked: ", err) - return - } - - s.Read(make([]byte, 1)) // block until the handler closes the stream - - // Hang forever. - select {} -} - -func handleKeepAlive(s network.Stream) error { - greeting := "troupe p2p go relay" - fmt.Println("handling the keep alive connection") - rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s)) - for { - str, err := rw.ReadString('\n') - if err != nil { - log.Println(err) - s.Reset() - return err - } - fmt.Print(str) - _, err = rw.WriteString(greeting + "/" + str) - rw.Flush() - if err != nil { - log.Println(err) - s.Reset() - return err - } - } -} diff --git a/relay/relay.mjs b/relay/relay.mjs index 7a6695f..54d6dc5 100644 --- a/relay/relay.mjs +++ b/relay/relay.mjs @@ -1,20 +1,22 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { createLibp2p } from 'libp2p' -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' -import { createFromJSON } from '@libp2p/peer-id-factory' +import { noise } from '@chainsafe/libp2p-noise'; +import { yamux } from '@chainsafe/libp2p-yamux'; +import { mplex } from '@libp2p/mplex'; +import { webSockets } from '@libp2p/websockets'; +import { createLibp2p } from 'libp2p'; +import { circuitRelayServer } from 'libp2p/circuit-relay'; +import { identifyService } from 'libp2p/identify'; +import { createFromJSON } from '@libp2p/peer-id-factory'; import { pipe } from 'it-pipe'; -import * as lp from 'it-length-prefixed' -import map from 'it-map' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import * as lp from 'it-length-prefixed'; +import map from 'it-map'; +import { toString as uint8ArrayToString } from 'uint8arrays/to-string'; +import { readFileSync } from 'fs'; async function main () { - // TODO: change this to the actual relay - const id = await createFromJSON({id : "12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf", - privKey : "CAESQEQ7HBed1HEMpRHdhDmsJOlzHsVNBEWVc7DjEzuQtElv+uET7jQtZlGNKpltf2w4P7UqMdSYm4cYAGzjHcGcSj4="}); + const relayId = readFileSync("keys/relay.id"); + const relayKey = readFileSync("keys/relay.priv"); + const id = await createFromJSON({id : relayId, privKey : relayKey}); + const node = await createLibp2p({ peerId : id, addresses: { From b515d730005ba1f16f3e713ee2bca38b0148f1f9 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Fri, 21 Jul 2023 11:12:10 +0200 Subject: [PATCH 19/22] Clean up makefile --- examples/network/pingpong/Makefile | 4 ++-- rt/src/p2p/p2p.mts | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/network/pingpong/Makefile b/examples/network/pingpong/Makefile index 854d45d..2554a31 100644 --- a/examples/network/pingpong/Makefile +++ b/examples/network/pingpong/Makefile @@ -3,10 +3,10 @@ MKALIASES=node $(TROUPE)/rt/built/p2p/mkaliases.js START=$(TROUPE)/network.sh zero.listener: - $(START) zero.trp --id=ids/pingpong-listener.json --rspawn=true --aliases=aliases.json --stdiolev={} --debug --debugp2p + $(START) zero.trp --id=ids/pingpong-listener.json --rspawn=true --aliases=aliases.json --stdiolev={} # --debug --debugp2p pingpong.dialer: - $(START) p2ppingpong.trp --id=ids/pingpong-dialer.json --aliases=aliases.json --debug --debugp2p + $(START) p2ppingpong.trp --id=ids/pingpong-dialer.json --aliases=aliases.json # --debug --debugp2p create-network-identifiers: mkdir -p ids diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 3254624..f905a6b 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -118,14 +118,15 @@ const MessageType = { let _node: Libp2p = null; // The libp2p node this peer uses let _rt = null; // The runtime object -let bootstrappers = [ // libp2p bootstrap nodes +const bootstrappers = [ + // libp2p bootstrap nodes + // (from https://github.com/libp2p/js-libp2p/blob/b36ec7f24e477af21cec31effc086a6c611bf271/examples/discovery-mechanisms/README.md?plain=1#L60) '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', - '/ip4/134.122.54.216/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' ]; /** From 15946b6cf2e6f0fda6b18b75d12ed46dbea807c1 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Fri, 11 Aug 2023 11:17:35 +0200 Subject: [PATCH 20/22] Delete old files --- rt/src/p2p/libp2p-bundle.js | 95 -------------------------------- rt/src/p2p/libp2p-bundle_ipfs.js | 51 ----------------- 2 files changed, 146 deletions(-) delete mode 100644 rt/src/p2p/libp2p-bundle.js delete mode 100644 rt/src/p2p/libp2p-bundle_ipfs.js diff --git a/rt/src/p2p/libp2p-bundle.js b/rt/src/p2p/libp2p-bundle.js deleted file mode 100644 index 7eb1c77..0000000 --- a/rt/src/p2p/libp2p-bundle.js +++ /dev/null @@ -1,95 +0,0 @@ -'use strict' - -const TCP = require('libp2p-tcp') -const MulticastDNS = require('libp2p-mdns') -const WS = require('libp2p-websockets') -const Bootstrap = require('libp2p-bootstrap') -const KadDHT = require('libp2p-kad-dht') - -const Multiplex = require('libp2p-mplex') -const SECIO = require('libp2p-secio') -const libp2p = require('libp2p') -const defaultsDeep = require('@nodeutils/defaults-deep') -const p2pconfig = require('./p2pconfig.mjs').default - -const bootstrapers = [ // TODO: 2020-02-10: check whether this list needs updating - // and ideally make this a configurable option; AA - - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', - '/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', - '/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', - '/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', - '/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', - '/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', - '/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', - '/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx' -] - -class Node extends libp2p { - constructor (_options) { - const defaults = { - connectionManager: { - maxPeers: 100, // this allows us to keep the memory footprint low! 2019-03-12; AA - minPeers: 5, - pollInterval: 2000, - defaultPeerValue: 1 // we later set the peer value of Troupe nodes to 1.0 - }, - - - modules: { - transport: [ - TCP, - WS - ], - streamMuxer: [ - Multiplex - ], - connEncryption: [ - SECIO - ], - peerDiscovery: [ - MulticastDNS, - Bootstrap - ], - dht: KadDHT - }, - dialer: { - maxParallelDials: 150, // How many multiaddrs we can dial in parallel - maxDialsPerPeer: 8, // How many multiaddrs we can dial per peer, in parallel - dialTimeout: 10e3, // 15 second dial timeout per peer - }, - metrics: { - enabled: true - }, - config: { - peerDiscovery: { - autoDial:true, - mdns: { - interval: 2e3, - enabled: true - }, - bootstrap: { - interval: 1000, - list : bootstrapers.concat(p2pconfig.relays), - enabled: true - } - }, - - dht: { - enabled:false, - kBucketSize: 20, - }, - - relay:{ - enabled: true, - hop : { enabled: false, active:false } - } - } - } - - super(defaultsDeep(_options, defaults)) - } -} - -module.exports = Node diff --git a/rt/src/p2p/libp2p-bundle_ipfs.js b/rt/src/p2p/libp2p-bundle_ipfs.js deleted file mode 100644 index 9d2a56c..0000000 --- a/rt/src/p2p/libp2p-bundle_ipfs.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict' - -const TCP = require('libp2p-tcp') -const MulticastDNS = require('libp2p-mdns') -const WS = require('libp2p-websockets') -const KadDHT = require('libp2p-kad-dht') -const Multiplex = require('libp2p-mplex') -const SECIO = require('libp2p-secio') - -module.exports = () => { - return { - dialer: { - maxParallelDials: 150, // 150 total parallel multiaddr dials - maxDialsPerPeer: 4, // Allow 4 multiaddrs to be dialed per peer in parallel - dialTimeout: 10e3 // 10 second dial timeout per peer dial - }, - modules: { - transport: [ - TCP, - WS - ], - streamMuxer: [ - Multiplex - ], - connEncryption: [ - SECIO - ], - peerDiscovery: [ - MulticastDNS - ], - dht: KadDHT, - }, - config: { - peerDiscovery: { - autoDial: true, - mdns: { - enabled: true - }, - bootstrap: { - enabled: true - }, - websocketStar: { - enabled: true - } - }, - }, - metrics: { - enabled: true - } - } -} \ No newline at end of file From 178d2f249da1558f4218d0f2c0754af928449d73 Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Mon, 14 Aug 2023 14:22:48 +0200 Subject: [PATCH 21/22] Fix localPeerId to be a string --- rt/src/runtimeMonitored.mts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rt/src/runtimeMonitored.mts b/rt/src/runtimeMonitored.mts index 6a840f8..2a25801 100644 --- a/rt/src/runtimeMonitored.mts +++ b/rt/src/runtimeMonitored.mts @@ -235,7 +235,7 @@ function rt_sendMessageNochecks(lRecipientPid, message, ret = true) { return $t().returnImmediateLValue(__unit); } } else { - // debug ("* rt rt_send remote *", recipientPid, message); + debug ("* rt rt_send remote *"/*, recipientPid, message*/); return sendMessageToRemote(recipientPid, message) } } @@ -485,7 +485,7 @@ export async function start(f) { debug("network not initialized") } - __nodeManager.setLocalPeerId(peerid); + __nodeManager.setLocalPeerId(peerid.toString()); let stopWhenAllThreadsAreDone = !__p2pRunning __sched.initScheduler(__nodeManager.getLocalNode() From b8d1636fd629087c9bcbf58fd733064ae67e525f Mon Sep 17 00:00:00 2001 From: Anna Blume Date: Mon, 14 Aug 2023 14:49:01 +0200 Subject: [PATCH 22/22] Fix tests --- rt/src/p2p/p2p.mts | 4 ++-- rt/src/runtimeMonitored.mts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index f905a6b..27ede44 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -134,7 +134,7 @@ const bootstrappers = [ * Also sets up the event queue block checker and * the connections to relays. */ -async function startp2p(nodeId, rt: any): Promise { +async function startp2p(nodeId, rt: any): Promise { // Load or create a peer id let id : PeerId = await obtainPeerId(nodeId); @@ -198,7 +198,7 @@ async function startp2p(nodeId, rt: any): Promise { // To use more than one relay, make sure to dial them all keepAliveRelay(p2pconfig.relays[0]); - return id; + return id.toString(); } /** diff --git a/rt/src/runtimeMonitored.mts b/rt/src/runtimeMonitored.mts index 2a25801..ec11e89 100644 --- a/rt/src/runtimeMonitored.mts +++ b/rt/src/runtimeMonitored.mts @@ -485,7 +485,7 @@ export async function start(f) { debug("network not initialized") } - __nodeManager.setLocalPeerId(peerid.toString()); + __nodeManager.setLocalPeerId(peerid); let stopWhenAllThreadsAreDone = !__p2pRunning __sched.initScheduler(__nodeManager.getLocalNode()