diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..0d53e989 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Filecoin Saturn Slack Channel + url: https://filecoinproject.slack.com/archives/C03DH0BL02E + about: Please ask any questions here + - name: Security Issue + url: "mailto:saturn@protocol.ai" + about: Please report security vulnerabilities here. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 00000000..3b2e42c8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,15 @@ +--- +name: Feature request +about: Use this template to request a feature +title: Feature request: +labels: "Low priority" +assignees: "" +--- + +### What is the feature you would like to see? + +### Why do you need this feature? + +### How would you like to see this feature implemented? + +### Additional context diff --git a/.github/ISSUE_TEMPLATE/ip-geolocation-override.md b/.github/ISSUE_TEMPLATE/fix-incorrect-node-ip-geolocation.md similarity index 51% rename from .github/ISSUE_TEMPLATE/ip-geolocation-override.md rename to .github/ISSUE_TEMPLATE/fix-incorrect-node-ip-geolocation.md index c99c0ff9..57dda861 100644 --- a/.github/ISSUE_TEMPLATE/ip-geolocation-override.md +++ b/.github/ISSUE_TEMPLATE/fix-incorrect-node-ip-geolocation.md @@ -1,6 +1,6 @@ --- -name: IP geolocation override -about: Template to request an IP geolocation override +name: Fix incorrect node IP geolocation +about: Use this template to fix an incorrect node IP geolocation title: Geolocation fix labels: "" assignees: "" diff --git a/.github/ISSUE_TEMPLATE/general-issue.md b/.github/ISSUE_TEMPLATE/general-issue.md new file mode 100644 index 00000000..b494f780 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/general-issue.md @@ -0,0 +1,17 @@ +--- +name: General issue +about: Use this template to report a general issue +title: General issue +labels: "Medium priority" +assignees: "" +--- + +### What did you do? + +### What happened? + +### What would you expect to have happened? + +### How can we reproduce this issue? + +### Additional context diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index b756ae3e..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: ["main"] - pull_request: - # The branches below must be a subset of the branches above - branches: ["main"] - schedule: - - cron: "24 3 * * 1" - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ["javascript"] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml new file mode 100644 index 00000000..23fea4ed --- /dev/null +++ b/.github/workflows/gateway-conformance.yml @@ -0,0 +1,107 @@ +name: Gateway Conformance + +on: + push: + branches: + - main + - gateway-conformance + paths: + - ".github/workflows/gateway-conformance.yml" + - "container/**" + - "Dockerfile" + pull_request: + +env: + L1_ORIGIN: http://127.0.0.1:80 + +jobs: + gateway-conformance: + runs-on: ubuntu-latest + steps: + # 1. Start the Kubo gateway + - name: Download Kubo gateway + uses: ipfs/download-ipfs-distribution-action@v1 + - name: Start Kubo gateway + uses: ipfs/start-ipfs-daemon-action@v1 + + # 2. Download the gateway-conformance fixtures + - name: Download gateway-conformance fixtures + uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.2.0 + with: + output: fixtures + + # 3. Populate the Kubo gateway with the gateway-conformance fixtures + - name: Import fixtures + run: | + find fixtures -name '*.car' -exec ipfs dag import --pin-roots=false {} \; + sudo rm -rf fixtures + + # 4. Build the L1 + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build local Docker image + uses: docker/build-push-action@v3 + with: + context: . + tags: saturn-node + cache-from: type=gha + cache-to: type=gha,mode=max + load: true + build-args: | + SATURN_NETWORK=local + ORCHESTRATOR_URL=http://localhost + LOG_INGESTOR_URL=http://localhost + + # 5. Start the L1 + - name: Start L1 + run: | + export ORCHESTRATOR_REGISTRATION=false + + # Configure lassie to fetch only from the localhost kubo + export LASSIE_ALLOW_PROVIDERS=$(ipfs id | jq --raw-output '.Addresses | @csv | sub("\"";"";"g") ') + export DOCKER_NETWORK=host + + sh scripts/run.sh & + + num_attempts=0 + max_attempts=5 + url=${{ env.L1_ORIGIN }} + + # wait for the container to be up + until curl -s "$url" -o /dev/null; do + if [ ${num_attempts} -eq ${max_attempts} ];then + echo "Max attempts reached" + exit 1 + fi + + num_attempts=$(($num_attempts+1)) + sleep 5; + done + + # 6. Run the gateway-conformance tests + - name: Run gateway-conformance tests + # Wait for release that contains "trustless-block-gateway,trustless-car-gateway" specs + uses: ipfs/gateway-conformance/.github/actions/test@v0.2.0 + with: + gateway-url: ${{ env.L1_ORIGIN }} + specs: trustless-block-gateway,trustless-car-gateway + json: output.json + xml: output.xml + html: output.html + markdown: output.md + args: -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length' + + # 7. Upload the results + - name: Upload Markdown summary + if: "!cancelled()" + run: cat output.md >> $GITHUB_STEP_SUMMARY + - name: Upload HTML report + if: "!cancelled()" + uses: actions/upload-artifact@v3 + with: + name: gateway-conformance.html + path: output.html diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 707bc92a..31039b33 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -32,8 +32,8 @@ jobs: with: context: . tags: saturn-node - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=l1 + cache-to: type=gha,mode=max,scope=l1 load: true build-args: | SATURN_NETWORK=local @@ -66,4 +66,4 @@ jobs: - name: Print L1 logs if: failure() - run: cat /home/runner/work/L1-node/L1-node/shared/nginx_log/error.log + run: cat /home/runner/work/L1-node/L1-node/shared/nginx_log/error.log || true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 58bf2901..4090cf69 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ env: jobs: build-and-push-image: - runs-on: ubuntu-latest + runs-on: larger permissions: contents: read @@ -100,8 +100,8 @@ jobs: ${{ steps.tags.outputs.mutable_docker_tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=l1 + cache-to: type=gha,mode=max,scope=l1 build-args: | NETWORK=${{ env.NETWORK }} VERSION=${{ github.run_number }}_${{ steps.git.outputs.sha_short }} diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index e3ea930d..a5588809 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -4,14 +4,15 @@ on: push: branches: ["main"] pull_request: + branches: ["main"] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: - check: - name: "Check linting and formatting" + lint-format: + name: Check linting and formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -23,3 +24,24 @@ jobs: - run: npm ci - run: npm run check:eslint - run: npm run check:prettier + + codeql-analysis: + name: CodeQL Analysis + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: javascript + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/Dockerfile b/Dockerfile index 516fe149..f899e63d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,8 +9,8 @@ ARG NGINX_BRANCH=default ARG NGINX_COMMIT=c38588d8376b # https://github.com/google/ngx_brotli ARG NGX_BROTLI_COMMIT=6e975bcb015f62e1f303054897783355e2a877dc -ARG NJS_VERSION=0.7.12 -ARG NGX_CAR_RANGE_VERSION="v0.5.0-rc1" +ARG NJS_VERSION=0.8.0 +ARG NGX_CAR_RANGE_VERSION="v0.6.0" # Install dependencies RUN apt-get update && apt-get install -y \ @@ -121,7 +121,6 @@ COPY --from=build /usr/src/${NGINX_NAME}/objs/ngx_http_brotli_static_module.so / COPY --from=build /usr/src/${NGINX_NAME}/objs/ngx_http_js_module.so /usr/lib/nginx/modules/ COPY --from=build /usr/src/ngx_car_range/target/release/libnginx_car_range.so /usr/lib/nginx/modules/ngx_http_car_range_module.so -# RUN curl -fsSL https://install.speedtest.net/app/cli/install.deb.sh | bash - RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ && curl -fsSL https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | bash - \ && apt-get install --no-install-recommends -y \ @@ -133,7 +132,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ # Download lassie ARG TARGETPLATFORM -ARG LASSIE_VERSION="v0.13.0" +ARG LASSIE_VERSION="v0.14.2" RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then ARCHITECTURE=amd64; \ elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then ARCHITECTURE=arm64; \ else ARCHITECTURE=386; fi \ diff --git a/README.md b/README.md index cafb107f..bd600d39 100644 --- a/README.md +++ b/README.md @@ -243,12 +243,14 @@ Having an uptime requirement has the following benefits: The current uptime requirement is as follows: -- For a node operator to qualify for earnings at the end of the month, their node must be online for at least 7 days during the month. It is important to note that earnings for nodes STILL get calculated before the node satisfies the uptime requirement. -- If a node is registered after the 21st day of a given month, the uptime requirement will be postponed to the following month. Its earnings will remain pending until it has satisfied the uptime requirement. -- Nodes that join before the 21st of a given month and do not satisfy the uptime requirement will forfeit their earnings for the given month. Their forfeited earnings will be added to the network reward pool for the following month. -- The uptime requirement must be satisfied on a monthly basis. +- For a node operator to qualify for earnings at the end of the month, their node must be online for at least 14 days during the month. It is important to note that earnings for nodes STILL get calculated before the node satisfies the uptime requirement. +- When a node first registers during a given month, its uptime requirement check will be postponed to the following month to give a fair opportunity for each node to meet the uptime requirement. Its earnings will remain pending until it has satisfied the uptime requirement. If the node satisfied the uptime requirement during the same month it registers, it will be eligible to receive earnings that month. +- Nodes that do not satisfy the uptime requirement in the months after their registration month will forfeit their earnings for the given month. Their forfeited earnings will be added to the network reward pool for the following month. +- The uptime requirement must be satisfied on a monthly basis after the registration month is over. -Note: Beginning July 1st, 2023, Saturn’s monthly node uptime requirement will increase from 7 days to 14 days. This means that for a node to qualify for earnings on August 1st, that node must have been online and operational for at least 14 contiguous days in July. +Note: Beginning July 1st, 2023, Saturn’s monthly node uptime requirement increased from 7 days to 14 days. This means that for a node to qualify for earnings on August 1st, 2023, that node must have been online and operational for at least 14 contiguous days in July. + +Read more about Saturn's node uptime requirement in the docs, [here](https://docs.saturn.tech/nodes-uptime-requirement). ### Obtaining a Filecoin wallet address diff --git a/container/nginx/conf.d/proxy.conf b/container/nginx/conf.d/proxy.conf index accb85fa..8b6229b6 100644 --- a/container/nginx/conf.d/proxy.conf +++ b/container/nginx/conf.d/proxy.conf @@ -1,5 +1,5 @@ # 2g of memory for keys is about 16 million cached items -proxy_cache_path /usr/src/app/shared/nginx_cache levels=2:2:2 keys_zone=my_cache:2000m inactive=90d min_free=50G use_temp_path=off manager_files=1000 loader_files=1000; +proxy_cache_path /usr/src/app/shared/nginx_cache levels=2:2:2 keys_zone=my_cache:2000m inactive=90d min_free=$cache_min_free use_temp_path=off manager_files=1000 loader_files=1000; upstream node_backend { server 127.0.0.1:10361 max_fails=0; diff --git a/container/nginx/conf.d/shared.conf b/container/nginx/conf.d/shared.conf index e3e8b135..bbf56cb1 100644 --- a/container/nginx/conf.d/shared.conf +++ b/container/nginx/conf.d/shared.conf @@ -44,6 +44,8 @@ location / { car_range; + js_header_filter ipfsResponse.setHeaders; + proxy_pass http://node_backend; proxy_buffering on; proxy_http_version 1.1; @@ -66,7 +68,7 @@ location / { proxy_cache_lock on; proxy_cache_valid 200 301 302 403 365d; proxy_cache_valid any 1m; - proxy_cache_min_uses 1; + proxy_cache_min_uses $cache_min_uses; proxy_cache_lock_age 30m; proxy_cache_lock_timeout 30m; proxy_cache_use_stale error timeout invalid_header updating http_500 http_503 http_429; @@ -86,8 +88,9 @@ location / { add_header 'Retry-After' $retry_after_seconds always; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Traceparent' always; add_header 'Access-Control-Expose-Headers' '*' always; + add_header 'Accept-Ranges' 'none' always; client_max_body_size 10g; @@ -95,7 +98,7 @@ location / { add_header 'Timing-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Traceparent' always; add_header 'Access-Control-Expose-Headers' '*' always; add_header 'Access-Control-Max-Age' 1728000 always; add_header 'Content-Type' 'text/plain; charset=utf-8'; diff --git a/container/nginx/confs/tls_proxy.conf b/container/nginx/confs/tls_proxy.conf index f50086ff..b3d1025d 100644 --- a/container/nginx/confs/tls_proxy.conf +++ b/container/nginx/confs/tls_proxy.conf @@ -58,7 +58,6 @@ server { include /etc/nginx/conf.d/register.conf; - # TODO: Temporary block to facilitate bifrost gateway tests. location /ipfs/ { proxy_http_version 1.1; proxy_set_header Host handoff.strn.localhost; diff --git a/container/nginx/nginx.conf b/container/nginx/nginx.conf index 06706901..af267161 100644 --- a/container/nginx/nginx.conf +++ b/container/nginx/nginx.conf @@ -17,6 +17,7 @@ http { js_path "/etc/nginx/njs/"; js_preload_object denylist.json; js_import filterCID from badbits.js; + js_import ipfsResponse from ipfs-response.js; include /etc/nginx/mime.types; default_type application/octet-stream; @@ -49,9 +50,9 @@ http { # uct: $upstream_connect_time (integer - 0.001) time in seconds it took to establish connection with upstream server # uht: $upstream_header_time (integer - 0.001) time in seconds it took to receive response headers from upstream server # urt: $upstream_response_time (integer - 3.14) time in seconds it took to receive full response from upstream server - # ubs: $upstream_bytes_sent (integer - 1234) bytes sent from upstream server to nginx including headers + # ubs: $upstream_bytes_sent (integer - 1234) bytes sent to upstream server from nginx including headers # ubr: $upstream_bytes_received (integer - 1234) bytes received from upstream server by nginx including headers - # bytes: $bytes_sent (integer - 1234) bytes sent from server to client including headers + # bytes: $body_bytes_sent (integer - 1234) bytes sent from server to client excluding headers # range: $http_range (string - bytes=0-4000) requested bytes range # cache: $upstream_cache_status (string - HIT) cache status of the response # host: $host (string - strn.pl) @@ -62,13 +63,14 @@ http { # ua: $http_user_agent (string - AppleTV5,3/9.1.1) client user agent # ff: $http_x_forwarded_for (string - 10.4.1.23) X-Forwarded-For header sent by client # sp: $server_protocol (string - HTTP/1.1) server protocol + # tp: $http_traceparent (string - 00-779efbcbc70ce91a26cfed853688dd1c-3a72e29d089f9d15-01) traceparent header sent by client log_format node escape=json 'time=$time_iso8601 server=$server_addr uri="$request_uri" method=$request_method ' 'status=$status rt=$request_time uct=$upstream_connect_time uht=$upstream_header_time ' 'urt=$upstream_response_time ubs=$upstream_bytes_sent ubr=$upstream_bytes_received ' - 'bytes=$bytes_sent range="$http_range" cache=$upstream_cache_status host=$host ' + 'bytes=$body_bytes_sent range="$http_range" cache=$upstream_cache_status host=$host ' 'scheme=$scheme addr=$remote_addr id=$request_id ref="$http_referer" ' - 'ua="$http_user_agent" ff="$http_x_forwarded_for" sp=$server_protocol'; + 'ua="$http_user_agent" ff="$http_x_forwarded_for" sp=$server_protocol tp=$http_traceparent'; limit_req_zone $binary_remote_addr zone=one:100m rate=300r/s; limit_req_status 429; diff --git a/container/nginx/njs/ipfs-response.js b/container/nginx/njs/ipfs-response.js new file mode 100644 index 00000000..8798ea95 --- /dev/null +++ b/container/nginx/njs/ipfs-response.js @@ -0,0 +1,28 @@ +function setHeaders(req) { + const format = req.variables.format_final; + const filename = req.args.filename; + + const pathSegments = req.uri.split("/"); + const cid = pathSegments[2]; + const filePathSegments = pathSegments.slice(3); + const lastSegment = filePathSegments[filePathSegments.length - 1]; + + let name; + if (filename) { + name = filename; + } else if (format === "car") { + name = cid; + if (lastSegment) { + name += "_" + lastSegment; + } + name += ".car"; + } else if (format === "raw") { + name = `${cid}.bin`; + } + + if (name) { + req.headersOut["content-disposition"] = `attachment; filename="${name}"`; + } +} + +export default { setHeaders }; diff --git a/container/shim/package-lock.json b/container/shim/package-lock.json index aa8be12c..edb8791b 100644 --- a/container/shim/package-lock.json +++ b/container/shim/package-lock.json @@ -7,30 +7,25 @@ "name": "shim", "dependencies": { "@glif/filecoin-address": "^2.0.43", - "@ipld/car": "^5.0.3", - "@multiformats/blake2": "^1.0.13", + "@ipld/car": "^5.2.0", "asn1.js-rfc2560": "^5.0.1", "asn1.js-rfc5280": "^3.0.0", "debug": "^4.3.4", "express": "^4.18.2", "express-async-handler": "^1.2.0", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.1", "logfmt": "^1.3.2", - "lru-cache": "^7.14.1", + "lru-cache": "^10.0.0", "mime-types": "^2.1.35", - "multiformats": "^11.0.2", - "node-fetch": "^3.3.1", - "p-defer": "^4.0.0", + "multiformats": "^12.0.1", + "node-fetch": "^3.3.2", "p-limit": "^4.0.0", - "p-timeout": "^6.1.0", - "pretty-bytes": "^6.0.0", - "server-timing": "^3.3.3", - "stream-write": "^2.0.0", - "xor-distance": "^2.0.0" + "pretty-bytes": "^6.1.1", + "server-timing": "^3.3.3" }, "devDependencies": { - "nock": "^13.3.1", - "test": "^3.2.1" + "nock": "^13.3.2", + "test": "^3.3.0" } }, "node_modules/@ethersproject/abi": { @@ -717,9 +712,9 @@ } }, "node_modules/@ipld/car": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.0.3.tgz", - "integrity": "sha512-omPSY65OSVmlFGJDn2xbd75o71GNHmgP5u2dQ5fITc0X/QqJZVfZi95NCs8oa1wWhjkaK3RTswRSg2iNqFUSAg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.2.0.tgz", + "integrity": "sha512-Y4DiyVoPaeGxY6gKV/0A/73SlIIuDu7fl25NdlrO6BYhyTN6v59KqcilmMXbiBA/zcf7cZr1GZVPHRyG2+nmAw==", "dependencies": { "@ipld/dag-cbor": "^9.0.0", "cborg": "^1.9.0", @@ -731,6 +726,15 @@ "npm": ">=7.0.0" } }, + "node_modules/@ipld/car/node_modules/multiformats": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", + "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@ipld/dag-cbor": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.1.tgz", @@ -744,25 +748,15 @@ "npm": ">=7.0.0" } }, - "node_modules/@multiformats/blake2": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@multiformats/blake2/-/blake2-1.0.13.tgz", - "integrity": "sha512-T1Kzya0wjj85CaVeRSpJ858EnSvW1pw94GSitxYf84VsNdv5XYbJ6QG8y26Ft1bVALzrUCmqkQrR53QHSyu6RA==", - "dependencies": { - "blakejs": "^1.1.1", - "multiformats": "^9.5.4" + "node_modules/@ipld/dag-cbor/node_modules/multiformats": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", + "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, - "node_modules/@multiformats/blake2/node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, - "node_modules/@multiformats/blake2/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -803,6 +797,18 @@ "node": ">= 8" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1277,6 +1283,24 @@ "@ethersproject/wordlists": "5.7.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -1337,9 +1361,9 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1907,11 +1931,11 @@ } }, "node_modules/lru-cache": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, "node_modules/media-typer": { @@ -2009,9 +2033,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multiformats": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.0.1.tgz", + "integrity": "sha512-s01wijBJoDUqESWSzePY0lvTw7J3PVO9x2Cc6ASI5AMZM2Gnhh7BC17+nlFhHKU7dDzaCaRfb+NiqNzOsgPUoQ==", "engines": { "node": ">=16.0.0", "npm": ">=7.0.0" @@ -2026,9 +2050,9 @@ } }, "node_modules/nock": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", - "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.2.tgz", + "integrity": "sha512-CwbljitiWJhF1gL83NbanhoKs1l23TDlRioNraPTZrzZIEooPemrHRj5m0FZCPkB1ecdYCSWWGcHysJgX/ngnQ==", "dev": true, "dependencies": { "debug": "^4.1.0", @@ -2059,9 +2083,9 @@ } }, "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -2129,17 +2153,6 @@ "node": ">= 0.8" } }, - "node_modules/p-defer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", - "integrity": "sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -2154,17 +2167,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-timeout": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.1.tgz", - "integrity": "sha512-yqz2Wi4fiFRpMmK0L2pGAU49naSUaP23fFIQL2Y6YT+qDGPoFwpvgQM/wzc6F8JoenUkIlAFa4Ql7NguXBxI7w==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2190,9 +2192,9 @@ } }, "node_modules/pretty-bytes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", - "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", "engines": { "node": "^14.13.1 || >=16.0.0" }, @@ -2200,6 +2202,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/propagate": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", @@ -2277,9 +2288,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2481,11 +2492,6 @@ "node": ">= 0.8" } }, - "node_modules/stream-write": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-write/-/stream-write-2.0.0.tgz", - "integrity": "sha512-QxthWbzSe3uNoHliTdIpgcBSNp4Rw7lGEH8zssKFqxN0ZHUIoNZ7t2wbJp07hJgTQ63hHnXpPd0CH2xCaoqqYw==" - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -2540,20 +2546,38 @@ } }, "node_modules/test": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/test/-/test-3.2.1.tgz", - "integrity": "sha512-D9eN4OxdhyYS3xHSsAh5A0e+UhaOPxeREwBHTknZHoVFd4TqnPtkVrQ7lIUATPgpO9vvGg1D+TyMckVmUyaEig==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/test/-/test-3.3.0.tgz", + "integrity": "sha512-JKlEohxDIJRjwBH/+BrTcAPHljBALrAHw3Zs99RqZlaC605f6BggqXhxkdqZThbSHgaYPwpNJlf9bTSWkb/1rA==", "dev": true, "dependencies": { "minimist": "^1.2.6", + "readable-stream": "^4.3.0", "string.prototype.replaceall": "^1.0.6" }, "bin": { "node--test": "bin/node--test.js", + "node--test-name-pattern": "bin/node--test-name-pattern.js", "node--test-only": "bin/node--test-only.js", "test": "bin/node-core-test.js" } }, + "node_modules/test/node_modules/readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -2696,11 +2720,6 @@ } } }, - "node_modules/xor-distance": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xor-distance/-/xor-distance-2.0.0.tgz", - "integrity": "sha512-AsAqZfPAuWx7qB/0kyRDUEvoU3QKsHWzHU9smFlkaiprEpGfJ/NBbLze2Uq0rdkxCxkNM9uOLvz/KoNBCbZiLQ==" - }, "node_modules/yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", @@ -3098,14 +3117,21 @@ } }, "@ipld/car": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.0.3.tgz", - "integrity": "sha512-omPSY65OSVmlFGJDn2xbd75o71GNHmgP5u2dQ5fITc0X/QqJZVfZi95NCs8oa1wWhjkaK3RTswRSg2iNqFUSAg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.2.0.tgz", + "integrity": "sha512-Y4DiyVoPaeGxY6gKV/0A/73SlIIuDu7fl25NdlrO6BYhyTN6v59KqcilmMXbiBA/zcf7cZr1GZVPHRyG2+nmAw==", "requires": { "@ipld/dag-cbor": "^9.0.0", "cborg": "^1.9.0", "multiformats": "^11.0.0", "varint": "^6.0.0" + }, + "dependencies": { + "multiformats": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", + "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==" + } } }, "@ipld/dag-cbor": { @@ -3115,26 +3141,12 @@ "requires": { "cborg": "^1.10.0", "multiformats": "^11.0.0" - } - }, - "@multiformats/blake2": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@multiformats/blake2/-/blake2-1.0.13.tgz", - "integrity": "sha512-T1Kzya0wjj85CaVeRSpJ858EnSvW1pw94GSitxYf84VsNdv5XYbJ6QG8y26Ft1bVALzrUCmqkQrR53QHSyu6RA==", - "requires": { - "blakejs": "^1.1.1", - "multiformats": "^9.5.4" }, "dependencies": { - "blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, "multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", + "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==" } } }, @@ -3166,6 +3178,15 @@ "resolved": "https://registry.npmjs.org/@sovpro/delimited-stream/-/delimited-stream-1.1.0.tgz", "integrity": "sha512-kQpk267uxB19X3X2T1mvNMjyvIEonpNSHrMlK5ZaBU6aZxw7wPbpgKJOjHN3+/GPVpXgAV9soVT2oyHpLkLtyw==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3523,6 +3544,18 @@ "@ethersproject/wordlists": "5.7.0" } }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, "express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -3582,9 +3615,9 @@ "integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==" }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3980,9 +4013,9 @@ } }, "lru-cache": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==" }, "media-typer": { "version": "0.3.0", @@ -4052,9 +4085,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multiformats": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.2.tgz", - "integrity": "sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==" + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.0.1.tgz", + "integrity": "sha512-s01wijBJoDUqESWSzePY0lvTw7J3PVO9x2Cc6ASI5AMZM2Gnhh7BC17+nlFhHKU7dDzaCaRfb+NiqNzOsgPUoQ==" }, "negotiator": { "version": "0.6.3", @@ -4062,9 +4095,9 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "nock": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", - "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.2.tgz", + "integrity": "sha512-CwbljitiWJhF1gL83NbanhoKs1l23TDlRioNraPTZrzZIEooPemrHRj5m0FZCPkB1ecdYCSWWGcHysJgX/ngnQ==", "dev": true, "requires": { "debug": "^4.1.0", @@ -4079,9 +4112,9 @@ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" }, "node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "requires": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -4124,11 +4157,6 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" }, - "p-defer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", - "integrity": "sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==" - }, "p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -4137,11 +4165,6 @@ "yocto-queue": "^1.0.0" } }, - "p-timeout": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.1.tgz", - "integrity": "sha512-yqz2Wi4fiFRpMmK0L2pGAU49naSUaP23fFIQL2Y6YT+qDGPoFwpvgQM/wzc6F8JoenUkIlAFa4Ql7NguXBxI7w==" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -4158,9 +4181,15 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pretty-bytes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", - "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true }, "propagate": { "version": "2.0.1", @@ -4207,9 +4236,9 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4356,11 +4385,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, - "stream-write": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-write/-/stream-write-2.0.0.tgz", - "integrity": "sha512-QxthWbzSe3uNoHliTdIpgcBSNp4Rw7lGEH8zssKFqxN0ZHUIoNZ7t2wbJp07hJgTQ63hHnXpPd0CH2xCaoqqYw==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4406,13 +4430,29 @@ } }, "test": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/test/-/test-3.2.1.tgz", - "integrity": "sha512-D9eN4OxdhyYS3xHSsAh5A0e+UhaOPxeREwBHTknZHoVFd4TqnPtkVrQ7lIUATPgpO9vvGg1D+TyMckVmUyaEig==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/test/-/test-3.3.0.tgz", + "integrity": "sha512-JKlEohxDIJRjwBH/+BrTcAPHljBALrAHw3Zs99RqZlaC605f6BggqXhxkdqZThbSHgaYPwpNJlf9bTSWkb/1rA==", "dev": true, "requires": { "minimist": "^1.2.6", + "readable-stream": "^4.3.0", "string.prototype.replaceall": "^1.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } } }, "through": { @@ -4518,11 +4558,6 @@ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "requires": {} }, - "xor-distance": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xor-distance/-/xor-distance-2.0.0.tgz", - "integrity": "sha512-AsAqZfPAuWx7qB/0kyRDUEvoU3QKsHWzHU9smFlkaiprEpGfJ/NBbLze2Uq0rdkxCxkNM9uOLvz/KoNBCbZiLQ==" - }, "yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", diff --git a/container/shim/package.json b/container/shim/package.json index ab317f99..64921131 100644 --- a/container/shim/package.json +++ b/container/shim/package.json @@ -9,25 +9,25 @@ }, "dependencies": { "@glif/filecoin-address": "^2.0.43", - "@ipld/car": "^5.0.3", + "@ipld/car": "^5.2.0", "asn1.js-rfc2560": "^5.0.1", "asn1.js-rfc5280": "^3.0.0", "debug": "^4.3.4", "express": "^4.18.2", "express-async-handler": "^1.2.0", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.1", "logfmt": "^1.3.2", - "lru-cache": "^7.14.1", + "lru-cache": "^10.0.0", "mime-types": "^2.1.35", - "multiformats": "^11.0.2", - "node-fetch": "^3.3.1", + "multiformats": "^12.0.1", + "node-fetch": "^3.3.2", "p-limit": "^4.0.0", - "pretty-bytes": "^6.0.0", + "pretty-bytes": "^6.1.1", "server-timing": "^3.3.3" }, "devDependencies": { - "nock": "^13.3.1", - "test": "^3.2.1" + "nock": "^13.3.2", + "test": "^3.3.0" }, "eslintConfig": { "extends": "ipfs", diff --git a/container/shim/src/bin/shim.js b/container/shim/src/bin/shim.js index 0fe73ba4..1064e98d 100644 --- a/container/shim/src/bin/shim.js +++ b/container/shim/src/bin/shim.js @@ -1,3 +1,4 @@ +import fs from "node:fs/promises"; import http from "node:http"; import { validateAddressString } from "@glif/filecoin-address"; @@ -5,17 +6,24 @@ import app from "../index.js"; import { register } from "../modules/registration.js"; import { FIL_WALLET_ADDRESS, - NODE_OPERATOR_EMAIL, - VERSION, + NETWORK, NODE_ID, - PORT, + NODE_ID_FILE_PATH, + NODE_OPERATOR_EMAIL, ORCHESTRATOR_REGISTRATION, - NETWORK, + PORT, + VERSION, } from "../config.js"; import { trapServer } from "../utils/trap.js"; import { debug } from "../utils/logging.js"; import startLogIngestor from "../modules/log_ingestor.js"; -import { refreshLocalNodes } from "../modules/local_nodes.js"; + +// verify that node id is a valid uuidv4 +if (!NODE_ID.match(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/)) { + debug("Invalid node ID, deleting node ID file"); + await fs.unlink(NODE_ID_FILE_PATH); + throw new Error("Invalid node ID"); +} debug("Saturn L1 Node"); debug.extend("id")(NODE_ID); @@ -43,7 +51,7 @@ setTimeout(async function () { // run log ingestor process in background (starts immediately and keeps running periodically) startLogIngestor(); - refreshLocalNodes(); + // refreshLocalNodes(); }, 500); const server = http.createServer(app); diff --git a/container/shim/src/config.js b/container/shim/src/config.js index cf920ada..cb52f2b6 100644 --- a/container/shim/src/config.js +++ b/container/shim/src/config.js @@ -1,6 +1,6 @@ import { readFile } from "fs/promises"; -const NODE_ID_FILE_PATH = "./shared/nodeId.txt"; +export const NODE_ID_FILE_PATH = "./shared/nodeId.txt"; export const DEV_VERSION = "0_dev"; export const PORT = 10361; diff --git a/container/shim/src/fetchers/lassie.js b/container/shim/src/fetchers/lassie.js index 95a26202..693c33dd 100644 --- a/container/shim/src/fetchers/lassie.js +++ b/container/shim/src/fetchers/lassie.js @@ -4,7 +4,7 @@ import { Transform, pipeline } from "node:stream"; import { pipeline as pipelinePromise } from "node:stream/promises"; import { CarBlockIterator } from "@ipld/car"; -import LRU from "lru-cache"; +import { LRUCache } from "lru-cache"; import { base64 } from "multiformats/bases/base64"; import fetch from "node-fetch"; @@ -24,7 +24,7 @@ const httpsAgent = new https.Agent(agentOpts); const httpAgent = new http.Agent(agentOpts); const ONE_GB = 1024 ** 3; -const blockCache = new LRU({ +const blockCache = new LRUCache({ maxSize: ONE_GB * 3, sizeCalculation: (block) => Buffer.byteLength(block), allowStale: true, @@ -159,6 +159,8 @@ export async function respondFromLassie(req, res, { cidObj, format }) { httpStatusCode: lassieRes?.status ?? null, requestErr, format, + traceparent: req.headers.traceparent, + serverTiming: lassieRes?.headers.get("server-timing"), }); } } @@ -246,6 +248,9 @@ function sendBlockResponse(res, block, cidObj, filename) { res.set("content-type", "application/vnd.ipld.raw"); res.set("content-disposition", `attachment; filename="${filename}"`); res.set("etag", `"${cidObj.toString()}.raw"`); + res.set("x-ipfs-path", `/ipfs/${cidObj.toString()}`); + res.set("x-ipfs-roots", cidObj.toString()); + res.set("x-content-type-options", "nosniff"); res.end(block); } diff --git a/container/shim/src/lib/ocsp/check.js b/container/shim/src/lib/ocsp/check.js index 0d6a34ec..1b2585f4 100644 --- a/container/shim/src/lib/ocsp/check.js +++ b/container/shim/src/lib/ocsp/check.js @@ -1,9 +1,9 @@ +import { promisify } from "node:util"; import rfc2560 from "asn1.js-rfc2560"; import { generate } from "./request.js"; import { getAuthorityInfo, getResponse } from "./utils.js"; import { verify } from "./verify.js"; -import { promisify } from "node:util"; const asyncGetResponse = promisify(getResponse); diff --git a/container/shim/src/modules/log_ingestor.js b/container/shim/src/modules/log_ingestor.js index 8352ff38..c1b0de81 100644 --- a/container/shim/src/modules/log_ingestor.js +++ b/container/shim/src/modules/log_ingestor.js @@ -24,6 +24,7 @@ const NGINX_LOG_KEYS_MAP = { referrer: (values) => values.ref, requestId: (values) => values.id, requestDurationSec: (values) => parseFloat(values.rt), + method: (values) => values.method, status: (values) => parseInt(values.status, 10), httpProtocol: (values) => values.sp, userAgent: (values) => values.ua, @@ -45,6 +46,7 @@ const NGINX_LOG_KEYS_MAP = { const parsed = parseFloat(values.urt); return isNaN(parsed) ? values.urt : parsed; }, + traceparent: (values) => values.tp, }; const LOG_FILE = "/usr/src/app/shared/nginx_log/node-access.log"; @@ -78,7 +80,11 @@ function parseSingleLine(line) { return acc; }, {}); - if (vars.clientAddress === "127.0.0.1") return null; + if (vars.method !== "GET") return null; + + if (vars.clientAddress === "127.0.0.1" && vars.url.hostname !== "handoff.strn.localhost") { + return null; + } const isIPFS = vars.url.pathname.startsWith("/ipfs/"); const isIPNS = vars.url.pathname.startsWith("/ipns/"); @@ -106,6 +112,7 @@ function parseSingleLine(line) { // the "http3" key can be removed. httpProtocol: vars.http3 || vars.httpProtocol, url: vars.url, + traceparent: vars.traceparent, }; } diff --git a/container/shim/src/modules/registration.js b/container/shim/src/modules/registration.js index 13a28fca..f9269eb2 100644 --- a/container/shim/src/modules/registration.js +++ b/container/shim/src/modules/registration.js @@ -45,7 +45,12 @@ export async function register(initial = false) { verifyHWRequirements(requirements, stats); - if (VERSION !== DEV_VERSION && initial) { + let preregisterResponse; + if (initial) { + preregisterResponse = await sendPreRegisterRequest(postOptions({ nodeId: NODE_ID })); + } + + if (VERSION !== DEV_VERSION && initial && preregisterResponse?.speedtestRequired !== false) { let speedtest; try { speedtest = await getSpeedtest(); @@ -171,6 +176,11 @@ async function checkCertValidity(certBuffer, registerOptions) { valid = false; } + if (NETWORK === "test" && cert.subjectAltName && !cert.subjectAltName.includes("l1s.saturn-test.ms")) { + debug("Certificate is missing l1s.saturn-test.ms SAN, getting a new one..."); + valid = false; + } + if (!valid) { try { await getNewTLSCert(registerOptions); @@ -213,7 +223,6 @@ async function sendRegisterRequest(initial, registerOptions) { ); if (!success) { - debug(error); throw new Error(error); } @@ -230,7 +239,7 @@ async function sendRegisterRequest(initial, registerOptions) { if (initial) prefillCache(); } catch (err) { - debug("Failed registration %s", err.message); + debug("Failed registration: %s", err.message); if (initial) { // we don't try again if we fail the initial registration process.exit(0); @@ -238,6 +247,26 @@ async function sendRegisterRequest(initial, registerOptions) { } } +async function sendPreRegisterRequest(postOptions) { + debug("Pre-registering with orchestrator"); + + try { + const res = await fetch(`${ORCHESTRATOR_URL}/pre-register`, postOptions); + + if (!res.ok) { + throw new Error(await res.text()); + } + + debug("Successful pre-registration"); + + return await res.json(); + } catch (err) { + debug("Failed pre-registration: %s", err.message); + // we don't try again if we fail the pre-registration + process.exit(0); + } +} + let deregistering; export async function deregister() { if (!ORCHESTRATOR_REGISTRATION) return; diff --git a/container/shim/src/utils/system.js b/container/shim/src/utils/system.js index 858de786..0b17ee0b 100644 --- a/container/shim/src/utils/system.js +++ b/container/shim/src/utils/system.js @@ -4,7 +4,7 @@ import { debug as Debug } from "./logging.js"; import { promisify } from "node:util"; import { exec as CpExec } from "node:child_process"; import prettyBytes from "pretty-bytes"; -import { SPEEDTEST_SERVER_CONFIG } from "../config.js"; +import { NETWORK, SPEEDTEST_SERVER_CONFIG } from "../config.js"; const exec = promisify(CpExec); @@ -48,8 +48,8 @@ export async function getDiskStats() { const usedDiskMB = valuesMB[2]; const availableDiskMB = valuesMB[3]; debug(`Disk Total: ${totalDiskMB / 1000} GB Used: ${usedDiskMB / 1000} GB Available: ${availableDiskMB / 1000} GB`); - if (availableDiskMB <= 50 * 1000) { - // 50 GB + if (availableDiskMB <= (NETWORK === "test" ? 10 : 50) * 1000) { + // 50 GB for mainnet, 10 GB for testnet debug( `WARNING: Full disk. Cache will be rotated and affect performance severely. Please consider upgrading your L1 node disk space.` ); diff --git a/container/start.sh b/container/start.sh index 34501ce5..60684dfd 100755 --- a/container/start.sh +++ b/container/start.sh @@ -36,6 +36,21 @@ else cp /etc/nginx/confs/non_tls_proxy.conf $L1_CONF_FILE; fi +min_uses=1 +min_free="50G" + +# If disk is full, set min_uses to 2 +if [ $(df -h /usr/src/app/shared | awk '(NR>1) { printf "%d", $5}') -ge 99 ]; then + min_uses=2; +fi + +# If network is test, set min_free to 10G +if [ "${NETWORK:-}" = "test" ]; then + min_free="10G" +fi + +sed -i "s@\$cache_min_uses@$min_uses@g" /etc/nginx/conf.d/shared.conf +sed -i "s@\$cache_min_free@$min_free@g" /etc/nginx/conf.d/proxy.conf sed -i "s@\$node_id@$(cat /usr/src/app/shared/nodeId.txt)@g" /etc/nginx/conf.d/shared.conf sed -i "s@\$node_version@$VERSION@g" /etc/nginx/conf.d/shared.conf @@ -65,7 +80,7 @@ export LASSIE_EVENT_RECORDER_URL="https://lassie-event-recorder.dev.cid.contact/ mkdir -p $LASSIE_TEMP_DIRECTORY # Clean up leftover files in lassie dir. -find $LASSIE_TEMP_DIRECTORY -name "lassie_carstorage*" -exec rm {} + +find $LASSIE_TEMP_DIRECTORY -name "lassie_car*" -exec rm {} + if [ "${LASSIE_ORIGIN:-}" != "" ]; then if [ "${NETWORK:-}" = "main" ]; then diff --git a/scripts/integration_tests.sh b/scripts/integration_tests.sh index 7dbd1f66..fcb0ef96 100644 --- a/scripts/integration_tests.sh +++ b/scripts/integration_tests.sh @@ -41,4 +41,4 @@ test_range_request "bafybeifpz6onienrgwvb3mw5rg7piq5jh63ystjn7s5wk6ttezy2gy5xwu/ test_range_request "QmafUYju2Ab4ETi5HJG1cqjmnjs2xw9PUuBKzU7Hi3zvXU/MC_TheSource.mp4?entity-bytes=0:1048576" # range request with offset -# test_range_request "bafybeifpz6onienrgwvb3mw5rg7piq5jh63ystjn7s5wk6ttezy2gy5xwu/Mexico.JPG?entity-bytes=1048576:2097152" +test_range_request "bafybeifpz6onienrgwvb3mw5rg7piq5jh63ystjn7s5wk6ttezy2gy5xwu/Mexico.JPG?entity-bytes=1048576:2097152" diff --git a/scripts/run.sh b/scripts/run.sh index ef66094d..464b9045 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -9,19 +9,23 @@ set -e : "${HTTP_PORT:=80}" : "${HTTPS_PORT:=443}" : "${IS_CORE_L1:=false}" +: "${LASSIE_ALLOW_PROVIDERS:-}" +: "${DOCKER_NETWORK:=bridge}" mkdir -p "$(pwd)/shared" echo "$(date -u) [host] Running Saturn node dev, with volume in $(pwd)/shared" # Start the docker image docker run --name saturn-node --rm $( [ "$CI" != "true" ] && printf "%s" "-it" ) \ + --network=$DOCKER_NETWORK \ -v "$(pwd)/shared:/usr/src/app/shared:Z" \ -e "FIL_WALLET_ADDRESS=$FIL_WALLET_ADDRESS" \ -e "NODE_OPERATOR_EMAIL=$NODE_OPERATOR_EMAIL" \ -e "IPFS_GATEWAY_ORIGIN=$IPFS_GATEWAY_ORIGIN" \ -e "ORCHESTRATOR_REGISTRATION=$ORCHESTRATOR_REGISTRATION" \ -e "SPEEDTEST_SERVER_CONFIG=$SPEEDTEST_SERVER_CONFIG" \ - -e "LASSIE_ORIGIN=$LASSIE_ORIGIN" \ -e "IS_CORE_L1=$IS_CORE_L1" \ + -e "LASSIE_ORIGIN=$LASSIE_ORIGIN" \ + -e "LASSIE_ALLOW_PROVIDERS=$LASSIE_ALLOW_PROVIDERS" \ -p "$HTTPS_PORT":443 -p "$HTTP_PORT":80 \ saturn-node