diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5bd08d101e..b15a2fa965 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,115 +1,42 @@ -# Notes: -# -# jobs. -# -# A seperate job id results in a lot of duplication of nix/cachix work. -# The build will have to download any substituted derivations from cachix -# for the steps with each distinct job id and upload built derivations to -# cachix after each job has completed, either succesfully or on failure. -# -# jobs..steps.run -# -# build + test are distinct as each step entry results in a collapsable title -# within the log output, which makes it easier to view failing builds or -# tests independently. -# -# jobs..strategy.fail-fast -# -# Set to false so developers working on vere or king-haskell can have their -# respective builds proceed without the other causing failure. -# -# shell.nix -# -# mkShell doesn't allow you to build it - so instantiate all the subshells -# defined for the individual pkg/*/shell.nix as a sanity check and to create -# some artefacts suitable for developers to pull from cachix. The top-level -# shell.nix build time is dominated by Haskell dependencies so it's built as -# part of the haskell build steps. -# -# Syntax: -# -# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions - name: build on: push: paths: + - '.github/workflows/build.yml' + - '.github/workflows/vere.yml' - 'pkg/arvo/**' - 'pkg/docker-image/**' - 'pkg/ent/**' - 'pkg/ge-additions/**' - 'pkg/libaes_siv/**' - 'pkg/urbit/**' + - 'pkg/urcrypt/**' - 'bin/**' - 'nix/**' + - 'default.nix' pull_request: paths: + - '.github/workflows/build.yml' + - '.github/workflows/vere.yml' - 'pkg/arvo/**' - 'pkg/docker-image/**' - 'pkg/ent/**' - 'pkg/ge-additions/**' - 'pkg/libaes_siv/**' - 'pkg/urbit/**' + - 'pkg/urcrypt/**' - 'bin/**' - 'nix/**' + - 'default.nix' jobs: - urbit: - strategy: - fail-fast: false - matrix: - include: - - { os: ubuntu-latest } - - { os: macos-latest } - - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v2 - - # We only want the extra nix config on linux, where it is necessary - # for the docker build. We don't want in on Mac, where it isn't but - # it breaks the nix install. The two `if` clauses should be mutually - # exclusive - - uses: cachix/install-nix-action@v16 - with: - extra_nix_config: | - system-features = nixos-test benchmark big-parallel kvm - if: ${{ matrix.os == 'ubuntu-latest' }} - - uses: cachix/install-nix-action@v16 - if: ${{ matrix.os != 'ubuntu-latest' }} - - - uses: cachix/cachix-action@v10 - with: - name: ares - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - - - run: nix-build -A urbit --arg enableStatic true - - - if: ${{ matrix.os == 'ubuntu-latest' }} - run: nix-build -A urbit-tests - - - if: ${{ matrix.os == 'ubuntu-latest' }} - run: nix-build -A docker-image - - mingw: - runs-on: windows-latest - defaults: - run: - shell: C:\msys64\msys2_shell.cmd -mingw64 -defterm -no-start -here -c ". <(cygpath '{0}')" - working-directory: ./pkg/urbit - - steps: - - uses: actions/checkout@v2 - with: - lfs: true - - # echo suppresses pacman prompt - - run: echo|./configure - env: - CACHIX_CACHE: ares - CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} - - - run: make build/urbit build/urbit-worker - - run: build/urbit -l -d -B ../../bin/solid.pill -F bus && curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}' http://localhost:12321 + call-vere: + uses: ./.github/workflows/vere.yml + with: + pace: 'often' + upload: >- + ${{ + (github.ref_name == 'next/vere' && github.ref_type == 'branch') + }} + secrets: inherit diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 0000000000..58331a0813 --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,14 @@ +name: pre-release + +on: + release: null + push: + tags: 'urbit-v[0-9]+.[0-9]+-rc[0-9]+' + +jobs: + call-vere: + uses: ./.github/workflows/vere.yml + with: + pace: 'soon' + upload: true + secrets: inherit diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index 293e0d0428..13fc3f9156 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -3,7 +3,7 @@ name: release-docker on: release: null push: - tags: ['urbit-v*'] + tags: 'urbit-v[0-9]+.[0-9]+' jobs: upload: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0af64103a9..8a8818b499 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,42 +3,12 @@ name: release on: release: null push: - tags: ['*'] + tags: 'urbit-v[0-9]+.[0-9]+' jobs: - upload: - strategy: - matrix: - include: - - { os: ubuntu-latest, system: x86_64-linux } - - { os: macos-latest, system: x86_64-darwin } - - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v16 - - uses: cachix/cachix-action@v10 - with: - name: ${{ secrets.CACHIX_NAME }} - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - - - uses: google-github-actions/setup-gcloud@v0.2.0 - with: - version: '290.0.1' - service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }} - project_id: ${{ secrets.GCS_PROJECT }} - export_default_credentials: true - - - run: nix-build -A tarball --arg enableStatic true - - - name: Run upload to bootstrap.urbit.org - run: | - version="$(cat ./pkg/urbit/version)" - system="$(nix-instantiate --eval --expr 'builtins.currentSystem')" - system=${system:1:${#system}-2} - target="gs://bootstrap.urbit.org/ci/urbit-v${version}-${system}-${GITHUB_SHA:0:9}.tgz" - - gsutil cp -n ./result "$target" - - echo "upload to $target complete." + call-vere: + uses: ./.github/workflows/vere.yml + with: + pace: 'live' + upload: true + secrets: inherit diff --git a/.github/workflows/tarballs.yml b/.github/workflows/tarballs.yml new file mode 100644 index 0000000000..9f8456cf62 --- /dev/null +++ b/.github/workflows/tarballs.yml @@ -0,0 +1,44 @@ +name: tarballs + +on: + release: null + push: + tags: ['*'] + +jobs: + upload: + strategy: + matrix: + include: + - { os: ubuntu-latest, system: x86_64-linux } + - { os: macos-latest, system: x86_64-darwin } + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - uses: cachix/install-nix-action@v16 + - uses: cachix/cachix-action@v10 + with: + name: ${{ secrets.CACHIX_NAME }} + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - uses: google-github-actions/setup-gcloud@v0.2.0 + with: + version: '290.0.1' + service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }} + project_id: ${{ secrets.GCS_PROJECT }} + export_default_credentials: true + + - run: nix-build -A tarball --arg enableStatic true + + - name: Run upload to bootstrap.urbit.org + run: | + version="$(cat ./pkg/urbit/version)" + system="$(nix-instantiate --eval --expr 'builtins.currentSystem')" + system=${system:1:${#system}-2} + target="gs://bootstrap.urbit.org/ci/urbit-v${version}-${system}-${GITHUB_SHA:0:9}.tgz" + + gsutil cp -n ./result "$target" + + echo "upload to $target complete." diff --git a/.github/workflows/vere.yml b/.github/workflows/vere.yml new file mode 100644 index 0000000000..9c1a0693ec --- /dev/null +++ b/.github/workflows/vere.yml @@ -0,0 +1,263 @@ + +name: vere + +on: + workflow_call: + inputs: + upload: + description: 'upload binaries to gcp' + type: boolean + default: false + required: false + pace: + description: 'release pace' + type: string + default: 'often' + required: false + secrets: + CACHIX_AUTH_TOKEN: + required: true + GCS_SERVICE_ACCOUNT_KEY: + required: true + GCS_PROJECT: + required: true + + workflow_dispatch: + inputs: + upload: + description: 'upload binaries to gcp' + type: boolean + default: false + required: false + pace: + description: 'release pace' + type: choice + options: + - often + - soon + - live + +env: + UPLOAD_BASE: bootstrap.urbit.org/vere + VERE_PACE: ${{ inputs.pace }} + VERSION_TYPE: ${{ (inputs.pace == 'soon' || inputs.pace == 'live') && 'real' || 'hash' }} + +jobs: + urbit: + strategy: + fail-fast: false + matrix: + include: + - { os: ubuntu-latest } + - { os: macos-latest } + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + # We only want the extra nix config on linux, where it is necessary + # for the docker build. We don't want in on Mac, where it isn't but + # it breaks the nix install. The two `if` clauses should be mutually + # exclusive + - uses: cachix/install-nix-action@v16 + with: + extra_nix_config: | + system-features = nixos-test benchmark big-parallel kvm + if: ${{ matrix.os == 'ubuntu-latest' }} + - uses: cachix/install-nix-action@v16 + if: ${{ matrix.os != 'ubuntu-latest' }} + + - uses: cachix/cachix-action@v10 + with: + name: ares + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - name: build static binary + run: | + nix-build -A urbit \ + --arg enableStatic true \ + --argstr verePace ${{ env.VERE_PACE }} > ./urbit-derivation + cat ./urbit-derivation + echo -n "urbit_static=" >> $GITHUB_ENV + cat ./urbit-derivation >> $GITHUB_ENV + cat ./urbit-derivation + + - name: confirm binary is mostly static + if: matrix.os == 'macos-latest' + run: | + bin="${{ env.urbit_static }}/bin/urbit" + + if [ ! -f "$bin" ]; then + echo "no binary at $bin" + exit 1; + fi + + libs="$(otool -L "${{ env.urbit_static }}/bin/urbit" | tail -n +2)" + + # XX CoreFoundation? + if [ -z "$(echo "$libs" | grep -v libSystem)" ]; then + echo "it's mostly static" + echo "$libs" + exit 0 + else + echo "dynamic links found:" + echo "$libs" + exit 1 + fi + + - name: get version string + run: | + if [ "real" == "$VERSION_TYPE" ]; then + version="$(cat ./pkg/urbit/version)" + else + version="${GITHUB_SHA:0:9}" + fi + + echo -n "$version" > ./version-string + + - name: upload version string artifact + if: matrix.os == 'ubuntu-latest' + uses: actions/upload-artifact@v3 + with: + name: version-string + path: version-string + + - uses: google-github-actions/setup-gcloud@v0.2.0 + if: inputs.upload + with: + version: '290.0.1' + service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }} + project_id: ${{ secrets.GCS_PROJECT }} + export_default_credentials: true + + - name: upload binary to bootstrap.urbit.org + if: inputs.upload + run: | + version="$(cat ./version-string)" + system="$(nix-instantiate --eval --expr 'builtins.currentSystem')" + system=${system:1:${#system}-2} + target="gs://${UPLOAD_BASE}/${VERE_PACE}/${version}/vere-v${version}-${system}" + + gsutil cp -n "${{ env.urbit_static }}/bin/urbit" "$target" + exitcode=$? + + test $exitcode -eq 0 && + echo "upload to $target complete." || + echo "upload to $target failed."; + exit $exitcode + + - if: ${{ matrix.os == 'ubuntu-latest' }} + run: nix-build -A urbit-tests + + - if: ${{ matrix.os == 'ubuntu-latest' }} + run: nix-build -A docker-image + + mingw: + runs-on: windows-latest + defaults: + run: + shell: > + C:\msys64\msys2_shell.cmd -mingw64 -defterm -no-start -here -c + ". <(cygpath '{0}')" + working-directory: ./pkg/urbit + + steps: + - uses: actions/checkout@v2 + with: + lfs: true + + # echo suppresses pacman prompt + - run: echo|./configure + env: + CACHIX_CACHE: ares + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - run: mingw32-make build/urbit + - run: > + build/urbit -l -d -B ../../bin/solid.pill -F bus && + curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}' + http://localhost:12321 + + - name: confirm binary is mostly static + run: | + if [ -z "$(ldd build/urbit | grep -vi "windows/system32")"]; then + echo "it's mostly static" + exit 0 + else + echo "dynamic links found:" + ldd build/urbit + exit 1 + fi + + - uses: actions/setup-python@v2 + if: inputs.upload + with: + python-version: 3.7 + + - uses: google-github-actions/setup-gcloud@v0.6.0 + if: inputs.upload + env: + # see https://github.com/google-github-actions/setup-gcloud/issues/100 + CLOUDSDK_PYTHON: ${{env.pythonLocation}}\python.exe + with: + service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }} + project_id: ${{ secrets.GCS_PROJECT }} + export_default_credentials: true + + - name: upload binary to bootstrap.urbit.org + if: inputs.upload + env: + CLOUDSDK_PYTHON: ${{env.pythonLocation}}\python.exe + shell: bash + run: | + if [ "real" == "$VERSION_TYPE" ]; then + version="$(cat ./version)" + else + version="${GITHUB_SHA:0:9}" + fi + + system="x86_64-windows" + target="gs://${UPLOAD_BASE}/${VERE_PACE}/${version}/vere-v${version}-${system}.exe" + + gsutil cp -n ./build/urbit.exe "$target" + exitcode=$? + + test $exitcode -eq 0 && + echo "upload to $target complete." || + echo "upload to $target failed."; + exit $exitcode + + + after: + runs-on: ubuntu-latest + needs: [urbit, mingw] + # XX disabled due to missing storage.objects.delete access + if: false + # if: inputs.upload + steps: + - uses: google-github-actions/setup-gcloud@v0.2.0 + with: + version: '290.0.1' + service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }} + project_id: ${{ secrets.GCS_PROJECT }} + export_default_credentials: true + + - name: download version-string + uses: actions/download-artifact@v3 + with: + name: version-string + + - name: update latest deployed version + run: | + target="gs://${UPLOAD_BASE}/${VERE_PACE}/last" + + # *not* -n, as we want to overwrite the latest version-string + # + gsutil cp ./version-string "$target" + exitcode=$? + + test $exitcode -eq 0 && + echo "upload to $target complete." || + echo "upload to $target failed."; + exit $exitcode diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da4c691d8e..e1f66402bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -216,7 +216,7 @@ Hoon kernel (anything under [`pkg/arvo/sys/`][sys]) is bootstrapped from a so-called *pill*, and must be recompiled if any changes are made. This should happen automatically when you make changes, but if it doesn't, the command to manually recompile and install the new kernel is `|reset` in `dojo`. This -rebuilds from the `sys` directory in the `home` desk in `%clay`. +rebuilds from the `sys` directory in the `base` desk in `%clay`. Currently, `|reset` does not reload apps like `dojo` itself, which will still reference the old kernel. To force them to reload, make a trivial edit to their diff --git a/MAINTAINERS.md b/MAINTAINERS.md index aa31bc4de0..29370a874a 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -326,7 +326,7 @@ separate releases. (**Note**: the following steps are automated by some other Tlon-internal tooling. Just ask `~nidsut-tomdun` for details.) -For Urbit OS updates, this means copying the files into ~zod's %home desk. The +For Urbit OS updates, this means copying the files into ~zod's %base desk. The changes should be merged into /~zod/kids and then propagated through other galaxies and stars to the rest of the network. @@ -335,10 +335,10 @@ For consistency, I create a release tarball and then rsync the files in. ``` $ wget https://github.com/urbit/urbit/archive/urbit-os-vx.y.tar.gz $ tar xzf urbit-os-vx.y.tar.gz -$ herb zod -p hood -d "+hood/mount /=home=" -$ rsync -zr --delete urbit-urbit-os-vx.y/pkg/arvo/ zod/home -$ herb zod -p hood -d "+hood/commit %home" -$ herb zod -p hood -d "+hood/merge %kids our %home" +$ herb zod -p hood -d "+hood/mount /=base=" +$ rsync -zr --delete urbit-urbit-os-vx.y/pkg/arvo/ zod/base +$ herb zod -p hood -d "+hood/commit %base" +$ herb zod -p hood -d "+hood/merge %kids our %base" ``` For Vere updates, this means simply shutting down each desired ship, installing diff --git a/bin/brass.pill b/bin/brass.pill index 99aaaee04f..ad7da6640a 100644 --- a/bin/brass.pill +++ b/bin/brass.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae4a7a69fe81c5f2114d7b7360c05602f614fe66b96d1db4c3dc0c2a2a5d856e -size 7536000 +oid sha256:c4247c64a7d9fc0c0f1d2f017c21dd3464ddfe56529c7d6eef0e64554bd453e8 +size 7611162 diff --git a/bin/ivory.pill b/bin/ivory.pill index 33b0f0a2cc..c782fb7250 100644 --- a/bin/ivory.pill +++ b/bin/ivory.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f59ec4eaf907227a1fd64e1d54810b769b5d39f6811c6bb254b2e89de528ca04 -size 1209494 +oid sha256:5123a1ac30b83ec026587574df1ce13a73e72d06588ff68b5c41c09e1bebb5b7 +size 949962 diff --git a/bin/multi-brass.pill b/bin/multi-brass.pill index 416e36f98b..debb8ecc8a 100644 --- a/bin/multi-brass.pill +++ b/bin/multi-brass.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e660fba934c5b80eeda64037a1f28c71eff4b2ea0bd28809b91432ca3d5ef08a -size 23052691 +oid sha256:2f46209c31bc7be965b6ba32db92fb0746be15d9613b1c3c8d09ce7fa0e5e157 +size 8280141 diff --git a/bin/multi.pill b/bin/multi.pill index 9e95dfefb6..a05f085f26 100644 --- a/bin/multi.pill +++ b/bin/multi.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c27cdb47bccda98ba68556181cae6cd845c6daf8d7426d82adf67c1e8f532be9 -size 7454265 +oid sha256:187ea751a274dba7ed69df3a5b8f6f7ac620e3f9787abd75b18cf494d0c41f05 +size 11174099 diff --git a/bin/solid.pill b/bin/solid.pill index 32d8e91132..a79fa3353c 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcab0698de6efda1bbac54b0833da5e853bca058919110aa5668aa63fb40626e -size 9392699 +oid sha256:c45166ff0f8ab8dc1552bcef519c77c0afa6ca52f8ed1ba31ed632012667d619 +size 8674763 diff --git a/default.nix b/default.nix index 60df74a193..3161c5363b 100644 --- a/default.nix +++ b/default.nix @@ -40,7 +40,9 @@ , crossOverlays ? [ ] # Whether to use pkgs.pkgsStatic.* to obtain statically linked package # dependencies - ie. when building fully-static libraries or executables. -, enableStatic ? false }: +, enableStatic ? false + # release channel (when static) +, verePace ? "" }: let @@ -95,7 +97,7 @@ let marsSources = callPackage ./nix/pkgs/marsSources { }; - urbit = callPackage ./nix/pkgs/urbit { inherit enableStatic; }; + urbit = callPackage ./nix/pkgs/urbit { inherit enableStatic verePace; }; urcrypt = callPackage ./nix/pkgs/urcrypt { inherit enableStatic; }; @@ -109,7 +111,6 @@ let urbit-debug = urbit.override { enableDebug = true; }; urbit-tests = libLocal.testFakeShip { - inherit herb; inherit arvo; urbit = urbit-debug; @@ -127,7 +128,6 @@ let contents = { "${name}/urbit" = "${urbit}/bin/urbit"; - "${name}/urbit-worker" = "${urbit}/bin/urbit-worker"; }; }; diff --git a/doc/spec/http-ports.txt b/doc/spec/http-ports.txt deleted file mode 100644 index 3476a70c9a..0000000000 --- a/doc/spec/http-ports.txt +++ /dev/null @@ -1,13 +0,0 @@ -.http.ports ABNF Format Specifiation -Version 0.1, 12 December 2016 - -http-ports-file = *(http-ports-line LF) - -http-ports-line = port-num SP secure-val SP loopback-val - -; number of a port being listened on -port-num = *DIGIT -; whether the http subsystem has the port marked as "secure" -secure-val = ("assumed-secure" / "insecure") -; whether the port is bound only on loopback or on all interfaces -loopback-val = ("loopback" / "public") diff --git a/nix/lib/boot-fake-ship.nix b/nix/lib/boot-fake-ship.nix index 9a5d01ea95..2b955c85fd 100644 --- a/nix/lib/boot-fake-ship.nix +++ b/nix/lib/boot-fake-ship.nix @@ -1,6 +1,6 @@ -{ lib, stdenvNoCC, cacert }: +{ lib, stdenvNoCC, curl }: -{ urbit, herb, arvo ? null, pill, ship, arguments ? [ "-l" ] }: +{ urbit, arvo ? null, pill, ship, arguments ? [ "-l" ] }: let @@ -10,16 +10,11 @@ let in stdenvNoCC.mkDerivation { name = "fake-${ship}"; - buildInputs = [ cacert urbit herb ]; + buildInputs = [ curl urbit ]; phases = [ "buildPhase" "installPhase " ]; buildPhase = '' - if ! [ -f "$SSL_CERT_FILE" ]; then - header "$SSL_CERT_FILE doesn't exist" - exit 1 - fi - set -xeuo pipefail urbit ${lib.concatStringsSep " " args} ./pier @@ -34,13 +29,27 @@ in stdenvNoCC.mkDerivation { trap cleanup EXIT + port=$(cat ./pier/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1) + + lensd() { + curl -f -s \ + --data "{\"source\":{\"dojo\":\"$1\"},\"sink\":{\"stdout\":null}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' + } + + lensa() { + curl -f -s \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' + } + check () { - [ 3 -eq "$(herb ./pier -d 3)" ] + [ 3 -eq "$(lensd 3)" ] } if check && sleep 10 && check; then header "boot success" - herb ./pier -p hood -d '+hood/exit' + lensa hood '+hood/exit' while [ -f ./pier/.vere.lock ]; do echo "waiting for pier to shut down" sleep 5 @@ -48,8 +57,11 @@ in stdenvNoCC.mkDerivation { else header "boot failure" kill $(< ./pier/.vere.lock) || true + set +x exit 1 fi + + set +x ''; installPhase = '' diff --git a/nix/lib/test-fake-ship.nix b/nix/lib/test-fake-ship.nix index b5b567e3c5..f9fc7e2fa0 100644 --- a/nix/lib/test-fake-ship.nix +++ b/nix/lib/test-fake-ship.nix @@ -1,16 +1,16 @@ -{ lib, stdenvNoCC, cacert, python3, bootFakeShip }: +{ lib, stdenvNoCC, curl, python3, bootFakeShip }: -{ urbit, herb, arvo ? null, pill, ship ? "bus", arguments ? urbit.meta.arguments +{ urbit, arvo ? null, pill, ship ? "bus", arguments ? urbit.meta.arguments , doCheck ? true }: stdenvNoCC.mkDerivation { name = "test-${ship}"; - src = bootFakeShip { inherit urbit herb arvo pill ship; }; + src = bootFakeShip { inherit urbit arvo pill ship; }; phases = [ "unpackPhase" "buildPhase" "checkPhase" ]; - buildInputs = [ cacert urbit herb python3 ]; + buildInputs = [ curl python3 urbit ]; unpackPhase = '' cp -R $src ./pier @@ -26,6 +26,22 @@ stdenvNoCC.mkDerivation { # See: https://github.com/travis-ci/travis-ci/issues/4704#issuecomment-348435959 python3 -c $'import os\n[os.set_blocking(i, True) for i in range(3)]\n' + port=$(cat ./pier/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1) + + lensd() { + # -f elided, this can hit server-side timeouts + curl -s \ + --data "{\"source\":{\"dojo\":\"$1\"},\"sink\":{\"stdout\":null}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' + } + + lensa() { + # -f elided, this can hit server-side timeouts + curl -s \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' + } + tail -F urbit-output >&2 & tailproc=$! @@ -41,69 +57,69 @@ stdenvNoCC.mkDerivation { # measure initial memory usage # - herb ./pier -d '~& ~ ~& %init-mass-start ~' - herb ./pier -p hood -d '+hood/mass' - herb ./pier -d '~& ~ ~& %init-mass-end ~' + lensd '~& ~ ~& %init-mass-start ~' + lensa hood '+hood/mass' + lensd '~& ~ ~& %init-mass-end ~' # run the unit tests # - herb ./pier -d '~& ~ ~& %test-unit-start ~' - herb ./pier -d '####-test %/tests ~' - herb ./pier -d '~& ~ ~& %test-unit-end ~' + lensd '~& ~ ~& %test-unit-start ~' + lensd '-test %/tests ~' + lensd '~& ~ ~& %test-unit-end ~' # use the :test app to build all agents, generators, and marks # - herb ./pier -p hood -d '+hood/start %test' + lensa hood '+hood/start %test' - herb ./pier -d '~& ~ ~& %test-agents-start ~' - herb ./pier -p test -d '%agents' - herb ./pier -d '~& ~ ~& %test-agents-end ~' + lensd '~& ~ ~& %test-agents-start ~' + lensa test '%agents' + lensd '~& ~ ~& %test-agents-end ~' - herb ./pier -d '~& ~ ~& %test-generators-start ~' - herb ./pier -p test -d '%generators' - herb ./pier -d '~& ~ ~& %test-generators-end ~' + lensd '~& ~ ~& %test-generators-start ~' + lensa test '%generators' + lensd '~& ~ ~& %test-generators-end ~' - herb ./pier -d '~& ~ ~& %test-marks-start ~' - herb ./pier -p test -d '%marks' - herb ./pier -d '~& ~ ~& %test-marks-end ~' + lensd '~& ~ ~& %test-marks-start ~' + lensa test '%marks' + lensd '~& ~ ~& %test-marks-end ~' # measure memory usage post tests # - herb ./pier -d '~& ~ ~& %test-mass-start ~' - herb ./pier -p hood -d '+hood/mass' - herb ./pier -d '~& ~ ~& %test-mass-end ~' + lensd '~& ~ ~& %test-mass-start ~' + lensa hood '+hood/mass' + lensd '~& ~ ~& %test-mass-end ~' # defragment the loom # - herb ./pier -d '~& ~ ~& %pack-start ~' - herb ./pier -p hood -d '+hood/pack' - herb ./pier -d '~& ~ ~& %pack-end ~' + lensd '~& ~ ~& %pack-start ~' + lensa hood '+hood/pack' + lensd '~& ~ ~& %pack-end ~' # reclaim space within arvo # - herb ./pier -d '~& ~ ~& %trim-start ~' - herb ./pier -p hood -d '+hood/trim' - herb ./pier -d '~& ~ ~& %trim-end ~' + lensd '~& ~ ~& %trim-start ~' + lensa hood '+hood/trim' + lensd '~& ~ ~& %trim-end ~' # measure memory usage pre |meld # - herb ./pier -d '~& ~ ~& %trim-mass-start ~' - herb ./pier -p hood -d '+hood/mass' - herb ./pier -d '~& ~ ~& %trim-mass-end ~' + lensd '~& ~ ~& %trim-mass-start ~' + lensa hood '+hood/mass' + lensd '~& ~ ~& %trim-mass-end ~' # globally deduplicate # - herb ./pier -d '~& ~ ~& %meld-start ~' - herb ./pier -p hood -d '+hood/meld' - herb ./pier -d '~& ~ ~& %meld-end ~' + lensd '~& ~ ~& %meld-start ~' + lensa hood '+hood/meld' + lensd '~& ~ ~& %meld-end ~' # measure memory usage post |meld # - herb ./pier -d '~& ~ ~& %meld-mass-start ~' - herb ./pier -p hood -d '+hood/mass' - herb ./pier -d '~& ~ ~& %meld-mass-end ~' + lensd '~& ~ ~& %meld-mass-start ~' + lensa hood '+hood/mass' + lensd '~& ~ ~& %meld-mass-end ~' - herb ./pier -p hood -d '+hood/exit' + lensa hood '+hood/exit' cleanup @@ -128,6 +144,8 @@ stdenvNoCC.mkDerivation { mkdir -p $out cp test-output-* $out/ + + set +x ''; checkPhase = '' @@ -145,7 +163,7 @@ stdenvNoCC.mkDerivation { fail=0 for f in $(find "$out/" -type f); do - if egrep "((FAILED|CRASHED)|(ford|warn):) " $f >/dev/null; then + if egrep "((FAILED|CRASHED)|warn:) " $f >/dev/null; then if [[ $fail -eq 0 ]]; then hdr "Test Failures" fi @@ -168,6 +186,4 @@ stdenvNoCC.mkDerivation { # Fix 'bind: operation not permitted' when nix.useSandbox = true on darwin. # See https://github.com/NixOS/nix/blob/5f6840fbb49ae5b534423bd8a4360646ee93dbaf/src/libstore/build.cc#L2961 __darwinAllowLocalNetworking = true; - - meta = { platforms = [ "x86_64-linux" ]; }; } diff --git a/nix/overlays/native.nix b/nix/overlays/native.nix index 76dee9c469..4f34fe1367 100644 --- a/nix/overlays/native.nix +++ b/nix/overlays/native.nix @@ -27,6 +27,10 @@ in { brotliSupport = false; }; + # lies, all lies + openssl-static-osx = prev.openssl; + zlib-static-osx = prev.zlib; + lmdb = prev.lmdb.overrideAttrs (attrs: { patches = optionalList attrs.patches ++ prev.lib.optional prev.stdenv.isDarwin [ diff --git a/nix/overlays/static.nix b/nix/overlays/static.nix index 64cf0a16e8..1d364a5986 100644 --- a/nix/overlays/static.nix +++ b/nix/overlays/static.nix @@ -16,12 +16,19 @@ let in { gmp = enableStatic prev.gmp; - curlUrbit = enableStatic prev.curlUrbit; + curlUrbit = enableStatic (prev.curlUrbit.override { openssl = final.openssl-static-osx; zlib = final.zlib-static-osx; }); libuv = enableStatic prev.libuv; libffi = enableStatic prev.libffi; + openssl-static-osx = prev.openssl.override { + static = true; + withPerl = false; + }; + + zlib-static-osx = if final.stdenv.isDarwin then prev.zlib.static else prev.zlib; + secp256k1 = enableStatic prev.secp256k1; lmdb = prev.lmdb.overrideAttrs (old: diff --git a/nix/pkgs/pill/brass.nix b/nix/pkgs/pill/brass.nix index 54a816df0a..36b18dd9ad 100644 --- a/nix/pkgs/pill/brass.nix +++ b/nix/pkgs/pill/brass.nix @@ -1,4 +1,4 @@ -{ lib, stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, herb +{ lib, stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, curl , withRopsten ? false }: let @@ -7,13 +7,13 @@ let in { build = import ./builder.nix { - inherit stdenvNoCC urbit herb; + inherit stdenvNoCC urbit curl; name = "brass" + lib.optionalString withRopsten "-ropsten"; builder = ./brass.sh; arvo = if withRopsten then arvo.ropsten else arvo; pier = bootFakeShip { - inherit urbit herb; + inherit urbit; pill = solid.lfs; ship = "zod"; diff --git a/nix/pkgs/pill/brass.sh b/nix/pkgs/pill/brass.sh index 114578d6b9..f158750ee2 100644 --- a/nix/pkgs/pill/brass.sh +++ b/nix/pkgs/pill/brass.sh @@ -15,9 +15,26 @@ cleanup () { trap cleanup EXIT -header "running herb +brass" +header "running +brass" -herb ./pier -P brass.pill -d '+brass' -herb ./pier -p hood -d '+hood/exit' +port=$(cat ./pier/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1) + +lensa() { + # -f elided, this can hit server-side timeouts + curl -s \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' +} + +lensf() { + # -f elided, this can hit server-side timeouts + d=$(echo $1 | sed 's/\./\//g') + curl -sJO \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"output-pill\":\"$d\"}}" \ + "http://localhost:$port" +} + +lensf brass.pill '+brass' +lensa hood '+hood/exit' stopNest diff --git a/nix/pkgs/pill/builder.nix b/nix/pkgs/pill/builder.nix index f97d0f81e9..e5860bc124 100644 --- a/nix/pkgs/pill/builder.nix +++ b/nix/pkgs/pill/builder.nix @@ -1,9 +1,9 @@ -{ stdenvNoCC, urbit, arvo, herb, name, builder, pier }: +{ stdenvNoCC, urbit, arvo, curl, name, builder, pier }: stdenvNoCC.mkDerivation { name = "${name}.pill"; src = pier; - buildInputs = [ urbit herb ]; + buildInputs = [ curl urbit ]; dontUnpack = true; buildPhase = builtins.readFile builder; diff --git a/nix/pkgs/pill/ivory.nix b/nix/pkgs/pill/ivory.nix index 354cfbd396..9eceef1093 100644 --- a/nix/pkgs/pill/ivory.nix +++ b/nix/pkgs/pill/ivory.nix @@ -1,4 +1,4 @@ -{ lib, stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, herb, xxd +{ lib, stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, curl, xxd , withRopsten ? false }: let @@ -7,13 +7,13 @@ let in { build = import ./builder.nix { - inherit stdenvNoCC urbit herb; + inherit stdenvNoCC urbit curl; name = "ivory" + lib.optionalString withRopsten "-ropsten"; builder = ./ivory.sh; arvo = if withRopsten then arvo.ropsten else arvo; pier = bootFakeShip { - inherit urbit herb; + inherit urbit; pill = solid.lfs; ship = "zod"; @@ -34,7 +34,7 @@ in { mkdir -p $out/include cat $src > $file - xxd -i $file > $out/include/ivory.h + xxd -i $file > $out/include/ivory_impl.h ''; preferLocalBuild = true; diff --git a/nix/pkgs/pill/ivory.sh b/nix/pkgs/pill/ivory.sh index fc5ced9a66..cd44c52fa7 100644 --- a/nix/pkgs/pill/ivory.sh +++ b/nix/pkgs/pill/ivory.sh @@ -15,9 +15,26 @@ cleanup () { trap cleanup EXIT -header "running herb +ivory" +header "running +ivory" -herb ./pier -P ivory.pill -d '+ivory' -herb ./pier -p hood -d '+hood/exit' +port=$(cat ./pier/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1) + +lensa() { + # -f elided, this can hit server-side timeouts + curl -s \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' +} + +lensf() { + # -f elided, this can hit server-side timeouts + d=$(echo $1 | sed 's/\./\//g') + curl -sJO \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"output-pill\":\"$d\"}}" \ + "http://localhost:$port" +} + +lensf ivory.pill '+ivory' +lensa hood '+hood/exit' stopNest diff --git a/nix/pkgs/pill/solid.nix b/nix/pkgs/pill/solid.nix index 17bcd4433e..7f4977173d 100644 --- a/nix/pkgs/pill/solid.nix +++ b/nix/pkgs/pill/solid.nix @@ -1,4 +1,4 @@ -{ stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, herb }: +{ stdenvNoCC, fetchGitHubLFS, bootFakeShip, solid, urbit, arvo, curl }: let @@ -8,12 +8,12 @@ in { inherit lfs; build = import ./builder.nix { - inherit stdenvNoCC urbit arvo herb; + inherit stdenvNoCC urbit arvo curl; name = "solid"; builder = ./solid.sh; pier = bootFakeShip { - inherit urbit herb; + inherit urbit; arvo = null; pill = solid.lfs; diff --git a/nix/pkgs/pill/solid.sh b/nix/pkgs/pill/solid.sh index 0c19370881..7787540715 100644 --- a/nix/pkgs/pill/solid.sh +++ b/nix/pkgs/pill/solid.sh @@ -17,47 +17,68 @@ cleanup () { trap cleanup EXIT -# Update pill strategy to ensure correct staging -herb ./pier -p hood -d "+hood/mount /=home=" +port=$(cat ./pier/.http.ports | grep loopback | tr -s ' ' '\n' | head -n 1) -until [ -d ./pier/home ]; do +lensa() { + # -f elided, this can hit server-side timeouts + curl -s \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"app\":\"$1\"}}" \ + "http://localhost:$port" | xargs printf %s | sed 's/\\n/\n/g' +} + +lensf() { + # -f elided, this can hit server-side timeouts + d=$(echo $1 | sed 's/\./\//g') + curl -sJO \ + --data "{\"source\":{\"dojo\":\"$2\"},\"sink\":{\"output-pill\":\"$d\"}}" \ + "http://localhost:$port" +} + +header "updating %base" + +# Update pill strategy to ensure correct staging +lensa hood "+hood/mount /=base=" + +until [ -d ./pier/base ]; do sleep 1 done # Update :lens, :dojo and dependencies # FIXME: reduce this list -cp $ARVO/app/lens.hoon ./pier/home/app/ -cp $ARVO/app/dojo.hoon ./pier/home/app/ -cp $ARVO/lib/plume.hoon ./pier/home/lib/ -cp $ARVO/lib/server.hoon ./pier/home/lib/ -cp $ARVO/lib/sole.hoon ./pier/home/lib/ -cp $ARVO/lib/xray.hoon ./pier/home/lib/ -cp $ARVO/lib/pprint.hoon ./pier/home/lib/ +cp $ARVO/app/lens.hoon ./pier/base/app/ +cp $ARVO/app/dojo.hoon ./pier/base/app/ +cp $ARVO/lib/plume.hoon ./pier/base/lib/ +cp $ARVO/lib/server.hoon ./pier/base/lib/ +cp $ARVO/lib/sole.hoon ./pier/base/lib/ +cp $ARVO/lib/xray.hoon ./pier/base/lib/ +cp $ARVO/lib/pprint.hoon ./pier/base/lib/ -mkdir -p ./pier/home/mar/lens/ +mkdir -p ./pier/base/mar/lens/ -cp $ARVO/mar/lens/* ./pier/home/mar/lens/ +cp $ARVO/mar/lens/* ./pier/base/mar/lens/ -cp $ARVO/sur/lens.hoon ./pier/home/sur/ -cp $ARVO/sur/plum.hoon ./pier/home/sur/ -cp $ARVO/sur/sole.hoon ./pier/home/sur/ -cp $ARVO/sur/xray.hoon ./pier/home/sur/ +cp $ARVO/sur/lens.hoon ./pier/base/sur/ +cp $ARVO/sur/plum.hoon ./pier/base/sur/ +cp $ARVO/sur/sole.hoon ./pier/base/sur/ +cp $ARVO/sur/xray.hoon ./pier/base/sur/ # Update +solid and its dependencies -cp $ARVO/lib/pill.hoon ./pier/home/lib/ -cp $ARVO/gen/solid.hoon ./pier/home/gen/ +cp $ARVO/lib/pill.hoon ./pier/base/lib/ +cp $ARVO/gen/solid.hoon ./pier/base/gen/ -chmod -R u+rw ./pier/home/ +chmod -R u+rw ./pier/base/ -herb ./pier -p hood -d "+hood/commit %home" -herb ./pier -p hood -d "+hood/unmount %home" +lensa hood "+hood/commit %base" +lensa hood "+hood/unmount %base" # FIXME: horrible hack to ensure the update is applied first sleep 10 +header "updating %stage" + # Stage new desk for pill contents -herb ./pier -p hood -d '+hood/merge %stage our %home' -herb ./pier -p hood -d "+hood/mount /=stage=" +lensa hood '+hood/merge %stage our %base' +lensa hood "+hood/mount /=stage=" until [ -d ./pier/stage ]; do sleep 1 @@ -67,9 +88,12 @@ rm -rf ./pier/stage cp -r $ARVO ./pier/stage chmod -R u+rw ./pier/stage -herb ./pier -p hood -d "+hood/commit %stage" -herb ./pier -p hood -d "+hood/unmount %stage" -herb ./pier -P solid.pill -d '+solid /=stage=/sys, =dub &' -herb ./pier -p hood -d '+hood/exit' +lensa hood "+hood/commit %stage" +lensa hood "+hood/unmount %stage" + +header "running +solid" + +lensf solid.pill '+solid /=stage=/sys, =dub &' +lensa hood '+hood/exit' stopNest diff --git a/nix/pkgs/urbit/default.nix b/nix/pkgs/urbit/default.nix index 0f979e3f17..e9da7b305b 100644 --- a/nix/pkgs/urbit/default.nix +++ b/nix/pkgs/urbit/default.nix @@ -1,9 +1,11 @@ { lib, stdenv, coreutils, pkgconfig # build/env , cacert, ca-bundle, ivory # codegen -, curlUrbit, ent, gmp, h2o, libsigsegv, libuv, lmdb # libs -, murmur3, openssl, softfloat3, urcrypt, zlib # +, curlUrbit, ent, gmp, h2o, libsigsegv, libuv, lmdb # libs +, murmur3, openssl, openssl-static-osx, softfloat3 # +, urcrypt, zlib, zlib-static-osx # , enableStatic ? stdenv.hostPlatform.isStatic # opts , enableDebug ? false +, verePace ? "" , doCheck ? true , enableParallelBuilding ? true , dontStrip ? true }: @@ -14,6 +16,12 @@ let version = builtins.readFile "${src}/version"; + # See https://github.com/urbit/urbit/issues/5561 + oFlags = + if stdenv.isDarwin + then (if enableDebug then [ "-O0" "-g" ] else [ "-O3" ]) + else [ (if enableDebug then "-O0" else "-O3") "-g" ]; + in stdenv.mkDerivation { inherit src version; @@ -34,10 +42,10 @@ in stdenv.mkDerivation { libuv lmdb murmur3 - openssl + (if stdenv.isDarwin && enableStatic then openssl-static-osx else openssl) softfloat3 urcrypt - zlib + (if stdenv.isDarwin && enableStatic then zlib-static-osx else zlib) ]; # Ensure any `/usr/bin/env bash` shebang is patched. @@ -50,7 +58,6 @@ in stdenv.mkDerivation { installPhase = '' mkdir -p $out/bin cp ./build/urbit $out/bin/urbit - cp ./build/urbit-worker $out/bin/urbit-worker ''; dontDisableStatic = enableStatic; @@ -59,12 +66,12 @@ in stdenv.mkDerivation { then [ "--disable-shared" "--enable-static" ] else []; - CFLAGS = [ (if enableDebug then "-O0" else "-O3") "-g" ] - ++ lib.optionals (!enableDebug) [ "-Werror" ]; + CFLAGS = oFlags ++ lib.optionals (!enableDebug) [ "-Werror" ]; MEMORY_DEBUG = enableDebug; CPU_DEBUG = enableDebug; EVENT_TIME_DEBUG = false; + VERE_PACE = if enableStatic then verePace else ""; # See https://github.com/NixOS/nixpkgs/issues/18995 hardeningDisable = lib.optionals enableDebug [ "all" ]; diff --git a/nix/pkgs/urcrypt/default.nix b/nix/pkgs/urcrypt/default.nix index 1726447c99..3aab6e91d8 100644 --- a/nix/pkgs/urcrypt/default.nix +++ b/nix/pkgs/urcrypt/default.nix @@ -1,5 +1,5 @@ { stdenv, autoreconfHook, pkgconfig -, libaes_siv, openssl, secp256k1 +, libaes_siv, openssl, openssl-static-osx, secp256k1 , enableStatic ? stdenv.hostPlatform.isStatic }: stdenv.mkDerivation rec { diff --git a/nix/sources-pmnsh.json b/nix/sources-pmnsh.json index 80dbd882c8..1f60716c16 100644 --- a/nix/sources-pmnsh.json +++ b/nix/sources-pmnsh.json @@ -43,10 +43,10 @@ "prepare": "./autogen.sh && ./configure --disable-shared --enable-benchmark=no --enable-exhaustive-tests=no --enable-experimental --enable-module-ecdh --enable-module-recovery --enable-module-schnorrsig --enable-tests=yes CFLAGS=-DSECP256K1_API=" }, "repo": "secp256k1", - "rev": "7973576f6e3ab27d036a09397152b124d747f4ae", - "sha256": "0vjk55dv0mkph4k6bqgkykmxn05ngzvhc4rzjnvn33xzi8dzlvah", + "rev": "5dcc6f8dbdb1850570919fc9942d22f728dbc0af", + "sha256": "x9qG2S6tBSRseWaFIN9N2fRpY1vkv8idT3d3rfJnmaU", "type": "tarball", - "url": "https://github.com/bitcoin-core/secp256k1/archive/7973576f6e3ab27d036a09397152b124d747f4ae.tar.gz", + "url": "https://github.com/bitcoin-core/secp256k1/archive/5dcc6f8dbdb1850570919fc9942d22f728dbc0af.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "uv": { diff --git a/nix/sources.json b/nix/sources.json index 82d5d419fa..afa2172be2 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -73,15 +73,15 @@ "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { - "branch": "nixos-21.11", + "branch": "master", "description": "Nix Packages collection", "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "573095944e7c1d58d30fc679c81af63668b54056", - "sha256": "07s5cwhskqvy82b4rld9b14ljc0013pig23i3jx3l3f957rk95pg", + "rev": "376d67e1cd05d5ac8a64a3f47f17b80fb6394792", + "sha256": "1l4ai1dppwdbkkjbvnavsivr5kx00b3q8640pilpnifskfmfc8mp", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/573095944e7c1d58d30fc679c81af63668b54056.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/376d67e1cd05d5ac8a64a3f47f17b80fb6394792.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "softfloat3": { diff --git a/pkg/arvo/README.md b/pkg/arvo/README.md index 206e47dffc..ad73d5e2fc 100644 --- a/pkg/arvo/README.md +++ b/pkg/arvo/README.md @@ -23,9 +23,9 @@ To boot a fake ship from your development files, run `urbit` with the following urbit -F zod -A /path/to/arvo -c fakezod ``` -Mount Arvo's filesystem allows you to update its contents through Unix. To do so, run `|mount` in dojo. It is most common to `|mount /=home=`. +Mount Arvo's filesystem allows you to update its contents through Unix. To do so, run `|mount` in dojo. It is most common to `|mount /=base=`. -To create a custom pill (bootstrapping object) from the files loaded into the home desk, run `.my/pill +solid`. Your pill will appear in `/path/to/fakezod/.urb/put/my.pill`. +To create a custom pill (bootstrapping object) from the files loaded into the base desk, run `.my/pill +solid`. Your pill will appear in `/path/to/fakezod/.urb/put/my.pill`. To boot a fake ship with a custom pill, use the `-B` flag: diff --git a/pkg/arvo/app/aqua.hoon b/pkg/arvo/app/aqua.hoon index ac4cdb1a67..574f4cd3f3 100644 --- a/pkg/arvo/app/aqua.hoon +++ b/pkg/arvo/app/aqua.hoon @@ -12,16 +12,15 @@ :: :aqua [%dojo ~[~bud ~dev] "[our eny (add 3 5)]"] :: :aqua [%dojo ~[~bud] "|hi ~dev"] :: :aqua [%wish ~[~bud ~dev] '(add 2 3)'] -:: :aqua [%peek ~[~bud] /cx/~bud/home/(scot %da now)/app/curl/hoon] +:: :aqua [%peek ~[~bud] /cx/~bud/base/(scot %da now)/app/curl/hoon] :: :aqua [%dojo ~[~bud ~dev] '|mount %'] :: :aqua [%file ~[~bud ~dev] %/sys/vane] :: :aqua [%pause-events ~[~bud ~dev]] :: -:: :: We get ++unix-event and ++pill from /-aquarium :: /- aquarium -/+ pill, azimuth, default-agent, aqua-azimuth, dbug, verb +/+ pill, azimuth, naive, default-agent, aqua-azimuth, dbug, verb =, pill-lib=pill =, aquarium => $~ |% @@ -33,6 +32,7 @@ pil=$>(%pill pill) assembled=* tym=@da + fresh-piers=(map [=ship fake=?] [=pier boths=(list unix-both)]) fleet-snaps=(map term fleet) piers=fleet == @@ -135,6 +135,8 @@ :: Represents a single ship's state. :: ++ pe + ::NOTE if we start needing the fake flag outside of +ahoy and +yaho, + :: probably add it as an argument here. |= who=ship =+ (~(gut by ships.piers) who *pier) =* pier-data - @@ -155,6 +157,31 @@ ~& pill-size=(met 3 (jam snap)) ..abet-pe :: + :: store post-pill ship for later re-use + :: + ++ ahoy + |= fake=? + =? fresh-piers !(~(has by fresh-piers) [who fake]) + %+ ~(put by fresh-piers) [who fake] + [pier-data (~(get ja unix-boths) who)] + ..ahoy + :: + :: restore post-pill ship for re-use + :: + ++ yaho + |= fake=? + =/ fresh (~(got by fresh-piers) [who fake]) + =. pier-data pier.fresh + =. boths.fresh (flop boths.fresh) + |- + ?~ boths.fresh ..yaho + =. ..yaho + ?- -.i.boths.fresh + %effect (publish-effect +.i.boths.fresh) + %event (publish-event +.i.boths.fresh) + == + $(boths.fresh t.boths.fresh) + :: :: Enqueue events to child arvo :: ++ push-events @@ -371,6 +398,24 @@ |= p=pill ^- (quip card:agent:gall _state) ?< ?=(%ivory -.p) + =. userspace-ova.p + :: if there is an azimuth-snapshot in the pill, we stub it out, + :: since it would interfere with aqua's azimuth simulation. + :: + ^+ userspace-ova.p + %+ turn userspace-ova.p + |= e=unix-event:pill-lib + ^+ e + ?. ?=(%park -.q.e) e + ?. ?=(%& -.yok.q.e) e + =- e(q.p.yok.q -) + ^- (map path (each page lobe:clay)) + %- ~(urn by q.p.yok.q.e) + |= [=path fil=(each page lobe:clay)] + ^+ fil + ?. =(/app/azimuth/version-0/azimuth-snapshot path) fil + ?: ?=(%| -.fil) fil + &+azimuth-snapshot+[%0 [0x0 0] *^state:naive ~ ~] =. this apex-aqua =< abet-aqua =. pil p ~& lent=(met 3 (jam boot-ova.pil)) @@ -381,6 +426,7 @@ %0 ~& %suc =. assembled +7.p.res + =. fresh-piers ~ this :: %1 @@ -439,7 +485,7 @@ =/ slim-dirs=(list path) ~[/app /ted /gen /lib /mar /sur /hoon/sys /arvo/sys /zuse/sys] :_ ~ - %- unix-event + %- unix-event:pill-lib %- %*(. file-ovum:pill-lib directories slim-dirs) /(scot %p our.hid)/work/(scot %da now.hid) =^ ms state (poke-pill pil) @@ -506,6 +552,18 @@ ?- -.ae :: %init-ship + ?: &(fake.ae (~(has by fresh-piers) [who fake]:ae)) + ~& [%aqua %cached-init +.ae] + =. this abet-pe:(yaho fake):[ae (pe who.ae)] + ?: fake.ae (pe who.ae) + :: for real ships, make sure they have their latest keys + :: + %. who.ae + =< pe:abet-pe:plow + %- push-events:(pe who.ae) + =/ =life lyfe:(~(got by lives.azi.piers) who.ae) + =/ =ring sec:ex:(get-keys:aqua-azimuth who.ae life) + [/j/aqua/rekey %rekey life ring]~ =. this abet-pe:(publish-effect:(pe who.ae) [/ %sleep ~]) =/ initted =< plow @@ -536,14 +594,20 @@ :: userspace-ova.pil :: load os :: - :~ [/b/behn/0v1n.2m9vh %born ~] + :* [/b/behn/0v1n.2m9vh %born ~] [/i/http-client/0v1n.2m9vh %born ~] [/e/http-server/0v1n.2m9vh %born ~] [/e/http-server/0v1n.2m9vh %live 8.080 `8.445] [/a/newt/0v1n.2m9vh %born ~] + [/d/term/1 %hail ~] + :: + ?: fake.ae ~ + =+ [%raw-poke %noun %refresh-rate ~s30] + [/g/aqua/reduce-refresh-rate %deal [. .]:who.ae %azimuth -]~ == == - =. this abet-pe:initted + =. this + abet-pe:(ahoy fake):[ae initted] (pe who.ae) :: %pause-events @@ -741,7 +805,8 @@ ++ dawn |= who=ship ^- dawn-event:jael - ?> ?=(?(%czar %king %duke) (clan:title who)) + =/ clan (clan:title who) + ?> ?=(?(%czar %king %duke %earl) clan) =/ spon=(list [ship point:azimuth]) %- flop |- ^- (list [ship point:azimuth]) @@ -764,7 +829,9 @@ [a-point]~ [a-point $(who ship)] =/ =seed:jael - =/ life-rift (~(got by lives.azi.piers) who) + =/ life-rift=[lyfe=life rut=rift] + ?: =(%earl clan) [1 0] + (~(got by lives.azi.piers) who) =/ =life lyfe.life-rift [who life sec:ex:(get-keys:aqua-azimuth who life) ~] :* seed @@ -772,7 +839,7 @@ get-czars ~[~['arvo' 'netw' 'ork']] 0 - `(need (de-purl:html 'http://localhost:8545')) + `(need (de-purl:html 'http://fake.aqua.domain/')) == :: :: Should only do galaxies diff --git a/pkg/arvo/app/azimuth-tracker.hoon b/pkg/arvo/app/azimuth-tracker.hoon index c9629c71d6..5e904b80d4 100644 --- a/pkg/arvo/app/azimuth-tracker.hoon +++ b/pkg/arvo/app/azimuth-tracker.hoon @@ -93,6 +93,7 @@ ^- config:eth-watcher :* url.state =(%czar (clan:title our)) ~m5 ~m30 launch:contracts:azimuth + ~ ~[azimuth:contracts:azimuth] ~ (topics whos.state) diff --git a/pkg/arvo/app/azimuth.hoon b/pkg/arvo/app/azimuth.hoon index b737d78455..6a7b81e438 100644 --- a/pkg/arvo/app/azimuth.hoon +++ b/pkg/arvo/app/azimuth.hoon @@ -1,4 +1,4 @@ -/- eth-watcher, *dice +/- eth-watcher, *dice, *hood /+ ethereum, azimuth, naive, @@ -21,9 +21,10 @@ =, jael |% +$ app-state - $: %5 + $: %6 url=@ta =net + refresh=_~m5 whos=(set ship) nas=^state:naive own=owners @@ -38,19 +39,52 @@ :: %watch: configure node url and network :: [%watch url=@ta =net] + :: %kick: re-start %azimuth subscriptions + :: + [%kick ~] == :: +$ tagged-diff [=id:block diff:naive] +$ card card:agent:gall -:: TODO: add to state? -:: -++ refresh ~m5 -- :: =| state=app-state %- agent:dbug %+ verb | ^- agent:gall +:: Cards +:: +=> |% + ++ subscribe-to-eth-watcher + |= =bowl:gall + ^- card + :* %pass /eth-watcher %agent [our.bowl %eth-watcher] + %watch /logs/[dap.bowl] + == + :: + ++ listen-to-azimuth + |= [ships=(set ship) =source:jael] + ^- card + [%pass /lo %arvo %j %listen ships source] + :: + ++ nuke-azimuth-tracker + |= =bowl:gall + ^- card + :* %pass /old-tracker %agent [our.bowl %hood] + %poke %kiln-nuke !>([%azimuth-tracker %|]) + == + :: + ++ init-timer + |= =bowl:gall + ^- card + [%pass /init %arvo %b %wait now.bowl] + :: + ++ start-log-retrieval + |= [=ship args=vase] + ^- card + [%pass /wa %agent [ship %eth-watcher] %poke %eth-watcher-poke args] + -- +:: =< |_ =bowl:gall +* this . @@ -72,12 +106,7 @@ :_ this ?: .^(? %j /(scot %p our.bowl)/fake/(scot %da now.bowl)) ~ - :~ :* %pass /old-tracker %agent [our.bowl %hood] - %poke %kiln-nuke !>([%azimuth-tracker %|]) - == - :: - [%pass /init %arvo %b %wait now.bowl] - == + ~[(nuke-azimuth-tracker bowl) (init-timer bowl)] :: ++ on-save !>(state) ++ on-load @@ -93,7 +122,7 @@ `old-state %- %- slog :_ ~ leaf+"ship: loading snapshot with {<(lent logs.old-state)>} events" - =. +.state +.old-state + =. +.state +:(state-5-to-6 old-state) =^ cards state (%*(run-logs do nas.state *^state:naive) logs.state) [(jael-update:do (to-udiffs:do cards)) state] @@ -101,7 +130,7 @@ ?. ?=(%2 -.old-state) `old-state ~& > '%azimuth: updating to state 3' - =. +.state +.old-state + =. +.state +:(state-5-to-6 old-state) :: replace naive state and indices with snapshot :: =: nas.state nas.snap @@ -117,7 +146,7 @@ %- %- slog :_ ~ leaf+"ship: processing azimuth snapshot ({} points)" =/ snap-cards=udiffs:point (run-state:do id.snap points.nas.state) - :_ [%3 +.state] + :_ [%3 url net whos nas own spo logs]:state %+ weld (jael-update:do snap-cards) :: start getting new logs after the last id:block in the snapshot @@ -131,17 +160,24 @@ =^ cards-4 old-state ?. ?=(%4 -.old-state) [cards-3 old-state] =^ cards this - %- %*(. on-poke +.state.this +.old-state) + %- %*(. on-poke +.state.this +:(state-5-to-6 old-state)) [%azimuth-poke !>([%watch [url net]:old-state])] ~& > '%azimuth: updating to state 5' - [cards state.this(- %5)] - ?> ?=(%5 -.old-state) + [cards [%5 url net whos nas own spo logs]:state.this] + =? old-state ?=(%5 -.old-state) + (state-5-to-6 old-state) + ?> ?=(%6 -.old-state) [cards-4 this(state old-state)] :: - ++ app-states $%(state-0 state-1-2-3-4 app-state) + ++ app-states $%(state-0 state-1-2-3-4-5 app-state) :: - +$ state-1-2-3-4 - $: ?(%1 %2 %3 %4) + ++ state-5-to-6 + |= state-1-2-3-4-5 + ^- app-state + [%6 url net ~m5 whos nas own spo logs] + :: + +$ state-1-2-3-4-5 + $: ?(%1 %2 %3 %4 %5) url=@ta =net whos=(set ship) @@ -167,6 +203,9 @@ ^- (quip card _this) ?: =(%noun mark) ?+ q.vase !! + [%refresh-rate @] + =. refresh.state +.q.vase + [start:do this] :: %rerun =/ points=@ud ~(wyt by points.nas.state) @@ -176,10 +215,8 @@ [(jael-update:do udiffs) this] :: %resub - :_ this :_ ~ - :* %pass /eth-watcher %agent [our.bowl %eth-watcher] - %watch /logs/[dap.bowl] - == + :_ this + [(subscribe-to-eth-watcher bowl)]~ :: %resnap =: nas.state nas.snap @@ -194,7 +231,48 @@ =+ !<(poke=poke-data vase) ?- -.poke %listen - [[%pass /lo %arvo %j %listen (silt whos.poke) source.poke]~ this] + [[(listen-to-azimuth (silt whos.poke) source.poke)]~ this] + :: + %kick + =/ last-block=@ + ?^ logs.state + number:(last-block-id:dice logs.state) + ~& >> %no-logs-in-azimuth-state + last-snap + =+ [our=(scot %p our.bowl) now=(scot %da now.bowl)] + =+ .^(dudes=(set [dude:gall ?]) %ge our %base now /) + =/ running=? (~(has in dudes) [%eth-watcher &]) + =/ installed=? + |((~(has in dudes) [%eth-watcher &]) (~(has in dudes) [%eth-watcher |])) + :_ this + =/ cards=(list card) + :- :: %jael will re-subscribe to get all azimuth diffs + :: + (listen-to-azimuth ~ [%| dap.bowl]) + :: we poke eth-watcher to retrieve logs from the latest we have + :: + %*(start do last-snap last-block) + =? cards !running + :: restart %eth-watcher + :: + ~& >> %starting-eth-watcher + =/ rein=[desk rein] [%base %.y [%eth-watcher ~ ~] ~] + :_ cards + [%pass /rein %agent [our.bowl %hood] %poke kiln-rein+!>(rein)] + =? cards !installed + :: reinstall %base desk + :: + =+ spo=(sein:title [our now our]:bowl) + ~& >> re-installing-base-from+spo + =/ fresh=[desk ship desk] [%base spo %kids] + :_ cards + [%pass /fresh %agent [our.bowl %hood] %poke kiln-install+!>(fresh)] + :: resubscribe if we somehow get unsubscribed from eth-watcher + :: + ?: (~(has by wex.bowl) [/eth-watcher our.bowl %eth-watcher]) + cards + ~& >> %resubscribing-to-eth-watcher + [(subscribe-to-eth-watcher bowl) cards] :: %watch =: nas.state ?:(?=(%default net.poke) nas.snap *^state:naive) @@ -245,7 +323,7 @@ [%x %dns ~] ``noun+!>(dns.nas.state) [%x %own ~] ``noun+!>(own.state) [%x %spo ~] ``noun+!>(spo.state) - [%x %refresh ~] ``atom+!>(refresh) + [%x %refresh ~] ``atom+!>(refresh.state) [%x %point @ ~] ``noun+(point i.t.t.path) == :: @@ -280,7 +358,7 @@ :: doing :azimuth|watch caused a l2-sig-fail when using the eth-log :: snapshot because we were not updating nas with the saved logs. :: - :: now (L: 189) nas.state is loaded with the contents of the snapshot, + :: now nas.state is loaded with the contents of the snapshot, :: if we are on the %default network. :: =^ effects state (run-logs:do loglist.diff) @@ -297,12 +375,7 @@ %- (slog 'azimuth: failed to initialize!' ~) `this :_ this - :~ :* %pass /eth-watcher %agent [our.bowl %eth-watcher] - %watch /logs/[dap.bowl] - == - :: - [%pass /lo %arvo %j %listen ~ [%| dap.bowl]] - == + ~[(subscribe-to-eth-watcher bowl) (listen-to-azimuth ~ [%| dap.bowl])] :: ++ on-fail on-fail:def -- @@ -413,7 +486,6 @@ ++ jael-update |= =udiffs:point ^- (list card) - :: ?: & ~ :: XX :- [%give %fact ~[/] %azimuth-udiffs !>(udiffs)] |- ^- (list card) ?~ udiffs @@ -441,11 +513,12 @@ =/ args=vase !> :+ %watch /[dap.bowl] ^- config:eth-watcher - :* url.state =(%czar (clan:title our.bowl)) refresh ~h30 + :* url.state =(%czar (clan:title our.bowl)) refresh.state ~h30 (max launch.net ?:(=(net.state %default) +(last-snap) 0)) + ~ ~[azimuth.net] ~[naive.net] (topics whos.state) == - [%pass /wa %agent [our.bowl %eth-watcher] %poke %eth-watcher-poke args]~ + [(start-log-retrieval our.bowl args)]~ -- diff --git a/pkg/arvo/app/dbug.hoon b/pkg/arvo/app/dbug.hoon index b5c4da98c6..fbec14e292 100644 --- a/pkg/arvo/app/dbug.hoon +++ b/pkg/arvo/app/dbug.hoon @@ -530,6 +530,7 @@ :: where an index is specified, the array is generally sorted by those. :: :: { life: 123, + :: rift: 0, :: route: { direct: true, lane: 'something' }, :: qos: { kind: 'status', last-contact: 123456 }, // ms timestamp :: flows: { forward: [snd, rcv, ...], backward: [snd, rcv, ...] } @@ -590,6 +591,9 @@ |= peer-state %- pairs :~ 'life'^(numb life) + :: TODO: needs to be updated in /pkg/interface/dbug + :: + 'rift'^(numb rift) :: :- 'route' %+ maybe route @@ -786,7 +790,7 @@ ++ v-clay =, clay |% - ++ start-path /(scot %p our.bowl)/home/(scot %da now.bowl) + ++ start-path /(scot %p our.bowl)/base/(scot %da now.bowl) :: +$ commit [=tako parents=(list tako) children=(list tako) wen=@da content-hash=@uvI] diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index 938d9f25ab..b127a3ce0b 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -679,7 +679,9 @@ [%face ^] a(q $(a q.a)) [%cell ^] a(p $(a p.a), q $(a q.a)) [%fork *] a(p (silt (turn ~(tap in p.a) |=(b=type ^$(a b))))) - [%hint *] !! + [%hint *] ?. ?=(%know -.q.p.a) $(a q.a) + ?@ p.q.p.a [(cat 3 '#' mark.p.q.p.a)]~ + [(rap 3 '#' auth.p.q.p.a (spat type.p.q.p.a) ~)]~ [%core ^] `wain`/core [%hold *] a(p $(a p.a)) == diff --git a/pkg/arvo/app/eth-watcher.hoon b/pkg/arvo/app/eth-watcher.hoon index 47b50375c5..a2cb9a625c 100644 --- a/pkg/arvo/app/eth-watcher.hoon +++ b/pkg/arvo/app/eth-watcher.hoon @@ -8,7 +8,7 @@ => |% +$ card card:agent:gall +$ app-state - $: %5 + $: %6 dogs=(map path watchdog) == :: @@ -133,14 +133,16 @@ :: =? old-state ?=(%4 -.old-state) %- (slog leaf+"upgrading eth-watcher from %4" ~) - ^- app-state + ^- app-state-5 %= old-state - %5 dogs %- ~(run by dogs.old-state) |= dog=watchdog-4 + ^- watchdog-5 %= dog - + ^- config-5 =, -.dog [url eager refresh-rate timeout-time from contracts ~ topics] :: @@ -160,10 +162,55 @@ == == :: - [cards-1 this(state ?>(?=(%5 -.old-state) old-state))] + =? old-state ?=(%5 -.old-state) + ^- app-state + %= old-state + - %6 + dogs + %- ~(run by dogs.old-state) + |= dog=watchdog-5 + ^- watchdog + %= dog + - + ^- config + =, -.dog + [url eager refresh-rate timeout-time from ~ contracts batchers topics] + :: + running + ?~ running.dog ~ + `[now.bowl tid.u.running.dog] + == + == + :: + [cards-1 this(state ?>(?=(%6 -.old-state) old-state))] :: +$ app-states - $%(app-state-0 app-state-1 app-state-2 app-state-3 app-state-4 app-state) + $%(app-state-0 app-state-1 app-state-2 app-state-3 app-state-4 app-state-5 app-state) + :: + +$ app-state-5 + $: %5 + dogs=(map path watchdog-5) + == + :: + +$ watchdog-5 + $: config-5 + running=(unit [since=@da =tid:spider]) + =number:block + =pending-logs + =history + blocks=(list block) + == + :: + +$ config-5 + $: url=@ta + eager=? + refresh-rate=@dr + timeout-time=@dr + from=number:block + contracts=(list address:ethereum) + batchers=(list address:ethereum) + =topics + == :: +$ app-state-4 $: %4 @@ -319,6 +366,17 @@ =/ dog=watchdog ?: restart *watchdog (~(got by dogs.state) path.poke) + =+ pending=(sort ~(tap in ~(key by pending-logs.dog)) lth) + =? pending-logs.dog + ?: restart | + ?~ pending | + (gte i.pending from.config.poke) + ?> ?=(^ pending) + :: if there are pending logs newer than what we poke with, + :: we need to clear those too avoid processing duplicates + :: + ~& %dropping-unreleased-logs^[from+i.pending n+(lent pending)] + ~ %_ dog - config.poke number from.config.poke @@ -464,15 +522,12 @@ ^- (quip card watchdog) ?: (lth number.dog 30) `dog - =/ rel-number (sub number.dog 30) =/ numbers=(list number:block) ~(tap in ~(key by pending-logs.dog)) =. numbers (sort numbers lth) =^ logs=(list event-log:rpc:ethereum) dog |- ^- (quip event-log:rpc:ethereum watchdog) ?~ numbers `dog - ?: (gth i.numbers rel-number) - $(numbers t.numbers) =^ rel-logs-1 dog =/ =loglist (~(get ja pending-logs.dog) i.numbers) =. pending-logs.dog (~(del by pending-logs.dog) i.numbers) @@ -530,6 +585,12 @@ :: ?^ running.dog `dog + :: if reached the to-block, don't start a new thread + :: + ?: ?& ?=(^ to.dog) + (gte number.dog u.to.dog) + == + `dog :: =/ new-tid=@ta (cat 3 'eth-watcher--' (scot %uv eny.bowl)) diff --git a/pkg/arvo/app/gaze.hoon b/pkg/arvo/app/gaze.hoon index 18f154e476..12fbea85b7 100644 --- a/pkg/arvo/app/gaze.hoon +++ b/pkg/arvo/app/gaze.hoon @@ -210,6 +210,7 @@ refresh-rate timeout-time public:mainnet-contracts + ~ ~[azimuth delegated-sending]:mainnet-contracts ~ ~ @@ -456,7 +457,7 @@ ^- card =- [%pass /export/[nom] %arvo %c %info -] %+ foal:space:userlib - /(scot %p our.bowl)/home/(scot %da now.bowl)/gaze-exports/[nom]/txt + /(scot %p our.bowl)/base/(scot %da now.bowl)/gaze-exports/[nom]/txt [%txt !>(dat)] :: :: +peek-x: accept gall scry diff --git a/pkg/arvo/app/language-server.hoon b/pkg/arvo/app/language-server.hoon index a93e57c7fc..c4aefac8e9 100644 --- a/pkg/arvo/app/language-server.hoon +++ b/pkg/arvo/app/language-server.hoon @@ -5,7 +5,7 @@ easy-print=language-server-easy-print, rune-snippet=language-server-rune-snippet, build=language-server-build, - default-agent, verb + default-agent, verb, dbug |% +$ card card:agent:gall +$ lsp-req @@ -44,6 +44,7 @@ == -- ^- agent:gall +%- agent:dbug %+ verb | =| state-zero =* state - @@ -196,7 +197,7 @@ %+ turn ~(tap in ~(key by builds)) |= uri=@t - [%pass /ford/[uri] %arvo %c %warp our.bow %home ~] + [%pass /ford/[uri] %arvo %c %warp our.bow %base ~] :: ++ handle-did-close |= [uri=@t version=(unit @)] @@ -208,7 +209,7 @@ =. builds (~(del by builds) uri) :_ state - [%pass /ford/[uri] %arvo %c %warp our.bow %home ~]~ + [%pass /ford/[uri] %arvo %c %warp our.bow %base ~]~ :: ++ handle-did-save |= [uri=@t version=(unit @)] @@ -240,18 +241,29 @@ ?> ?=([%writ *] gift) =/ uri=@t (snag 1 path) - =; res=(quip card _state) - [(snoc -.res (build-file | uri path)) +.res] + =/ loc=^path (uri-to-path:build uri) + =; [res=(quip card _state) dek=desk] + [(snoc -.res (build-file | uri loc `dek)) +.res] ?~ p.gift - [~ state] + [[~ state] %base] =. builds (~(put by builds) uri q.r.u.p.gift) =. ford-diagnostics (~(del by ford-diagnostics) uri) - =+ .^(=open:clay %cs /(scot %p our.bow)/home/(scot %da now.bow)/open/foo) - =/ =type -:(open (uri-to-path:build uri)) + =/ bek byk.bow(r da+now.bow) + =/ desks=(list desk) ~(tap in .^((set desk) %cd (en-beam bek /))) + =| dek=desk + |- + ?~ desks [[~ state] %base] + =. dek ?: =(%kids i.desks) %base i.desks + =/ exists=? .^(? %cu (en-beam bek(q dek) loc)) + ?. exists $(desks t.desks) + =+ .^(=open:clay %cs /(scot %p our.bow)/[dek]/(scot %da now.bow)/open/foo) + =/ =type -:(open loc) + =. preludes (~(put by preludes) uri type) + :_ dek :_ state (give-rpc-notification (get-diagnostics uri)) :: @@ -265,19 +277,28 @@ (get-parser-diagnostics uri) :: ++ build-file - |= [eager=? uri=@t =path] + |= [eager=? uri=@t =path desk=(unit desk)] ^- card =/ =rave:clay ?: eager [%sing %a da+now.bow path] [%next %a da+now.bow path] - [%pass /ford/[uri] %arvo %c %warp our.bow %home `rave] + =/ des=^desk ?^ desk u.desk %base + [%pass /ford/[uri] %arvo %c %warp our.bow des `rave] :: ++ handle-did-open |= item=text-document-item:lsp-sur ^- (quip card _state) =/ =path (uri-to-path:build uri.item) + =/ bek byk.bow + =/ desks=(list desk) ~(tap in .^((set desk) %cd (en-beam bek /))) + =| dek=desk + |- + ?~ desks [~ state] + =. dek ?: =(%kids i.desks) %base i.desks + =/ exists=? .^(? %cu (en-beam bek(q dek) path)) + ?. exists $(desks t.desks) ?: ?=(%sys -.path) `state =/ buf=wall @@ -287,7 +308,7 @@ :_ state %+ weld (give-rpc-notification (get-diagnostics uri.item)) - [(build-file & uri.item path) ~] + [(build-file & uri.item path `dek) ~] :: ++ get-parser-diagnostics |= uri=@t diff --git a/pkg/arvo/app/roller.hoon b/pkg/arvo/app/roller.hoon index b2d1d63057..a83d6d9258 100644 --- a/pkg/arvo/app/roller.hoon +++ b/pkg/arvo/app/roller.hoon @@ -31,7 +31,7 @@ :: |% +$ app-state - $: %4 + $: %6 :: pending: the next l2 txs to be sent :: sending: l2 txs awaiting l2 confirmation, ordered by nonce :: finding: sig+raw-tx hash reverse lookup for txs in sending map @@ -263,8 +263,8 @@ [~d7 7 ~m5 ~m1] =, old-state :* %1 - pending sending finding history - ship-quota next-nonce next-batch + pending ^-((tree [l1-tx-pointer old-send-tx-4]) sending) + finding history ship-quota next-nonce next-batch pre own pk slice quota derive frequency endpoint contract chain-id resend-time update-rate @@ -294,7 +294,7 @@ resend-time update-rate == =? old-state ?=(%3 -.old-state) - ^- app-state + ^- state-4 =, old-state =/ fallback-gas-price=@ud 10.000.000.000 :* %4 @@ -305,10 +305,61 @@ frequency endpoint contract chain-id resend-time update-rate fallback-gas-price == - ?> ?=(%4 -.old-state) + =? old-state ?=(%4 -.old-state) + ^- state-5 + =/ new-sending=(tree [l1-tx-pointer old-send-tx-5]) + %+ run:ors:dice sending.old-state + |= old=old-send-tx-4 + ^- old-send-tx-5 + old(txs (turn txs.old (lead |))) + =, old-state + :* %5 + pending new-sending finding history + ship-quota allowances + next-nonce next-batch next-slice + pre own spo pk slice quota derive + frequency endpoint contract chain-id + resend-time update-rate fallback-gas-price + == + =? old-state ?=(%5 -.old-state) + ^- app-state + =/ new-sending=(tree [l1-tx-pointer send-tx]) + %+ run:ors:dice sending.old-state + |= old=old-send-tx-5 + ^- send-tx + %= old + txs + %+ turn txs.old + |= [force=? =raw-tx:naive] + =/ sign-address=(unit @ux) + (extract-address:lib raw-tx pre chain-id) + :_ [force raw-tx] + ?. ?=(^ sign-address) + 0x0 + u.sign-address + == + =, old-state + :* %6 + pending new-sending finding history + ship-quota allowances + next-nonce next-batch next-slice + pre own spo pk slice quota derive + frequency endpoint contract chain-id + resend-time update-rate fallback-gas-price + == + ?> ?=(%6 -.old-state) [cards this(state old-state)] :: - ++ app-states $%(state-0 state-1 state-2 state-3 app-state) + ++ app-states + $% state-0 + state-1 + state-2 + state-3 + state-4 + state-5 + app-state + == + :: ++ state-0 $: %0 pending=(list pend-tx) @@ -330,7 +381,7 @@ ++ state-1 $: %1 pending=(list pend-tx) - sending=(tree [l1-tx-pointer send-tx]) + sending=(tree [l1-tx-pointer old-send-tx-4]) finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) history=(map address:ethereum (tree hist-tx)) ship-quota=(map ship @ud) @@ -353,7 +404,7 @@ ++ state-2 $: %2 pending=(list pend-tx) - sending=(tree [l1-tx-pointer send-tx]) + sending=(tree [l1-tx-pointer old-send-tx-4]) finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) history=(map address:ethereum (tree hist-tx)) ship-quota=(map ship @ud) @@ -373,10 +424,11 @@ resend-time=@dr update-rate=@dr == + :: ++ state-3 $: %3 pending=(list pend-tx) - sending=(tree [l1-tx-pointer send-tx]) + sending=(tree [l1-tx-pointer old-send-tx-4]) finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) history=(map address:ethereum (tree hist-tx)) ship-quota=(map ship @ud) @@ -398,6 +450,65 @@ resend-time=@dr update-rate=@dr == + :: + +$ old-send-tx-4 [next-gas-price=@ud sent=? txs=(list =raw-tx:naive)] + :: + ++ state-4 + $: %4 + pending=(list pend-tx) + sending=(tree [l1-tx-pointer old-send-tx-4]) + finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) + history=(map address:ethereum (tree hist-tx)) + ship-quota=(map ship @ud) + allowances=(map ship (unit @ud)) + next-nonce=(unit @ud) + next-batch=time + next-slice=time + pre=^state:naive + own=owners + spo=sponsors + pk=@ + slice=@dr + quota=@ud + derive=? + frequency=@dr + endpoint=(unit @t) + contract=@ux + chain-id=@ + resend-time=@dr + update-rate=@dr + fallback-gas-price=@ud + == + :: + +$ old-send-tx-5 + [next-gas-price=@ud sent=? txs=(list [force=? =raw-tx:naive])] + :: + ++ state-5 + $: %5 + pending=(list pend-tx) + sending=(tree [l1-tx-pointer old-send-tx-5]) + finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) + history=(map address:ethereum (tree hist-tx)) + ship-quota=(map ship @ud) + allowances=(map ship (unit @ud)) + next-nonce=(unit @ud) + next-batch=time + next-slice=time + pre=^state:naive + own=owners + spo=sponsors + pk=@ + slice=@dr + quota=@ud + derive=? + frequency=@dr + endpoint=(unit @t) + contract=@ux + chain-id=@ + resend-time=@dr + update-rate=@dr + fallback-gas-price=@ud + == -- :: ++ on-poke @@ -498,9 +609,20 @@ :: [%resend @ @ ~] =/ [address=@ux nonce=@ud] - [(slav %ux i.t.wire) (rash i.t.t.wire dem)] - ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) - %wake [(send-roll:do address nonce) this] + [(slav %ux i.t.wire) (slav %ud i.t.t.wire)] + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) + %wake + =/ cards=(list card) (send-roll:do address nonce) + =? sending + ?& ?=(~ cards) + (has:ors:dice sending [address nonce]) + =(0 (lent txs:(got:ors:dice sending [address nonce]))) + == + ~& > "empty sending, removing {<[nonce address]>}" + =^ * sending + (del:ors:dice sending [address nonce]) + sending + [cards this] == == :: @@ -572,7 +694,7 @@ |= [address=@t nonce=@t =sign:agent:gall] ^- (quip card _this) =/ [address=@ux nonce=@ud] - [(slav %ux address) (rash nonce dem)] + [(slav %ux address) (slav %ud nonce)] ?- -.sign %poke-ack ?~ p.sign @@ -602,7 +724,7 @@ [cards this] :: %thread-done - =+ !<(result=(each @ud [term @t]) q.cage.sign) + =+ !<(result=(each [@ud @ud] [term @t]) q.cage.sign) =^ cards state (on-batch-result:do address nonce result) [cards this] @@ -674,7 +796,7 @@ ++ refresh |= [nonce=@t =sign:agent:gall] ^- (quip card _this) - =/ failed-nonce=@ud (rash nonce dem) + =/ failed-nonce=@ud (slav %ud nonce) ?- -.sign %poke-ack ?~ p.sign @@ -776,16 +898,17 @@ :: =* key key.i.sorted =* val val.i.sorted - =+ txs=(turn txs.val |=(=raw-tx:naive [| 0x0 *time raw-tx])) + =/ txs=(list pend-tx) + %+ turn txs.val + |=([addr=@ux force=? =raw-tx:naive] force^addr^*time^raw-tx) =^ [new-valid=_txs nups=_ups] state (apply-txs txs %sending `nonce.key) + =/ new-sending + (turn new-valid |=([force=? addr=@ux * =raw-tx:naive] addr^force^raw-tx)) :: we only hear updates for this nonce if it has been sent :: =. valid ::=? valid sent.val - %^ put:ors:dice valid - key - :: TODO: too much functional hackery? - val(txs (turn new-valid (cork tail (cork tail tail)))) + (put:ors:dice valid key val(txs new-sending)) $(sorted t.sorted, ups (welp ups nups)) :: ++ apply-txs @@ -809,8 +932,14 @@ ?: gud [~ history] =. time.tx ?: ?=(%pending type) time.tx - =+ wer=(~(got by finding) keccak) - ?>(?=(^ wer) time.wer) + ?~ wer=(~(get by finding) keccak) + ~& >>> "missing %sending tx in finding"^[ship raw-tx] + now.bowl + ?@ u.wer + ~& >>> "weird tx in finding gud: {} {}"^[ship raw-tx] + now.bowl + time.u.wer + ~? =(0x0 address.tx) %weird-null-tx-address^'apply-txs' (update-history:dice history [tx]~ %failed) =? finding !gud (~(put by finding) keccak %failed) =. updates :(welp up-2 up-1 updates) @@ -1031,7 +1160,8 @@ sending %^ put:ors:dice sending [address nonce] - [0 | (turn pending (cork tail (cork tail tail)))] + :+ 0 | + (turn pending |=([force=? addr=@ux * =raw-tx:naive] addr^force^raw-tx)) :: finding %- ~(gas by finding) @@ -1084,11 +1214,11 @@ :: If %.y, the roller has been trying to send a batch for a whole frequency. :: :: The cause of not sending the previous batch can happen because -:: of thread failure (see line 1251) or because the private key loaded onto +:: of thread failure or because the private key loaded onto :: the roller was used for something other than signing L2 batches right :: after the send-batch thread started. :: -:: After reaching this state, any subsequents attempts have failed (L: 1251) +:: After reaching this state, any subsequents attempts have failed :: (prior to updating the sending nonce if we hit the on-out-of-sync case) :: which would possibly require a manual intervention (e.g. changing the :: ethereum node URL, adding funds to the roller's address, manually bumping @@ -1139,7 +1269,7 @@ :: ++ process-l2-txs %+ roll txs.q - |= [=raw-tx:naive nif=_finding sih=_history] + |= [[@ @ =raw-tx:naive] nif=_finding sih=_history] =/ =keccak (hash-raw-tx:lib raw-tx) |^ ?~ val=(~(get by nif) keccak) @@ -1205,17 +1335,18 @@ nonce fallback-gas-price :: - =< [next-gas-price txs] - (got:ors:dice sending [address nonce]) + =< [next-gas-price (turn txs (cork tail tail))] + [. (got:ors:dice sending [address nonce])] == :: +on-batch-result: await resend after thread success or failure :: ++ on-batch-result - |= [=address:ethereum nonce=@ud result=(each @ud [term @t])] + |= [=address:ethereum nonce=@ud result=(each [@ud @ud] [term @t])] ^- (quip card _state) + |^ :: print error if there was one :: - ~? ?=(%| -.result) [dap.bowl %send-error +.p.result] + ~? ?=(%| -.result) [dap.bowl %send-error nonce+nonce +.p.result] :: if this nonce was removed from the queue by a :: previous resend-with-higher-gas thread, it's done :: @@ -1230,6 +1361,24 @@ (del:ors:dice sending [address nonce]) `state =/ =send-tx (got:ors:dice sending [address nonce]) + :: if the number of txs sent is less than the ones in sending, we remove + :: them from the latest sending batch and add them on top of the pending list + :: + =/ n-txs=@ud ?:(?=(%& -.result) -.p.result (lent txs.send-tx)) + =/ not-sent=(list [=address:naive force=? =raw-tx:naive]) + (slag n-txs txs.send-tx) + =/ partial-send=? &(?=(%& -.result) (lth n-txs (lent txs.send-tx))) + =? txs.send-tx partial-send + (oust [n-txs (lent txs.send-tx)] txs.send-tx) + =? pending partial-send + (fix-not-sent-pending not-sent) + =/ [nif=_finding sih=_history] + (fix-not-sent-status not-sent) + =: finding nif + history sih + == + ~? partial-send [%extracting-txs-from-batch (lent not-sent)] + :: =? sending ?| ?=(%& -.result) ?=([%| %crash *] result) == @@ -1238,15 +1387,22 @@ :: update gas price for this tx in state :: ?: ?=(%& -.result) - send-tx(next-gas-price p.result, sent &) - :: if the thread crashed, we don't know the gas used, - :: so we udpate it manually, same as the thread would do + send-tx(next-gas-price +.p.result, sent &) + :: if the thread crashed, we don't know the gas used, so we udpate it + :: manually, same as the thread would do. this has the problem of causing + :: the batch to be blocked if the thread keeps crashing, and we don't have + :: enough funds to pay. :: - %_ send-tx - next-gas-price - ?: =(0 next-gas-price.send-tx) - fallback-gas-price - (add next-gas-price.send-tx 5.000.000.000) + :: on the other hand if the thread fails because +fetch-gas-price fails + :: (e.g. API change), and our fallback gas price is too low, the batch will + :: also be blocked, if we don't increase the next-gas-price, so either way + :: the batch will be stuck because of another underlying issue. + :: + %_ send-tx + next-gas-price + ?: =(0 next-gas-price.send-tx) + fallback-gas-price + (add next-gas-price.send-tx 5.000.000.000) == :_ state ?: ?& !sent.send-tx @@ -1270,6 +1426,44 @@ %+ wait:b:sys /resend/(scot %ux address)/(scot %ud nonce) (add resend-time now.bowl) + :: + ++ fix-not-sent-pending + |= not-sent=(list [=address:naive force=? =raw-tx:naive]) + =; txs=(list pend-tx) + (weld txs pending) + :: TODO: this would not be needed if txs.send-tx was a (list pend-tx) + :: + %+ murn not-sent + |= [=address:naive force=? =raw-tx:naive] + =/ =keccak (hash-raw-tx:lib raw-tx) + ?~ wer=(~(get by finding) keccak) + ~& >>> %missing-tx-in-finding + ~ + ?@ u.wer + ~& >>> %missing-tx-in-finding + ~ + `[force address time.u.wer raw-tx] + :: + ++ fix-not-sent-status + |= not-sent=(list [=address:naive force=? =raw-tx:naive]) + %+ roll not-sent + |= [[@ @ =raw-tx:naive] nif=_finding sih=_history] + =/ =keccak (hash-raw-tx:lib raw-tx) + ?~ val=(~(get by nif) keccak) + [nif sih] + ?. ?=(^ u.val) + [nif sih] + =* time time.u.val + =* address address.u.val + =* ship ship.from.tx.raw-tx + =/ l2-tx (l2-tx +<.tx.raw-tx) + =/ =roll-tx [ship %pending keccak l2-tx] + =+ txs=(~(got by sih) address) + =. txs +:(del:orh:dice txs time) + :- (~(del by nif) keccak) + %+ ~(put by sih) address + (put:orh:dice txs [time roll-tx]) + -- :: +on-naive-diff: process l2 tx confirmations :: ++ on-naive-diff @@ -1309,7 +1503,7 @@ ?~ sen=(get:ors:dice sending [address nonce]) ~? lverb [dap.bowl %weird-double-remove nonce+nonce] sending - ?~ nin=(find [raw-tx.diff]~ txs.u.sen) + ?~ nin=(find [raw-tx.diff]~ (turn txs.u.sen (cork tail tail))) ~? lverb [dap.bowl %weird-unknown nonce+nonce] sending =. txs.u.sen (oust [u.nin 1] txs.u.sen) @@ -1331,6 +1525,7 @@ :: ~? !forced [dap.bowl %aggregated-tx-failed-anyway err.diff] %failed :: + ~? =(0x0 tx-address) %weird-null-tx-address^'on-naive-diff' =^ updates history %^ update-history:dice history @@ -1507,11 +1702,17 @@ |= wat=@t ?~ who=(slaw %p wat) [~ ~] =/ [exceeded=? next-quota=@ud] (quota-exceeded u.who) + =/ allow=(unit (unit @ud)) (~(get by allowances) u.who) :+ ~ ~ :- %atom !> ^- @ud - ?: exceeded 0 - (sub quota.state (dec next-quota)) + ?: exceeded 0 + =/ max-quota=@ quota.state + ?: &(?=(^ allow) ?=(~ u.allow)) + max-quota + =? max-quota &(?=(^ allow) ?=(^ u.allow)) + u.u.allow + (sub max-quota (dec next-quota)) :: ++ allowance |= wat=@t diff --git a/pkg/arvo/app/spider.hoon b/pkg/arvo/app/spider.hoon index 83e360d2d1..bb1adf7aeb 100644 --- a/pkg/arvo/app/spider.hoon +++ b/pkg/arvo/app/spider.hoon @@ -9,14 +9,10 @@ +$ input input:spider +$ yarn (list tid) +$ thread-form _*eval-form:eval:(strand ,vase) -+$ trie - $~ [*thread-form ~] - [=thread-form kid=(map tid trie)] -:: -+$ trying ?(%build %none) ++$ trying ?(%build %none) +$ state $: starting=(map yarn [=trying =vase]) - running=trie + running=(axal thread-form) tid=(map tid yarn) serving=(map tid [(unit @ta) =mark =desk]) == @@ -72,85 +68,6 @@ running=(list yarn) tid=(map tid yarn) == -:: -+$ start-args - [parent=(unit tid) use=(unit tid) =beak file=term =vase] --- -:: -:: Trie operations -:: -~% %spider ..card ~ -|% -++ get-yarn - |= [=trie =yarn] - ^- (unit =thread-form) - ?~ yarn - `thread-form.trie - =/ son (~(get by kid.trie) i.yarn) - ?~ son - ~ - $(trie u.son, yarn t.yarn) -:: -++ get-yarn-children - |= [=trie =yarn] - ^- (list ^yarn) - ?~ yarn - (turn (tap-yarn trie) head) - =/ son (~(get by kid.trie) i.yarn) - ?~ son - ~ - $(trie u.son, yarn t.yarn) -:: -:: -++ has-yarn - |= [=trie =yarn] - !=(~ (get-yarn trie yarn)) -:: -++ put-yarn - |= [=trie =yarn =thread-form] - ^+ trie - ?~ yarn - trie(thread-form thread-form) - =/ son (~(gut by kid.trie) i.yarn [*^thread-form ~]) - %= trie - kid - %+ ~(put by kid.trie) i.yarn - $(trie son, yarn t.yarn) - == -:: -++ del-yarn - |= [=trie =yarn] - ^+ trie - ?~ yarn - trie - |- - ?~ t.yarn - trie(kid (~(del by kid.trie) i.yarn)) - =/ son (~(get by kid.trie) i.yarn) - ?~ son - trie - %= trie - kid - %+ ~(put by kid.trie) i.yarn - $(trie u.son, yarn t.yarn) - == -:: -++ tap-yarn - |= =trie - %- flop :: preorder - =| =yarn - |- ^- (list [=^yarn =thread-form]) - %+ welp - ?~ yarn - ~ - [(flop yarn) thread-form.trie]~ - =/ kids ~(tap by kid.trie) - |- ^- (list [=^yarn =thread-form]) - ?~ kids - ~ - =/ next-1 ^$(yarn [p.i.kids yarn], trie q.i.kids) - =/ next-2 $(kids t.kids) - (welp next-1 next-2) -- :: %- agent:dbug @@ -250,7 +167,7 @@ =^ cards state ?+ mark (on-poke:def mark vase) %spider-input (on-poke-input:sc !<(input vase)) - %spider-start (handle-start-thread:sc !<(start-args vase)) + %spider-start (handle-start-thread:sc !<(start-args:spider vase)) %spider-stop (handle-stop-thread:sc !<([tid ?] vase)) :: %handle-http-request @@ -277,10 +194,10 @@ ^- (unit (unit cage)) ?+ path (on-peek:def path) [%x %tree ~] - ``noun+!>((turn (tap-yarn running.state) head)) + ``noun+!>((turn ~(tap of running.state) head)) :: [%x %starting @ ~] - ``noun+!>((has-yarn running.state (~(got by tid.state) i.t.t.path))) + ``noun+!>((~(has of running.state) (~(got by tid.state) i.t.t.path))) :: [%x %saxo @ ~] ``noun+!>((~(got by tid.state) i.t.t.path)) @@ -316,7 +233,7 @@ (on-load on-save) -- :: -~% %spider-helper ..get-yarn ~ +~% %spider-helper ..card ~ |_ =bowl:gall ++ bec `beak`byk.bowl(r da+now.bowl) ++ bind-eyre @@ -349,7 +266,7 @@ =/ body=json (need (de-json:html q.u.body.request.inbound-request)) =/ input=vase (slop !>(~) (tube !>(body))) =/ boc bec - =/ =start-args [~ `tid boc(q desk, r da+now.bowl) thread input] + =/ =start-args:spider [~ `tid boc(q desk, r da+now.bowl) thread input] (handle-start-thread start-args) :: ++ on-poke-input @@ -394,7 +311,7 @@ =/ new-tid (fall use (new-thread-id file)) =/ =yarn (snoc parent-yarn new-tid) :: - ?: (has-yarn running.state yarn) + ?: (~(has of running.state) yarn) ~| [%already-started yarn] !! ?: (~(has by starting.state) yarn) @@ -439,7 +356,7 @@ |= [=yarn =thread] ^- (quip card ^state) =/ =vase vase:(~(got by starting.state) yarn) - ?< (has-yarn running.state yarn) + ?< (~(has of running.state) yarn) =/ m (strand ,^vase) =/ res (mule |.((thread vase))) ?: ?=(%| -.res) @@ -447,7 +364,7 @@ =/ =eval-form:eval:m (from-form:eval:m p.res) =: starting.state (~(del by starting.state) yarn) - running.state (put-yarn running.state yarn eval-form) + running.state (~(put of running.state) yarn eval-form) == (take-input yarn ~) :: @@ -458,7 +375,7 @@ ?~ yarn ~& %stopping-nonexistent-thread [~ state] - ?: (has-yarn running.state u.yarn) + ?: (~(has of running.state) u.yarn) ?: nice (thread-done u.yarn *vase) (thread-fail u.yarn %cancelled ~) @@ -474,11 +391,11 @@ |= [=yarn input=(unit input:strand)] ^- (quip card ^state) =/ m (strand ,vase) - ?. (has-yarn running.state yarn) + ?. (~(has of running.state) yarn) %- (slog leaf+"spider got input for non-existent {}" ~) `state =/ =eval-form:eval:m - thread-form:(need (get-yarn running.state yarn)) + (need fil:(~(dip of running.state) yarn)) =| cards=(list card) |- ^- (quip card ^state) =^ r=[cards=(list card) =eval-result:eval:m] eval-form @@ -489,7 +406,7 @@ %& p.out %| [[~ [%fail %crash p.out]] eval-form] == - =. running.state (put-yarn running.state yarn eval-form) + =. running.state (~(put of running.state) yarn eval-form) =/ =tid (yarn-to-tid yarn) =. cards.r %+ turn cards.r @@ -593,7 +510,10 @@ |= =yarn ^- (quip card ^state) =/ children=(list ^yarn) - [yarn (get-yarn-children running.state yarn)] + %+ turn + ~(tap of (~(dip of running.state) yarn)) + |= [child=^yarn *] + (welp yarn child) |- ^- (quip card ^state) ?~ children `state @@ -601,9 +521,10 @@ =^ cards-our state =/ =^yarn i.children =/ =tid (yarn-to-tid yarn) - =: running.state (del-yarn running.state yarn) + =: running.state (~(lop of running.state) yarn) + tid.state (~(del by tid.state) tid) - serving.state (~(del by serving.state) (yarn-to-tid yarn)) + serving.state (~(del by serving.state) (yarn-to-tid yarn)) == :_ state %+ murn ~(tap by wex.bowl) @@ -648,7 +569,6 @@ :: ++ yarn-to-byk |= [=yarn =bowl:gall] - =/ [* * =desk] ~| "no desk associated with {}" %- ~(got by serving.state) (yarn-to-tid yarn) @@ -657,7 +577,7 @@ :: ++ clean-state !> ^- clean-slate - 4+state(running (turn (tap-yarn running.state) head)) + 4+state(running (turn ~(tap of running.state) head)) :: ++ convert-tube |= [from=mark to=mark =desk =bowl:gall] @@ -666,5 +586,4 @@ %cc /(scot %p our.bowl)/[desk]/(scot %da now.bowl)/[from]/[to] == - -- diff --git a/pkg/arvo/gen/azimuth/kick.hoon b/pkg/arvo/gen/azimuth/kick.hoon index 9082cfe83c..ad63d5236a 100644 --- a/pkg/arvo/gen/azimuth/kick.hoon +++ b/pkg/arvo/gen/azimuth/kick.hoon @@ -1,4 +1,5 @@ :: Kick azimuth +:: :- %say |= * -[%azimuth-poke %listen ~ %| %azimuth] +[%azimuth-poke %kick ~] diff --git a/pkg/arvo/gen/azimuth/watch.hoon b/pkg/arvo/gen/azimuth/watch.hoon index e85ad14704..97c0d74b07 100644 --- a/pkg/arvo/gen/azimuth/watch.hoon +++ b/pkg/arvo/gen/azimuth/watch.hoon @@ -1,4 +1,5 @@ :: Change node url and network for azimuth +:: :- %say |= [* [url=@ta net=?(%mainnet %ropsten %local %default) ~] ~] [%azimuth-poke %watch url net] diff --git a/pkg/arvo/gen/brass.hoon b/pkg/arvo/gen/brass.hoon index 67a1cd8f00..98c39ec7e7 100644 --- a/pkg/arvo/gen/brass.hoon +++ b/pkg/arvo/gen/brass.hoon @@ -26,7 +26,7 @@ :: ~ == -:- %boot-pill +:- %pill ^- pill:pill :: sys: root path to boot system, `/~me/[desk]/now/sys` :: bas: root path to boot system' desk diff --git a/pkg/arvo/gen/dns-bind/authority.hoon b/pkg/arvo/gen/dns-bind/authority.hoon index 9b6be44276..55750e3b28 100644 --- a/pkg/arvo/gen/dns-bind/authority.hoon +++ b/pkg/arvo/gen/dns-bind/authority.hoon @@ -20,7 +20,7 @@ %- crip +:(scow %p .^(@p %j /(scot %p our)/code/(scot %da now)/(scot %p our))) =/ secrets - .^(@t %cx :(weld /(scot %p our)/home/(scot %da now)/sec domain /atom)) + .^(@t %cx :(weld /(scot %p our)/base/(scot %da now)/sec domain /atom)) :: =- ?~ arg - (fun.q.q [%& dom.arg]) diff --git a/pkg/arvo/gen/help.hoon b/pkg/arvo/gen/help.hoon index 7b893eb4eb..277b41e93a 100644 --- a/pkg/arvo/gen/help.hoon +++ b/pkg/arvo/gen/help.hoon @@ -42,7 +42,7 @@ :: :- %say |= [[now=time @ our=ship ^] typ=$@(~ [p=term ~]) ~] -=/ pax=path /(scot %p our)/home/(scot %da now)/gen :: XX hardcoded +=/ pax=path /(scot %p our)/base/(scot %da now)/gen :: XX hardcoded =+ len=(lent pax) =. pax ?~(typ pax (welp pax /[p.typ])) :- %tang %- flop ^- tang diff --git a/pkg/arvo/gen/hood/ames-prod.hoon b/pkg/arvo/gen/hood/ames-prod.hoon new file mode 100644 index 0000000000..4641f430b1 --- /dev/null +++ b/pkg/arvo/gen/hood/ames-prod.hoon @@ -0,0 +1,4 @@ +:- %say +|= [^ ships=(list ship) ~] +:- %helm-ames-prod +ships diff --git a/pkg/arvo/gen/hood/fuse.hoon b/pkg/arvo/gen/hood/fuse.hoon index 59940b3639..af3a290fbc 100644 --- a/pkg/arvo/gen/hood/fuse.hoon +++ b/pkg/arvo/gen/hood/fuse.hoon @@ -13,7 +13,7 @@ +$ fuse-arg $: des=desk :: specified as [germ path] instead of [path germ] so - :: users can write mate//=home= instead of [/=home= %mate] + :: users can write mate//=base= instead of [/=base= %mate] :: res=[?([%cancel ~] [bas=path con=(list [germ path])])] == diff --git a/pkg/arvo/gen/hood/fuse/help.txt b/pkg/arvo/gen/hood/fuse/help.txt index 009a7e0358..661947214e 100644 --- a/pkg/arvo/gen/hood/fuse/help.txt +++ b/pkg/arvo/gen/hood/fuse/help.txt @@ -1,6 +1,6 @@ Usage: - |fuse %dest /=kids= mate//~nel/home= meet//~zod/kids/track + |fuse %dest /=kids= mate//~nel/base= meet//~zod/kids/track |fuse %old-desk /=kids= only-that//~nus/test=, =overwrite & |fuse %desk-to-cancel-fuse-into %cancel diff --git a/pkg/arvo/gen/hood/merge/help.txt b/pkg/arvo/gen/hood/merge/help.txt index 613bcb8f18..738708d9ad 100644 --- a/pkg/arvo/gen/hood/merge/help.txt +++ b/pkg/arvo/gen/hood/merge/help.txt @@ -7,7 +7,7 @@ Usage: We support various merge strategies. A "commit" is a snapshot of the files with a list of parents plus a date. Most commits have one parent; a "merge" commit is a commit with two parents. The -%home desk starts with an initial commit with no parents; commits +%base desk starts with an initial commit with no parents; commits with several parents ("octopus merges") are possible but we don't generate them right now. @@ -72,13 +72,13 @@ We speak of merging into a destination *desk* from a source *commit* because while you can only merge on top of a desk, you can merge from historical commits. For example, - |merge %old our %home, =cas ud+5, =gem %init + |merge %old our %base, =cas ud+5, =gem %init -will create a new desk called %old with the 5th commit in %home. +will create a new desk called %old with the 5th commit in %base. You can revert the contents of a desk to what they were yesterday with - |merge %home our %home, =cas da+(sub now ~d1), =gem %only-that + |merge %base our %base, =cas da+(sub now ~d1), =gem %only-that Note this is a normal %only-that merge, which means you're creating a *new* commit with the old *contents*. diff --git a/pkg/arvo/gen/hood/norm.hoon b/pkg/arvo/gen/hood/norm.hoon new file mode 100644 index 0000000000..2cdd7dfe0a --- /dev/null +++ b/pkg/arvo/gen/hood/norm.hoon @@ -0,0 +1,11 @@ +:: Add rule to tombstone policy +:: +:- %say +|= [[now=@da eny=@uvJ bec=beak] [=ship =desk =path keep=? ~] ~] +:- %helm-pass +=+ .^(=cone:clay %cx /(scot %p p.bec)//(scot %da now)/domes) +=/ =norm:clay + ?~ got=(~(get by cone) ship desk) + *norm:clay + nor.u.got +[%c %tomb %norm ship desk (~(put of norm) path keep)] diff --git a/pkg/arvo/gen/hood/pick.hoon b/pkg/arvo/gen/hood/pick.hoon new file mode 100644 index 0000000000..929b36865f --- /dev/null +++ b/pkg/arvo/gen/hood/pick.hoon @@ -0,0 +1,6 @@ +:: Execute tombstone policy +:: +:- %say +|= [[now=@da eny=@uvJ bec=beak] ~ ~] +:- %helm-pass +[%c %tomb %pick ~] diff --git a/pkg/arvo/gen/hood/story-init.hoon b/pkg/arvo/gen/hood/story-init.hoon new file mode 100644 index 0000000000..d682864480 --- /dev/null +++ b/pkg/arvo/gen/hood/story-init.hoon @@ -0,0 +1,23 @@ +:: story: Create a story file for a given desk, optionally overwriting +:: +:::: + :: +/- *story +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[~] =desk overwrite=_| ~] + == +=/ our p.bec +=? desk =(*^desk desk) q.bec :: use current desk if user didn't provide +?: !(~(has in .^((set ^desk) %cd /(scot %p our)/$/(scot %da now))) desk) + ~& >> "Error: desk {} does not exist." + helm-pass+[%d %noop ~] +=/ existing-story .^(? %cu /(scot %p our)/[desk]/(scot %da now)/story) +?: ?&(existing-story !overwrite) + ~& >> "Error: /{(trip (slav %tas desk))}/story already exists." + ~& >> "To forcibly overwrite, use `=overwrite %.y`" + :: XX could use a better way to noop + helm-pass+[%d %noop ~] +=| tale=story +:- %helm-pass +[%c [%info desk %& [/story %ins story+!>(tale)]~]] \ No newline at end of file diff --git a/pkg/arvo/gen/hood/story-remove.hoon b/pkg/arvo/gen/hood/story-remove.hoon new file mode 100644 index 0000000000..8a3fe4c171 --- /dev/null +++ b/pkg/arvo/gen/hood/story-remove.hoon @@ -0,0 +1,36 @@ +:: story: Remove any commit message(s) for a given commit +:: +:: Optionally targeting a specific desk or prose +:: +:::: + :: +/- *story +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[cas=cash ~] =desk prz=prose ~] + == +=/ our p.bec +=? desk =(*^desk desk) q.bec :: use current desk if user didn't provide +=? cas =(*case cas) r.bec :: use case from beak if cas not provided +?: !(~(has in .^((set ^desk) %cd /(scot %p our)/$/(scot %da now))) desk) + ~& >> "Error: desk {} does not exist." + helm-pass+[%d %noop ~] +=/ tak=tako:clay + ?: ?=([%tako tako:clay] cas) + p.cas + ?: !.^(? %cs /(scot %p our)/[desk]/(scot cas)/case) + ~& >> "Error: invalid case {} provided" + !! + .^(tako:clay %cs /(scot %p our)/[desk]/(scot cas)/tako/~) +:: +=/ pax /(scot %p our)/[desk]/(scot %da now)/story +?: !.^(? %cu pax) + ~& >> "Error: No story file found. Please use |story-init to create one." + helm-pass+[%d %noop ~] +=/ tale=story .^(story %cx pax) +=. tale + ?: =(*prose prz) + (~(del by tale) tak) + (~(del ju tale) tak prz) +:- %helm-pass +[%c [%info desk %& [/story %ins story+!>(tale)]~]] \ No newline at end of file diff --git a/pkg/arvo/gen/hood/story-write.hoon b/pkg/arvo/gen/hood/story-write.hoon new file mode 100644 index 0000000000..5c213dad1f --- /dev/null +++ b/pkg/arvo/gen/hood/story-write.hoon @@ -0,0 +1,34 @@ +:: story: Attach a commit message (to the last commit by default) +:: +:: Optionally takes a case and desk +:: +:::: + :: +/- *story +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[title=@t body=$@(~ [p=@t ~])] =desk cas=cash ~] + == +=/ our p.bec +=? desk =(*^desk desk) q.bec :: use current desk if user didn't provide +=? cas =(*case cas) r.bec :: use case from beak if cas not provided +?: !(~(has in .^((set ^desk) %cd /(scot %p our)/$/(scot %da now))) desk) + ~& >> "Error: desk {} does not exist." + helm-pass+[%d %noop ~] +=/ tak=tako:clay + ?: ?=([%tako tako:clay] cas) + p.cas + ?: !.^(? %cs /(scot %p our)/[desk]/(scot cas)/case) + ~& >> "Error: invalid case {} provided" + !! + .^(tako:clay %cs /(scot %p our)/[desk]/(scot cas)/tako/~) +:: +=/ pax /(scot %p our)/[desk]/(scot %da now)/story +?: !.^(? %cu pax) + ~& >> "Error: No story file found. Please use |story-init to create one." + helm-pass+[%d %noop ~] +=/ tale=story .^(story %cx /(scot %p our)/[desk]/(scot %da now)/story) +=/ =prose [title ?~(body '' p.body)] +=. tale (~(put ju tale) tak prose) +:- %helm-pass +[%c [%info desk %& [/story %ins story+!>(tale)]~]] \ No newline at end of file diff --git a/pkg/arvo/gen/hood/tomb.hoon b/pkg/arvo/gen/hood/tomb.hoon new file mode 100644 index 0000000000..6d20b54591 --- /dev/null +++ b/pkg/arvo/gen/hood/tomb.hoon @@ -0,0 +1,65 @@ +:: Perform minimal norm change to delete a file, use =dry & for dry run +:: +:: TODO: recognize when it's going to fail because it's in the head of +:: a desk, and maybe offer to |rm +:: +=, clay +:- %say +|= [[now=@da eny=@uvJ bec=beak] [target=path ~] dry=_|] +:- %helm-pans +=+ .^(=arch %cy target) +?~ fil.arch + [%d %flog %text "tomb: not a file"]~ :: should recurse +=/ =lobe u.fil.arch +=+ .^(=rang %cx /(scot %p p.bec)//(scot %da now)/rang) +=+ .^(=cone %cx /(scot %p p.bec)//(scot %da now)/domes) +=/ domes=(list [[=ship =desk] =dome tom=(map tako norm) nor=norm]) + ~(tap by cone) +=/ norms + |^ + |- ^- (set [ship desk tako norm path]) + ?~ domes + ~ + =/ n 1 + =/ =aeon 1 + %- ~(uni in $(domes t.domes)) + |- ^- (set [ship desk tako norm path]) + ?: (lth let.dome.i.domes aeon) + ~ + =/ =tako (~(got by hit.dome.i.domes) aeon) + =/ paths (draw-tako ship.i.domes desk.i.domes +.i.domes tako) + (~(uni in paths) $(aeon +(aeon))) + :: + ++ draw-tako + |= [=ship =desk [dome tom=(map tako norm) nor=norm] =tako] + ^- (set [^ship ^desk ^tako norm path]) + ~+ + =/ =yaki (~(got by hut.rang) tako) + =/ takos + |- ^- (set [^ship ^desk ^tako norm path]) + ?~ p.yaki + ~ + (~(uni in $(p.yaki t.p.yaki)) ^$(tako i.p.yaki)) + |- ^- (set [^ship ^desk ^tako norm path]) + ?~ q.yaki + takos + %- ~(uni in $(q.yaki l.q.yaki)) + %- ~(uni in $(q.yaki r.q.yaki)) + ^- (set [^ship ^desk ^tako norm path]) + ?. =(lobe q.n.q.yaki) + ~ + [[ship desk tako (~(gut by tom) tako nor) p.n.q.yaki] ~ ~] + -- +^- (list note-arvo) +%+ welp + %+ murn ~(tap in norms) + |= [=ship =desk =tako =norm =path] + ?: ?=([~ %|] (~(fit of norm) path)) + ~ + %- (slog leaf+"tomb: {}" ~) + ?: dry + ~ + `[%c %tomb %worn ship desk tako (~(put of norm) path %|)] +?: dry + ~ +[%c %tomb %pick ~]~ diff --git a/pkg/arvo/gen/norms.hoon b/pkg/arvo/gen/norms.hoon new file mode 100644 index 0000000000..81cc3594f0 --- /dev/null +++ b/pkg/arvo/gen/norms.hoon @@ -0,0 +1,15 @@ +:: Display tombstone policies +:: +=, clay +:- %say +|= [[now=@da eny=@uvJ bec=beak] ~ ~] +:- %tang +=+ .^(=cone %cx /(scot %p p.bec)//(scot %da now)/domes) +%- flop ^- tang +%- zing +%+ turn ~(tap by cone) +|= [[=ship =desk] dome tom=(map tako norm) nor=norm] +:- leaf+"{}/{}:" +%+ turn ~(tap of nor) +|= [=path keep=?] +leaf+" {}: {}" diff --git a/pkg/arvo/gen/show-vat.hoon b/pkg/arvo/gen/show-vat.hoon index 180b29eedb..922cc92bc4 100644 --- a/pkg/arvo/gen/show-vat.hoon +++ b/pkg/arvo/gen/show-vat.hoon @@ -7,8 +7,8 @@ %- flop ^- tang =/ pax=path /(scot %p p.bec)/[desk]/(scot %da now) =+ .^([lal=@tas num=@ud] cx+(weld pax /sys/kelvin)) -:~ 'sys.kelvin:' - leaf/"[%{} %{}]" - 'desk.bill:' +:~ '/sys/kelvin:' + leaf/"[{} {}]" + '/desk/bill:' (sell !>(.^((list dude:gall) cx+(weld pax /desk/bill)))) == diff --git a/pkg/arvo/gen/solid.hoon b/pkg/arvo/gen/solid.hoon index 5a747004e0..d131a73387 100644 --- a/pkg/arvo/gen/solid.hoon +++ b/pkg/arvo/gen/solid.hoon @@ -29,7 +29,7 @@ :: dub=_| == -:- %boot-pill +:- %pill ^- pill:pill :: sys: root path to boot system, `/~me/[desk]/now/sys` :: bas: root path to boot system' desk diff --git a/pkg/arvo/gen/story-list.hoon b/pkg/arvo/gen/story-list.hoon new file mode 100644 index 0000000000..bc46a44387 --- /dev/null +++ b/pkg/arvo/gen/story-list.hoon @@ -0,0 +1,23 @@ +:: story: List unordered commit messages for the given desk, including orphans +:: +:::: + :: +/- *story +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[~] =desk ~] + == +=/ our p.bec +=? desk =(*^desk desk) q.bec :: use current desk if user didn't provide +=/ cas r.bec :: use case from beak +=/ pax /(scot %p our)/[desk]/(scot cas)/story +?: !(~(has in .^((set ^desk) %cd /(scot %p our)/$/(scot %da now))) desk) + tang+[leaf+"Error: desk {} does not exist." ~] +?: !.^(? %cu pax) + tang+['Error: No story file found. Please use |story-init to create one.' ~] +=/ story-to-txt + .^($-(story wain) %cf /(scot %p our)/[desk]/(scot cas)/story/txt) +:: +=/ tale .^(story %cx pax) +=/ tale-text (story-to-txt tale) +tang+tale-text \ No newline at end of file diff --git a/pkg/arvo/gen/story-read.hoon b/pkg/arvo/gen/story-read.hoon new file mode 100644 index 0000000000..dd6e21c1fd --- /dev/null +++ b/pkg/arvo/gen/story-read.hoon @@ -0,0 +1,154 @@ +:: story: log commits in order +:: +:::: + :: +/- *story +/+ lib=story +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[~] =desk ~] + == +|^ +=/ our p.bec +=? desk =(*^desk desk) q.bec :: use current desk if user didn't provide +=/ cas r.bec :: use case from beak +=/ pax /(scot %p our)/[desk]/(scot cas)/story +?: !(~(has in .^((set ^desk) %cd /(scot %p our)/$/(scot %da now))) desk) + tang+[leaf+"Error: desk {} does not exist." ~] +?: !.^(? %cu pax) + tang+['Error: No story file found. Please use |story-init to create one.' ~] +=/ tak .^(tako:clay %cs /(scot %p our)/[desk]/(scot cas)/tako/~) +=/ yak .^(yaki:clay %cs /(scot %p our)/[desk]/(scot cas)/yaki/(scot %uv tak)) +=/ tale .^(story %cx pax) +:- %tang +(story-read [our desk cas] yak tale) +:::: +:: Remarks: +:: +:: There are two recursions in the logging process: +:: 1. the outer loop `commit-loop` threads down into each commit by ancestor +:: 2. the inner loop `ancestor-loop` threads left-to-right on reverse-ancestors +:: +:: +story-read outputs a tang with the least-recent commits at the head +:: of the list, even though we want most-recent commits to print first. +:: But because dojo prints tangs in reverse, we don't flop the results. +:::: +++ story-read + |= [[our=ship syd=^desk cas=case] this-commit=yaki:clay tale=story] + ^- tang + :: TODO factor out /(scot %p our)/[syd]/(scot cas) + %- head :: result from state + =| state=[result=tang mergebase=(unit tako:clay)] + |- + ^- _state + =* commit-loop $ + =/ reverse-ancestors (flop p.this-commit) + |- + =* ancestor-loop $ + ?- reverse-ancestors + ~ + :: stop here and return the current message + =/ msg=(list cord) (msg-from-commit this-commit tale) + [(weld msg result.state) mergebase=~] + :: + [tako:clay ~] + =/ parent i.reverse-ancestors + =/ parent-commit + .^(yaki:clay %cs /(scot %p our)/[syd]/(scot cas)/yaki/(scot %uv parent)) + :: + =/ msg + (msg-from-commit this-commit tale) + :: + :: If there is a mergebase and we are visting it right now: + :: stop here and clear the mergebase. + :: skip adding the mergebase's msg itself, + :: because it will be added through the other branch. + :: Otherwise, record the current message if exists and recur. + ?: ?&(?=(^ mergebase.state) =(u.mergebase.state r.this-commit)) + [result=result.state mergebase=~] + commit-loop(this-commit parent-commit, result.state (weld msg result.state)) + :: + [tako:clay tako:clay ~] + :: + :: mainline: ultimate base chain + :: nowline: relative mainline + :: sideline: side-chain, featurebranch + :: + :: From the context of e, commit c is on its relative mainline, or nowline, + :: while commit d is on its sideline. + :: + :: %base a--b-------------X :: mainline + :: %new \--c------e--/ :: nowline + :: %new2 \--d--/ :: sideline + :: + :: + =/ sideline i.reverse-ancestors + =/ mainline i.t.reverse-ancestors + :: XX base-tako ignores beak + :: + =/ mergebases + .^ (list tako:clay) %cs + (scot %p our) syd (scot cas) + /base-tako/(scot %uv mainline)/(scot %uv sideline) + == + :: + :: Take the first valid mergebase (by convention) if exists, else none + :: + =/ next-mergebase + ?~(mergebases ~ (some i.mergebases)) + :: + =/ sideline-commit + .^(yaki:clay %cs /(scot %p our)/[syd]/(scot cas)/yaki/(scot %uv sideline)) + :: + =/ mainline-commit + .^(yaki:clay %cs /(scot %p our)/[syd]/(scot cas)/yaki/(scot %uv mainline)) + :: + =/ msg=(list cord) + (msg-from-commit this-commit tale) + :: + :: 1 - process current commit + :: 2 - recur and queue processing on all commits on the sideline + :: 3 - recur and queue processing on all commits on the mainline + :: + :: Because mainline messages are cons'd to result last, they are + :: (by definition) towards the less recent side of the flopped list + :: + =. state [result=(weld msg result.state) mergebase=next-mergebase] :: 1 + =. state commit-loop(this-commit sideline-commit) :: 2 + =. state commit-loop(this-commit mainline-commit) :: 3 + state + :: + [tako:clay tako:clay tako:clay *] + :: ~& "in 3+ ancestor commit" + =/ sideline i.reverse-ancestors + =/ nowline i.t.reverse-ancestors + =/ mergebases + .^ (list tako:clay) %cs + (scot %p our) syd (scot cas) + /base-tako/(scot %uv nowline)/(scot %uv sideline) + == + :: + :: Take the first valid mergebase (by convention) if exists, else none + :: + =/ next-mergebase ?~(mergebases ~ (some i.mergebases)) + =/ sideline-commit + .^(yaki:clay %cs /(scot %p our)/[syd]/(scot cas)/yaki/(scot %uv sideline)) + =. mergebase.state next-mergebase + =. state commit-loop(this-commit sideline-commit) :: downward + =. state ancestor-loop(reverse-ancestors t.reverse-ancestors) :: rightward + state + == +:: +++ msg-from-commit + |= [commit=yaki:clay tale=story] + ^- (list cord) + =/ proses (~(get by tale) r.commit) + ?~ proses ~ + %- flop :: fixes formatting reversal in dojo + %- to-wain:format + %- crip + ;: welp + (tako-to-text:lib r.commit) + (proses-to-text:lib u.proses) + == +-- diff --git a/pkg/arvo/gen/vat.hoon b/pkg/arvo/gen/vat.hoon new file mode 100644 index 0000000000..703ade5635 --- /dev/null +++ b/pkg/arvo/gen/vat.hoon @@ -0,0 +1,10 @@ +/- *hood +:- %say +|= $: [now=@da eny=@uvJ bec=beak] + [[=desk ~] ~] + == +?: =(desk %kids) [%tang ~[(report-kids p.bec now)]] +=+ .^ =vat %gx + /(scot %p p.bec)/hood/(scot %da now)/kiln/vat/[desk]/noun + == +[%tang ~[(report-vat p.bec now vat)]] diff --git a/pkg/arvo/lib/aqua-azimuth.hoon b/pkg/arvo/lib/aqua-azimuth.hoon index 4aec08d1c6..75ff042ece 100644 --- a/pkg/arvo/lib/aqua-azimuth.hoon +++ b/pkg/arvo/lib/aqua-azimuth.hoon @@ -14,7 +14,7 @@ |= [our=ship her=ship uf=unix-effect azi=az-state] ^- (unit card:agent:gall) =, enjs:format - =/ ask (extract-request uf 'http://localhost:8545/') + =/ ask (extract-request uf 'http://fake.aqua.domain/') ?~ ask ~ ?~ body.request.u.ask diff --git a/pkg/arvo/lib/azimuth-roll-rpc.hoon b/pkg/arvo/lib/azimuth-roll-rpc.hoon index 7bd33374b7..3fc2161558 100644 --- a/pkg/arvo/lib/azimuth-roll-rpc.hoon +++ b/pkg/arvo/lib/azimuth-roll-rpc.hoon @@ -179,6 +179,12 @@ ^- (unit @ud) ?~ nonce=(~(get by params) 'nonce') ~ (ni u.nonce) + :: + ++ force + |= params=(map @t json) + ^- (unit ?) + ?~ force=(~(get by params) 'force') ~ + (bo u.force) -- :: ++ to-json @@ -520,15 +526,20 @@ ++ process-rpc |= [id=@t params=(map @t json) action=l2-tx over-quota=$-(@p ?)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 4) + ?. ?| =((lent ~(tap by params)) 4) + =((lent ~(tap by params)) 5) + == [~ ~(params error:json-rpc id)] + =? params =((lent ~(tap by params)) 4) + (~(put by params) 'force' b+|) =+ ^- $: sig=(unit @) from=(unit [=ship proxy:naive]) addr=(unit @ux) + force=(unit ?) == =, from-json - [(sig params) (from params) (address params)] - ?: |(?=(~ sig) ?=(~ from) ?=(~ addr)) + [(sig params) (from params) (address params) (force params)] + ?: |(?=(~ sig) ?=(~ from) ?=(~ addr) ?=(~ force)) [~ ~(parse error:json-rpc id)] ?: (over-quota ship.u.from) `[%error id '-32002' 'Max tx quota exceeded'] @@ -537,7 +548,7 @@ =+ (gen-tx-octs:lib u.tx) :_ [%result id (hex:to-json 32 (hash-tx:lib p q))] %- some - roller-action+!>([%submit | u.addr u.sig %don u.tx]) + roller-action+!>([%submit u.force u.addr u.sig %don u.tx]) :: ++ nonce |= [id=@t params=(map @t json) scry=$-([ship proxy:naive] (unit @))] diff --git a/pkg/arvo/lib/desk-jam.hoon b/pkg/arvo/lib/desk-jam.hoon index 7e650c7c04..442c224083 100644 --- a/pkg/arvo/lib/desk-jam.hoon +++ b/pkg/arvo/lib/desk-jam.hoon @@ -3,11 +3,12 @@ ++ jam-desk |= [our=ship =desk now=@da] ~> %slog.0^leaf/"jamming desk {}" + =+ .^(=rang:clay %cx /(scot %p our)//(scot %da now)) + =+ .^(=tako:clay %cs /(scot %p our)/[desk]/(scot %da now)) %- jam %- ?:(=(%base desk) remove-misc-dirs same) - %- ankh-to-map - =< ank - .^(dome:clay %cv /(scot %p our)/[desk]/(scot %da now)) + %- ~(run by q:(~(got by hut.rang) tako)) + ~(got by lat.rang) :: ++ remove-misc-dirs |= fiz=(map path page) @@ -18,15 +19,4 @@ ?| ?=([%tmp *] p) ?=([%tests *] p) == -:: -++ ankh-to-map - =| res=(map path page) - =| pax=path - |= a=ankh - ^- (map path page) - =? res ?=(^ fil.a) (~(put by res) pax [p q.q]:q.u.fil.a) - =/ dir=(list [seg=@ta =ankh]) ~(tap by dir.a) - |- ^+ res - ?~ dir res - $(dir t.dir, res ^$(pax (snoc pax seg.i.dir), a ankh.i.dir)) -- diff --git a/pkg/arvo/lib/dice.hoon b/pkg/arvo/lib/dice.hoon index 55f918d83f..c59b7907b2 100644 --- a/pkg/arvo/lib/dice.hoon +++ b/pkg/arvo/lib/dice.hoon @@ -68,13 +68,13 @@ ?. (verify-sig-and-nonce:naive verifier chain-t nas raw-tx) =+ [force ~ nas indices] ?. verb - - ~& >>> [verb+verb %verify-sig-and-nonce %failed tx.raw-tx] - + ~& >>> [force+force %verify-sig-and-nonce %failed tx.raw-tx] - =^ effects-1 points.nas (increment-nonce:naive nas from.tx.raw-tx) ?~ nex=(receive-tx:naive nas tx.raw-tx) =+ [force ~ ?:(force nas cache) indices] ?. verb - - ~& >>> [verb+verb %receive-tx %failed] - + ~& >>> [force+force %receive-tx %failed] - =* new-nas +.u.nex =/ effects (welp effects-1 -.u.nex) =^ updates indices diff --git a/pkg/arvo/lib/hood/helm.hoon b/pkg/arvo/lib/hood/helm.hoon index 055cec9f37..3fb38c7806 100644 --- a/pkg/arvo/lib/hood/helm.hoon +++ b/pkg/arvo/lib/hood/helm.hoon @@ -109,6 +109,26 @@ this (emit %pass / %arvo %j %moon u.sed) :: +++ poke-moon-breach + |= =ship + ?> ?| =(our src):bowl + =(src.bowl ship) + == + abet:(emit %pass /helm/moon-breach/(scot %p ship) %arvo %b %wait now.bowl) +:: +++ take-wake-moon-breach + |= [way=wire error=(unit tang)] + ?^ error + %- (slog %take-wake-moon-breach-fail u.error) + abet + ?> ?=([@ ~] way) + =/ =ship (slav %p i.way) + ?> =(%earl (clan:title ship)) + ?> =(our.bowl (sein:title our.bowl now.bowl ship)) + =/ =rift + +(.^(rift j+/(scot %p our.bowl)/rift/(scot %da now.bowl)/(scot %p ship))) + abet:(emit %pass / %arvo %j %moon ship *id:block:jael %rift rift %.n) +:: ++ poke-code |= act=?(~ %reset) =< abet @@ -138,6 +158,12 @@ |= ~ =< abet (emit %pass /pack %arvo %d %flog %pack ~) :: +++ poke-pans + |= pans=(list note-arvo) + ?~ pans abet + =. this (emit %pass /helm/pans %arvo i.pans) + $(pans t.pans) +:: ++ poke-pass |= =note-arvo =< abet (emit %pass /helm/pass %arvo note-arvo) @@ -172,6 +198,10 @@ !! abet:(flog %text "< {}: {(trip mes)}") :: +++ poke-ames-prod + |= ships=(list ship) + abet:(emit %pass /helm/prod %arvo %a %prod ships) +:: ++ poke-atom |= ato=@ =+ len=(scow %ud (met 3 ato)) @@ -225,9 +255,11 @@ ++ poke |= [=mark =vase] ?> ?| ?=(%helm-hi mark) + ?=(%helm-moon-breach mark) =(our src):bowl == ?+ mark ~|([%poke-helm-bad-mark mark] !!) + %helm-ames-prod =;(f (f !<(_+<.f vase)) poke-ames-prod) %helm-ames-sift =;(f (f !<(_+<.f vase)) poke-ames-sift) %helm-ames-verb =;(f (f !<(_+<.f vase)) poke-ames-verb) %helm-ames-wake =;(f (f !<(_+<.f vase)) poke-ames-wake) @@ -239,9 +271,11 @@ %helm-cors-reject =;(f (f !<(_+<.f vase)) poke-cors-reject) %helm-hi =;(f (f !<(_+<.f vase)) poke-hi) %helm-knob =;(f (f !<(_+<.f vase)) poke-knob) + %helm-pans =;(f (f !<(_+<.f vase)) poke-pans) %helm-mass =;(f (f !<(_+<.f vase)) poke-mass) %helm-meld =;(f (f !<(_+<.f vase)) poke-meld) %helm-moon =;(f (f !<(_+<.f vase)) poke-moon) + %helm-moon-breach =;(f (f !<(_+<.f vase)) poke-moon-breach) %helm-pack =;(f (f !<(_+<.f vase)) poke-pack) %helm-pass =;(f (f !<(_+<.f vase)) poke-pass) %helm-rekey =;(f (f !<(_+<.f vase)) poke-rekey) @@ -266,10 +300,12 @@ ++ take-arvo |= [=wire =sign-arvo] ?+ wire ~|([%helm-bad-take-wire wire +<.sign-arvo] !!) - [%automass *] %+ take-wake-automass t.wire - ?>(?=(%wake +<.sign-arvo) +>.sign-arvo) - [%serv *] %+ take-bound t.wire - ?>(?=(%bound +<.sign-arvo) +>.sign-arvo) - [%pass *] abet + [%automass *] %+ take-wake-automass t.wire + ?>(?=(%wake +<.sign-arvo) +>.sign-arvo) + [%serv *] %+ take-bound t.wire + ?>(?=(%bound +<.sign-arvo) +>.sign-arvo) + [%moon-breach *] %+ take-wake-moon-breach t.wire + ?>(?=(%wake +<.sign-arvo) +>.sign-arvo) + [%pass *] abet == -- diff --git a/pkg/arvo/lib/hood/kiln.hoon b/pkg/arvo/lib/hood/kiln.hoon index d87de9cd98..c8edd21d7f 100644 --- a/pkg/arvo/lib/hood/kiln.hoon +++ b/pkg/arvo/lib/hood/kiln.hoon @@ -1050,9 +1050,7 @@ =+ .^(=cass:clay %cw /(scot %p our)/[desk]/(scot %da now)) ?- ud.cass %0 %init - * %take-that - ::%1 %take-that - ::* %mate + * %only-that == :: ++ poke @@ -1630,7 +1628,7 @@ :: fail. :: :: We want to always use %only-that for the first remote merge. - :: But we also want local syncs (%base to %home or %kids) to + :: But we also want local syncs (%base to %base or %kids) to :: succeed after that first remote sync. To accomplish both we :: simply use %only-that for the first three sync merges. (The :: first two are from the pill.) diff --git a/pkg/arvo/lib/story.hoon b/pkg/arvo/lib/story.hoon new file mode 120000 index 0000000000..226ddf06f1 --- /dev/null +++ b/pkg/arvo/lib/story.hoon @@ -0,0 +1 @@ +../../base-dev/lib/story.hoon \ No newline at end of file diff --git a/pkg/arvo/lib/trie.hoon b/pkg/arvo/lib/trie.hoon deleted file mode 100644 index 1d41761e41..0000000000 --- a/pkg/arvo/lib/trie.hoon +++ /dev/null @@ -1,29 +0,0 @@ -|% -++ trie - |$ [key-t val-t] - [val=(unit val-t) kid=(map key-t (trie key-t val-t))] --- -:: -=| a=(trie * *) -=* val-t ?>(?=(^ val.a) val.a) -|@ -++ put - |* [b=(list *) c=*] - => .(b (homo b)) - |- ^+ a - ?~ b - a(val `c) - =/ son (~(gut by kid.a) i.b [~ ~]) - a(kid (~(put by kid.a) i.b $(a son, b t.b))) -:: -++ get - |* b=(list *) - => .(b (homo b)) - |- - ?~ b - [~ val.a] - =/ son (~(get by kid.a) i.b) - ?~ son - [b val.a] - $(a u.son, b t.b) --- diff --git a/pkg/arvo/mar/helm-moon-breach.hoon b/pkg/arvo/mar/helm-moon-breach.hoon new file mode 100644 index 0000000000..05b87d2213 --- /dev/null +++ b/pkg/arvo/mar/helm-moon-breach.hoon @@ -0,0 +1,12 @@ +|_ mun=ship +:: +++ grad %noun +++ grab + |% + ++ noun ship + -- +++ grow + |% + ++ noun mun + -- +-- diff --git a/pkg/arvo/mar/pill.hoon b/pkg/arvo/mar/pill.hoon index f1e1ffa739..8c10fa93f8 100644 --- a/pkg/arvo/mar/pill.hoon +++ b/pkg/arvo/mar/pill.hoon @@ -1,8 +1,7 @@ :: :::: /hoon/pill/mar :: -/- aquarium -=, aquarium +/+ *pill =, mimes:html |_ pil=pill ++ grow diff --git a/pkg/arvo/mar/story.hoon b/pkg/arvo/mar/story.hoon new file mode 120000 index 0000000000..915f279d88 --- /dev/null +++ b/pkg/arvo/mar/story.hoon @@ -0,0 +1 @@ +../../base-dev/mar/story.hoon \ No newline at end of file diff --git a/pkg/arvo/mar/thread-done.hoon b/pkg/arvo/mar/thread-done.hoon new file mode 120000 index 0000000000..87001ee941 --- /dev/null +++ b/pkg/arvo/mar/thread-done.hoon @@ -0,0 +1 @@ +../../base-dev/mar/thread-done.hoon \ No newline at end of file diff --git a/pkg/arvo/mar/thread-fail.hoon b/pkg/arvo/mar/thread-fail.hoon new file mode 120000 index 0000000000..cd1d4ade44 --- /dev/null +++ b/pkg/arvo/mar/thread-fail.hoon @@ -0,0 +1 @@ +../../base-dev/mar/thread-fail.hoon \ No newline at end of file diff --git a/pkg/arvo/sur/dice.hoon b/pkg/arvo/sur/dice.hoon index d88c66cde6..59c158996f 100644 --- a/pkg/arvo/sur/dice.hoon +++ b/pkg/arvo/sur/dice.hoon @@ -85,7 +85,13 @@ +$ hist-tx [p=time q=roll-tx] +$ roll-tx [=ship =status hash=keccak type=l2-tx] +$ pend-tx [force=? =address:naive =time =raw-tx:naive] -+$ send-tx [next-gas-price=@ud sent=? txs=(list raw-tx:naive)] ++$ send-tx + $: next-gas-price=@ud + sent=? + :: TODO: make txs as (list pend-tx)? + :: + txs=(list [=address:naive force=? =raw-tx:naive]) + == +$ part-tx $% [%raw raw=octs] [%don =tx:naive] diff --git a/pkg/arvo/sur/eth-watcher.hoon b/pkg/arvo/sur/eth-watcher.hoon index 71618721e9..f1316fc663 100644 --- a/pkg/arvo/sur/eth-watcher.hoon +++ b/pkg/arvo/sur/eth-watcher.hoon @@ -9,6 +9,7 @@ :: refresh-rate: rate at which to check for updates :: timeout-time: time an update check is allowed to take :: from: oldest block number to look at + :: to: optional newest block number to look at :: contracts: contract addresses to look at :: topics: event descriptions to look for :: @@ -17,6 +18,7 @@ refresh-rate=@dr timeout-time=@dr from=number:block + to=(unit number:block) contracts=(list address:ethereum) batchers=(list address:ethereum) =topics diff --git a/pkg/arvo/sur/story.hoon b/pkg/arvo/sur/story.hoon new file mode 120000 index 0000000000..4624552bd3 --- /dev/null +++ b/pkg/arvo/sur/story.hoon @@ -0,0 +1 @@ +../../base-dev/sur/story.hoon \ No newline at end of file diff --git a/pkg/arvo/sys.kelvin b/pkg/arvo/sys.kelvin index e68acb6a4c..e77a3de08a 100644 --- a/pkg/arvo/sys.kelvin +++ b/pkg/arvo/sys.kelvin @@ -1 +1 @@ -[%zuse 419] +[%zuse 418] diff --git a/pkg/arvo/sys/arvo.hoon b/pkg/arvo/sys/arvo.hoon index 3c85edda6c..e804242642 100644 --- a/pkg/arvo/sys/arvo.hoon +++ b/pkg/arvo/sys/arvo.hoon @@ -1,11 +1,12 @@ => ..ride => +!: |% +| %global :: ++ arvo %240 :: :: $arch: node identity -:: $axal: fundamental node, recursive +:: $axal: fundamental node, recursive (trie) :: $axil: fundamental node :: $beak: global context :: $beam: global name @@ -18,6 +19,7 @@ :: $gang: infinite set of peers :: $mark: symbolic content type :: $mien: orientation +:: $page: untyped cage :: +omen: namespace path and data :: $ship: network identity :: $sink: subscription @@ -25,7 +27,7 @@ +$ arch (axil @uvI) ++ axal |$ [item] - [fil=(unit item) dir=(map @ta $)] :: + [fil=(unit item) dir=(map @ta $)] ++ axil |$ [item] [fil=(unit item) dir=(map @ta ~)] @@ -49,6 +51,7 @@ +$ gang (unit (set ship)) +$ mark @tas +$ mien [our=ship now=@da eny=@uvJ] ++$ page (cask) ++ omen |$ [a] (pair path (cask a)) +$ ship @p +$ sink (trel bone ship path) @@ -414,11 +417,19 @@ :: :: |de: axal engine :: -++ de +++ of =| fat=(axal) |@ + ++ del + |= pax=path + ^+ fat + ?~ pax [~ dir.fat] + =/ kid (~(get by dir.fat) i.pax) + ?~ kid fat + fat(dir (~(put by dir.fat) i.pax $(fat u.kid, pax t.pax))) + :: Descend to the axal at this path :: - ++ get + ++ dip |= pax=path ^+ fat ?~ pax fat @@ -426,21 +437,51 @@ ?~ kid [~ ~] $(fat u.kid, pax t.pax) :: - ++ put - |* [pax=path dat=*] - => .(dat `_?>(?=(^ fil.fat) u.fil.fat)`dat) - ^+ fat - ?~ pax fat(fil `dat) - =/ kid (~(get by dir.fat) i.pax) - =/ new (fall kid fat(fil ~, dir ~)) - fat(dir (~(put by dir.fat) i.pax $(fat new, pax t.pax))) - :: ++ gas |= lit=(list (pair path _?>(?=(^ fil.fat) u.fil.fat))) ^+ fat ?~ lit fat $(fat (put p.i.lit q.i.lit), lit t.lit) :: + ++ get + |= pax=path + fil:(dip pax) + :: Fetch file at longest existing prefix of the path + :: + ++ fit + |= pax=path + ^+ [pax fil.fat] + ?~ pax [~ fil.fat] + =/ kid (~(get by dir.fat) i.pax) + ?~ kid [pax fil.fat] + =/ low $(fat u.kid, pax t.pax) + ?~ +.low + [pax fil.fat] + low + :: + ++ has + |= pax=path + !=(~ (get pax)) + :: Delete subtree + :: + ++ lop + |= pax=path + ^+ fat + ?~ pax fat + |- + ?~ t.pax fat(dir (~(del by dir.fat) i.pax)) + =/ kid (~(get by dir.fat) i.pax) + ?~ kid fat + fat(dir (~(put by dir.fat) i.pax $(fat u.kid, pax t.pax))) + :: + ++ put + |* [pax=path dat=*] + => .(dat `_?>(?=(^ fil.fat) u.fil.fat)`dat, pax `path`pax) + |- ^+ fat + ?~ pax fat(fil `dat) + =/ kid (~(gut by dir.fat) i.pax ^+(fat [~ ~])) + fat(dir (~(put by dir.fat) i.pax $(fat kid, pax t.pax))) + :: ++ tap =| pax=path =| out=(list (pair path _?>(?=(^ fil.fat) u.fil.fat))) @@ -453,6 +494,10 @@ dir t.dir out ^$(pax (weld pax /[p.i.dir]), fat q.i.dir) == + :: Serialize to map + :: + ++ tar + (~(gas by *(map path _?>(?=(^ fil.fat) u.fil.fat))) tap) -- :: ++ wa :: cached compile @@ -781,8 +826,8 @@ :: =* pax p.i.fal =* dat q.i.fal - =/ hav (~(get de fat) pax) - =? del |(?=(~ fil.hav) !=(u.fil.hav dat)) + =/ hav (~(get of fat) pax) + =? del |(?=(~ hav) !=(u.hav dat)) ?: ?=([%sys *] pax) del(sys (~(put by sys.del) pax dat)) del(use (~(put by use.del) pax dat)) @@ -799,7 +844,7 @@ `[`(sole u.arv) [/sys/arvo u.arv] ~] =/ rav ~| %usurp-hoon-no-arvo - ((bond |.((need fil:(~(get de fat) /sys/arvo)))) arv) + ((bond |.((need (~(get of fat) /sys/arvo)))) arv) ~! rav :+ ~ [`(sole u.hun) (sole rav)] @@ -814,10 +859,10 @@ =^ lul fat ?^ hav=(~(get by sys.del) /sys/lull) :- `(sole u.hav) - (~(put de fat) /sys/lull u.hav) + (~(put of fat) /sys/lull u.hav) :_ fat ~| %adorn-no-lull - ?.(all ~ `(sole (need fil:(~(get de fat) /sys/lull)))) + ?.(all ~ `(sole (need (~(get of fat) /sys/lull)))) :: zuse: shared library :: :: %lull is the subject of %zuse; force all if we have a new %lull @@ -826,10 +871,10 @@ =^ zus fat ?^ hav=(~(get by sys.del) /sys/zuse) :- `(sole u.hav) - (~(put de fat) /sys/zuse u.hav) + (~(put of fat) /sys/zuse u.hav) :_ fat ~| %adorn-no-zuse - ?.(all ~ `(sole (need fil:(~(get de fat) /sys/zuse)))) + ?.(all ~ `(sole (need (~(get of fat) /sys/zuse)))) :: kernel modules :: :: %zuse is the subject of the vanes; force all if we have a new %zuse @@ -839,7 +884,7 @@ =? nav all %- ~(gas by nav) %+ turn - ~(tap by dir:(~(get de fat) /sys/vane)) + ~(tap by dir:(~(dip of fat) /sys/vane)) |=([name=@ta _fat] [`@tas`name (sole (need fil))]) :: =^ new fat @@ -852,7 +897,7 @@ ?> ?=([%sys %vane @tas ~] p) =* nam i.t.t.p ?> ((sane %tas) nam) - [[`@tas`nam (sole q)] (~(put de taf) p q)] + [[`@tas`nam (sole q)] (~(put of taf) p q)] :: =; van [[lul zus van] fat] @@ -1008,7 +1053,7 @@ ++ create |= [our=ship zus=vase lal=term pax=path txt=@t] ^- vase - =/ cap "vane %{(trip lal)}" + =/ cap "vane: %{(trip lal)}" (slym (smit cap zus pax txt) our) :: ++ settle @@ -1310,7 +1355,7 @@ :: %+ turn (sort ~(tap by van.mod) |=([[a=@tas *] [b=@tas *]] (aor a b))) - =/ bem=beam [[our %home da+now] /whey] ::TODO %base? + =/ bem=beam [[our %base da+now] /whey] ::TODO %base? |= [nam=term =vane] =; mas=(list mass) nam^|+(welp mas [dot+&+q.vase typ+&+p.vase sac+&+worm ~]:vane) @@ -1437,7 +1482,7 @@ ++ lod |= kel=(list (pair path (cask))) ^+ ..pith - =. fat.mod.sol (~(gas de fat.mod.sol) kel) + =. fat.mod.sol (~(gas of fat.mod.sol) kel) %+ mod (~(group adapt fat.mod.sol) fil) %+ lien kel @@ -1505,7 +1550,7 @@ [%fad %lac ~] ``noun/!>(lac.fad) [%zen %lag ~] ``noun/!>(lag.zen) [%zen %ver ~] ``noun/!>(ver.zen) - [%mod %fat *] ``noun/!>((~(get de fat.mod) t.t.s.bem)) + [%mod %fat *] ``noun/!>((~(dip of fat.mod) t.t.s.bem)) == :: ++ poke @@ -1574,7 +1619,7 @@ |= [kel=wynn hun=(unit @t) van=@t] ^- $-(heir (trap ^)) ~> %mean.'arvo: upgrade failed' - ~> %slog.[1 'arvo: beginning upgrade'] + ~> %slog.[0 'arvo: beginning upgrade'] ?~ hun =/ gat ~> %slog.[0 'arvo: compiling next arvo'] @@ -1583,7 +1628,7 @@ =/ lod (slap (slot 7 gat) [%limb %load]) |= =heir - |. ~> %slog.[1 'arvo: +load next'] + |. ~> %slog.[0 'arvo: +load next'] ;;(^ q:(slam lod !>(heir))) :: :: hyp: hoon core type @@ -1678,6 +1723,7 @@ %g %gall %i %iris %j %jael + %k %khan == -- => :: @@ -1836,7 +1882,7 @@ =? taf =(~ dir.taf) :: XX TMI ~| %larval-need-kernel ?> &(?=(^ tub) ?=(^ hun.p.u.tub)) - (~(gas de taf) q.u.tub) + (~(gas of taf) q.u.tub) :: =^ job=oped:part taf (~(adorn adapt:part taf) del |) =? lul ?=(^ lul.job) @@ -1852,7 +1898,7 @@ |= [[nam=term txt=cord] =_van] ^+ van %+ ~(put by van) nam - (smit "vane %{(trip nam)}" u.zus /sys/vane/[nam]/hoon txt) + (smit "vane: %{(trip nam)}" u.zus /sys/vane/[nam]/hoon txt) gub(fat `taf) -- :: diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 566010fbe3..43fee2f55c 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -264,8 +264,8 @@ ++ tail |*(^ ,:+<+) :: get tail ++ test |=(^ =(+<- +<+)) :: equality :: -++ lead |*(* |*(* [+>+< +<])) :: put head -++ late |*(* |*(* [+< +>+<])) :: put tail +++ lead |*(* |*(* [+>+< +<])) :: put head +++ late |*(* |*(* [+< +>+<])) :: put tail :: :: # %containers :: @@ -1453,7 +1453,6 @@ ++ by :: map engine ~/ %by =| a=(tree (pair)) :: (map) - =* node ?>(?=(^ a) n.a) |@ ++ all :: logical AND ~/ %all @@ -1717,14 +1716,14 @@ =+ b=a |@ ++ $ - |= meg=$-([_p:node _q:node _q:node] _q:node) + |* meg=$-([* * *] *) |- ^+ a ?~ b a ?~ a b ?: =(p.n.b p.n.a) - :+ [p.n.a (meg p.n.a q.n.a q.n.b)] + :+ [p.n.a `_?>(?=(^ a) q.n.a)`(meg p.n.a q.n.a q.n.b)] $(b l.b, a l.a) $(b r.b, a r.a) ?: (mor p.n.a p.n.b) @@ -2205,7 +2204,7 @@ ++ si :: signed integer ^? |% - ++ abs |=(a=@s (add (end 0 a) (rsh 0 a))) :: absolute value + ++ abs |=(a=@s (add (end 0 a) (rsh 0 a))) :: absolute value ++ dif |= [a=@s b=@s] :: subtraction (sum a (new !(syn b) (abs b))) ++ dul |= [a=@s b=@] :: modulus @@ -7781,7 +7780,7 @@ [%bcgl *] $(mod q.mod) [%bcgr *] $(mod q.mod) [%bckt *] $(mod q.mod) - [%bcls *] $(mod q.mod) + [%bcls *] [%note [%know p.mod] $(mod q.mod)] [%bcmc *] :: borrow sample :: [%tsgl [%$ 6] p.mod] @@ -7832,7 +7831,7 @@ [%bchp *] (decorate (function:clear p.mod q.mod)) [%bcmc *] (decorate (home [%tsgl [%limb %$] p.mod])) [%bcsg *] [%ktls example(mod q.mod) (home p.mod)] - [%bcls *] (decorate example(mod q.mod)) + [%bcls *] (decorate [%note [%know p.mod] example(mod q.mod)]) [%bcts *] (decorate [%ktts p.mod example:clear(mod q.mod)]) [%bcdt *] (decorate (home (interface %gold p.mod q.mod))) [%bcfs *] (decorate (home (interface %iron p.mod q.mod))) @@ -7866,7 +7865,12 @@ :: :+ %brcl [%ktsg spore] - ~(relative analyze:(descend 7) 6) + :+ %tsls + ~(relative analyze:(descend 7) 6) + :: trigger unifying equality + :: + :+ %tsls [%dtts $/14 $/2] + $/6 :: ++ analyze :: normalize a fragment of the subject @@ -8189,7 +8193,7 @@ relative:clear(mod q.mod) relative:clear(mod p.mod) :: - [%bcls *] relative(mod q.mod) + [%bcls *] [%note [%know p.mod] relative(mod q.mod)] [%bcdt *] (decorate (home (interface %gold p.mod q.mod))) [%bcfs *] (decorate (home (interface %iron p.mod q.mod))) [%bczp *] (decorate (home (interface %lead p.mod q.mod))) @@ -8580,15 +8584,7 @@ == :: [%mcfs *] =+(zoy=[%rock %ta %$] [%clsg [zoy [%clsg [zoy p.gen] ~]] ~]) - [%mcgl *] - :^ %cnls - :+ %cnhp - q.gen - [%ktcl p.gen] - r.gen - :+ %brts - p.gen - s.gen + [%mcgl *] [%cnls [%cnhp q ktcl+p] r [%brts p [%tsgr $+3 s]]]:gen :: [%mcsg *] :: ;~ |- ^- hoon @@ -9060,7 +9056,7 @@ :: ^- type ~+ - ~= sut + =- ?.(=(sut -) - sut) ?+ sut sut [%cell *] [%cell burp(sut p.sut) burp(sut q.sut)] [%core *] :+ %core @@ -9074,7 +9070,7 @@ == [%face *] [%face p.sut burp(sut q.sut)] [%fork *] [%fork (~(run in p.sut) |=(type burp(sut +<)))] - [%hint *] (hint p.sut burp(sut q.sut)) + [%hint *] (hint [burp(sut p.p.sut) q.p.sut] burp(sut q.sut)) [%hold *] [%hold burp(sut p.sut) q.sut] == :: @@ -10914,6 +10910,7 @@ [%stop p=@ud] :: [%tree p=term q=wine] :: [%unit p=term q=wine] :: + [%name p=stud q=wine] :: == :: -- |_ sut=type @@ -11004,6 +11001,11 @@ [%unit *] =^ cox gid $(q.ham q.q.ham) :_(gid [%rose [" " (weld (trip p.q.ham) "(") ")"] cox ~]) + :: + [%name *] + :_ gid + ?@ p.q.ham (cat 3 '#' mark.p.q.ham) + (rap 3 '#' auth.p.q.ham '+' (spat type.p.q.ham) ~) == -- :: @@ -11191,6 +11193,9 @@ ?~ wal ~ [~ %rose [[' ' ~] ['[' ~] [']' ~]] [%leaf '~' ~] u.wal ~] + :: + [%name *] + $(q.ham q.q.ham) == :: ++ doge @@ -11295,7 +11300,9 @@ == :: [%hint *] - $(sut q.sut) + =+ yad=$(sut q.sut) + ?. ?=(%know -.q.p.sut) yad + [p.yad [%name p.q.p.sut q.yad]] :: [%face *] =+ yad=$(sut q.sut) @@ -13010,6 +13017,7 @@ ['=' (rune tis %bcts exqg)] ['?' (rune wut %bcwt exqs)] [';' (rune mic %bcmc expa)] + ['+' (rune lus %bcls exqg)] == == :- '%' @@ -13080,6 +13088,7 @@ ['-' (stag %ktcl (rune hep %bchp exqb))] ['=' (stag %ktcl (rune tis %bcts exqg))] ['?' (stag %ktcl (rune wut %bcwt exqs))] + ['+' (stag %ktcl (rune lus %bcls exqg))] ['.' (rune dot %kttr exqa)] [',' (rune com %ktcl exqa)] == diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index cef2295a14..827cad33dd 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -3,7 +3,7 @@ :: => ..part |% -++ lull %330 +++ lull %329 :: :: :: :::: :: :: (1) models :: :: :: @@ -59,7 +59,7 @@ [r=@uxD g=@uxD b=@uxD] :: 24bit true color +$ turf (list @t) :: domain, tld first :: :::: -:::: ++ethereum-types :: eth surs for jael +:::: ++ethereum-types :: eth surs for jael :: :::: ++ ethereum-types |% @@ -73,7 +73,7 @@ ++ events (set event-id) -- :: :::: -:::: ++azimuth-types :: az surs for jael +:::: ++azimuth-types :: az surs for jael :: :::: ++ azimuth-types =, ethereum-types @@ -153,7 +153,7 @@ [%plea =ship =plea:ames] == :: :::: -:::: ++http :: +:::: ++http :: :: :::: :: http: shared representations of http concepts :: @@ -340,7 +340,7 @@ == -- :: :::: -:::: ++ames :: (1a) network +:::: ++ames :: (1a) network :: :::: ++ ames ^? |% @@ -357,6 +357,7 @@ :: :: %born: process restart notification :: %init: vane boot + :: %prod: re-send a packet per flow, to all peers if .ships is ~ :: %sift: limit verbosity to .ships :: %spew: set verbosity toggles :: %trim: release memory @@ -370,6 +371,7 @@ :: $>(%born vane-task) $>(%init vane-task) + [%prod ships=(list ship)] [%sift ships=(list ship)] [%spew veb=(list verb)] [%stir arg=@t] @@ -513,6 +515,7 @@ +$ peer-state $: $: =symmetric-key =life + =rift =public-key sponsor=ship == @@ -766,53 +769,58 @@ des=desk :: target desk bas=beak :: base desk con=(list [beak germ]) :: merges - == + == :: [%mont pot=term bem=beam] :: mount to unix - [%dirk des=desk] :: mark mount dirty - [%ogre pot=$@(desk beam)] :: delete mount point + [%dirk pot=term] :: mark mount dirty + [%ogre pot=$@(term beam)] :: delete mount point [%park des=desk yok=yoki ran=rang] :: synchronous commit [%perm des=desk pax=path rit=rite] :: change permissions [%pork ~] :: resume commit + [%stir arg=*] :: debug + [%tomb =clue] :: tombstone specific $>(%trim vane-task) :: trim state $>(%vega vane-task) :: report upgrade [%warp wer=ship rif=riff] :: internal file req [%werp who=ship wer=ship rif=riff-any] :: external file req $>(%plea vane-task) :: ames request == :: - :: + :: :: :::: :: (1c2) - :: + :: :: +$ aeon @ud :: version number - +$ ankh :: fs node (new) - $~ [~ ~] - $: fil=(unit [p=lobe q=cage]) :: file - dir=(map @ta ankh) :: folders - == :: +$ beam [[p=ship q=desk r=case] s=path] :: global name +$ beak [p=ship q=desk r=case] :: path prefix - +$ blob :: fs blob - $% [%delta p=lobe q=[p=mark q=lobe] r=page] :: delta on q - [%direct p=lobe q=page] :: immediate + +$ cable :: lib/sur/mark ref + $: face=(unit term) :: + file-path=term :: == :: - :: +cable: a reference to something on the filesystem - :: face: the face to wrap around the imported file - :: file-path: location in clay - +$ cable - $: face=(unit term) - file-path=term - == - +$ care ?(%a %b %c %d %e %f %p %r %s %t %u %v %w %x %y %z) :: clay submode + +$ care :: clay submode + ?(%a %b %c %d %e %f %p %r %s %t %u %v %w %x %y %z) :: +$ case :: ship desk case spur $% [%da p=@da] :: date [%tas p=@tas] :: label [%ud p=@ud] :: number == :: + +$ cash :: case or tako + $% [%tako p=tako] :: + case :: + == :: +$ cass [ud=@ud da=@da] :: cases for revision + +$ clue :: murder weapon + $% [%lobe =lobe] :: specific lobe + [%all ~] :: all safe targets + [%pick ~] :: collect garbage + [%norm =ship =desk =norm] :: set default norm + [%worn =ship =desk =tako =norm] :: set commit norm + [%seek =ship =desk =cash] :: fetch source blobs + == :: + +$ cone :: domes + %+ map [ship desk] :: + [dome tom=(map tako norm) nor=norm] :: +$ crew (set ship) :: permissions group +$ dict [src=path rul=real] :: effective permission +$ dome :: project state - $: ank=ankh :: state - let=@ud :: top id + $: let=@ud :: top id hit=(map @ud tako) :: changes by id lab=(map @tas @ud) :: labels == :: @@ -830,8 +838,7 @@ %meet-that :: hers if conflict == :: +$ lobe @uvI :: blob ref - +$ maki [p=@ta q=@ta r=@ta s=path] :: - +$ miso :: ankh delta + +$ miso :: file delta $% [%del ~] :: delete [%ins p=cage] :: insert [%dif p=cage] :: mutate from diff @@ -856,12 +863,12 @@ $% [%& p=suba] :: delta [%| p=@tas] :: label == :: + +$ norm (axal ?) :: tombstone policy +$ open $-(path vase) :: get prelude - +$ page (cask *) :: untyped cage - +$ plop blob :: unvalidated blob + +$ page ^page :: export for compat +$ rang :: repository $: hut=(map tako yaki) :: changes - lat=(map lobe blob) :: data + lat=(map lobe page) :: data == :: +$ rant :: response to request $: p=[p=care q=case r=desk] :: clade release book @@ -880,9 +887,9 @@ == :: +$ regs (map path rule) :: rules for paths +$ riff [p=desk q=(unit rave)] :: request+desist - +$ riff-any - $% [%1 =riff] - == + +$ riff-any :: + $% [%1 =riff] :: + == :: +$ rite :: new permissions $% [%r red=(unit rule)] :: for read [%w wit=(unit rule)] :: for write @@ -894,7 +901,7 @@ +$ saba [p=ship q=@tas r=moar s=dome] :: patch+merge +$ soba (list [p=path q=miso]) :: delta +$ suba (list [p=path q=misu]) :: delta - +$ tako @ :: yaki ref + +$ tako @uvI :: yaki ref +$ toro [p=@ta q=nori] :: general change ++ unce :: change part |* a=mold :: @@ -2092,6 +2099,32 @@ +$ oath @ :: signature -- :: pki -- :: jael +:: :::: +:::: ++khan :: (1i) threads + :: :::: +++ khan ^? + |% + +$ gift :: out result <-$ + $% [%arow p=(avow cage)] :: in-arvo result + [%avow p=(avow page)] :: external result + == :: + +$ task :: in request ->$ + $~ [%vega ~] :: + $% $>(%born vane-task) :: new unix process + [%done ~] :: socket closed + :: XX mark ignored + :: + [%fard p=(fyrd cage)] :: in-arvo thread + [%fyrd p=(fyrd cast)] :: external thread + $>(%trim vane-task) :: trim state + $>(%vega vane-task) :: report upgrade + == :: + :: :: + ++ avow |$ [a] (each a goof) :: $fyrd result + +$ bear $@(desk beak) :: partial $beak + +$ cast (pair mark page) :: output mark + input + ++ fyrd |$ [a] [=bear name=term args=a] :: thread run request + -- ::khan :: +$ gift-arvo :: out result <-$ $~ [%doze ~] @@ -2103,6 +2136,7 @@ gift:gall gift:iris gift:jael + gift:khan == +$ task-arvo :: in request ->$ $% task:ames @@ -2113,6 +2147,7 @@ task:gall task:iris task:jael + task:khan == +$ note-arvo :: out request $-> $~ [%b %wake ~] @@ -2124,6 +2159,7 @@ [%g task:gall] [%i task:iris] [%j task:jael] + [%k task:khan] [%$ %whiz ~] [@tas %meta vase] == @@ -2145,6 +2181,7 @@ [%gall gift:gall] [%iris gift:iris] [%jael gift:jael] + [%khan gift:khan] == :: $unix-task: input from unix :: diff --git a/pkg/arvo/sys/vane/ames.hoon b/pkg/arvo/sys/vane/ames.hoon index 6a3f8e7e45..b2b4f8c9bc 100644 --- a/pkg/arvo/sys/vane/ames.hoon +++ b/pkg/arvo/sys/vane/ames.hoon @@ -196,22 +196,38 @@ :+ (add 4 next-bone.ossuary) (~(put by by-duct.ossuary) duct next-bone.ossuary) (~(put by by-bone.ossuary) next-bone.ossuary duct) -:: +make-bone-wire: encode ship and bone in wire for sending to vane +:: +make-bone-wire: encode ship, rift and bone in wire for sending to vane :: ++ make-bone-wire - |= [her=ship =bone] + |= [her=ship =rift =bone] ^- wire :: - /bone/(scot %p her)/(scot %ud bone) -:: +parse-bone-wire: decode ship and bone from wire from local vane + /bone/(scot %p her)/(scot %ud rift)/(scot %ud bone) +:: +parse-bone-wire: decode ship, bone and rift from wire from local vane :: ++ parse-bone-wire |= =wire - ^- [her=ship =bone] + ^- %- unit + $% [%old her=ship =bone] + [%new her=ship =rift =bone] + == + ?. ?| ?=([%bone @ @ @ ~] wire) + ?=([%bone @ @ ~] wire) + == + :: ignore malformed wires + :: + ~ + ?+ wire ~ + [%bone @ @ ~] + `[%old `@p`(slav %p i.t.wire) `@ud`(slav %ud i.t.t.wire)] :: - ~| %ames-wire-bone^wire - ?> ?=([%bone @ @ ~] wire) - [`@p`(slav %p i.t.wire) `@ud`(slav %ud i.t.t.wire)] + [%bone @ @ @ ~] + %- some + :^ %new + `@p`(slav %p i.t.wire) + `@ud`(slav %ud i.t.t.wire) + `@ud`(slav %ud i.t.t.t.wire) + == :: +make-pump-timer-wire: construct wire for |packet-pump timer :: ++ make-pump-timer-wire @@ -352,6 +368,18 @@ %earl 8 %pawn 16 == +:: +encode-keys-packet: create key request $packet +:: +++ encode-keys-packet + ~/ %encode-keys-packet + |= [sndr=ship rcvr=ship sndr-life=life] + ^- packet + :* [sndr rcvr] + (mod sndr-life 16) + `@`1 + origin=~ + content=`@`%keys + == :: +encode-open-packet: convert $open-packet attestation to $packet :: ++ encode-open-packet @@ -397,6 +425,8 @@ :: ++ encode-shut-packet ~/ %encode-shut-packet + :: TODO add rift to signed messages to prevent replay attacks? + :: |= $: =shut-packet =symmetric-key sndr=ship @@ -502,6 +532,7 @@ :: $: =symmetric-key =her=life + =her=rift =her=public-key her-sponsor=ship == == @@ -529,6 +560,8 @@ :: This data structure gets signed and jammed to form the .contents :: field of a $packet. :: +:: TODO add rift to prevent replay attacks +:: +$ open-packet $: =public-key sndr=ship @@ -565,6 +598,36 @@ :: +$ naxplanation [=message-num =error] :: ++$ ames-state-4 ames-state-5 ++$ ames-state-5 + $: peers=(map ship ship-state-5) + =unix=duct + =life + crypto-core=acru:ames + =bug + == +:: ++$ ship-state-4 ship-state-5 ++$ ship-state-5 + $% [%alien alien-agenda] + [%known peer-state-5] + == +:: ++$ peer-state-5 + $: $: =symmetric-key + =life + =public-key + sponsor=ship + == + route=(unit [direct=? =lane]) + =qos + =ossuary + snd=(map bone message-pump-state) + rcv=(map bone message-sink-state) + nax=(set [=bone =message-num]) + heeds=(set duct) + == +:: +| %statics :: :: $ames-state: state for entire vane @@ -654,12 +717,14 @@ :: %memo: packetize and send application-level message :: %hear: handle receipt of ack on fragment or message :: %near: handle receipt of naxplanation +:: $prod: reset congestion control :: %wake: handle timer firing :: +$ message-pump-task $% [%memo =message-blob] [%hear =message-num =ack-meat] [%near =naxplanation] + [%prod ~] [%wake ~] == :: $message-pump-gift: effect from |message-pump @@ -681,12 +746,14 @@ :: %done: deal with message acknowledgment :: %halt: finish event, possibly updating timer :: %wake: handle timer firing +:: %prod: reset congestion control :: +$ packet-pump-task $% [%hear =message-num =fragment-num] [%done =message-num lag=@dr] [%halt ~] [%wake current=message-num] + [%prod ~] == :: $packet-pump-gift: effect from |packet-pump :: @@ -728,10 +795,18 @@ :: =< =* adult-gate . =| queued-events=(qeu queued-event) + =| cached-state=(unit [%5 ames-state-5]) :: |= [now=@da eny=@ rof=roof] =* larval-gate . =* adult-core (adult-gate +<) + =< |% + ++ call ^call + ++ load ^load + ++ scry ^scry + ++ stay ^stay + ++ take ^take + -- |% :: +call: handle request $task :: @@ -739,12 +814,14 @@ |= [=duct dud=(unit goof) wrapped-task=(hobo task)] :: =/ =task ((harden task) wrapped-task) - :: :: reject larval error notifications :: ?^ dud ~|(%ames-larval-call-dud (mean tang.u.dud)) :: + ?: &(?=(^ cached-state) ?=(~ queued-events)) + =^ moves adult-gate (call:adult-core duct dud task) + (molt moves) :: %born: set .unix-duct and start draining .queued-events :: ?: ?=(%born -.task) @@ -774,11 +851,17 @@ ~|(%ames-larval-take-dud (mean tang.u.dud)) :: enqueue event if not a larval drainage timer :: + =? queued-events !=(/larva wire) + (~(put to queued-events) %take wire duct sign) + :: start drainage timer if have regressed from adult ames + :: + ?: ?& !=(/larva wire) + ?=(^ cached-state) + == + [[duct %pass /larva %b %wait now]~ larval-gate] :: XX what to do with errors? :: - ?. =(/larva wire) - =. queued-events (~(put to queued-events) %take wire duct sign) - [~ larval-gate] + ?. =(/larva wire) [~ larval-gate] :: larval event drainage timer; pop and process a queued event :: ?. ?=([%behn %wake *] sign) @@ -820,6 +903,7 @@ :: .queued-events has been cleared; metamorphose :: ?~ queued-events + ?: ?=(^ cached-state) (molt moves) ~> %slog.0^leaf/"ames: metamorphosis" [moves adult-gate] :: set timer to drain next event @@ -829,41 +913,67 @@ :: lifecycle arms; mostly pass-throughs to the contained adult ames :: ++ scry scry:adult-core - ++ stay [%5 %larva queued-events ames-state.adult-gate] + ++ stay [%6 %larva queued-events ames-state.adult-gate] ++ load |= $= old $% $: %4 $% $: %larva events=(qeu queued-event) - state=_ames-state.adult-gate + state=ames-state-4 == - [%adult state=_ames-state.adult-gate] + [%adult state=ames-state-4] == == $: %5 + $% $: %larva + events=(qeu queued-event) + state=ames-state-5 + == + [%adult state=ames-state-5] + == == + $: %6 $% $: %larva events=(qeu queued-event) state=_ames-state.adult-gate == [%adult state=_ames-state.adult-gate] - == == - == + == == == ?- old - [%4 %adult *] (load:adult-core %4 state.old) + [%4 %adult *] + $(old [%5 %adult (state-4-to-5:load:adult-core state.old)]) :: [%4 %larva *] - ~> %slog.1^leaf/"ames: larva: load" - =. queued-events events.old - =. adult-gate (load:adult-core %4 state.old) - larval-gate + =. state.old (state-4-to-5:load:adult-core state.old) + $(-.old %5) :: - [%5 %adult *] (load:adult-core %5 state.old) + [%5 %adult *] + =. cached-state `[%5 state.old] + ~> %slog.0^leaf/"ames: larva reload" + larval-gate :: [%5 %larva *] - ~> %slog.1^leaf/"ames: larva: load" + ~> %slog.0^leaf/"ames: larva: load" =. queued-events events.old - =. adult-gate (load:adult-core %5 state.old) + larval-gate + :: + [%6 %adult *] (load:adult-core %6 state.old) + :: + [%6 %larva *] + ~> %slog.0^leaf/"ames: larva: load" + =. queued-events events.old + =. adult-gate (load:adult-core %6 state.old) larval-gate == + :: +molt: re-evolve to adult-ames + :: + ++ molt + |= moves=(list move) + ^- (quip move _adult-gate) + =. ames-state.adult-gate + ?> ?=(^ cached-state) + (state-5-to-6:load:adult-core +.u.cached-state) + =. cached-state ~ + ~> %slog.0^leaf/"ames: metamorphosis reload" + [moves adult-gate] -- :: adult ames, after metamorphosis from larva :: @@ -898,6 +1008,7 @@ %heed (on-heed:event-core ship.task) %init on-init:event-core %jilt (on-jilt:event-core ship.task) + %prod (on-prod:event-core ships.task) %sift (on-sift:event-core ships.task) %spew (on-spew:event-core veb.task) %stir (on-stir:event-core arg.task) @@ -934,27 +1045,23 @@ [moves ames-gate] :: +stay: extract state before reload :: -++ stay [%5 %adult ames-state] +++ stay [%6 %adult ames-state] :: +load: load in old state after reload :: ++ load - |= $= old-state - $% [%4 ^ames-state] - [%5 ^ames-state] - == - |^ - ^+ ames-gate - =? old-state ?=(%4 -.old-state) %5^(state-4-to-5 +.old-state) - :: - ?> ?=(%5 -.old-state) - ames-gate(ames-state +.old-state) + =< |= old-state=[%6 ^ames-state] + ^+ ames-gate + ?> ?=(%6 -.old-state) + ames-gate(ames-state +.old-state) + |% + :: +state-4-to-5 called from larval-ames :: ++ state-4-to-5 - |= =^ames-state - ^- ^^ames-state + |= ames-state=ames-state-4 + ^- ames-state-4 =. peers.ames-state %- ~(run by peers.ames-state) - |= =ship-state + |= ship-state=ship-state-4 ?. ?=(%known -.ship-state) ship-state =. snd.ship-state @@ -965,6 +1072,31 @@ message-pump-state ship-state ames-state + :: +state-5-to-6 called from larval-ames + :: + ++ state-5-to-6 + |= ames-state=ames-state-5 + ^- ^^ames-state + :_ +.ames-state + %- ~(rut by peers.ames-state) + |= [=ship ship-state=ship-state-5] + ^- ^ship-state + ?. ?=(%known -.ship-state) + ship-state + =/ peer-state=peer-state-5 +.ship-state + =/ =rift + :: harcoded because %jael doesn't have data about comets + :: + ?: ?=(%pawn (clan:title ship)) 0 + ;; @ud + =< q.q %- need %- need + (rof ~ %j `beam`[[our %rift %da now] /(scot %p ship)]) + =/ =^peer-state + :_ +.peer-state + =, -.peer-state + [symmetric-key life rift public-key sponsor] + ^- ^ship-state + [-.ship-state peer-state] -- :: +scry: dereference namespace :: @@ -1105,31 +1237,61 @@ ^+ event-core :: relay the vane ack to the foreign peer :: - =+ ^- [her=ship =bone] (parse-bone-wire wire) - :: + ?~ parsed=(parse-bone-wire wire) + :: no-op + :: + ~> %slog.0^leaf/"ames: dropping malformed wire: {(spud wire)}" + event-core + ?> ?=([@ her=ship *] u.parsed) + =* her her.u.parsed =/ =peer-state (got-peer-state her) =/ =channel [[our her] now channel-state -.peer-state] =/ peer-core (make-peer-core peer-state channel) + |^ + ?: ?& ?=([%new *] u.parsed) + (lth rift.u.parsed rift.peer-state) + == + :: ignore events from an old rift + :: + %- %^ trace odd.veb her + |.("dropping old rift wire: {(spud wire)}") + event-core + =/ =bone + ?-(u.parsed [%new *] bone.u.parsed, [%old *] bone.u.parsed) + =? peer-core ?=([%old *] u.parsed) + %- %^ trace odd.veb her + |.("parsing old wire: {(spud wire)}") + peer-core + ?~ error + (send-ack bone) + (send-nack bone u.error) + :: :: if processing succeded, send positive ack packet and exit :: - ?~ error + ++ send-ack + |= =bone + ^+ event-core abet:(run-message-sink:peer-core bone %done ok=%.y) :: failed; send message nack packet :: - =. event-core abet:(run-message-sink:peer-core bone %done ok=%.n) - =/ =^peer-state (got-peer-state her) - =/ =^channel [[our her] now channel-state -.peer-state] - :: construct nack-trace message, referencing .failed $message-num - :: - =/ failed=message-num last-acked:(~(got by rcv.peer-state) bone) - =/ =naxplanation [failed u.error] - =/ =message-blob (jam naxplanation) - :: send nack-trace message on associated .nack-trace-bone - :: - =. peer-core (make-peer-core peer-state channel) - =/ nack-trace-bone=^bone (mix 0b10 bone) - :: - abet:(run-message-pump:peer-core nack-trace-bone %memo message-blob) + ++ send-nack + |= [=bone =^error] + ^+ event-core + =. event-core abet:(run-message-sink:peer-core bone %done ok=%.n) + =/ =^peer-state (got-peer-state her) + =/ =^channel [[our her] now channel-state -.peer-state] + :: construct nack-trace message, referencing .failed $message-num + :: + =/ failed=message-num last-acked:(~(got by rcv.peer-state) bone) + =/ =naxplanation [failed error] + =/ =message-blob (jam naxplanation) + :: send nack-trace message on associated .nack-trace-bone + :: + =. peer-core (make-peer-core peer-state channel) + =/ nack-trace-bone=^bone (mix 0b10 bone) + :: + abet:(run-message-pump:peer-core nack-trace-bone %memo message-blob) + -- :: +on-sift: handle request to filter debug output by ship :: ++ on-sift @@ -1158,6 +1320,29 @@ %rot acc(rot %.y) == event-core + :: +on-prod: re-send a packet per flow to each of .ships + :: + ++ on-prod + |= ships=(list ship) + ^+ event-core + =? ships =(~ ships) ~(tap in ~(key by peers.ames-state)) + |^ ^+ event-core + ?~ ships event-core + $(ships t.ships, event-core (prod-peer i.ships)) + :: + ++ prod-peer + |= her=ship + ^+ event-core + =/ par (get-peer-state her) + ?~ par event-core + =/ =channel [[our her] now channel-state -.u.par] + =/ peer-core (make-peer-core u.par channel) + =/ bones ~(tap in ~(key by snd.u.par)) + |- ^+ event-core + ?~ bones abet:peer-core + =. peer-core (run-message-pump:peer-core i.bones %prod ~) + $(bones t.bones) + -- :: +on-stir: start timers for any flow that lack them :: :: .arg is unused, meant to ease future debug commands @@ -1247,6 +1432,8 @@ ~/ %on-hear-packet |= [=lane =packet dud=(unit goof)] ^+ event-core + %- %^ trace odd.veb sndr.packet + |.("received packet") :: ?: =(our sndr.packet) event-core @@ -1256,6 +1443,8 @@ ?. =(our rcvr.packet) on-hear-forward :: + ?: =(%keys content.packet) + on-hear-keys ?: ?& ?=(%pawn (clan:title sndr.packet)) !?=([~ %known *] (~(get by peers.ames-state) sndr.packet)) == @@ -1285,12 +1474,24 @@ :: =/ =blob (encode-packet packet) (send-blob & rcvr.packet blob) + :: +on-hear-keys: handle receipt of attestion request + :: + ++ on-hear-keys + ~/ %on-hear-keys + |= [=lane =packet dud=(unit goof)] + =+ %^ trace msg.veb sndr.packet + |.("requested attestation") + ?. =(%pawn (clan:title our)) + event-core + (send-blob | sndr.packet (attestation-packet sndr.packet 1)) :: +on-hear-open: handle receipt of plaintext comet self-attestation :: ++ on-hear-open ~/ %on-hear-open |= [=lane =packet dud=(unit goof)] ^+ event-core + =+ %^ trace msg.veb sndr.packet + |.("got attestation") :: assert the comet can't pretend to be a moon or other address :: ?> ?=(%pawn (clan:title sndr.packet)) @@ -1301,25 +1502,29 @@ event-core :: =/ =open-packet (decode-open-packet packet our life.ames-state) - :: store comet as peer in our state + :: add comet as an %alien if we haven't already + :: + =? peers.ames-state ?=(~ ship-state) + (~(put by peers.ames-state) sndr.packet %alien *alien-agenda) + :: upgrade comet to %known via on-publ-full + :: + =. event-core + =/ crypto-suite=@ud 1 + =/ keys + (my [sndr-life.open-packet crypto-suite public-key.open-packet]~) + =/ =point + :* ^= rift 0 + ^= life sndr-life.open-packet + ^= keys keys + ^= sponsor `(^sein:title sndr.packet) + == + (on-publ / [%full (my [sndr.packet point]~)]) + :: manually add the lane to the peer state :: =. peers.ames-state - %+ ~(put by peers.ames-state) sndr.packet - ^- ^ship-state - :- %known - =| =peer-state - =/ our-private-key sec:ex:crypto-core.ames-state - =/ =symmetric-key - (derive-symmetric-key public-key.open-packet our-private-key) - :: - %_ peer-state - qos [%unborn now] - symmetric-key symmetric-key - life sndr-life.open-packet - public-key public-key.open-packet - sponsor (^sein:title sndr.packet) - route `[direct=%.n lane] - == + =/ =peer-state (gut-peer-state sndr.packet) + =. route.peer-state `[direct=%.n lane] + (~(put by peers.ames-state) sndr.packet %known peer-state) :: event-core :: +on-hear-shut: handle receipt of encrypted packet @@ -1329,7 +1534,10 @@ |= [=lane =packet dud=(unit goof)] ^+ event-core =/ sndr-state (~(get by peers.ames-state) sndr.packet) - :: if we don't know them, ask jael for their keys and enqueue + :: If we don't know them, ask Jael for their keys. If they're a + :: comet, this will also cause us to request a self-attestation + :: from the sender. The packet itself is dropped; we can assume it + :: will be resent. :: ?. ?=([~ %known *] sndr-state) (enqueue-alien-todo sndr.packet |=(alien-agenda +<)) @@ -1382,13 +1590,31 @@ ++ on-take-boon |= [=wire payload=*] ^+ event-core + ?~ parsed=(parse-bone-wire wire) + ~> %slog.0^leaf/"ames: dropping malformed wire: {(spud wire)}" + event-core :: - =+ ^- [her=ship =bone] (parse-bone-wire wire) - :: + ?> ?=([@ her=ship *] u.parsed) + =* her her.u.parsed =/ =peer-state (got-peer-state her) =/ =channel [[our her] now channel-state -.peer-state] + =/ peer-core (make-peer-core peer-state channel) :: - abet:(on-memo:(make-peer-core peer-state channel) bone payload %boon) + ?: ?& ?=([%new *] u.parsed) + (lth rift.u.parsed rift.peer-state) + == + :: ignore events from an old rift + :: + %- %^ trace odd.veb her + |.("dropping old rift wire: {(spud wire)}") + event-core + =/ =bone + ?-(u.parsed [%new *] bone.u.parsed, [%old *] bone.u.parsed) + =? peer-core ?=([%old *] u.parsed) + %- %^ trace odd.veb her + |.("parsing old wire: {(spud wire)}") + peer-core + abet:(on-memo:peer-core bone payload %boon) :: +on-plea: handle request to send message :: ++ on-plea @@ -1420,6 +1646,20 @@ |= [=wire error=(unit tang)] ^+ event-core :: + ?: ?=([%alien @ ~] wire) + :: if we haven't received an attestation, ask again + :: + ?^ error + %- (slog leaf+"ames: attestation timer failed: {}" ~) + event-core + ?~ ship=`(unit @p)`(slaw %p i.t.wire) + %- (slog leaf+"ames: got timer for strange wire: {}" ~) + event-core + =/ ship-state (~(get by peers.ames-state) u.ship) + ?: ?=([~ %known *] ship-state) + event-core + (request-attestation u.ship) + :: =/ res=(unit [her=ship =bone]) (parse-pump-timer-wire wire) ?~ res %- (slog leaf+"ames: got timer for strange wire: {}" ~) @@ -1478,7 +1718,8 @@ :: ?- public-keys-result [%diff @ %rift *] - event-core + :: event-core + (on-publ-rift [who to.diff]:public-keys-result) :: [%diff @ %keys *] (on-publ-rekey [who to.diff]:public-keys-result) @@ -1655,6 +1896,24 @@ :: event-core(duct original-duct) -- + :: on-publ-rift: XX + :: + ++ on-publ-rift + |= [=ship =rift] + ^+ event-core + ?~ ship-state=(~(get by peers.ames-state) ship) + :: print error here? %rift was probably called before %keys + :: + ~> %slog.1^leaf/"ames: missing peer-state on-publ-rift" + event-core + ?: ?=([%alien *] u.ship-state) + :: ignore aliens + :: + event-core + =/ =peer-state +.u.ship-state + =. rift.peer-state rift + =. peers.ames-state (~(put by peers.ames-state) ship %known peer-state) + event-core :: ++ insert-peer-state |= [=ship =point] @@ -1703,7 +1962,6 @@ (rof ~ %j `beam`[[our %turf %da now] /]) :: (emit unix-duct.ames-state %give %turf turfs) - :: +on-trim: handle request to free memory :: +on-vega: handle kernel reload :: +on-trim: handle request to free memory :: @@ -1712,7 +1970,7 @@ :: +enqueue-alien-todo: helper to enqueue a pending request :: :: Also requests key and life from Jael on first request. - :: On a comet, enqueues self-attestation packet on first request. + :: If talking to a comet, requests attestation packet. :: ++ enqueue-alien-todo |= [=ship mutate=$-(alien-agenda alien-agenda)] @@ -1729,14 +1987,26 @@ :: =. todos (mutate todos) =. peers.ames-state (~(put by peers.ames-state) ship %alien todos) - :: ask jael for .sndr life and keys on first contact - :: ?: already-pending event-core + :: + ?: =(%pawn (clan:title ship)) + (request-attestation ship) :: NB: we specifically look for this wire in +public-keys-give in :: Jael. if you change it here, you must change it there. :: (emit duct %pass /public-keys %j %public-keys [n=ship ~ ~]) + :: +request-attestation: helper to request attestation from comet + :: + :: Also sets a timer to resend the request every 30s. + :: + ++ request-attestation + |= =ship + ^+ event-core + =+ (trace msg.veb ship |.("requesting attestion")) + =. event-core (send-blob | ship (sendkeys-packet ship)) + =/ =wire /alien/(scot %p ship) + (emit duct %pass wire %b %wait (add now ~s30)) :: +send-blob: fire packet at .ship and maybe sponsors :: :: Send to .ship and sponsors until we find a direct lane, @@ -1757,6 +2027,8 @@ =/ ship-state (~(get by peers.ames-state) ship) :: ?. ?=([~ %known *] ship-state) + ?: ?=(%pawn (clan:title ship)) + (try-next-sponsor (^sein:title ship)) %+ enqueue-alien-todo ship |= todos=alien-agenda todos(packets (~(put in packets.todos) blob)) @@ -1820,6 +2092,16 @@ ^= rcvr her ^= rcvr-life her-life == + :: +sendkeys-packet: generate a request for a self-attestation. + :: + :: Sent by non-comets to comets. Not acked. + :: + ++ sendkeys-packet + |= her=ship + ^- blob + ?> ?=(%pawn (clan:title her)) + %- encode-packet + (encode-keys-packet our her life.ames-state) :: +get-peer-state: lookup .her state or ~ :: ++ get-peer-state @@ -2287,10 +2569,9 @@ :: =+ ;; =plea message :: - =/ =wire (make-bone-wire her.channel bone) + =/ =wire (make-bone-wire her.channel her-rift.channel bone) :: ?+ vane.plea ~| %ames-evil-vane^our^her.channel^vane.plea !! - %a (emit duct %pass wire %a %plea her.channel plea) %c (emit duct %pass wire %c %plea her.channel plea) %g (emit duct %pass wire %g %plea her.channel plea) %j (emit duct %pass wire %j %plea her.channel plea) @@ -2342,6 +2623,7 @@ ^+ message-pump :: ?- -.task + %prod (run-packet-pump %prod ~) %memo (on-memo message-blob.task) %wake (run-packet-pump %wake current.state) %hear @@ -2560,8 +2842,29 @@ %hear (on-hear [message-num fragment-num]:task) %done (on-done message-num.task) %wake (on-wake current.task) + %prod on-prod %halt set-wake == + :: +on-prod: reset congestion control, re-send packets + :: + ++ on-prod + ^+ packet-pump + ?: =(~ next-wake.state) + packet-pump + :: + =. metrics.state %*(. *pump-metrics counter counter.metrics.state) + =. live.state + %+ run:packet-queue live.state + |=(p=live-packet-val p(- *packet-state)) + :: + =/ sot (max 1 num-slots:gauge) + =/ liv live.state + |- ^+ packet-pump + ?: =(0 sot) packet-pump + ?: =(~ liv) packet-pump + =^ hed liv (pop:packet-queue liv) + =. packet-pump (give %send (to-static-fragment hed)) + $(sot (dec sot)) :: +on-wake: handle packet timeout :: ++ on-wake @@ -2570,7 +2873,6 @@ :: assert temporal coherence :: ?< =(~ next-wake.state) - ?> (gte now.channel (need next-wake.state)) =. next-wake.state ~ :: tell congestion control a packet timed out :: diff --git a/pkg/arvo/sys/vane/clay.hoon b/pkg/arvo/sys/vane/clay.hoon index 871bbe376b..ab938a0786 100644 --- a/pkg/arvo/sys/vane/clay.hoon +++ b/pkg/arvo/sys/vane/clay.hoon @@ -1,30 +1,57 @@ :: clay (4c), revision control !: -:: This is split in three top-level sections: structure definitions, main -:: logic, and arvo interface. +:: The way to understand Clay is to take it section-by-section: +:: +:: - Data structures. You *must* start here; make sure you understand +:: the entire contents of +raft. +:: +:: - Individual reads. +aver is the entry point, follow it through +:: +read-at-aeon to understand each kind of read. +:: +:: - Subscriptions. +wake is the center of this mechanism; nothing +:: else responds to subscriptions. +wake has no arguments, which means +:: every subscription response happens when something in Clay's *state* +:: has changed. No edge-triggered responses. +:: +:: - Receiving foreign data. For individual requests, this is +:: +take-foreign-answer. For sync requests (%many, which is %sing %v +:: for a foreign desk), this is +foreign-update. +:: +:: - Ford. +ford builds hoon files and gives files their types. +:: Read +build-file for the first, and +read-file is the second. +:: +:: - Writing to a desk. Every write to a desk goes through +park, read +:: it thoroughly. +:: +:: - Merges. Control flow starts at +start-merge, then +merge, but +:: everything is scaffolding for +merge-by-germ, which is the ideal of +:: a merge function: it takes two commits and a merge strategy and +:: produces a new commit. +:: +:: - Tombstoning. This is in +tomb. :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: Here are the structures. `++raft` is the formal arvo state. It's also -:: worth noting that many of the clay-related structures are defined in zuse. +:: worth noting that many of the clay-related structures are defined in lull. :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +=/ bud + ^~ + =/ zuse !>(..zuse) + :* zuse=zuse + nave=(slap zuse !,(*hoon nave:clay)) + cork=(slap zuse !,(*hoon cork)) + same=(slap zuse !,(*hoon same)) + mime=(slap zuse !,(*hoon mime)) + cass=(slap zuse !,(*hoon cass:clay)) + == +:: |= our=ship =, clay => |% +$ aeon @ud :: version number :: -:: Recursive structure of a desk's data. -:: -:: We keep an ankh only for the current version of local desks. Everywhere -:: else we store it as (map path lobe). -:: -+$ ankh :: expanded node - $~ [~ ~] - $: fil=(unit [p=lobe q=cage]) :: file - dir=(map @ta ankh) :: folders - == :: -:: :: Part of ++mery, representing the set of changes between the mergebase and :: one of the desks being merged. :: @@ -90,12 +117,13 @@ :: Whenever you give an `%ergo`, you must update this. :: +$ dome - $: ank=ankh :: state - let=aeon :: top id + $: let=aeon :: top id hit=(map aeon tako) :: versions by id lab=(map @tas aeon) :: labels + tom=(map tako norm) :: tomb policies + nor=norm :: default policy mim=(map path mime) :: mime cache - fod=ford-cache :: ford cache + fod=flue :: ford cache == :: :: :: Commit state. @@ -115,39 +143,108 @@ mut=(list (trel path lobe cage)) :: mutations == :: :: -:: Over-the-wire backfill request +:: Over-the-wire backfill request/response :: +$ fill $% [%0 =desk =lobe] + [%1 =desk =lobe] == :: -:: Ford cache -:: -+$ ford-cache - $: files=(map path [res=vase dez=(set [dir=? =path])]) - naves=(map mark [res=vase dez=(set [dir=? =path])]) - marks=(map mark [res=dais dez=(set [dir=? =path])]) - casts=(map mars [res=vase dez=(set [dir=? =path])]) - tubes=(map mars [res=tube dez=(set [dir=? =path])]) ++$ fell + $% [%direct p=lobe q=page] + [%delta p=lobe q=[p=mark q=lobe] r=page] + [%dead p=lobe ~] + [%1 peg=(unit page)] == :: -:: Hash of a blob, for lookup in the object store (lat.ran) +:: Global ford cache :: -+$ lobe @uvI :: blob ref +:: Refcount includes references from other items in the cache, and +:: from spills in each desk +:: +:: This is optimized for minimizing the number of rebuilds, and given +:: that, minimizing the amount of memory used. It is relatively slow +:: to lookup, because generating a cache key can be fairly slow (for +:: files, it requires parsing; for tubes, it even requires building +:: the marks). +:: ++$ flow (map leak [refs=@ud =soak]) +:: +:: Per-desk ford cache +:: +:: Spill is the set of "roots" we have into the global ford cache. +:: We add a root for everything referenced directly or indirectly on +:: a desk, then invalidate them on commit only if their dependencies +:: change. +:: +:: Sprig is a fast-lookup index over the global ford cache. The only +:: goal is to make cache hits fast. +:: ++$ flue [spill=(set leak) sprig=(map mist [=leak =soak])] +:: +:: Ford build without content. +:: ++$ mist + $% [%file =path] + [%nave =mark] + [%dais =mark] + [%cast =mars] + [%tube =mars] + [%vale =path] + [%arch =path] + == +:: +:: Ford build with content. +:: ++$ pour + $% [%file =path] + [%nave =mark] + [%dais =mark] + [%cast =mars] + [%tube =mars] + :: leafs + :: + [%vale =path =lobe] + [%arch =path =(map path lobe)] + == +:: +:: Ford result. +:: ++$ soak + $% [%cage =cage] + [%vase =vase] + [%arch dir=(map @ta vase)] + [%dais =dais] + [%tube =tube] + == +:: +:: Ford cache key +:: +:: This includes all build inputs, including transitive dependencies, +:: recursively. +:: ++$ leak + $~ [*pour ~] + $: =pour + deps=(set leak) + == :: :: New desk data. :: -:: Sent to other ships to update them about a particular desk. Includes a map -:: of all new aeons to hashes of their commits, the most recent aeon, and sets -:: of all new commits and data. +:: Sent to other ships to update them about a particular desk. +:: Includes a map of all new aeons to hashes of their commits, the most +:: recent aeon, and sets of all new commits and data. `bar` is always +:: empty now because we expect you to request any data you don't have +:: yet :: +$ nako :: subscription state $: gar=(map aeon tako) :: new ids let=aeon :: next id lar=(set yaki) :: new commits - bar=(set plop) :: new content + bar=~ :: new content == :: :: +:: :: Formal vane state. :: :: -- `rom` is our domestic state. @@ -164,21 +261,12 @@ $: rom=room :: domestic hoy=(map ship rung) :: foreign ran=rang :: hashes + fad=flow :: ford cache mon=(map term beam) :: mount points hez=(unit duct) :: sync duct cez=(map @ta crew) :: permission groups pud=(unit [=desk =yoki]) :: pending update - :: REMOVE on next upgrade - dist-upgraded=_| :: are we in dist yet? - == :: -:: -:: Object store. -:: -:: Maps of commit hashes to commits and content hashes to content. -:: -+$ rang :: - $: hut=(map tako yaki) :: - lat=(map lobe blob) :: + bug=[veb=@ mas=@] :: verbosity == :: :: :: Unvalidated response to a request. @@ -235,22 +323,11 @@ +$ update-state $: =duct =rave - have=(map lobe blob) need=(list lobe) nako=(qeu (unit nako)) busy=_| == :: -:: Result of a subscription -:: -+$ sub-result - $% [%blab =mood data=(each cage lobe)] - [%bleb ver=@ud ins=@ud range=(unit (pair aeon aeon))] - [%balk cage=(unit (each cage lobe)) =mood] - [%blas moods=(set mood)] - [%blub ~] - == -:: :: Domestic ship. :: :: `hun` is the duct to dill, and `dos` is a collection of our desks. @@ -265,7 +342,9 @@ :: Like a +$rave but with caches of current versions for %next and %many. :: Generally used when we store a request in our state somewhere. :: -+$ cach (unit (unit (each cage lobe))) :: cached result +:: TODO: remove lobes from %many +:: ++$ cach (unit (unit cage)) :: cached result +$ wove [for=(unit [=ship ver=@ud]) =rove] :: stored source + req +$ rove :: stored request $% [%sing =mood] :: single request @@ -285,7 +364,8 @@ $: rus=(map desk rede) :: neighbor desks == :: -+$ move [p=duct q=(wind note gift)] :: local move ++$ card (wind note gift) :: local card ++$ move [p=duct q=card] :: local move +$ note :: out request $-> $~ [%b %wait *@da] :: $% $: %$ :: to arvo @@ -337,7 +417,7 @@ == :: $: %behn :: $% $>(%wake gift:behn) :: timer activate - $>(%writ gift) :: XX %slip + $>(%writ gift) :: == == :: $: %clay :: $> $? %mere :: @@ -411,6 +491,44 @@ `[(weld pax pat) %mime !>(u.mim)] :: [deletes changes] +:: +++ pour-to-mist + |= =pour + ^- mist + ?+ -.pour pour + %vale [%vale path.pour] + %arch [%arch path.pour] + == +:: +++ fell-to-page + |= =fell + ^- (unit page) + ?- -.fell + %dead ~ + %direct `q.fell + %delta ~ + %1 peg.fell + == +:: +++ rave-to-rove + |= rav=rave + ^- rove + ?- -.rav + %sing rav + %next [- mood ~ ~]:rav + %mult [- mool ~ ~ ~]:rav + %many [- track moat ~]:rav + == +:: +++ rove-to-rave + |= rov=rove + ^- rave + ?- -.rov + %sing rov + %next [- mood]:rov + %mult [- mool]:rov + %many [- track moat]:rov + == -- => ~% %clay + ~ |% @@ -440,7 +558,7 @@ :: ++ wrap |* [* state:ford] - [+<- +<+>-] :: cache.state + [+<- +<+< +<+>-] :: [result cache.state flue] :: ++ with-face |=([face=@tas =vase] vase(p [%face face p.vase])) ++ with-faces @@ -453,105 +571,87 @@ $(vaz t.vaz) :: ++ ford - !. => |% - +$ build - $% [%file =path] - [%mark =mark] - [%dais =mark] - [%cast =mars] - [%tube =mars] - [%vale =path] - == +$ state - $: baked=(map path cage) - cache=ford-cache - stack=(list (set [dir=? =path])) - cycle=(set build) + $: cache=flow + flue + cycle=(set mist) + drain=(map mist leak) + stack=(list (set leak)) == +$ args - $: =ankh - deletes=(set path) - changes=(map path (each page lobe)) - file-store=(map lobe blob) - =ford-cache + $: files=(map path (each page lobe)) + file-store=(map lobe page) + verb=@ + cache=flow + flue == -- |= args :: nub: internal mutable state for this computation :: =| nub=state - =. cache.nub ford-cache + =. cache.nub cache + =. spill.nub spill + =. sprig.nub sprig |% - :: +pop-stack: pop build stack, copying deps downward - :: - ++ pop-stack - ^- [(set [dir=? =path]) _stack.nub] - =^ top=(set [dir=? =path]) stack.nub stack.nub - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) top)) - [top stack.nub] :: +read-file: retrieve marked, validated file contents at path :: ++ read-file |= =path ^- [cage state] ~| %error-validating^path - ?^ got=(~(get by baked.nub) path) - [u.got nub] - =; [res=cage bun=state] - =. nub bun - =. baked.nub (~(put by baked.nub) path res) - [res nub] + %- soak-cage + %+ gain-sprig vale+path |. + =. stack.nub [~ stack.nub] ?: (~(has in cycle.nub) vale+path) - ~|(cycle+vale+path^stack.nub !!) + ~|(cycle+vale+path^cycle.nub !!) =. cycle.nub (~(put in cycle.nub) vale+path) - ::~> %slog.0^leaf/"ford: read file {(spud path)}" - ?^ change=(~(get by changes) path) - =^ page nub - ?: ?=(%& -.u.change) - [p.u.change nub] - ~| %ugly-lobe^p.u.change^path - (lobe-to-page p.u.change) - =^ cage nub (validate-page path page) - [cage nub] - ?< (~(has in deletes) path) - ~| %file-not-found^path - :_(nub (need (~(get an:cloy ankh) path))) + %+ gain-leak vale+path + |= nob=state + =. nub nob + %- (trace 1 |.("read file {(spud path)}")) + =/ file + ~| %file-not-found^path + (~(got by files) path) + =/ page + ?: ?=(%& -.file) + p.file + ~| %tombstoned-file^path^p.file + (~(got by file-store) p.file) + =^ =cage nub (validate-page path page) + [[%cage cage] nub] + :: :: +build-nave: build a statically typed mark core :: ++ build-nave |= mak=mark ^- [vase state] ~| %error-building-mark^mak - ?^ got=(~(get by naves.cache.nub) mak) - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) dez.u.got)) - [res.u.got nub] - ?: (~(has in cycle.nub) mark+mak) - ~|(cycle+mark+mak^stack.nub !!) - =. cycle.nub (~(put in cycle.nub) mark+mak) + %- soak-vase + %+ gain-sprig nave+mak |. =. stack.nub [~ stack.nub] - =; res=[=vase nub=state] - =. nub nub.res - =^ top stack.nub pop-stack - =. naves.cache.nub (~(put by naves.cache.nub) mak [vase.res top]) - [vase.res nub] - :: ~> %slog.0^leaf/"ford: make mark {}" + ?: (~(has in cycle.nub) nave+mak) + ~|(cycle+nave+mak^cycle.nub !!) + =. cycle.nub (~(put in cycle.nub) nave+mak) + %- (trace 1 |.("make mark {}")) =^ cor=vase nub (build-fit %mar mak) =/ gad=vase (slap cor limb/%grad) ?@ q.gad =+ !<(mok=mark gad) - =^ deg=vase nub $(mak mok) + =^ deg=vase nub ^$(mak mok) =^ tub=vase nub (build-cast mak mok) =^ but=vase nub (build-cast mok mak) - :_ nub + %+ gain-leak nave+mak + |= nob=state + =. nub nob + :_ nub :- %vase ^- vase :: vase of nave %+ slap - (with-faces deg+deg tub+tub but+but cor+cor nave+!>(nave) ~) + (with-faces deg+deg tub+tub but+but cor+cor nave+nave.bud ~) !, *hoon =/ typ _+<.cor - =/ dif diff:deg + =/ dif _*diff:deg ^- (nave typ dif) |% ++ diff @@ -567,9 +667,12 @@ (but (pact:deg (tub v) d)) ++ vale noun:grab:cor -- - :_ nub + %+ gain-leak nave+mak + |= nob=state + =. nub nob + :_ nub :- %vase ^- vase :: vase of nave - %+ slap (slop (with-face cor+cor) !>(..zuse)) + %+ slap (slop (with-face cor+cor) zuse.bud) !, *hoon =/ typ _+<.cor =/ dif _*diff:grad:cor @@ -598,23 +701,20 @@ |= mak=mark ^- [dais state] ~| %error-building-dais^mak - ?^ got=(~(get by marks.cache.nub) mak) - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) dez.u.got)) - [res.u.got nub] - ?: (~(has in cycle.nub) dais+mak) - ~|(cycle+dais+mak^stack.nub !!) - =. cycle.nub (~(put in cycle.nub) dais+mak) + %- soak-dais + %+ gain-sprig dais+mak |. =. stack.nub [~ stack.nub] - =; res=[=dais nub=state] - =. nub nub.res - =^ top stack.nub pop-stack - =. marks.cache.nub (~(put by marks.cache.nub) mak [dais.res top]) - [dais.res nub] + ?: (~(has in cycle.nub) dais+mak) + ~|(cycle+dais+mak^cycle.nub !!) + =. cycle.nub (~(put in cycle.nub) dais+mak) =^ nav=vase nub (build-nave mak) - :: ~> %slog.0^leaf/"ford: make dais {}" - :_ nub + %+ gain-leak dais+mak + |= nob=state + =. nub nob + %- (trace 1 |.("make dais {}")) + :_ nub :- %dais ^- dais + => [nav=nav ..zuse] |_ sam=vase ++ diff |= new=vase @@ -633,8 +733,8 @@ =/ res=vase %+ slam (slap nav limb/%mash) %+ slop - :(slop !>(ship.a) !>(desk.a) diff.a) - :(slop !>(ship.b) !>(desk.b) diff.b) + :(slop [[%atom %p ~] ship.a] [[%atom %tas ~] desk.a] diff.a) + :(slop [[%atom %p ~] ship.b] [[%atom %tas ~] desk.b] diff.b) ?~ q.res ~ `(slap res !,(*hoon ?>((^ .) u))) @@ -651,23 +751,16 @@ |= [a=mark b=mark] ^- [vase state] ~| error-building-cast+[a b] - ?: =([%mime %hoon] [a b]) - :_(nub !>(|=(m=mime q.q.m))) - ?^ got=(~(get by casts.cache.nub) [a b]) - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) dez.u.got)) - [res.u.got nub] - ?: (~(has in cycle.nub) cast+[a b]) - ~|(cycle+cast+[a b]^stack.nub !!) + %- soak-vase + %+ gain-sprig cast+a^b |. =. stack.nub [~ stack.nub] - =; res=[=vase nub=state] - =. nub nub.res - =^ top stack.nub pop-stack - =. casts.cache.nub (~(put by casts.cache.nub) [a b] [vase.res top]) - [vase.res nub] + ?: (~(has in cycle.nub) cast+[a b]) + ~|(cycle+cast+[a b]^cycle.nub !!) + ?: =([%mime %hoon] [a b]) + :_(nub [%vase =>(..zuse !>(|=(m=mime q.q.m)))]) :: try +grow; is there a +grow core with a .b arm? :: - :: ~> %slog.0^leaf/"ford: make cast {} -> {}" + %- (trace 1 |.("make cast {} -> {}")) =^ old=vase nub (build-fit %mar a) ?: =/ ram (mule |.((slap old !,(*hoon grow)))) ?: ?=(%| -.ram) %.n @@ -676,7 +769,10 @@ p.lab :: +grow core has .b arm; use that :: - :_ nub + %+ gain-leak cast+a^b + |= nob=state + =. nub nob + :_ nub :- %vase %+ slap (with-faces cor+old ~) ^- hoon :+ %brcl !,(*hoon v=+<.cor) @@ -687,7 +783,10 @@ =^ new=vase nub (build-fit %mar b) =/ rab (mule |.((slap new tsgl/[limb/a limb/%grab]))) ?: &(?=(%& -.rab) ?=(^ q.p.rab)) - :_(nub p.rab) + %+ gain-leak cast+a^b + |= nob=state + =. nub nob + :_(nub vase+p.rab) :: try +jump :: =/ jum (mule |.((slap old tsgl/[limb/b limb/%jump]))) @@ -696,53 +795,41 @@ ?: ?=(%& -.rab) (compose-casts a !<(mark p.rab) b) ?: ?=(%noun b) - :_(nub !>(|=(* +<))) + %+ gain-leak cast+a^b + |= nob=state + =. nub nob + :_(nub vase+same.bud) ~|(no-cast-from+[a b] !!) :: ++ compose-casts |= [x=mark y=mark z=mark] - ^- [vase state] + ^- [soak state] =^ uno=vase nub (build-cast x y) =^ dos=vase nub (build-cast y z) - :_ nub + %+ gain-leak cast+x^z + |= nob=state + =. nub nob + :_ nub :- %vase %+ slap - (with-faces uno+uno dos+dos cork+!>(cork) ~) - !,(*hoon (cork uno dos)) + (with-faces uno+uno dos+dos ~) + !,(*hoon |=(_+<.uno (dos (uno +<)))) :: +build-tube: produce a $tube mark conversion gate from .a to .b :: ++ build-tube |= [a=mark b=mark] ^- [tube state] ~| error-building-tube+[a b] - ?^ got=(~(get by tubes.cache.nub) [a b]) - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) dez.u.got)) - [res.u.got nub] - ?: (~(has in cycle.nub) tube+[a b]) - ~|(cycle+tube+[a b]^stack.nub !!) + %- soak-tube + %+ gain-sprig tube+a^b |. =. stack.nub [~ stack.nub] - =; res=[=tube nub=state] - =. nub nub.res - =^ top stack.nub pop-stack - =. tubes.cache.nub (~(put by tubes.cache.nub) [a b] [tube.res top]) - [tube.res nub] + ?: (~(has in cycle.nub) tube+[a b]) + ~|(cycle+tube+[a b]^cycle.nub !!) =^ gat=vase nub (build-cast a b) - :: ~> %slog.0^leaf/"ford: make tube {} -> {}" - :_(nub |=(v=vase (slam gat v))) - :: - ++ lobe-to-page - |= =lobe - ^- [page state] - =/ =blob (~(got by file-store) lobe) - |- ^- [page state] - ?- -.blob - %direct [q.blob nub] - %delta - =/ [[=mark =parent=^lobe] diff=page] [q r]:blob - =^ parent-page nub $(blob (~(got by file-store) parent-lobe)) - =^ =cage nub (run-pact parent-page diff) - [[p q.q]:cage nub] - == + %+ gain-leak tube+a^b + |= nob=state + =. nub nob + %- (trace 1 |.("make tube {} -> {}")) + :_(nub [%tube =>([gat=gat ..zuse] |=(v=vase (slam gat v)))]) :: ++ validate-page |= [=path =page] @@ -753,15 +840,15 @@ (page-to-cage page) =^ [mark vax=vase] nub (page-to-cage page) =^ =tube nub (build-tube p.page mak) - :_(nub [mak (tube vax)]) + :_(nub [mak (road |.((tube vax)))]) :: ++ page-to-cage |= =page ^- [cage state] ?: =(%hoon p.page) - :_(nub [%hoon -:!>(*@t) q.page]) + :_(nub [%hoon [%atom %t ~] q.page]) ?: =(%mime p.page) - :_(nub [%mime !>(;;(mime q.page))]) + :_(nub [%mime =>([;;(mime q.page) ..zuse] !>(-))]) =^ =dais nub (build-dais p.page) :_(nub [p.page (vale:dais q.page)]) :: @@ -775,7 +862,7 @@ [cag nub] =^ =tube nub (build-tube mok mak) ~| error-running-cast+[path mok mak] - :_(nub [mak (tube q.cag)]) + :_(nub [mak (road |.((tube q.cag)))]) :: ++ run-pact |= [old=page diff=page] @@ -784,7 +871,7 @@ =/ txt=wain (to-wain:format ;;(@t q.old)) =+ ;;(dif=(urge cord) q.diff) =/ new=@t (of-wain:format (lurk:differ txt dif)) - :_(nub [%hoon !>(new)]) + :_(nub [%hoon =>([new ..zuse] !>(-))]) =^ dys=dais nub (build-dais p.old) =^ syd=dais nub (build-dais p.diff) :_(nub [p.old (~(pact dys (vale:dys q.old)) (vale:syd q.diff))]) @@ -797,7 +884,7 @@ =/ tex=tape (trip !<(@t q.cag)) =/ =pile (parse-pile path tex) =. hoon.pile !,(*hoon .) - =^ res=vase nub (run-pile pile) + =^ res=vase nub (run-prelude pile) res :: ++ build-dependency @@ -806,25 +893,23 @@ =/ =path ?:(?=(%| -.dep) p.dep fil.p.dep) ~| %error-building^path - ?^ got=(~(get by files.cache.nub) path) - =? stack.nub ?=(^ stack.nub) - stack.nub(i (~(uni in i.stack.nub) dez.u.got)) - [res.u.got nub] + %- soak-vase + %+ gain-sprig file+path |. + =. stack.nub [~ stack.nub] + %- (trace 1 |.("make file {(spud path)}")) ?: (~(has in cycle.nub) file+path) - ~|(cycle+file+path^stack.nub !!) + ~|(cycle+file+path^cycle.nub !!) =. cycle.nub (~(put in cycle.nub) file+path) - =. stack.nub - =- [(sy - ~) stack.nub] - ?:(?=(%| -.dep) dep [& dir.p.dep]) - :: ~> %slog.0^leaf/"ford: make file {(spud path)}" =^ cag=cage nub (read-file path) ?> =(%hoon p.cag) =/ tex=tape (trip !<(@t q.cag)) =/ =pile (parse-pile path tex) - =^ res=vase nub (run-pile pile) - =^ top stack.nub pop-stack - =. files.cache.nub (~(put by files.cache.nub) path [res top]) - [res nub] + =^ sut=vase nub (run-prelude pile) + %+ gain-leak file+path + |= nob=state + =. nub nob + =/ res=vase (road |.((slap sut hoon.pile))) + [[%vase res] nub] :: ++ build-file |= =path @@ -838,27 +923,36 @@ ++ build-directory |= =path ^- [(map @ta vase) state] + %- soak-arch + %+ gain-sprig arch+path |. + =. stack.nub [~ stack.nub] + %+ gain-leak arch+path + |= nob=state + =. nub nob =/ fiz=(list @ta) - =/ nuk=(unit _ankh) (~(dug an:cloy ankh) path) - ?~ nuk ~ - %+ murn - ~(tap by dir.u.nuk) - |= [nom=@ta nak=_ankh] - ?. ?=([~ [~ *] *] (~(get by dir.nak) %hoon)) ~ - `nom + =/ len (lent path) + %+ murn ~(tap by files) + |= [pax=^path *] + ^- (unit @ta) + ?. =(path (scag len pax)) + ~ + =/ pat (slag len pax) + ?: ?=([@ %hoon ~] pat) + `i.pat + ~ :: =| rez=(map @ta vase) |- ?~ fiz - [rez nub] + [[%arch rez] nub] =* nom=@ta i.fiz =/ pax=^path (weld path nom %hoon ~) =^ res nub (build-dependency &+[path pax]) $(fiz t.fiz, rez (~(put by rez) nom res)) :: - ++ run-pile + ++ run-prelude |= =pile - =/ sut=vase !>(..zuse) + =/ sut=vase zuse.bud =^ sut=vase nub (run-tauts sut %sur sur.pile) =^ sut=vase nub (run-tauts sut %lib lib.pile) =^ sut=vase nub (run-raw sut raw.pile) @@ -866,8 +960,7 @@ =^ sut=vase nub (run-maz sut maz.pile) =^ sut=vase nub (run-caz sut caz.pile) =^ sut=vase nub (run-bar sut bar.pile) - =/ res=vase (road |.((slap sut hoon.pile))) - [res nub] + [sut nub] :: ++ parse-pile |= [pax=path tex=tape] @@ -1031,16 +1124,156 @@ ^- path =/ paz (segments pax) |- ^- path - ?~ paz ~_(leaf/"clay: no files match /{(trip pre)}/{(trip pax)}/hoon" !!) + ?~ paz + ~_(leaf/"clay: no files match /{(trip pre)}/{(trip pax)}/hoon" !!) =/ pux=path pre^(snoc i.paz %hoon) - ?: (~(has in deletes) pux) - $(paz t.paz) - ?: (~(has by changes) pux) - pux - ?^ (~(get an:cloy ankh) pux) + ?: (~(has by files) pux) pux $(paz t.paz) + :: + ++ all-fits + |= [=term suf=term] + ^- (list path) + %+ turn (segments suf) + |= seg=path + [term (snoc seg %hoon)] + :: + :: Gets a map of the data at the given path and all children of it. + :: + :: i.e. +dip:of for a map, except doesn't shorten paths + :: + ++ dip-hat + |= pax=path + ^- (map path (each page lobe)) + %- malt + %+ skim ~(tap by files) + |= [p=path *] + ?| ?=(~ pax) + ?& !?=(~ p) + =(-.pax -.p) + $(p +.p, pax +.pax) + == == + :: + ++ trace + |= [pri=@ print=(trap tape)] + (^trace verb pri print) + :: + ++ mist-to-pour + |= =mist + ^- pour + ?+ -.mist mist + %vale + :+ %vale path.mist + ~| %file-not-found-mist^path.mist + =/ lob (~(got by files) path.mist) + ?- -.lob + %& (page-to-lobe p.lob) + %| p.lob + == + :: + %arch + =/ dip (dip-hat path.mist) + :+ %arch path.mist + %- ~(run by dip) + |= file=(each page lobe) + ?- -.file + %& (page-to-lobe p.file) + %| p.file + == + == + :: + ++ soak-cage |=([s=soak n=state] ?>(?=(%cage -.s) [cage.s n])) + ++ soak-vase |=([s=soak n=state] ?>(?=(%vase -.s) [vase.s n])) + ++ soak-dais |=([s=soak n=state] ?>(?=(%dais -.s) [dais.s n])) + ++ soak-tube |=([s=soak n=state] ?>(?=(%tube -.s) [tube.s n])) + ++ soak-arch |=([s=soak n=state] ?>(?=(%arch -.s) [dir.s n])) + :: + ++ gain-sprig + |= [=mist next=(trap [soak state])] + ^- [soak state] + ?~ got=(~(get by sprig.nub) mist) + $:next + =? stack.nub ?=(^ stack.nub) + stack.nub(i (~(put in i.stack.nub) leak.u.got)) + [soak.u.got nub] + :: + ++ gain-leak + |= [=mist next=$-(state [soak state])] + ^- [soak state] + =^ top=(set leak) stack.nub stack.nub + =/ =leak [(mist-to-pour mist) top] + =. cycle.nub (~(del in cycle.nub) mist) + =? stack.nub ?=(^ stack.nub) + stack.nub(i (~(put in i.stack.nub) leak)) + =/ spilt (~(has in spill.nub) leak) + =^ =soak nub + ?^ got=(~(get by cache.nub) leak) + %- %+ trace 3 |. + =/ refs ?:(spilt 0 1) + %+ welp "cache {}: adding {}, " + "giving {<(add refs refs.u.got)>}" + =? cache.nub !spilt + (~(put by cache.nub) leak [+(refs.u.got) soak.u.got]) + [soak.u.got nub] + %- (trace 2 |.("cache {}: creating")) + =^ =soak nub (next nub) + =. cache.nub (~(put by cache.nub) leak [1 soak]) + :: If we're creating a cache entry, add refs to our dependencies + :: + =/ deps ~(tap in deps.leak) + |- + ?~ deps + [soak nub] + =/ got (~(got by cache.nub) i.deps) + %- %+ trace 3 |. + %+ welp "cache {} for {}" + ": bumping to ref {}" + =. cache.nub (~(put by cache.nub) i.deps got(refs +(refs.got))) + $(deps t.deps) + ?: spilt + [soak nub] + %- (trace 3 |.("spilt {}")) + =: spill.nub (~(put in spill.nub) leak) + sprig.nub (~(put by sprig.nub) mist leak soak) + == + [soak nub] -- + :: + ++ lose-leak + |= [verb=@ fad=flow =leak] + ^- flow + ?~ got=(~(get by fad) leak) + %- (trace verb 0 |.("lose missing leak {}")) + fad + ?: (lth 1 refs.u.got) + %- (trace verb 3 |.("cache {}: decrementing from {}")) + =. fad (~(put by fad) leak u.got(refs (dec refs.u.got))) + fad + =+ ?. =(0 refs.u.got) ~ + ((trace verb 0 |.("lose zero leak {}")) ~) + %- (trace verb 2 |.("cache {}: freeing")) + =. fad (~(del by fad) leak) + =/ leaks ~(tap in deps.leak) + |- ^- flow + ?~ leaks + fad + =. fad ^$(leak i.leaks) + $(leaks t.leaks) + :: + ++ lose-leaks + |= [verb=@ fad=flow leaks=(set leak)] + ^- flow + =/ leaks ~(tap in leaks) + |- + ?~ leaks + fad + $(fad (lose-leak verb fad i.leaks), leaks t.leaks) + :: + ++ trace + |= [verb=@ pri=@ print=(trap tape)] + ?: (lth verb pri) + same + (slog leaf+"ford: {(print)}" ~) -- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: section 4cA, filesystem logic @@ -1088,7 +1321,7 @@ ++ de :: per desk |= [now=@da rof=roof hen=duct raft] |= [her=ship syd=desk] - :: XX ruf=raft crashes in the compiler + :: NB: ruf=raft crashes in the compiler :: =* ruf |3.+6.^$ :: @@ -1131,21 +1364,24 @@ :: ++ aver |= [for=(unit ship) mun=mood] - ^- [(unit (unit (each cage lobe))) ford-cache] + ^- [(unit (unit cage)) _..park] =+ ezy=?~(ref ~ (~(get by haw.u.ref) mun)) ?^ ezy - :_(fod.dom.red `(bind u.ezy |=(a=cage [%& a]))) + [`u.ezy ..park] ?: ?=([%s [%ud *] %late *] mun) - :_ fod.dom.red - ^- (unit (unit (each cage lobe))) - :^ ~ ~ %& + :_ ..park + ^- (unit (unit cage)) + :+ ~ ~ ^- cage :- %cass ?~ let.dom !>([0 *@da]) !>([let.dom t:(~(got by hut.ran) (~(got by hit.dom) let.dom))]) =+ nao=(case-to-aeon case.mun) - ?~(nao [~ fod.dom.red] (read-at-aeon:ze for u.nao mun)) + ?: ?=([%s case %case ~] mun) + :: case existence check + [``[%flag !>(!=(~ nao))] ..park] + ?~(nao [~ ..park] (read-at-aeon:ze for u.nao mun)) :: :: Queue a move. :: @@ -1165,16 +1401,6 @@ |= mof=(list move) %_(+> mow (weld mow (flop mof))) :: - :: Produce either null or a result along a subscription. - :: - :: Producing null means subscription has been completed or cancelled. - :: - ++ balk - |= [hen=duct cay=(unit (each cage lobe)) mun=mood] - ^+ +> - ?~ cay (blub hen) - (blab hen mun u.cay) - :: :: Set timer. :: ++ bait @@ -1187,28 +1413,18 @@ |= [hen=duct tym=@da] (emit hen %pass /tyme/(scot %p her)/[syd] %b %rest tym) :: - :: Give subscription result. + :: Give %writ, or slip a drip if foreign desk :: - :: Result can be either a direct result (cage) or a lobe of a result. In - :: the latter case we fetch the data at the lobe and produce that. - :: - ++ blab - |= [hen=duct mun=mood dat=(each cage lobe)] - ^+ +> - =^ =cage fod.dom - ?: ?=(%& -.dat) - [p.dat fod.dom] - =^ =page fod.dom - %- wrap:fusion - (lobe-to-page:(ford:fusion static-ford-args) p.dat) - =^ =cage fod.dom - %- wrap:fusion - (page-to-cage:(ford:fusion static-ford-args) page) - [cage fod.dom] - =/ gift [%writ ~ [care.mun case.mun syd] path.mun cage] - ?: ?=(^ ref) - (emit hen %slip %b %drip !>(gift)) - (emit hen %give gift) + ++ writ + |= res=(unit [=mood =cage]) + ^- card + =/ =riot + ?~ res + ~ + `[[care.mood case.mood syd] path.mood cage]:[u.res syd=syd] + ?~ ref + [%give %writ riot] + [%slip %b %drip !>([%writ riot])] :: ++ case-to-date |= =case @@ -1236,6 +1452,8 @@ |= [lim=@da lok=case] ^- (unit aeon) ?- -.lok + %tas (~(get by lab.dom) p.lok) + %ud ?:((gth p.lok let.dom) ~ [~ p.lok]) %da ?: (gth p.lok lim) ~ |- ^- (unit aeon) @@ -1248,67 +1466,29 @@ let.dom [~ let.dom] $(let.dom (dec let.dom)) - :: - %tas (~(get by lab.dom) p.lok) - %ud ?:((gth p.lok let.dom) ~ [~ p.lok]) == :: - ++ blas - |= [hen=duct das=(set mood)] - ^+ +> - ?> ?=(^ das) - :: translate the case to a date + :: Create a ford appropriate for the aeon + :: + :: Don't forget to call +aeon-flow! + :: + ++ aeon-ford + |= yon=aeon + %- ford:fusion + =/ files (~(run by q:(aeon-to-yaki:ze yon)) |=(=lobe |+lobe)) + [files lat.ran veb.bug fad ?:(=(yon let.dom) fod.dom [~ ~])] + :: Produce ford cache appropriate for the aeon + :: + ++ aeon-flow + |* [yon=aeon res=* fud=flow fod=flue] + :- res + ^+ ..park + ?: &(?=(~ ref) =(let.dom yon)) + ..park(fad fud, fod.dom fod) + :: if in the past, don't update ford cache, since any results have + :: no roots :: - =/ cas [%da (case-to-date case.n.das)] - =/ res - (~(run in `(set mood)`das) |=(m=mood [care.m path.m])) - =/ gift [%wris cas res] - ?: ?=(^ ref) - (emit hen %slip %b %drip !>(gift)) - (emit hen %give gift) - :: - :: Give next step in a subscription. - :: - ++ bleb - |= [hen=duct ver=@ud ins=@ud hip=(unit (pair aeon aeon))] - ^+ +> - %^ blab hen [%w [%ud ins] ~] - :- %& - ?~ hip - [%null [%atom %n ~] ~] - [%nako !>((make-nako:ze ver u.hip))] - :: - :: Tell subscriber that subscription is done. - :: - ++ blub - |= hen=duct - ?: ?=(^ ref) - (emit hen %slip %b %drip !>([%writ ~])) - (emit hen %give %writ ~) - :: - :: Lifts a function so that a single result can be fanned out over a set of - :: subscriber ducts. - :: - :: Thus, `((duct-lift func) subs arg)` runs `(func sub arg)` for each `sub` - :: in `subs`. - :: - ++ duct-lift - |* send=_|=([duct *] ..duct-lift) - |= [a=(set duct) arg=_+<+.send] ^+ ..duct-lift - =+ all=~(tap by a) - |- ^+ ..duct-lift - ?~ all ..duct-lift - =. +>.send ..duct-lift - $(all t.all, duct-lift (send i.all arg)) - :: - ++ blub-all (duct-lift |=([a=duct ~] (blub a))) - ++ blab-all (duct-lift blab) - ++ blas-all (duct-lift blas) - ++ balk-all (duct-lift balk) - ++ bleb-all (duct-lift bleb) - :: - ++ static-ford-args [ank.dom ~ ~ lat.ran fod.dom] - :: + ..park :: Transfer a request to another ship's clay. :: ++ send-over-ames @@ -1367,7 +1547,7 @@ (send-over-ames hen her inx syd `rave) %= +>+.$ nix.u.ref +(nix.u.ref) - bom.u.ref (~(put by bom.u.ref) inx [hen rave ~ ~ ~ |]) + bom.u.ref (~(put by bom.u.ref) inx [hen rave ~ ~ |]) fod.u.ref (~(put by fod.u.ref) hen inx) == :: @@ -1445,6 +1625,18 @@ == == :: + ++ set-norm + |= =norm + =. nor.dom norm + ..park + :: + ++ set-worn + |= [=tako =norm] + ?: &(=(our her) =(tako (aeon-to-tako:ze let.dom))) + (mean leaf+"clay: can't set norm for current commit in {}" ~) + =. tom.dom (~(put by tom.dom) tako norm) + ..park + :: :: Attach label to aeon :: ++ label @@ -1457,7 +1649,7 @@ ?~ yen =. lab.dom (~(put by lab.dom) bel yon) ..park - :: an aeon is bound to this label, + :: an aeon is bound to this label, :: but it is the same as the existing one, so we no-op :: ?: =(u.yen yon) @@ -1524,9 +1716,7 @@ :: :: Guaranteed to finish in one event. :: - :: XX needs to check that head is ancestor of tako - :: XX needs to check tako in rang - :: XX needs to check that commit doesn't have same date + :: TODO: needs to check tako in rang :: ++ park =/ check-sane | @@ -1541,6 +1731,12 @@ %& q.p.yoki %| (~(run by q.p.yoki) |=(=lobe |+lobe)) == + ?. %- ~(all in new-data) :: use +all:in so we get the key + |= [=path tum=(each page lobe)] + ?: |(?=(%& -.tum) (~(has by lat.ran) p.tum)) + & + (mean leaf/"clay: commit failed, file tombstoned: {} {<`@uv`p.tum>}" ~) + !! :: find desk kelvin :: =/ kel=weft (get-kelvin yoki) @@ -1556,34 +1752,42 @@ ~| [from=let.dom deletes=deletes changes=~(key by changes)] :: :: promote ford cache - :: promote and fill in ankh :: promote and fill in mime cache :: =/ invalid (~(uni in deletes) ~(key by changes)) ?: &(=(%base syd) !updated (~(any in invalid) is-kernel-path)) (sys-update yoki new-data) :: - ~? (did-kernel-update invalid) %clay-kernel-updated + =+ ?. (did-kernel-update invalid) ~ + ((slog 'clay: kernel updated' ~) ~) =? updated updated (did-kernel-update invalid) => ?. updated . ~>(%slog.0^leaf/"clay: rebuilding {} after kernel update" .) :: clear caches if zuse reloaded :: + =/ old-fod fod.dom =. fod.dom - ?: updated *ford-cache + ?: updated [~ ~] (promote-ford fod.dom invalid) - =? ank.dom updated *ankh + =. fad + (lose-leaks:fusion veb.bug fad (~(dif in spill.old-fod) spill.fod.dom)) =? changes updated (changes-for-upgrade q.old-yaki deletes changes) :: - =/ =args:ford:fusion [ank.dom deletes changes lat.ran fod.dom] + =/ files + =/ original=(map path (each page lobe)) + (~(run by q.old-yaki) |=(=lobe |+lobe)) + %- ~(dif by (~(uni by original) changes)) + %- ~(gas by *(map path (each page lobe))) + (turn ~(tap in deletes) |=(=path [path |+*lobe])) + =/ =args:ford:fusion [files lat.ran veb.bug fad fod.dom] :: - =^ change-cages ford-cache.args (checkout-changes args changes) + =^ change-cages args (checkout-changes args changes) =/ sane-continuation (sane-changes changes change-cages) - =/ new-blobs=(map lobe blob) + =/ new-pages=(map lobe page) %- malt %+ turn ~(tap by change-cages) |= [=path =lobe =cage] - [lobe %direct lobe [p q.q]:cage] + [lobe [p q.q]:cage] =/ data=(map path lobe) %- ~(urn by new-data) |= [=path value=(each page lobe)] @@ -1606,120 +1810,30 @@ =: let.dom +(let.dom) hit.dom (~(put by hit.dom) +(let.dom) r.yaki) hut.ran (~(put by hut.ran) r.yaki yaki) - lat.ran (~(uni by new-blobs) lat.ran) + lat.ran (~(uni by new-pages) lat.ran) == =. file-store.args lat.ran :: - =^ ankh ford-cache.args - (checkout-ankh args deletes change-cages ank.dom) - =/ null (sane-ankh sane-continuation ankh) - =. ankh.args ankh - =. ank.dom ankh - =^ mim ford-cache.args - (checkout-mime args deletes ~(key by changes)) - =. mim.dom (apply-changes-to-mim mim.dom mim) - =. fod.dom ford-cache.args - =. ..park (emil (print q.old-yaki data)) - =? ..park &(updated !dist-upgraded.ruf) migrate-dist - wake:(ergo mim) + =/ mem (want-mime 0) + =/ res=[mum=(map path (unit mime)) mim=_mim.dom args=_args] + ?. mem [~ ~ args] + =^ mum args (checkout-mime args deletes ~(key by changes)) + [mum (apply-changes-to-mim mim.dom mum) args] + =. mim.dom mim.res + =. args args.res + :: + =. fod.dom [spill sprig]:args + =. fad cache.args + =. ..park (emil (print q.old-yaki data)) + wake:?:(mem (ergo 0 mum.res) ..park) :: - ++ migrate-dist - ~> %slog.0^'clay: migrating for third-party software distribution' - |^ ^+ ..park - =. ..park purge - :: first make sure gall has molted and has :hood running - :: - =. ..park (emit hen %pass /dist/hood %g %jolt %home %hood) - :: now ask :hood to install all the new desks - :: - :: NOTE: reverse order, since we're prepending moves each time - :: - =. ..park (install-from-tmp %bitcoin) - =. ..park (install-from-tmp %webterm) - =. ..park (install-from-tmp %landscape) - =. ..park (install-from-tmp %garden) - =. ..park (install-from-tmp %base) - ..park(dist-upgraded.ruf &) - :: - ++ purge - ^+ ..park - =/ wux=(list [=wove dux=(set duct)]) ~(tap by qyx) - |- ^+ ..park - ?~ wux ..park - =/ rov rove.wove.i.wux - =? qyx - ?+ -.rov | - %sing ?=([%a * %app %publish %hoon ~] mood.rov) - %next ?=([%a * %app %publish %hoon ~] mood.rov) - == - (~(del by qyx) wove.i.wux) - $(wux t.wux) - :: - ++ install-from-tmp - |= =desk - ^+ ..park - =/ sen (^^sein:title rof our now our) - %- lime - |^ ^- (list move) - =- (murn - same) - ^- (list (unit move)) - :~ `create-desk - `install-local - :: - ?: =(sen our) ~ - `install-remote - :: - ?: =(%base desk) ~ - `publish-desk - == - :: - ++ create-desk ^- move - :^ hen %pass /dist/create/[desk] - %^ new-desk:cloy desk - (latest-tako %home) - ;;((map path page) (cue (get-tmp-jam desk))) - :: - ++ publish-desk ^- move - :^ hen %pass /dist/public/[desk] - [%c %perm desk / %r `[%black ~]] - :: - ++ install-local ^- move - :^ hen %pass /dist/install-local/[desk] - [%g %deal [our our] %hood %poke %kiln-install !>([desk our desk])] - :: - ++ install-remote ^- move - =/ rem ?:(=(%base desk) %kids desk) - :: - :^ hen %pass /dist/install-remote/[desk] - [%g %deal [our our] %hood %poke %kiln-install !>([desk sen rem])] - -- - :: - ++ latest-tako - |= =desk - ^- (unit tako) - ?~ doj=(~(get by dos.rom) desk) ~ - =, dom.u.doj - (~(get by hit) let) - :: - ++ get-tmp-jam - |= =desk - ^- @ - ~| [%missing-tmp-desk-jam desk] - ?~ tmp=(~(get by dir.ank.dom) ~.tmp) !! - ?~ new=(~(get by dir.u.tmp) desk) !! - ?~ jam=(~(get by dir.u.new) ~.jam) !! - ?~ fil.u.jam !! - =* fil u.fil.u.jam - ?> =(%jam p.q.fil) - ;;(@ q.q.q.fil) - -- :: +is-kernel-path: should changing .pax cause a kernel or vane reload? :: ++ is-kernel-path |=(pax=path ?=([%sys *] pax)) :: ++ did-kernel-update |= invalid=(set path) - ?. |(=(%base syd) &(=(%home syd) !dist-upgraded.ruf)) + ?. |(=(%base syd) &(=(%home syd))) | %- ~(any in invalid) |=(p=path &((is-kernel-path p) !?=([%sys %vane *] p))) @@ -1745,16 +1859,14 @@ %| (lobe-to-weft p.fil) == == + :: ++ lobe-to-weft |= =lobe ^- weft - =/ =blob (lobe-to-blob:ze lobe) - =/ =page - ?- -.blob - %direct q.blob - %delta r.blob - == - (page-to-weft page) + =/ peg=(unit page) (~(get by lat.ran) lobe) + ?~ peg ~|([%sys-kelvin-tombstoned syd] !!) + (page-to-weft u.peg) + :: ++ page-to-weft |= =page ^- weft @@ -1808,59 +1920,43 @@ =/ pre=_changes (~(run by old) |=(lob=lobe |+lob)) (~(uni by pre) changes) :: - :: Keep any parts of the ford cache whose dependencies didn't change - :: - :: Make sure to invalidate any paths whose '-'s or '/'s could be - :: converted in an import; i.e. /mar, /lib, and /sur hoon files. - :: - :: If anything in the kernel other than a vane updated, - :: clear the cache. - :: ++ promote-ford - |= [=ford-cache invalid=(set path)] - ^+ ford-cache - :: - =. invalid - %- ~(gas in invalid) - %- zing - %+ turn ~(tap in invalid) - |= pax=path - ^- (list path) - =/ xap=path (flop pax) - ?. &(=(%hoon (head xap)) ?=([?(%mar %sur %lib) @ @ *] pax)) - ~ - =- (turn - |=(suf=path [i.pax (snoc suf %hoon)])) - %- segments - %- crip - =/ xup (tail xap) :: lose %hoon extension - =/ pux (tail (flop xup)) :: lose static prefix - %+ turn (tail (spud pux)) :: lose leading '/' - |=(c=@tD `@tD`?:(=('/' c) '-' c)) :: convert '/' to '-' - :: - :* ((invalidate path vase) files.ford-cache invalid) - ((invalidate mark vase) naves.ford-cache invalid) - ((invalidate mark dais) marks.ford-cache invalid) - ((invalidate mars vase) casts.ford-cache invalid) - ((invalidate mars tube) tubes.ford-cache invalid) - == - :: - ++ invalidate - |* [key=mold value=mold] - |= [cache=(map key [value dez=(set [dir=? =path])]) invalid=(set path)] - =/ builds=(list [key value dez=(set [dir=? =path])]) - ~(tap by cache) - |- ^+ cache - ?~ builds - ~ - ?: %- ~(any in dez.i.builds) - |= [dir=? =path] - ?. dir (~(has in invalid) path) - =+ l=(lent path) - %- ~(any in invalid) - |= i=^path - &(=(path (scag l i)) ?=([@ %hoon ~] (slag l i))) - $(builds t.builds) - (~(put by $(builds t.builds)) i.builds) + |= [fod=flue invalid=(set path)] + ^- flue + =/ old=(list leak) ~(tap in spill.fod) + =| new=flue + |- ^- flue + ?~ old + new + =/ invalid + |- ^- ? + ?| ?+ -.pour.i.old %| + %vale (~(has in invalid) path.pour.i.old) + %arch + :: TODO: overly conservative, should be only direct hoon + :: children + :: + =/ len (lent path.pour.i.old) + %- ~(any in invalid) + |= =path + =(path.pour.i.old (scag len path)) + == + :: + =/ deps ~(tap in deps.i.old) + |- ^- ? + ?~ deps + %| + ?| ^$(i.old i.deps) + $(deps t.deps) + == + == + =? new !invalid + :- (~(put in spill.new) i.old) + =/ =mist (pour-to-mist pour.i.old) + ?~ got=(~(get by sprig.fod) mist) + sprig.new + (~(put by sprig.new) mist u.got) + $(old t.old) :: ++ page-to-cord |= =page @@ -1870,50 +1966,32 @@ %mime q.q:;;(mime q.page) == :: - ++ path-to-hoon - |= [data=(map path (each page lobe)) =path] - (rain path (path-to-cord data path)) - :: - ++ path-to-cord - |= [data=(map path (each page lobe)) =path] - ^- @t - =/ datum (~(got by data) path) - ?- -.datum - %& (page-to-cord p.datum) - %| (lobe-to-cord p.datum) - == - :: ++ lobe-to-cord |= =lobe ^- @t - =- ?:(?=(%& -<) p.- (of-wain:format p.-)) - |- ^- (each @t wain) - =/ =blob (~(got by lat.ran) lobe) - ?- -.blob - %direct [%& ;;(@t q.q.blob)] - %delta - :- %| - %+ lurk:differ - =- ?:(?=(%| -<) p.- (to-wain:format p.-)) - $(lobe q.q.blob) - ;;((urge cord) q.r.blob) - == + =/ peg=(unit page) (~(get by lat.ran) lobe) + ?~ peg + ~|([%lobe-to-cord-tombstoned syd lobe] !!) + ;;(@t q.u.peg) :: :: Updated q.yaki :: ++ checkout-changes |= [=ford=args:ford:fusion changes=(map path (each page lobe))] - ^- [(map path [=lobe =cage]) ford-cache] + ^- [(map path [=lobe =cage]) args:ford:fusion] %+ roll `(list [path (each page lobe)])`~(tap by changes) |= $: [=path change=(each page lobe)] - [built=(map path [lobe cage]) cache=_ford-cache.ford-args] + [built=(map path [lobe cage]) cache=_ford-args] == - ^+ [built cache] - =. ford-cache.ford-args cache - =^ cage ford-cache.ford-args + ^+ [built ford-args] + =. ford-args cache + =/ [=cage fud=flow fod=flue] :: ~> %slog.[0 leaf/"clay: validating {(spud path)}"] %- wrap:fusion (read-file:(ford:fusion ford-args) path) + =. cache.ford-args fud + =. spill.ford-args spill.fod + =. sprig.ford-args sprig.fod =/ =lobe ?- -.change %| p.change @@ -1922,60 +2000,7 @@ :: %& (page-to-lobe [p q.q]:cage) == - [(~(put by built) path [lobe cage]) ford-cache.ford-args] - :: - :: Update ankh - :: - ++ checkout-ankh - |= $: =ford=args:ford:fusion - deletes=(set path) - changes=(map path [lobe cage]) - =ankh - == - ^+ [ankh ford-cache.ford-args] - :: Delete - :: - =. ankh - =/ dels ~(tap in deletes) - |- ^- ^ankh - =* outer-loop $ - ?~ dels - ankh - =. ankh - |- ^- ^ankh - =* inner-loop $ - ?~ i.dels - ankh(fil ~) - %= ankh - dir - %+ ~(put by dir.ankh) i.i.dels - %= inner-loop - i.dels t.i.dels - ankh (~(gut by dir.ankh) i.i.dels *^ankh) - == - == - outer-loop(dels t.dels) - :: Add/change - :: - =/ cans=(list [=path =lobe =cage]) ~(tap by changes) - |- ^+ [ankh ford-cache.ford-args] - =* outer-loop $ - ?~ cans - [ankh ford-cache.ford-args] - =^ new-ankh ford-cache.ford-args - |- ^+ [ankh ford-cache.ford-args] - =* inner-loop $ - ?^ path.i.cans - =^ child-ankh ford-cache.ford-args - %= inner-loop - path.i.cans t.path.i.cans - ankh (~(gut by dir.ankh) i.path.i.cans *^ankh) - == - :- ankh(dir (~(put by dir.ankh) i.path.i.cans child-ankh)) - ford-cache.ford-args - [ankh(fil `[lobe.i.cans cage.i.cans]) ford-cache.ford-args] - =. ankh new-ankh - outer-loop(cans t.cans) + [(~(put by built) path [lobe cage]) ford-args] :: :: Print notification to console :: @@ -2030,28 +2055,25 @@ ?~ tak ~ =/ =yaki (~(got by hut.ran) u.tak) - :: Assert all blobs hash to their lobe + :: Assert all pages hash to their lobe :: =/ foo %- ~(urn by lat.ran) - |= [=lobe =blob] - ?: ?=(%delta -.blob) - ~ - =/ actual-lobe=^lobe `@uv`(page-to-lobe q.blob) - ~| [lobe p.blob actual-lobe] - ?> &(=(lobe p.blob) =(lobe actual-lobe)) + |= [=lobe =page] + =/ actual-lobe=^lobe `@uv`(page-to-lobe page) + ~| [%bad-lobe have=lobe need=actual-lobe] + ?> =(lobe actual-lobe) ~ :: Assert we calculated the same change-cages w/o cache :: - :: XX remove deletes + :: ? remove deletes :: =/ all-changes=(map path (each page lobe)) =/ original=(map path (each page lobe)) (~(run by q.yaki) |=(=lobe |+lobe)) (~(uni by original) changes) - =/ =args:ford:fusion [*ankh ~ all-changes lat.ran *ford-cache] - =^ all-change-cages ford-cache.args - (checkout-changes args all-changes) + =/ =args:ford:fusion [all-changes lat.ran veb.bug ~ ~ ~] + =^ all-change-cages args (checkout-changes args all-changes) =/ ccs=(list [=path =lobe =cage]) ~(tap by change-cages) |- ^+ *sane-changes ?^ ccs @@ -2061,59 +2083,6 @@ $(ccs t.ccs) `[all-change-cages args] :: - ++ sane-ankh - |= $: $= cont - (unit [all-changes=(map path [lobe cage]) =ford=args:ford:fusion]) - =test=ankh - == - ?. check-sane - ~ - :: Assert all new lobes are reachable. - :: - :: Needs to run after dome is updated - :: - =/ tak=(unit tako) (~(get by hit.dom) let.dom) - ?~ tak - ~ - =/ =yaki (~(got by hut.ran) u.tak) - =/ files=(list [=path =lobe]) ~(tap by q.yaki) - |- ^+ *sane-ankh - ?^ files - ?. (~(has by lat.ran) lobe.i.files) - ~| missing-lobe=[path lobe] - !! - $(files t.files) - :: - :: Assert we can rebuild the ankh - :: - ?~ cont - ~ - =+ u.cont - =^ ankh ford-cache.ford-args - (checkout-ankh ford-args ~ all-changes *ankh) - =| =path - |- ^- ~ - =* loop $ - =/ fil (bind fil.ankh |=([=lobe =cage] [lobe p.cage q.q.cage])) - =/ test (bind fil.ankh |=([=lobe =cage] [lobe p.cage q.q.cage])) - ?. =(fil test) - ~| [%not-same-file path ?=(~ fil.ankh) ?=(~ fil.test-ankh)] - ~| ?~(fil.ankh ~ [[p p.q]:u.fil.ankh `@uv`(page-to-lobe [p q.q]:q.u.fil.ankh)]) - ~| ?~(fil.test-ankh ~ [[p p.q]:u.fil.test-ankh `@uv`(page-to-lobe [p q.q]:q.u.fil.test-ankh)]) - !! - ?. =(~(key by dir.ankh) ~(key by dir.test-ankh)) - ~| [%not-same-children path ~(key by dir.ankh) ~(key by dir.test-ankh)] - !! - =< ~ - %+ turn ~(tap by dir.ankh) - |= [=@ta =child=^ankh] - ~| sane-ankh=[path ta] - %= loop - path (snoc path ta) - ankh child-ankh - test-ankh (~(got by dir.test-ankh) ta) - == - :: :: Delay current update until sys update is complete :: ++ sys-update @@ -2136,6 +2105,7 @@ ?> ?=(^ xap) ?. ?=(%hoon i.xap) ~ :^ ~ (flop t.xap) %hoon + ~| [pax=pax p.dat] ?- -.dat %& (page-to-cord p.dat) %| (lobe-to-cord p.dat) @@ -2230,7 +2200,7 @@ =| rag=rang =/ clean-state ..take-fuse =/ initial-dome=dome:clay (need (~(got by sto.fiz) bas.fiz)) - =/ continuation-yaki=yaki + =/ next-yaki=yaki (~(got by hut.ran) (~(got by hit.initial-dome) let.initial-dome)) =/ parents=(list tako) ~[(~(got by hit.initial-dome) let.initial-dome)] =/ merges con.fiz @@ -2238,10 +2208,10 @@ ^+ ..take-fuse ?~ merges =. ..take-fuse (done-fuse clean-state %& ~) - (park | [%| continuation-yaki(p (flop parents))] rag) + (park | [%| next-yaki(p (flop parents))] rag) =/ [bec=beak g=germ] i.merges =/ ali-dom=dome:clay (need (~(got by sto.fiz) bec)) - =/ result (merge-helper p.bec q.bec g ali-dom `continuation-yaki) + =/ result (merge-helper p.bec q.bec g ali-dom `next-yaki) ?- -.result %| =/ failing-merge=tape "{} {}" @@ -2260,31 +2230,30 @@ :: (done-fuse clean-state %& conflicts.u.merge-result) =/ merged-yaki=yaki - ?- -.new.u.merge-result - %| - +.new.u.merge-result - :: - %& - :: - :: Convert the yuki to yaki - :: - =/ yuk=yuki +.new.u.merge-result - =/ lobes=(map path lobe) - %- ~(run by q.yuk) - |= val=(each page lobe) - ^- lobe - ?- -.val - %& (page-to-lobe +.val) - %| +.val - == - (make-yaki p.yuk lobes now) - == + ?- -.new.u.merge-result + %| +.new.u.merge-result + %& + :: + :: Convert the yuki to yaki + :: + =/ yuk=yuki +.new.u.merge-result + =/ lobes=(map path lobe) + %- ~(run by q.yuk) + |= val=(each page lobe) + ^- lobe + ?- -.val + %& (page-to-lobe +.val) + %| +.val + == + (make-yaki p.yuk lobes now) + == %= $ - continuation-yaki merged-yaki - merges t.merges - hut.ran (~(put by hut.ran) r.merged-yaki merged-yaki) - lat.rag (~(uni by lat.rag) lat.u.merge-result) - parents [(~(got by hit.ali-dom) let.ali-dom) parents] + next-yaki merged-yaki + merges t.merges + hut.ran (~(put by hut.ran) r.merged-yaki merged-yaki) + lat.rag (~(uni by lat.u.merge-result) lat.rag) + lat.ran (~(uni by lat.u.merge-result) lat.ran) + parents [(~(got by hit.ali-dom) let.ali-dom) parents] == == :: +done-fuse: restore state after a fuse is attempted, whether it @@ -2307,13 +2276,14 @@ ^+ ..merge ?~ riot (done %| %ali-unavailable ~[>[ali-ship ali-desk germ]<]) - =/ ali-dome=dome:clay !<(dome:clay q.r.u.riot) + =/ ali-dome=dome:clay + ?: &(?=(@ -.q.q.r.u.riot) !=(~ -.q.q.r.u.riot)) + !<(dome:clay q.r.u.riot) + +:!<([* dome:clay] q.r.u.riot) =/ result=(each (unit merge-result) (pair term tang)) - (merge-helper ali-ship ali-desk germ ali-dome ~) + (merge-helper ali-ship ali-desk germ ali-dome ~) ?- -.result - %| - (done %| +.result) - :: + %| (done %| +.result) %& =/ mr=(unit merge-result) +.result ?~ mr @@ -2322,36 +2292,40 @@ (park | new.u.mr ~ lat.u.mr) == :: - +$ merge-result [conflicts=(set path) new=yoki lat=(map lobe blob)] + +$ merge-result [conflicts=(set path) new=yoki lat=(map lobe page)] :: ++ merge-helper - |= [=ali=ship =ali=desk =germ ali-dome=dome:clay continuation-yaki=(unit yaki)] + |= [=ali=ship =ali=desk =germ ali-dome=dome:clay next-yaki=(unit yaki)] ^- (each (unit merge-result) [term tang]) |^ ^- (each (unit merge-result) [term tang]) =/ ali-yaki=yaki (~(got by hut.ran) (~(got by hit.ali-dome) let.ali-dome)) =/ bob-yaki=(unit yaki) - ?~ continuation-yaki + ?~ next-yaki ?~ let.dom ~ (~(get by hut.ran) (~(got by hit.dom) let.dom)) - continuation-yaki - (merge-by-germ ali-yaki bob-yaki) + next-yaki + =/ res (mule |.((merge-by-germ ali-yaki bob-yaki))) + ?- -.res + %& &+p.res + %| |+merge-failed+p.res + == :: ++ merge-by-germ |= [=ali=yaki bob-yaki=(unit yaki)] - ^- (each (unit merge-result) [term tang]) + ^- (unit merge-result) :: :: If this is an %init merge, we set the ali's commit to be :: bob's. :: ?: ?=(%init germ) ?> ?=(~ bob-yaki) - &+`[conflicts=~ new=|+ali-yaki lat=~] + `[conflicts=~ new=|+ali-yaki lat=~] :: =/ bob-yaki (need bob-yaki) |^ - ^- (each (unit merge-result) [term tang]) + ^- (unit merge-result) ?- germ :: :: If this is a %only-this merge, we check to see if ali's and bob's @@ -2361,8 +2335,8 @@ :: %only-this ?: =(r.ali-yaki r.bob-yaki) - &+~ - :* %& ~ + ~ + :* ~ conflicts=~ new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki q.bob-yaki)] lat=~ @@ -2375,8 +2349,8 @@ :: %only-that ?: =(r.ali-yaki r.bob-yaki) - &+~ - :* %& ~ + ~ + :* ~ conflicts=~ new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki q.ali-yaki)] lat=~ @@ -2388,9 +2362,9 @@ :: %take-this ?: =(r.ali-yaki r.bob-yaki) - &+~ + ~ =/ new-data (~(uni by q.ali-yaki) q.bob-yaki) - :* %& ~ + :* ~ conflicts=~ new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki new-data)] lat=~ @@ -2402,9 +2376,9 @@ :: %take-that ?: =(r.ali-yaki r.bob-yaki) - &+~ + ~ =/ new-data (~(uni by q.bob-yaki) q.ali-yaki) - :* %& ~ + :* ~ conflicts=~ new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki new-data)] lat=~ @@ -2420,27 +2394,27 @@ :: %fine ?: =(r.ali-yaki r.bob-yaki) - &+~ + ~ ?: (~(has in (reachable-takos:ze r.bob-yaki)) r.ali-yaki) - &+~ + ~ ?. (~(has in (reachable-takos:ze r.ali-yaki)) r.bob-yaki) - :~ %| %bad-fine-merge - leaf+"tried fast-forward but is not ancestor or descendant" - == - &+`[conflicts=~ new=|+ali-yaki lat=~] + ~_ %bad-fine-merge + ~| "tried fast-forward but is not ancestor or descendant" + !! + `[conflicts=~ new=|+ali-yaki lat=~] :: ?(%meet %mate %meld %meet-this %meet-that) ?: =(r.ali-yaki r.bob-yaki) - &+~ + ~ ?: (~(has in (reachable-takos:ze r.bob-yaki)) r.ali-yaki) - &+~ + ~ ?: (~(has in (reachable-takos:ze r.ali-yaki)) r.bob-yaki) $(germ %fine) =/ merge-points (find-merge-points ali-yaki bob-yaki) ?~ merge-points - :~ %| %merge-no-merge-base - leaf+"consider a %this or %that merge to get a mergebase" - == + ~_ %merge-no-merge-base + ~| "consider a %this or %that merge to get a mergebase" + !! =/ merge-point=yaki n.merge-points ?: ?=(?(%mate %meld) germ) =/ ali-diffs=cane (diff-base ali-yaki bob-yaki merge-point) @@ -2461,10 +2435,9 @@ %- ~(uni by `(map path *)`can.bob-diffs) `(map path *)`old.bob-diffs ?: &(?=(%meet germ) !=(~ both-diffs)) - :~ %| %meet-conflict - >~(key by both-diffs)< - leaf+"consider a %mate merge" - == + ~_ %meet-conflict + ~| [~(key by both-diffs) "consider a %mate merge"] + !! =/ both-done=(map path lobe) |^ ?- germ @@ -2498,7 +2471,7 @@ %- ~(uni by new.bob-diffs) %- ~(uni by cal.ali-diffs) cal.bob-diffs - :* %& ~ + :* ~ conflicts=~ new=&+[[r.bob-yaki r.ali-yaki ~] (to-yuki hat)] lat=~ @@ -2600,7 +2573,13 @@ ~ ?: =(u.in-yak u.in-yuk) ~ - `[path (diff-lobes lobe u.in-yak)] + =/ cug=(unit cage) (diff-lobes lobe u.in-yak) + ?~ cug + ~_ %tombstoned-mergebase + ~| path + ~| "consider a 2-way merge such as %only-this or %only-that" + !! + `[path u.cug] :: =/ old=(map path ~) %- malt ^- (list [path ~]) @@ -2616,33 +2595,35 @@ :: ++ lobe-to-cage |= =lobe - ^- cage - =^ =page fod.dom + ^- (unit cage) + =/ peg=(unit page) (~(get by lat.ran) lobe) + ?~ peg + ~ + =/ [=cage *] %- wrap:fusion - (lobe-to-page:(ford:fusion static-ford-args) lobe) - =^ =cage fod.dom - %- wrap:fusion - (page-to-cage:(ford:fusion static-ford-args) page) - cage + (page-to-cage:(aeon-ford let.dom) u.peg) + `cage :: ++ get-dais |= =mark ^- dais - =^ =dais fod.dom + =/ [=dais *] %- wrap:fusion - (build-dais:(ford:fusion static-ford-args) mark) + (build-dais:(aeon-ford let.dom) mark) dais :: :: Diff two files on bob-desk :: ++ diff-lobes |= [=a=lobe =b=lobe] - ^- cage + ^- (unit cage) =/ a-cage (lobe-to-cage a-lobe) =/ b-cage (lobe-to-cage b-lobe) - ?> =(p.a-cage p.b-cage) - =/ =dais (get-dais p.a-cage) - [form:dais (~(diff dais q.a-cage) q.b-cage)] + ?: |(?=(~ a-cage) ?=(~ b-cage)) + ~ + ?> =(p.u.a-cage p.u.b-cage) + =/ =dais (get-dais p.u.a-cage) + `[form:dais (~(diff dais q.u.a-cage) q.u.b-cage)] :: :: Merge diffs that are on the same file. :: @@ -2679,7 +2660,7 @@ dob=cane bof=(map path (unit cage)) == - ^- (each (unit merge-result) [term tang]) + ^- (unit merge-result) =/ both-patched=(map path cage) %- malt %+ murn ~(tap by bof) @@ -2692,7 +2673,9 @@ ?~ - ~| %mate-strange-diff-no-base !! - =/ =cage (lobe-to-cage u.-) + :: +need ok because we would have crashed in +diff-base + :: + =/ =cage ~|([%build-need path] (need (lobe-to-cage u.-))) =/ =dais (get-dais p.cage) ?> =(p.u.cay form.dais) :- p.cage @@ -2731,20 +2714,23 @@ =((~(got by new.dal) pax) (~(got by new.dob) pax)) ?: &(?=(%mate germ) ?=(^ con)) =+ (turn ~(tap by `(map path *)`con) |=([path *] >[+<-]<)) - [%| %mate-conflict -] + ~_ %mate-conflict + ~| (turn ~(tap by `(map path *)`con) |=([path *] +<-)) + !! =/ old=(map path lobe) :: oldies but goodies %+ roll ~(tap by (~(uni by old.dal) old.dob)) =< .(old q.bob) |= [[pax=path ~] old=(map path lobe)] (~(del by old) pax) - =/ [hot=(map path lobe) lat=(map lobe blob)] :: new content + =/ [hot=(map path lobe) lat=(map lobe page)] :: new content %+ roll ~(tap by both-patched) - |= [[pax=path cay=cage] hat=(map path lobe) lat=(map lobe blob)] - =/ =blob [%direct (page-to-lobe [p q.q]:cay) [p q.q]:cay] - :- (~(put by hat) pax p.blob) - ?: (~(has by lat) p.blob) + |= [[pax=path cay=cage] hat=(map path lobe) lat=(map lobe page)] + =/ =page [p q.q]:cay + =/ =lobe (page-to-lobe page) + :- (~(put by hat) pax lobe) + ?: (~(has by lat) lobe) lat - (~(put by lat) p.blob blob) + (~(uni by (malt [lobe page] ~)) lat) =/ hat=(map path lobe) :: all the content %- ~(uni by old) %- ~(uni by new.dal) @@ -2754,9 +2740,9 @@ %- ~(uni by hot) cab =/ del=(map path ?) - (~(run by (~(uni by old.dal) old.dob)) |=(~ %|)) + (~(run by (~(uni by old.dal) old.dob)) |=(~ %|)) =/ new &+[[r.bob r.ali ~] (~(run by hat) |=(=lobe |+lobe))] - :* %& ~ + :* ~ (silt (turn ~(tap by con) head)) new lat @@ -2825,6 +2811,12 @@ takos (~(gas to takos) new-candidates) == :: + ++ want-mime + |= yon=aeon + %- ~(any by mon) + |= =beam + &(=(p.beam her) =(q.beam syd) =(r.beam ud+yon)) + :: :: Update mime cache :: ++ checkout-mime @@ -2832,7 +2824,7 @@ deletes=(set path) changes=(set path) == - ^- [(map path (unit mime)) ford-cache] + ^- [(map path (unit mime)) args:ford:fusion] =/ mim=(map path (unit mime)) =/ dels=(list path) ~(tap by deletes) |- ^- (map path (unit mime)) @@ -2840,14 +2832,17 @@ ~ (~(put by $(dels t.dels)) i.dels ~) =/ cans=(list path) ~(tap by changes) - |- ^- [(map path (unit mime)) ford-cache] + |- ^- [(map path (unit mime)) args:ford:fusion] ?~ cans - [mim ford-cache.ford-args] - =^ cage ford-cache.ford-args + [mim ford-args] + =/ [=cage fud=flow fod=flue] ~| mime-cast-fail+i.cans (wrap:fusion (cast-path:(ford:fusion ford-args) i.cans %mime)) - =^ mim ford-cache.ford-args $(cans t.cans) - [(~(put by mim) i.cans `!<(mime q.cage)) ford-cache.ford-args] + =. cache.ford-args fud + =. spill.ford-args spill.fod + =. sprig.ford-args sprig.fod + =^ mim ford-args $(cans t.cans) + [(~(put by mim) i.cans `!<(mime q.cage)) ford-args] :: :: Add or remove entries to the mime cache :: @@ -2866,9 +2861,9 @@ :: Emit update to unix sync :: ++ ergo - |= mim=(map path (unit mime)) + |= [yon=aeon mim=(map path (unit mime))] ^+ ..park - =/ must (must-ergo her syd mon (turn ~(tap by mim) head)) + =/ must (must-ergo yon mon (turn ~(tap by mim) head)) %- emil %+ turn ~(tap by must) |= [pot=term len=@ud pak=(set path)] @@ -2881,7 +2876,7 @@ :: Output is a map of mount points to {length-of-mounted-path set-of-paths}. :: ++ must-ergo - |= [our=ship syd=desk mon=(map term beam) can=(list path)] + |= [yon=aeon mon=(map term beam) can=(list path)] ^- (map term (pair @ud (set path))) %- malt ^- (list (trel term @ud (set path))) %+ murn ~(tap by mon) @@ -2890,7 +2885,7 @@ =- ?~(- ~ `[nam (lent s.bem) (silt `(list path)`-)]) %+ skim can |= pax=path - &(=(p.bem our) =(q.bem syd) =(s.bem (scag (lent s.bem) pax))) + &(=(p.bem her) =(q.bem syd) =(r.bem ud+yon) =(s.bem (scag (lent s.bem) pax))) :: :: Mount a beam to unix :: @@ -2901,15 +2896,31 @@ ?^ old-mon %- (slog >%already-mounted< >u.old-mon< ~) ..mount - =. mon (~(put by mon) pot [her syd case] spur) - =/ =yaki (~(got by hut.ran) (~(got by hit.dom) let.dom)) - =/ changes (~(run by q.yaki) |=(=lobe |+lobe)) - =/ =args:ford:fusion [ank.dom ~ changes lat.ran fod.dom] - =^ mim ford-cache.args - (checkout-mime args ~ ~(key by changes)) + =/ yon (case-to-aeon case) + ?~ yon + %- (slog >%unknown-case< >[her syd case spur]< ~) + ..mount + =/ for-yon ?:(=(let.dom u.yon) 0 u.yon) + =. mon + (~(put by mon) pot [her syd ud+for-yon] spur) + =/ =yaki (~(got by hut.ran) (~(got by hit.dom) u.yon)) + =/ files (~(run by q.yaki) |=(=lobe |+lobe)) + =/ =args:ford:fusion + [files lat.ran veb.bug fad ?:(=(yon let.dom) fod.dom [~ ~])] + =^ mim args + (checkout-mime args ~ ~(key by files)) =. mim.dom (apply-changes-to-mim mim.dom mim) - =. fod.dom ford-cache.args - (ergo mim) + (ergo for-yon mim) + :: + :: Unmount a beam + :: + ++ unmount + |= [pot=term =case =spur] + ^+ ..unmount + ?> ?=(^ hez.ruf) + =. mon (~(del by mon) pot) + =? mim.dom !(want-mime 0) ~ + (emit u.hez.ruf %give %ogre pot) :: :: Set permissions for a node. :: @@ -2980,23 +2991,23 @@ :_ (~(run by qyx) |=(a=(set duct) (~(del in a) hen))) %- ~(rep by qyx) |= [[a=wove b=(set duct)] c=(list wove)] - ?.((~(has in b) hen) c [a c]) + ?:((~(has in b) hen) [a c] c) :: ?~ ref - => .(ref `(unit rind)`ref) :: XX TMI - ?: =(~ wos) ..cancel-request :: XX handle? + => .(ref `(unit rind)`ref) + ?: =(~ wos) ..cancel-request :: TODO handle? |- ^+ ..cancel-request ?~ wos ..cancel-request =. ..cancel-request (run-if-future rove.i.wos |=(@da (best hen +<))) $(wos t.wos) :: ?~ nux=(~(get by fod.u.ref) hen) - ..cancel-request(ref `(unit rind)`ref) :: XX TMI + ..cancel-request(ref `(unit rind)`ref) =: fod.u.ref (~(del by fod.u.ref) hen) bom.u.ref (~(del by bom.u.ref) u.nux) == %. [hen her u.nux [syd ~]] - send-over-ames(ref `(unit rind)`ref) :: XX TMI + send-over-ames(ref `(unit rind)`ref) :: :: Handles a request. :: @@ -3012,9 +3023,9 @@ ?: &(?=(^ for) !(foreign-capable rav)) ~& [%bad-foreign-request-care from=for rav] ..start-request - =^ [new-sub=(unit rove) sub-results=(list sub-result)] fod.dom + =^ [new-sub=(unit rove) cards=(list card)] ..start-request (try-fill-sub for (rave-to-rove rav)) - =. ..start-request (send-sub-results sub-results [hen ~ ~]) + =. ..start-request (send-cards cards [hen ~ ~]) ?~ new-sub ..start-request (duce for u.new-sub) @@ -3106,10 +3117,11 @@ %- mule |. %- wrap:fusion :: Use %base's marks to validate, so we don't have to build the - :: foreign hoon/zuse + :: foreign marks :: - =/ args %*(static-ford-args . dom dom:(~(got by dos.rom) %base)) - (page-to-cage:(ford:fusion args) peg) + =/ base-dome dom:(~(got by dos.rom) %base) + =/ f (%*(. aeon-ford dom base-dome) let.base-dome) + (page-to-cage:f peg) ?: ?=(%| -.vale-result) %- (slog >%validate-x-failed< p.vale-result) ~ @@ -3127,14 +3139,20 @@ :: :: Respond to backfill request :: - :: Maybe should verify the requester is allowed to access this blob? + :: Maybe should verify the requester is allowed to access this lobe? :: ++ give-backfill - |= =lobe + |= [ver=?(%0 %1) =lobe] ^+ ..give-backfill - (emit hen %give %boon (~(got by lat.ran) lobe)) + =/ peg=(unit page) (~(get by lat.ran) lobe) + =/ res + ?- ver + %0 ?~(peg [%1 ~] [%direct lobe u.peg]) + %1 [%1 peg] + == + (emit hen %give %boon res) :: - :: Ingest foreign update, requesting missing blobs if necessary + :: Ingest foreign update, requesting missing lobes if necessary :: ++ foreign-update |= inx=@ud @@ -3169,88 +3187,91 @@ work ?> ?=(%nako p.r.u.rut) =/ nako ;;(nako q.r.u.rut) - =/ missing (missing-blobs nako) - =. need.sat `(list lobe)`(welp need.sat ~(tap in missing)) + =/ missing (missing-lobes nako) + :: must be appended because we delete off front + :: + =. need.sat (welp need.sat ~(tap in missing)) =. nako.sat (~(put to nako.sat) ~ nako) work :: - ++ missing-blobs + ++ missing-lobes |= =nako ^- (set lobe) + =| missing=(set lobe) + =/ let-tako (~(got by gar.nako) let.nako) =/ yakis ~(tap in lar.nako) |- ^- (set lobe) =* yaki-loop $ ?~ yakis - ~ + missing + =/ =norm + :: Always try to fetch the entire last commit, because often we + :: want to merge from it. + :: + ?: =(let-tako r.i.yakis) + *norm:clay + (~(gut by tom.dom) r.i.yakis nor.dom) =/ lobes=(list [=path =lobe]) ~(tap by q.i.yakis) |- ^- (set lobe) - =* blob-loop $ + =* lobe-loop $ ?~ lobes yaki-loop(yakis t.yakis) - ?: (~(has by lat.ran) lobe.i.lobes) - blob-loop(lobes t.lobes) - (~(put in blob-loop(lobes t.lobes)) lobe.i.lobes) + =? missing + ?& !(~(has by lat.ran) lobe.i.lobes) + !=([~ %|] +:(~(fit of norm) path.i.lobes)) + == + (~(put in missing) lobe.i.lobes) + lobe-loop(lobes t.lobes) :: :: Receive backfill response :: ++ take-backfill - |= =blob + |= =fell ^+ ..abet ?: lost ..abet - =? need.sat - ?& ?=(%delta -.blob) - !(~(has by lat.ran) q.q.blob) - !(~(has by have.sat) q.q.blob) - == - [q.q.blob need.sat] - :: We can't put a blob in lat.ran if its parent isn't already - :: there. Unions are in reverse order so we don't overwrite - :: existing blobs. - :: - =. ..abet - ?: &(?=(%delta -.blob) !(~(has by lat.ran) q.q.blob)) - ..abet(have.sat (~(uni by (malt [p.blob `^blob`blob] ~)) have.sat)) - ..abet(lat.ran (~(uni by (malt [p.blob blob] ~)) lat.ran)) + =? need.sat ?=(^ need.sat) t.need.sat + =. ..park =>((take-fell fell) ?>(?=(^ ref) .)) work(busy.sat |) :: - :: Fetch next blob + :: Fetch next lobe :: ++ work ^+ ..abet ?: busy.sat ..abet |- ^+ ..abet - ?: =(~ need.sat) - :: NB: if you change to release nakos as we get enough blobs + ?~ need.sat + :: NB: if you change to release nakos as we get enough lobes :: for them instead of all at the end, you *must* store the :: `lim` that should be applied after the nako is complete and :: not use the one in the rave, since that will apply to the :: end of subscription. :: - =. lat.ran (~(uni by have.sat) lat.ran) |- ^+ ..abet ?: =(~ nako.sat) ..abet =^ next=(unit nako) nako.sat ~(get to nako.sat) ?~ next ..abet(done &) - =. ..abet (apply-foreign-update u.next) + =. ..abet =>((apply-foreign-update u.next) ?>(?=(~ need.sat) .)) =. ..foreign-update =<(?>(?=(^ ref) .) wake) $ - ?> ?=(^ need.sat) - :: This is what removes an item from `need`. This happens every - :: time we take a backfill response, but it could happen more than - :: once if we somehow got this data in the meantime (maybe from - :: another desk updating concurrently, or a previous update on this - :: same desk). + :: This used to be what always removed an item from `need`. Now, + :: we remove in +take-backfill, but in the meantime we could have + :: received the next data from elsewhere (such as another desk + :: updating). Additionally, this is needed for backward + :: compatibility with old /backfill wires. :: - ?: ?| (~(has by lat.ran) i.need.sat) - (~(has by have.sat) i.need.sat) - == + ?: (~(has by lat.ran) i.need.sat) $(need.sat t.need.sat) - :: Otherwise, fetch the next blob + (fetch i.need.sat) + :: + ++ fetch + |= =lobe + ^+ ..abet + :: TODO: upgrade to %1 when most ships have upgaded :: - =/ =fill [%0 syd i.need.sat] + =/ =fill [%0 syd lobe] =/ =wire /back-index/(scot %p her)/[syd]/(scot %ud inx) =/ =path [%backfill syd (scot %ud inx) ~] =. ..foreign-update @@ -3260,9 +3281,9 @@ :: :: When we get a %w foreign update, store this in our state. :: - :: We get the commits and blobs from the nako and add them to our - :: object store, then we update the map of aeons to commits and the - :: latest aeon. + :: We get the commits from the nako and add them to our object + :: store, then we update the map of aeons to commits and the latest + :: aeon. :: ++ apply-foreign-update |= =nako @@ -3270,18 +3291,14 @@ :: hit: updated commit-hashes by @ud case :: nut: new commit-hash/commit pairs :: hut: updated commits by hash - :: nat: new blob-hash/blob pairs - :: lat: updated blobs by hash :: =/ hit (~(uni by hit.dom) gar.nako) =/ nut (turn ~(tap in lar.nako) |=(=yaki [r.yaki yaki])) =/ hut (~(uni by (malt nut)) hut.ran) - =/ nat (turn ~(tap in bar.nako) |=(=blob [p.blob blob])) - =/ lat (~(uni by (malt nat)) lat.ran) :: traverse updated state and sanity check :: =+ ~| :* %bad-foreign-update - [gar=gar.nako let=let.nako nut=(turn nut head) nat=(turn nat head)] + [gar=gar.nako let=let.nako nut=(turn nut head)] [hitdom=hit.dom letdom=let.dom] == ?: =(0 let.nako) @@ -3292,12 +3309,6 @@ ~| [%missing-aeon aeon] (~(got by hit) aeon) =/ =yaki ~| [%missing-tako tako] (~(got by hut) tako) - =+ %+ turn - ~(tap by q.yaki) - |= [=path =lobe] - ~| [%missing-blob path lobe] - ?> (~(has by lat) lobe) - ~ ?: =(let.nako aeon) ~ $(aeon +(aeon)) @@ -3308,7 +3319,6 @@ =: let.dom (max let.nako let.dom) hit.dom hit hut.ran hut - lat.ran lat :: Is this correct? Seeems like it should only go to `to` if :: we've gotten all the way to the end. Leaving this :: behavior unchanged for now, but I believe it's wrong. @@ -3318,97 +3328,102 @@ ..abet -- :: + ++ seek + |= =cash + ^+ ..park + ?> ?=(^ ref) + =/ =tako + ?: ?=(%tako -.cash) + p.cash + (aeon-to-tako:ze (need (case-to-aeon cash))) + =/ =yaki (tako-to-yaki:ze tako) + =/ lobes=(list lobe) + %+ murn ~(tap by q.yaki) + |= [=path =lobe] + ?: (~(has by lat.ran) lobe) + ~ + `lobe + %- emil + %+ turn lobes + |= =lobe + :: TODO: upgrade to %1 when most ships have upgaded + :: + =/ =fill [%0 syd lobe] + =/ =wire /seek/(scot %p her)/[syd] + =/ =path [%backfill syd ~] + [hen %pass wire %a %plea her %c path fill] + :: + ++ take-fell + |= =fell + ^+ ..park + ?> ?=(^ ref) + =/ peg=(unit page) (fell-to-page fell) + =? lat.ran ?=(^ peg) + (~(uni by (malt [(page-to-lobe u.peg) u.peg] ~)) lat.ran) + ..park + :: :: fire function if request is in future :: ++ run-if-future |= [rov=rove fun=$-(@da _.)] ^+ +>.$ - %+ fall - %+ bind - ^- (unit @da) - ?- -.rov - %sing - ?. ?=(%da -.case.mood.rov) ~ - `p.case.mood.rov - :: - %next ~ - %mult ~ - %many - %^ hunt lth - ?. ?=(%da -.from.moat.rov) ~ - ?. (lth now p.from.moat.rov) ~ - [~ p.from.moat.rov] - ?. ?=(%da -.to.moat.rov) ~ - `(max now p.to.moat.rov) - == - fun - +>.$ - :: - ++ rave-to-rove - |= rav=rave - ^- rove - ?- -.rav - %sing rav - %next [- mood ~ ~]:rav - %mult [- mool ~ ~ ~]:rav - %many [- track moat ~]:rav - == - :: - ++ rove-to-rave - |= rov=rove - ^- rave - ?- -.rov - %sing rov - %next [- mood]:rov - %mult [- mool]:rov - %many [- track moat]:rov - == - :: - ++ send-sub-results - |= [sub-results=(list sub-result) ducts=(set duct)] - ^+ ..wake - ?~ sub-results - ..wake - =. ..wake - ?- -.i.sub-results - %blab (blab-all ducts +.i.sub-results) - %bleb (bleb-all ducts +.i.sub-results) - %balk (balk-all ducts +.i.sub-results) - %blas (blas-all ducts +.i.sub-results) - %blub (blub-all ducts +.i.sub-results) + =/ date=(unit @da) + ?- -.rov + %sing + ?. ?=(%da -.case.mood.rov) ~ + `p.case.mood.rov + :: + %next ~ + %mult ~ + %many + %^ hunt lth + ?. ?=(%da -.from.moat.rov) ~ + ?. (lth now p.from.moat.rov) ~ + [~ p.from.moat.rov] + ?. ?=(%da -.to.moat.rov) ~ + `(max now p.to.moat.rov) == - $(sub-results t.sub-results) + ?~ date + +>.$ + (fun u.date) + :: + ++ send-cards + |= [cards=(list card) ducts=(set duct)] + ^+ ..wake + %- emil + %- zing + %+ turn cards + |= =card + %+ turn ~(tap by ducts) + |= =duct + [duct card] :: :: Loop through open subscriptions and check if we can fill any of :: them. :: ++ wake ^+ . - =/ old-subs=(list [=wove ducts=(set duct)]) ~(tap by qyx) - =| new-subs=(list [=wove ducts=(set duct)]) + =/ subs=(list [=wove ducts=(set duct)]) ~(tap by qyx) + =| qux=cult |- ^+ ..wake - ?~ old-subs - :: install new subs - :: - ..wake(qyx (~(gas by *cult) new-subs)) - ?: =(~ ducts.i.old-subs) - :: drop forgotten roves - :: - $(old-subs t.old-subs) - =^ [new-sub=(unit rove) sub-results=(list sub-result)] fod.dom - (try-fill-sub wove.i.old-subs) - =. ..wake (send-sub-results sub-results ducts.i.old-subs) - =. new-subs - ?~ new-sub - new-subs - [[[for.wove.i.old-subs u.new-sub] ducts.i.old-subs] new-subs] - $(old-subs t.old-subs) + ?~ subs + ..wake(qyx qux) + ?: =(~ ducts.i.subs) + $(subs t.subs) + =^ [new-sub=(unit rove) cards=(list card)] ..park + (try-fill-sub wove.i.subs) + =. ..wake (send-cards cards ducts.i.subs) + =? qux ?=(^ new-sub) + =/ =wove [for.wove.i.subs u.new-sub] + %+ ~(put by qux) wove + (~(uni in ducts.i.subs) (~(get ju qux) wove)) + $(subs t.subs) :: :: Try to fill a subscription :: ++ try-fill-sub |= [far=(unit [=ship ver=@ud]) rov=rove] - ^- [[new-sub=(unit rove) (list sub-result)] ford-cache] + ^- [[(unit rove) (list card)] _..park] =/ for=(unit ship) ?~(far ~ `ship.u.far) ?- -.rov %sing @@ -3417,32 +3432,32 @@ ?^ cache-value :: if we have a result in our cache, produce it :: - :_ fod.dom - :- ~ - ?~ u.cache-value - [%blub ~]~ - [%blab mood.rov %& u.u.cache-value]~ + :_ ..park :- ~ :_ ~ + (writ ?~(u.cache-value ~ `[mood.rov u.u.cache-value])) :: else, check to see if rove is for an aeon we know :: =/ aeon=(unit aeon) (case-to-aeon case.mood.rov) ?~ aeon - [[`rov ~] fod.dom] + [[`rov ~] ..park] :: we have the appropriate aeon, so read in the data :: - =^ value=(unit (unit (each cage lobe))) fod.dom + =^ value=(unit (unit cage)) ..park (read-at-aeon:ze for u.aeon mood.rov) ?~ value - :: We don't have the data directly, which is potentially - :: problematical. How can we fetch the data? + :: we don't have the data directly. how can we fetch it? :: ?: =(0 u.aeon) ~& [%clay-sing-indirect-data-0 `path`[syd '0' path.mood.rov]] - [[~ ~] fod.dom] + [[~ ~] ..park] ~& [%clay-sing-indirect-data desk=syd mood=mood.rov aeon=u.aeon] - [[`rov ~] fod.dom] - :: we have the data, so we produce the results + [[`rov ~] ..park] + :: we have the data, so produce the results :: - [[~ [%balk u.value mood.rov]~] fod.dom] + :_ ..park :- ~ :_ ~ + %- writ + ?~ u.value + ~ + `[mood.rov u.u.value] :: :: %next is just %mult with one path, so we pretend %next = %mult here. :: @@ -3464,89 +3479,81 @@ ~ == ?> ?=(%mult -.rov) - :: we will either respond or store the maybe updated request. - :: - =; [res=(each (map mood (unit (each cage lobe))) rove) fod=ford-cache] - :_ fod - ?: ?=(%& -.res) - (respond p.res) - (store p.res) :: recurse here on next aeon if possible/needed. :: - |- ^- [(each (map mood (unit (each cage lobe))) rove) ford-cache] + |- :: if we don't have an aeon yet, see if we have one now. :: ?~ aeon.rov =/ aeon=(unit aeon) (case-to-aeon case.mool.rov) :: if we still don't, wait. :: - ?~ aeon [|+rov fod.dom] + ?~ aeon [(store rov) ..park] :: if we do, update the request and retry. :: $(aeon.rov `+(u.aeon), old-cach.rov ~, new-cach.rov ~) :: if old isn't complete, try filling in the gaps. :: - =^ o fod.dom + =^ o ..park ?: (complete old-cach.rov) - [old-cach.rov fod.dom] + [old-cach.rov ..park] (read-unknown mool.rov(case [%ud (dec u.aeon.rov)]) old-cach.rov) =. old-cach.rov o :: if the next aeon we want to compare is in the future, wait again. :: =/ next-aeon=(unit aeon) (case-to-aeon [%ud u.aeon.rov]) - ?~ next-aeon [|+rov fod.dom] + ?~ next-aeon [(store rov) ..park] :: if new isn't complete, try filling in the gaps. :: - =^ n fod.dom + =^ n ..park ?: (complete new-cach.rov) - [new-cach.rov fod.dom] + [new-cach.rov ..park] (read-unknown mool.rov(case [%ud u.aeon.rov]) new-cach.rov) =. new-cach.rov n - ?: ?& !(complete old-cach.rov) - (complete new-cach.rov) - == - :_ fod.dom :- %& + :: if new still isn't complete, wait again. + :: + ?. (complete new-cach.rov) + [(store rov) ..park] + :: if old not complete, give a result (possible false positive). + :: + ?: !(complete old-cach.rov) + :_ ..park + %- respond %- malt %+ murn ~(tap in paths.mool.rov) |= [=care =path] - ^- (unit [mood (unit (each cage lobe))]) + ^- (unit [mood (unit cage)]) =/ cached (~(get by new-cach.rov) [care path]) ?. ?=([~ ~ *] cached) %- (slog 'clay: strange new-cache' >[care path cached]< ~) ~ `u=[[care [%ud let.dom] path] u.u.cached] - :: if they're still not both complete, wait again. - :: - ?. ?& (complete old-cach.rov) - (complete new-cach.rov) - == - [|+rov fod.dom] :: both complete, so check if anything has changed :: - =/ changes=(map mood (unit (each cage lobe))) + =/ changes=(map mood (unit cage)) %+ roll ~(tap by old-cach.rov) - |= $: [[car=care pax=path] old-cach-value=cach] - changes=(map mood (unit (each cage lobe))) + |= $: [[car=care pax=path] old-cach=cach] + changes=(map mood (unit cage)) == - =/ new-cach-value=cach (~(got by new-cach.rov) car pax) - ?< |(?=(~ old-cach-value) ?=(~ new-cach-value)) - =/ new-entry=(unit (pair mood (unit (each cage lobe)))) + =/ new-cach=cach (~(got by new-cach.rov) car pax) + ?< |(?=(~ old-cach) ?=(~ new-cach)) + =/ new-entry=(unit (pair mood (unit cage))) =/ =mood [car [%ud u.aeon.rov] pax] - ?~ u.new-cach-value + ?~ u.new-cach :: if new does not exist, always notify :: `[mood ~] - ?~ u.old-cach-value + ?~ u.old-cach :: added :: - `[mood `u.u.new-cach-value] - ?: (equivalent-data:ze u.u.new-cach-value u.u.old-cach-value) + `[mood `u.u.new-cach] + ?: =([p q.q]:u.u.new-cach [p q.q]:u.u.old-cach) :: unchanged :: ~ :: changed :: - `[mood `u.u.new-cach-value] + `[mood `u.u.new-cach] :: if changed, save the change :: ?~ new-entry @@ -3555,14 +3562,14 @@ :: if there are any changes, send response. if none, move on to :: next aeon. :: - ?^ changes [&+changes fod.dom] + ?^ changes [(respond changes) ..park] $(u.aeon.rov +(u.aeon.rov), new-cach.rov ~) :: :: check again later :: ++ store |= rov=rove - ^- [new-sub=(unit rove) (list sub-result)] + ^- [(unit rove) (list card)] =/ new-rove=rove ?> ?=(%mult -.rov) ?: ?=(%mult -.vor) rov @@ -3574,22 +3581,34 @@ :: send changes :: ++ respond - |= res=(map mood (unit (each cage lobe))) - ^- [new-sub=(unit rove) (list sub-result)] + |= res=(map mood (unit cage)) + ^- [(unit rove) (list card)] :- ~ ?: ?=(%mult -.vor) - [%blas ~(key by res)]~ + :_ ~ + =/ moods ~(key by res) + =/ cas + ?> ?=(^ moods) + [%da (case-to-date case.n.moods)] + =/ res + (~(run in moods) |=(m=mood [care.m path.m])) + =/ gift [%wris cas res] + ?: ?=(^ ref) + [%slip %b %drip !>(gift)] + [%give gift] ?> ?=([* ~ ~] res) + :_ ~ + %- writ ?~ q.n.res - [%blub ~]~ - [%blab [p u.q]:n.res]~ + ~ + `[p u.q]:n.res :: :: no unknowns :: ++ complete |= hav=(map (pair care path) cach) - ?& ?=(^ hav) - (levy ~(tap by `(map (pair care path) cach)`hav) know) + ?& !=(~ hav) + (levy ~(tap by hav) know) == :: :: know about file in cach @@ -3600,7 +3619,7 @@ :: ++ read-unknown |= [=mool hav=(map (pair care path) cach)] - ^- [_hav ford-cache] + ^- [_hav _..park] =? hav ?=(~ hav) %- malt ^- (list (pair (pair care path) cach)) %+ turn @@ -3608,63 +3627,47 @@ |= [c=care p=path] ^- [[care path] cach] [[c p] ~] - |- ^+ [hav fod.dom] - ?~ hav [hav fod.dom] - =^ lef fod.dom $(hav l.hav) + |- ^+ [hav ..park] + ?~ hav [hav ..park] + =^ lef ..park $(hav l.hav) =. l.hav lef - =^ rig fod.dom $(hav r.hav) + =^ rig ..park $(hav r.hav) =. r.hav rig =/ [[=care =path] =cach] n.hav ?^ cach - [hav fod.dom] - =^ q fod.dom (aver for care case.mool path) + [hav ..park] + =^ q ..park (aver for care case.mool path) =. q.n.hav q - [hav fod.dom] + [hav ..park] -- :: %many - :_ fod.dom + :_ ..park =/ from-aeon (case-to-aeon from.moat.rov) ?~ from-aeon :: haven't entered the relevant range, so do nothing :: [`rov ~] =/ to-aeon (case-to-aeon to.moat.rov) + :: TODO: shouldn't skip if tracking + :: + =/ up-to ?~(to-aeon let.dom u.to-aeon) =/ ver ?~(far %1 ver.u.far) + =. from.moat.rov [%ud +(let.dom)] + =/ =card + =/ =cage + ?: track.rov + [%null [%atom %n ~] ~] + [%nako !>((make-nako:ze ver u.from-aeon up-to))] + (writ ~ [%w ud+let.dom /] cage) ?~ to-aeon :: we're in the middle of the range, so produce what we can, :: but don't end the subscription :: - :: update "from" case to the aeon after now - :: - =. from.moat.rov - [%ud +(let.dom)] - :- `rov - =/ new-lobes=(map path lobe) - (lobes-at-path:ze for let.dom path.moat.rov) - ?: =(lobes.rov new-lobes) - :: if no changes, don't produce results - :: - ~ - :: else changes, so produce them - :: - [%bleb ver let.dom ?:(track.rov ~ `[u.from-aeon let.dom])]~ + [`rov card ~] :: we're past the end of the range, so end subscription :: - :- ~ - =/ new-lobes=(map path lobe) - (lobes-at-path:ze for u.to-aeon path.moat.rov) - :: if changed, give subscription result - :: - =/ bleb=(list sub-result) - ?: =(lobes.rov new-lobes) - ~ - [%bleb ver +(u.from-aeon) ?:(track.rov ~ `[u.from-aeon u.to-aeon])]~ - :: end subscription - :: - =/ blub=(list sub-result) - [%blub ~]~ - (weld bleb blub) + [~ [card (writ ~) ~]] == :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -3685,10 +3688,6 @@ :: :: The dome is composed of the following: :: - :: -- `ank` is the ankh, which is the file data itself. An ankh is both - :: a possible file and a possible directory. An ankh has both: - :: -- `fil`, a possible file, stored as both a cage and its hash - :: -- `dir`, a map of @ta to more ankhs. :: -- `let` is the number of the most recent revision. :: -- `hit` is a map of revision numbers to commit hashes. :: -- `lab` is a map of labels to revision numbers. @@ -3700,56 +3699,12 @@ :: ++ ze |% - :: These convert between aeon (version number), tako (commit hash), yaki - :: (commit data structure), lobe (content hash), and blob (content). - :: - :: XX the following are duplicated from the +state core + :: These convert between aeon (version number), tako (commit hash), + :: and yaki (commit data structure) :: ++ aeon-to-tako ~(got by hit.dom) ++ aeon-to-yaki |=(=aeon (tako-to-yaki (aeon-to-tako aeon))) - ++ lobe-to-blob ~(got by lat.ran) ++ tako-to-yaki ~(got by hut.ran) - ++ lobe-to-mark - |= a=lobe - => (lobe-to-blob a) - ?- - - %delta p.q - %direct p.q - == - :: - :: Checks whether two pieces of data (either cages or lobes) are the same. - :: - ++ equivalent-data - |= [one=(each cage lobe) two=(each cage lobe)] - ^- ? - ?: ?=(%& -.one) - ?: ?=(%& -.two) - =([p q.q]:p.one [p q.q]:p.two) - =(p.two (page-to-lobe [p q.q]:p.one)) - ?: ?=(%& -.two) - =(p.one (page-to-lobe [p q.q]:p.two)) - =(p.one p.two) - :: - :: Gets a map of the data at the given path and all children of it. - :: - ++ lobes-at-path - |= [for=(unit ship) yon=aeon pax=path] - ^- (map path lobe) - ?: =(0 yon) ~ - :: we use %z for the check because it looks at all child paths. - ?. |(?=(~ for) (may-read u.for %z yon pax)) ~ - %- malt - %+ skim - %~ tap by - =< q - %- aeon-to-yaki - yon - |= [p=path q=lobe] - ?| ?=(~ pax) - ?& !?=(~ p) - =(-.pax -.p) - $(p +.p, pax +.pax) - == == :: :: Creates a nako of all the changes between a and b. :: @@ -3801,120 +3756,76 @@ =. s ^$(p i.p.y) $(p.y t.p.y) :: - :: Get all the lobes that are referenced in `a` except those that are - :: already in `b`. - :: - ++ new-lobes :: object hash set - |= [b=(set lobe) a=(set tako)] :: that aren't in b - ^- (set lobe) - %+ roll ~(tap in a) - |= [tak=tako bar=(set lobe)] - ^- (set lobe) - =+ yak=(tako-to-yaki tak) - %+ roll ~(tap by q.yak) - =< .(far bar) - |= [[path lob=lobe] far=(set lobe)] - ^- (set lobe) - ?~ (~(has in b) lob) :: don't need - far - =+ gar=(lobe-to-blob lob) - ?- -.gar - %direct (~(put in far) lob) - %delta (~(put in $(lob q.q.gar)) lob) - == - :: - :: Probably can get rid of the cache checks because they happen in - :: ford - :: ++ read-a !. |= [=aeon =path] - ^- [(unit (unit (each cage lobe))) ford-cache] - ?. =(aeon let.dom) - ~> %slog.0^leaf/"clay: %a unknown aeon {<[syd aeon path]>}" - [~ fod.dom] - =/ cached=(unit [=vase *]) (~(get by files.fod.dom) path) - ?^ cached - :_(fod.dom [~ ~ %& %vase !>(vase.u.cached)]) - =/ x (read-x aeon path) - ?~ x - ~> %slog.0^leaf/"clay: %a can't read file at path {<[syd aeon path]>}" - [~ fod.dom] - ?~ u.x - ~> %slog.0^leaf/"clay: %a no file at path {<[syd aeon path]>}" - [[~ ~] fod.dom] - :: should never happen at current aeon - ?: ?=(%| -.u.u.x) - [~ fod.dom] - =^ =vase fod.dom + ^- [(unit (unit cage)) _..park] + =^ =vase ..park ~_ leaf/"clay: %a build failed {<[syd aeon path]>}" + %+ aeon-flow aeon %- wrap:fusion - (build-file:(ford:fusion static-ford-args) path) - :_(fod.dom [~ ~ %& %vase !>(vase)]) + (build-file:(aeon-ford aeon) path) + :_(..park [~ ~ %vase !>(vase)]) :: ++ read-b !. |= [=aeon =path] - ^- [(unit (unit (each cage lobe))) ford-cache] - ?. =(aeon let.dom) - [~ fod.dom] + ^- [(unit (unit cage)) _..park] ?. ?=([@ ~] path) - [[~ ~] fod.dom] - =/ cached=(unit [=dais *]) (~(get by marks.fod.dom) i.path) - ?^ cached - :_(fod.dom [~ ~ %& %dais !>(dais.u.cached)]) - =^ =dais fod.dom + [[~ ~] ..park] + =^ =dais ..park + %+ aeon-flow aeon %- wrap:fusion - (build-dais:(ford:fusion static-ford-args) i.path) - :_(fod.dom [~ ~ %& %dais !>(dais)]) + (build-dais:(aeon-ford aeon) i.path) + :_(..park [~ ~ %dais !>(dais)]) :: ++ read-c !. |= [=aeon =path] - ^- [(unit (unit (each cage lobe))) ford-cache] - ?. =(aeon let.dom) - [~ fod.dom] + ^- [(unit (unit cage)) _..park] ?. ?=([@ @ ~] path) - [[~ ~] fod.dom] - =/ cached=(unit [=tube *]) (~(get by tubes.fod.dom) [i i.t]:path) - ?^ cached - :_(fod.dom [~ ~ %& %tube !>(tube.u.cached)]) - =^ =tube fod.dom + [[~ ~] ..park] + =^ =tube ..park + %+ aeon-flow aeon %- wrap:fusion - (build-tube:(ford:fusion static-ford-args) [i i.t]:path) - :_(fod.dom [~ ~ %& %tube !>(tube)]) + (build-tube:(aeon-ford aeon) [i i.t]:path) + :_(..park [~ ~ %tube !>(tube)]) :: ++ read-e !. |= [=aeon =path] - ^- [(unit (unit (each cage lobe))) ford-cache] - ?. =(aeon let.dom) - [~ fod.dom] + ^- [(unit (unit cage)) _..park] ?. ?=([@ ~] path) - [[~ ~] fod.dom] - =/ cached=(unit [=vase *]) (~(get by naves.fod.dom) i.path) - ?^ cached - :_(fod.dom [~ ~ %& %nave vase.u.cached]) - =^ =vase fod.dom + [[~ ~] ..park] + =^ =vase ..park + %+ aeon-flow aeon %- wrap:fusion - (build-nave:(ford:fusion static-ford-args) i.path) - :_(fod.dom [~ ~ %& %nave vase]) + (build-nave:(aeon-ford aeon) i.path) + :_(..park [~ ~ %nave vase]) :: ++ read-f !. |= [=aeon =path] - ^- [(unit (unit (each cage lobe))) ford-cache] - ?. =(aeon let.dom) - [~ fod.dom] + ^- [(unit (unit cage)) _..park] ?. ?=([@ @ ~] path) - [[~ ~] fod.dom] - =/ cached=(unit [=vase *]) (~(get by casts.fod.dom) [i i.t]:path) - ?^ cached - :_(fod.dom [~ ~ %& %cast vase.u.cached]) - =^ =vase fod.dom + [[~ ~] ..park] + =^ =vase ..park + %+ aeon-flow aeon %- wrap:fusion - (build-cast:(ford:fusion static-ford-args) [i i.t]:path) - :_(fod.dom [~ ~ %& %cast vase]) + (build-cast:(aeon-ford aeon) [i i.t]:path) + :_(..park [~ ~ %cast vase]) + :: + :: XX move to +read-buc + :: + ++ read-d + !. + |= [=aeon =path] + ^- (unit (unit cage)) + ?. =(our her) + [~ ~] + ?^ path + ~&(%no-cd-path [~ ~]) + [~ ~ %noun !>(~(key by dos.rom.ruf))] :: :: Gets the permissions that apply to a particular node. :: @@ -3924,8 +3835,8 @@ :: ++ read-p |= pax=path - ^- (unit (unit (each cage lobe))) - =- [~ ~ %& %noun !>(-)] + ^- (unit (unit cage)) + =- [~ ~ %noun !>(-)] :- (read-p-in pax per.red) (read-p-in pax pew.red) :: @@ -4011,20 +3922,26 @@ :: ++ read-r |= [yon=aeon pax=path] - ^- (unit (unit cage)) - =/ x (read-x yon pax) + ^- [(unit (unit cage)) _..park] + =^ x ..park (read-x yon pax) + :_ ..park ?~ x ~ ?~ u.x [~ ~] - ?> ?=(%& -.u.u.x) - ``[p.p.u.u.x !>(q.p.u.u.x)] - :: +read-s: produce yaki or blob for given tako or lobe + ``[p.u.u.x !>(q.u.u.x)] + :: +read-s: produce miscellaneous :: ++ read-s |= [yon=aeon pax=path] ^- (unit (unit cage)) - ?. ?=([?(%yaki %blob %hash %cage %open %late %base) * *] pax) + ?. ?=([@ * *] pax) `~ - ?- i.pax + ?+ i.pax `~ + %tako + =/ tak=(unit tako) (~(get by hit.dom) yon) + ?~ tak + ~ + ``tako+[-:!>(*tako) u.tak] + :: %yaki =/ yak=(unit yaki) (~(get by hut.ran) (slav %uv i.t.pax)) ?~ yak @@ -4032,10 +3949,10 @@ ``yaki+[-:!>(*yaki) u.yak] :: %blob - =/ bol=(unit blob) (~(get by lat.ran) (slav %uv i.t.pax)) - ?~ bol + =/ peg=(unit page) (~(get by lat.ran) (slav %uv i.t.pax)) + ?~ peg ~ - ``blob+[-:!>(*blob) u.bol] + ``blob+[-:!>(*page) u.peg] :: %hash =/ yak=(unit yaki) (~(get by hut.ran) (slav %uv i.t.pax)) @@ -4047,18 +3964,31 @@ :: should save ford cache :: =/ =lobe (slav %uv i.t.pax) - =^ =page fod.dom + =/ peg=(unit page) (~(get by lat.ran) lobe) + ?~ peg + ~ + =/ [=cage *] %- wrap:fusion - (lobe-to-page:(ford:fusion static-ford-args) lobe) - =^ =cage fod.dom - %- wrap:fusion - (page-to-cage:(ford:fusion static-ford-args) page) + (page-to-cage:(aeon-ford yon) u.peg) ``cage+[-:!>(*^cage) cage] :: - %open - ``open+!>(prelude:(ford:fusion static-ford-args)) - :: + %open ``open+!>(prelude:(aeon-ford yon)) %late !! :: handled in +aver + %case !! :: handled in +aver + %base-tako + :: XX this ignores the given beak + :: maybe move to +aver? + ?> ?=(^ t.t.pax) + :^ ~ ~ %uvs !> + ^- (list @uv) + =/ tako-a (slav %uv i.t.pax) + =/ tako-b (slav %uv i.t.t.pax) + =/ yaki-a (~(got by hut.ran) tako-a) + =/ yaki-b (~(got by hut.ran) tako-b) + %+ turn ~(tap in (find-merge-points yaki-a yaki-b)) + |= =yaki + r.yaki + :: %base ?> ?=(^ t.t.pax) :^ ~ ~ %uvs !> @@ -4111,11 +4041,11 @@ :: ++ read-u |= [yon=aeon pax=path] - ^- (unit (unit (each [%flag (hypo ?)] lobe))) + ^- (unit (unit [%flag (hypo ?)])) :: if asked for version 0, that never exists, so always give false :: ?: =(0 yon) - ``[%& %flag -:!>(*?) |] + ``[%flag -:!>(*?) |] :: if asked for a future version, we don't have an answer :: ?~ tak=(~(get by hit.dom) yon) @@ -4125,88 +4055,66 @@ =/ yak=yaki (tako-to-yaki u.tak) :: produce the result based on whether or not there's a file at :pax :: - ``[%& %flag -:!>(*?) (~(has by q.yak) pax)] + ``[%flag -:!>(*?) (~(has by q.yak) pax)] :: :: Gets the dome (desk state) at a particular aeon. :: - :: For past aeons, we don't give an actual ankh in the dome, but the rest - :: of the data is legit. We also never send the mime cache over the wire. - :: ++ read-v |= [yon=aeon pax=path] ^- (unit (unit [%dome (hypo dome:clay)])) ?: (lth yon let.dom) :* ~ ~ %dome -:!>(*dome:clay) ^- dome:clay - :* ank=`[[%ank-in-old-v-not-implemented *ankh] ~ ~] - let=yon + :* let=yon hit=(molt (skim ~(tap by hit.dom) |=([p=@ud *] (lte p yon)))) lab=(molt (skim ~(tap by lab.dom) |=([* p=@ud] (lte p yon)))) == == ?: (gth yon let.dom) ~ - ``[%dome -:!>(*dome:clay) [ank let hit lab]:dom] + ``[%dome -:!>(*dome:clay) [let hit lab]:dom] :: :: Gets all cases refering to the same revision as the given case. :: :: For the %da case, we give just the canonical timestamp of the revision. :: ++ read-w - |= cas=case - ^- (unit (unit (each cage lobe))) - =+ aey=(case-to-aeon cas) - ?~ aey ~ - =- [~ ~ %& %cass !>(-)] + |= yon=aeon + ^- (unit (unit cage)) + =- [~ ~ %cass !>(-)] ^- cass - :- u.aey - ?: =(0 u.aey) `@da`0 - t:(aeon-to-yaki u.aey) + :- yon + ?: =(0 yon) `@da`0 + t:(aeon-to-yaki yon) :: :: Get the data at a node. :: - :: If it's in our ankh (current state cache), we can just produce - :: the result. Otherwise, we've got to look up the node at the - :: aeon to get the content hash, use that to find the blob, and use - :: the blob to get the data. We also special-case the hoon mark - :: for bootstrapping purposes. + :: Use ford to read the file. Note this special-cases the hoon + :: mark for bootstrapping purposes. :: ++ read-x |= [yon=aeon pax=path] - ^- (unit (unit (each cage lobe))) + ^- [(unit (unit cage)) _..park] ?: =(0 yon) - [~ ~] + [[~ ~] ..park] =+ tak=(~(get by hit.dom) yon) ?~ tak - ~ - ?: &(?=(~ ref) =(yon let.dom)) - :- ~ - %+ bind - fil.ank:(descend-path:(zu ank.dom) pax) - |=(a=[p=lobe q=cage] [%& q.a]) + [~ ..park] =+ yak=(tako-to-yaki u.tak) =+ lob=(~(get by q.yak) pax) ?~ lob - [~ ~] - =+ mar=(lobe-to-mark u.lob) + [[~ ~] ..park] + =/ peg=(unit page) (~(get by lat.ran) u.lob) + :: if tombstoned, nothing to return + :: + ?~ peg + [~ ..park] :: should convert any lobe to cage :: - ?. ?=(%hoon mar) - [~ ~ %| u.lob] - :^ ~ ~ %& - :+ mar [%atom %t ~] - |- ^- @t :: (urge cord) would be faster - =+ bol=(lobe-to-blob u.lob) - ?: ?=(%direct -.bol) - ;;(@t q.q.bol) - ?> ?=(%delta -.bol) - =+ txt=$(u.lob q.q.bol) - ?> ?=(%txt-diff p.r.bol) - =+ dif=;;((urge cord) q.r.bol) - =, format - =+ pac=(of-wain (lurk:differ (to-wain (cat 3 txt '\0a')) dif)) - ?~ pac - '' - (end [3 (dec (met 3 pac))] pac) + =^ =cage ..park + %+ aeon-flow yon + %- wrap:fusion + (page-to-cage:(aeon-ford yon) u.peg) + [``cage ..park] :: :: Gets an arch (directory listing) at a node. :: @@ -4246,71 +4154,48 @@ =+ tak=(~(get by hit.dom) yon) ?~ tak ~ - [~ ~ %uvi -:!>(*@uvI) (content-hash (tako-to-yaki u.tak) pax)] + [~ ~ %uvi [%atom %'uvI' ~] (content-hash (tako-to-yaki u.tak) pax)] :: :: Get a value at an aeon. :: :: Value can be either null, meaning we don't have it yet, [null null], - :: meaning we know it doesn't exist, or [null null (each cage lobe)], + :: meaning we know it doesn't exist, or [null null cage], :: meaning we either have the value directly or a content hash of the :: value. :: ++ read-at-aeon :: read-at-aeon:ze |= [for=(unit ship) yon=aeon mun=mood] :: seek and read - ^- [(unit (unit (each cage lobe))) ford-cache] - =* fod fod.dom + ^- [(unit (unit cage)) _..park] ?. |(?=(~ for) (may-read u.for care.mun yon path.mun)) - [~ fod] + [~ ..park] :: virtualize to catch and produce deterministic failures :: !: - =- ?: ?=(%& -<) p.- - %. [[~ ~] fod] - (slog leaf+"clay: read-at-aeon fail {<[desk=syd mun]>}" p.-) - %- mule |. - ?- care.mun - %d - :_ fod - :: XX this should only allow reads at the current date - :: - ?: !=(our her) - [~ ~] - ?^ path.mun - ~&(%no-cd-path [~ ~]) - [~ ~ %& %noun !>(~(key by dos.rom.ruf))] + |^ =/ res (mule |.(read)) + ?: ?=(%& -.res) p.res + %. [[~ ~] ..park] + (slog leaf+"clay: read-at-aeon fail {<[desk=syd mun]>}" p.res) :: - %a (read-a yon path.mun) - %b (read-b yon path.mun) - %c (read-c yon path.mun) - %e (read-e yon path.mun) - %f (read-f yon path.mun) - %p :_(fod (read-p path.mun)) - %r :_(fod (bind (read-r yon path.mun) (lift |=(a=cage [%& a])))) - %s :_(fod (bind (read-s yon path.mun) (lift |=(a=cage [%& a])))) - %t :_(fod (bind (read-t yon path.mun) (lift |=(a=cage [%& a])))) - %u :_(fod (read-u yon path.mun)) - %v :_(fod (bind (read-v yon path.mun) (lift |=(a=cage [%& a])))) - %w :_(fod (read-w case.mun)) - %x :_(fod (read-x yon path.mun)) - %y :_(fod (bind (read-y yon path.mun) (lift |=(a=cage [%& a])))) - %z :_(fod (bind (read-z yon path.mun) (lift |=(a=cage [%& a])))) - == - :: Traverse an ankh. - :: - ++ zu :: filesystem - |= ank=ankh :: filesystem state - =| ram=path :: reverse path into - |% - ++ descend :: descend - |= lol=@ta - ^+ +> - =+ you=(~(get by dir.ank) lol) - +>.$(ram [lol ram], ank ?~(you [~ ~] u.you)) - :: - ++ descend-path :: descend recursively - |= way=path - ^+ +> - ?~(way +> $(way t.way, +> (descend i.way))) + ++ read + ^- [(unit (unit cage)) _..park] + ?- care.mun + %a (read-a yon path.mun) + %b (read-b yon path.mun) + %c (read-c yon path.mun) + %d [(read-d yon path.mun) ..park] + %e (read-e yon path.mun) + %f (read-f yon path.mun) + %p [(read-p path.mun) ..park] + %r (read-r yon path.mun) + %s [(read-s yon path.mun) ..park] + %t [(read-t yon path.mun) ..park] + %u [(read-u yon path.mun) ..park] + %v [(read-v yon path.mun) ..park] + %w [(read-w yon) ..park] + %x (read-x yon path.mun) + %y [(read-y yon path.mun) ..park] + %z [(read-z yon path.mun) ..park] + == -- -- -- @@ -4329,7 +4214,7 @@ :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: =| :: instrument state - $: ver=%10 :: vane version + $: ver=%12 :: vane version ruf=raft :: revision tree == :: |= [now=@da eny=@uvJ rof=roof] :: current invocation @@ -4345,7 +4230,7 @@ :: =/ req=task ((harden task) wrapped-task) :: - :: XX handle error notifications + :: TODO handle error notifications :: ?^ dud [[[hen %slip %d %flog %crud [-.req tang.u.dud]] ~] ..^$] @@ -4425,7 +4310,7 @@ [mos ..^$] :: %init - [~ ..^$(hun.rom.ruf hen, dist-upgraded.ruf &)] + [~ ..^$(hun.rom.ruf hen)] :: %into =. hez.ruf `hen @@ -4471,32 +4356,33 @@ ?~ hez.ruf ~& %no-sync-duct [~ ..^$] - ?. (~(has by mon.ruf) des.req) - ~& [%not-mounted des.req] + ?. (~(has by mon.ruf) pot.req) + ~& [%not-mounted pot.req] [~ ..^$] - [~[[u.hez.ruf %give %dirk des.req]] ..^$] + [~[[u.hez.ruf %give %dirk pot.req]] ..^$] :: %ogre - ?~ hez.ruf + ?: =(~ hez.ruf) ~& %no-sync-duct [~ ..^$] =* pot pot.req - ?@ pot - ?. (~(has by mon.ruf) pot) - ~& [%not-mounted pot] - [~ ..^$] - :_ ..^$(mon.ruf (~(del by mon.ruf) pot)) - [u.hez.ruf %give %ogre pot]~ - :_ %_ ..^$ - mon.ruf - %- molt - %+ skip ~(tap by mon.ruf) - (corl (cury test pot) tail) - == - %+ turn - (skim ~(tap by mon.ruf) (corl (cury test pot) tail)) - |= [pon=term bem=beam] - [u.hez.ruf %give %ogre pon] + =/ bem=(list [pot=term beam]) + ?@ pot + ?~ got=(~(get by mon.ruf) pot) + ~& [%not-mounted pot] + ~ + [pot u.got]~ + %+ skim ~(tap by mon.ruf) + |= [=term =beam] + =(pot beam) + |- ^- [(list move) _..^^$] + ?~ bem + [~ ..^^$] + =^ moves-1 ruf + =/ den ((de now rof hen ruf) p.i.bem q.i.bem) + abet:(unmount:den pot.i.bem r.i.bem s.i.bem) + =^ moves-2 ..^^$ $(bem t.bem) + [(weld moves-1 moves-2) ..^^$] :: %park =^ mos ruf @@ -4518,7 +4404,31 @@ abet:(perm:den pax.req rit.req) [mos ..^$] :: - %trim [~ ..^$] + %stir + ?+ arg.req ~|(%strange-stir !!) + [%verb @] [~ ..^$(veb.bug.ruf +.arg.req)] + [%mass @] [~ ..^$(mas.bug.ruf +.arg.req)] + == + :: + %tomb (tomb-clue:tomb hen clue.req) + %trim + =: fad.ruf *flow + dos.rom.ruf + %- ~(run by dos.rom.ruf) + |= =dojo + dojo(fod.dom *flue) + :: + hoy.ruf + %- ~(run by hoy.ruf) + |= =rung + %= rung + rus + %- ~(run by rus.rung) + |= =rede + rede(fod.dom *flue) + == + == + [~ ..^$] :: %vega :: wake all desks, then send pending notifications @@ -4572,7 +4482,7 @@ =+ ;;(=fill res) =^ mos ruf =/ den ((de now rof hen ruf) our desk.fill) - abet:(give-backfill:den lobe.fill) + abet:(give-backfill:den -.fill lobe.fill) [[[hen %give %done ~] mos] ..^$] ?> ?=([%question *] pax) =+ ryf=;;(riff-any res) @@ -4587,26 +4497,131 @@ ++ load => |% +$ raft-any - $% [%10 raft-10] + $% [%12 raft-12] + [%11 raft-11] + [%10 raft-10] [%9 raft-9] [%8 raft-8] [%7 raft-7] [%6 raft-6] == - +$ raft-10 raft + +$ raft-12 raft + +$ raft-11 + $: rom=room + hoy=(map ship rung) + ran=rang + fad=flow + mon=(map term beam) + hez=(unit duct) + cez=(map @ta crew) + pud=(unit [=desk =yoki]) + == + +$ raft-10 + $: rom=room-10 + hoy=(map ship rung-10) + ran=rang-10 + mon=(map term beam) + hez=(unit duct) + cez=(map @ta crew) + pud=(unit [=desk =yoki]) + dist-upgraded=_| + == + +$ rang-10 + $: hut=(map tako yaki) + lat=(map lobe blob-10) + == + +$ blob-10 + $% [%delta p=lobe q=[p=mark q=lobe] r=page] + [%direct p=lobe q=page] + [%dead p=lobe ~] + == + +$ room-10 + $: hun=duct + dos=(map desk dojo-10) + == + +$ dojo-10 + $: qyx=cult-10 + dom=dome-10 + per=regs + pew=regs + fiz=melt-10 + == + +$ dome-10 + $: ank=ankh-10 + let=aeon + hit=(map aeon tako) + lab=(map @tas aeon) + mim=(map path mime) + fod=* + == + +$ ankh-10 (axal [p=lobe q=cage]) + +$ rung-10 + $: rus=(map desk rede-10) + == + +$ rede-10 + $: lim=@da + ref=(unit rind-10) + qyx=cult-10 + dom=dome-10 + per=regs + pew=regs + fiz=melt-10 + == + +$ rind-10 + $: nix=@ud + bom=(map @ud update-state-10) + fod=(map duct @ud) + haw=(map mood (unit cage)) + == + +$ update-state-10 + $: =duct + =rave + have=(map lobe blob-10) + need=(list lobe) + nako=(qeu (unit nako-10)) + busy=_| + == + +$ nako-10 + $: gar=(map aeon tako) + let=aeon + lar=(set yaki) + bar=(set blob-10) + == + +$ melt-10 + [bas=beak con=(list [beak germ]) sto=(map beak (unit dome-clay-10))] + +$ dome-clay-10 + $: ank=ankh-10 + let=@ud + hit=(map @ud tako) + lab=(map @tas @ud) + == + +$ cult-10 (jug wove-10 duct) + +$ wove-10 [for=(unit [=ship ver=@ud]) =rove-10] + +$ rove-10 + $% [%sing =mood] + [%next =mood aeon=(unit aeon) =cach-10] + $: %mult + =mool + aeon=(unit aeon) + old-cach=(map [=care =path] cach-10) + new-cach=(map [=care =path] cach-10) + == + [%many track=? =moat lobes=(map path lobe)] + == + +$ cach-10 (unit (unit (each cage lobe))) +$ raft-9 - $: rom=room :: domestic - hoy=(map ship rung) :: foreign - ran=rang :: hashes - mon=(map term beam) :: mount points - hez=(unit duct) :: sync duct - cez=(map @ta crew) :: permission groups - pud=(unit [=desk =yoki]) :: pending update - == :: + $: rom=room-10 + hoy=(map ship rung-10) + ran=rang-10 + mon=(map term beam) + hez=(unit duct) + cez=(map @ta crew) + pud=(unit [=desk =yoki]) + == +$ raft-8 $: rom=room-8 hoy=(map ship rung-8) - ran=rang + ran=rang-10 mon=(map term beam) hez=(unit duct) cez=(map @ta crew) @@ -4620,34 +4635,34 @@ $: rus=(map desk rede-8) == +$ dojo-8 - $: qyx=cult + $: qyx=cult-10 dom=dome-8 per=regs pew=regs - fiz=melt + fiz=melt-10 == +$ dome-8 - $: ank=ankh + $: ank=ankh-10 let=aeon hit=(map aeon tako) lab=(map @tas aeon) mim=(map path mime) - fod=ford-cache + fod=* fer=* :: reef cache, obsolete == +$ rede-8 $: lim=@da - ref=(unit rind) - qyx=cult + ref=(unit rind-10) + qyx=cult-10 dom=dome-8 per=regs pew=regs - fiz=melt + fiz=melt-10 == +$ raft-7 $: rom=room-7 hoy=(map ship rung-7) - ran=rang + ran=rang-10 mon=(map term beam) hez=(unit duct) cez=(map @ta crew) @@ -4661,57 +4676,55 @@ $: rus=(map desk rede-7) == +$ dojo-7 - $: qyx=cult + $: qyx=cult-10 dom=dome-8 per=regs pew=regs == +$ rede-7 $: lim=@da - ref=(unit rind) - qyx=cult + ref=(unit rind-10) + qyx=cult-10 dom=dome-8 per=regs pew=regs == - +$ ford-cache-7 ford-cache +$ raft-6 - $: rom=room-6 :: domestic - hoy=(map ship rung-6) :: foreign - ran=rang :: hashes - mon=(map term beam) :: mount points - hez=(unit duct) :: sync duct - cez=(map @ta crew) :: permission groups - pud=(unit [=desk =yoki]) :: pending update + $: rom=room-6 + hoy=(map ship rung-6) + ran=rang-10 + mon=(map term beam) + hez=(unit duct) + cez=(map @ta crew) + pud=(unit [=desk =yoki]) == :: +$ room-6 [hun=duct dos=(map desk dojo-6)] +$ dojo-6 - $: qyx=cult :: subscribers - dom=dome-6 :: desk state - per=regs :: read perms per path - pew=regs :: write perms per path + $: qyx=cult-10 + dom=dome-6 + per=regs + pew=regs == +$ dome-6 - $: ank=ankh :: state - let=aeon :: top id - hit=(map aeon tako) :: versions by id - lab=(map @tas aeon) :: labels - mim=(map path mime) :: mime cache - fod=ford-cache-6 :: ford cache - fer=* :: reef cache + $: ank=ankh-10 + let=aeon + hit=(map aeon tako) + lab=(map @tas aeon) + mim=(map path mime) + fod=* + fer=* == +$ rung-6 $: rus=(map desk rede-6) == +$ rede-6 $: lim=@da - ref=(unit rind) - qyx=cult + ref=(unit rind-10) + qyx=cult-10 dom=dome-6 per=regs pew=regs == - +$ ford-cache-6 * :: discard old cache -- |= old=raft-any |^ @@ -4719,7 +4732,9 @@ =? old ?=(%7 -.old) 8+(raft-7-to-8 +.old) =? old ?=(%8 -.old) 9+(raft-8-to-9 +.old) =? old ?=(%9 -.old) 10+(raft-9-to-10 +.old) - ?> ?=(%10 -.old) + =? old ?=(%10 -.old) 11+(raft-10-to-11 +.old) + =? old ?=(%11 -.old) 12+(raft-11-to-12 +.old) + ?> ?=(%12 -.old) ..^^$(ruf +.old) :: +raft-6-to-7: delete stale ford caches (they could all be invalid) :: @@ -4731,14 +4746,14 @@ %- ~(run by dos.rom.raf) |= doj=dojo-6 ^- dojo-7 - doj(fod.dom *ford-cache-7) + doj(fod.dom **) :: hoy %- ~(run by hoy.raf) |= =rung-6 %- ~(run by rus.rung-6) |= =rede-6 - rede-6(dom dom.rede-6(fod *ford-cache-7)) + rede-6(dom dom.rede-6(fod **)) == :: +raft-7-to-8: create bunted melts in each dojo/rede :: @@ -4750,7 +4765,7 @@ %- ~(run by dos.rom.raf) |= doj=dojo-7 ^- dojo-8 - [qyx.doj dom.doj per.doj pew.doj *melt] + [qyx.doj dom.doj per.doj pew.doj *melt-10] :: hoy %- ~(run by hoy.raf) @@ -4758,7 +4773,7 @@ %- ~(run by rus.rung-7) |= r=rede-7 ^- rede-8 - [lim.r ref.r qyx.r dom.r per.r pew.r *melt] + [lim.r ref.r qyx.r dom.r per.r pew.r *melt-10] == :: +raft-8-to-9: remove reef cache :: @@ -4769,24 +4784,173 @@ dos.rom %- ~(run by dos.rom.raf) |= =dojo-8 - ^- dojo + ^- dojo-10 =/ dom dom.dojo-8 - dojo-8(dom [ank.dom let.dom hit.dom lab.dom mim.dom *ford-cache]) + dojo-8(dom [ank.dom let.dom hit.dom lab.dom mim.dom *flow]) :: hoy %- ~(run by hoy.raf) |= =rung-8 %- ~(run by rus.rung-8) |= =rede-8 - ^- rede + ^- rede-10 =/ dom dom.rede-8 - rede-8(dom [ank.dom let.dom hit.dom lab.dom mim.dom *ford-cache]) + rede-8(dom [ank.dom let.dom hit.dom lab.dom mim.dom *flow]) == :: +raft-9-to-10: add .dist-upgraded + :: ++ raft-9-to-10 |= raf=raft-9 ^- raft-10 raf(pud [pud.raf dist-upgraded=|]) + :: + :: +raft-10-to-11: + :: + :: add tom and nor to dome + :: remove parent-mark from delta blobs + :: change blobs to pages + :: remove have from update-state + :: remove bar from nako + :: remove ankh + :: set cases in mon to ud+0 + :: add fad + :: change fod type in dom + :: + :: + ++ raft-10-to-11 + |= raf=raft-10 + |^ + ^- raft-11 + %= raf + dos.rom + %- ~(run by dos.rom.raf) + |= =dojo-10 + ^- dojo + %= dojo-10 + fiz *melt + qyx (cult-10-to-cult qyx.dojo-10) + dom + :* let.dom.dojo-10 + hit.dom.dojo-10 + lab.dom.dojo-10 + ~ + *norm + mim.dom.dojo-10 + ~ + ~ + == + == + :: + hoy + %- ~(run by hoy.raf) + |= =rung-10 + %- ~(run by rus.rung-10) + |= =rede-10 + ^- rede + %= rede-10 + fiz *melt + qyx (cult-10-to-cult qyx.rede-10) + dom + :* let.dom.rede-10 + hit.dom.rede-10 + lab.dom.rede-10 + ~ + *norm + mim.dom.rede-10 + ~ + ~ + == + :: + ref + ?~ ref.rede-10 + ~ + %= ref.rede-10 + bom.u + %- ~(run by bom.u.ref.rede-10) + |= =update-state-10 + %= update-state-10 + |2 + %= |3.update-state-10 + nako + %- ~(gas to *(qeu (unit nako))) + %+ turn ~(tap to nako.update-state-10) + |= nak=(unit nako-10) + ?~ nak ~ + `u.nak(bar ~) + == + == + == + == + :: + lat.ran + %- ~(gas by *(map lobe page)) + %+ murn ~(tap by lat.ran.raf) + |= [=lobe =blob-10] + ^- (unit [^lobe page]) + ?- -.blob-10 + %delta ((slog 'clay: tombstoning delta!' ~) ~) + %dead ~ + %direct `[lobe q.blob-10] + == + :: + |3 + :- *flow + %= |3.raf + mon (~(run by mon.raf) |=(=beam beam(r ud+0))) + |3 pud.raf + == + == + :: + ++ cult-10-to-cult + |= qyx=cult-10 + ^- cult + =/ qux=(list [=wove-10 ducts=(set duct)]) ~(tap by qyx) + %- malt + |- ^- (list [wove (set duct)]) + ?~ qux + ~ + :_ $(qux t.qux) + %= i.qux + rove-10.wove-10 + ?- -.rove-10.wove-10.i.qux + %sing rove-10.wove-10.i.qux + %many rove-10.wove-10.i.qux + %next + %= rove-10.wove-10.i.qux + cach-10 (cach-10-to-cach cach-10.rove-10.wove-10.i.qux) + == + :: + %mult + %= rove-10.wove-10.i.qux + old-cach (caches-10-to-caches old-cach.rove-10.wove-10.i.qux) + new-cach (caches-10-to-caches new-cach.rove-10.wove-10.i.qux) + == + == + == + :: + ++ cach-10-to-cach + |= =cach-10 + ^- cach + ?~ cach-10 + ~ + ?~ u.cach-10 + [~ ~] + ?- -.u.u.cach-10 + %& ``p.u.u.cach-10 + %| ~ + == + :: + ++ caches-10-to-caches + |= caches-10=(map [=care =path] cach-10) + ^- (map [=care =path] cach) + (~(run by caches-10) cach-10-to-cach) + -- + :: +raft-11-to-12: add bug + :: + ++ raft-11-to-12 + |= raf=raft-11 + ^- raft-12 + raf(pud [pud.raf 0 0]) -- :: ++ scry :: inspect @@ -4794,6 +4958,8 @@ ^- roon |= [lyc=gang car=term bem=beam] ^- (unit (unit cage)) + =* scry-loop $ + |^ =* ren car =/ why=shop &/p.bem =* syd q.bem @@ -4815,30 +4981,128 @@ ::TODO if it ever gets filled properly, pass in the full fur. :: =/ for=(unit ship) ?~(lyc ~ ?~(u.lyc ~ `n.u.lyc)) + ?: &(=(our his) =(%x ren) =(%$ syd) =([%da now] u.luk)) + (read-buc u.run tyl) =/ den ((de now rof [/scryduct ~] ruf) his syd) =/ result (mule |.(-:(aver:den for u.run u.luk tyl))) ?: ?=(%| -.result) %- (slog >%clay-scry-fail< p.result) ~ - ?~ p.result ~ - ?~ u.p.result [~ ~] - :: should convert %| case to cage + p.result :: - ?: ?=(%& -.u.u.p.result) ``p.u.u.p.result - ~ + ++ read-buc + |= [=care =path] + ^- (unit (unit cage)) + ?~ path + ~ + ?+ i.path ~ + %sweep ``[%sweep !>(sweep)] + %rang ``[%rang !>(ran.ruf)] + %tomb ``[%flag !>((tomb t.path))] + %domes domes + == + :: + ++ domes + =/ domes + %- ~(gas by *cone) + %+ turn ~(tap by dos.rom.ruf) + |= [=desk =dojo] + [[our desk] [[let hit lab] tom nor]:dom.dojo] + =. domes + %- ~(uni by domes) + %- ~(gas by *cone) + ^- (list [[ship desk] dome:clay (map tako norm) norm]) + %- zing + ^- (list (list [[ship desk] dome:clay (map tako norm) norm])) + %+ turn ~(tap by hoy.ruf) + |= [=ship =rung] + ^- (list [[^ship desk] dome:clay (map tako norm) norm]) + %+ turn ~(tap by rus.rung) + |= [=desk =rede] + [[ship desk] [[let hit lab] tom nor]:dom.rede] + ``[%domes !>(`cone`domes)] + :: + :: True if file is accessible + :: + ++ tomb + |= =path + ^- ? + =/ bem (de-beam path) + ?~ bem %| + =/ cay scry-loop(car %y, bem u.bem) + ?~ cay %| + ?~ u.cay %| + =+ !<(=arch q.u.u.cay) + ?~ fil.arch %| + (~(has by lat.ran.ruf) u.fil.arch) + :: + :: Check for refcount errors + :: + ++ sweep + ^- (list [need=@ud have=@ud leak]) + =/ marked=(map leak [need=@ud have=@ud]) + (~(run by fad.ruf) |=([refs=@ud *] [0 refs])) + =. marked + =/ items=(list [=leak *]) ~(tap by fad.ruf) + |- ^+ marked + ?~ items + marked + =/ deps ~(tap in deps.leak.i.items) + |- ^+ marked + ?~ deps + ^$(items t.items) + =. marked + %+ ~(put by marked) i.deps + =/ gut (~(gut by marked) i.deps [0 0]) + [+(-.gut) +.gut] + $(deps t.deps) + :: + =/ spills=(list (set leak)) + %+ welp + %+ turn ~(tap by dos.rom.ruf) + |= [* =dojo] + spill.fod.dom.dojo + %- zing + %+ turn ~(tap by hoy.ruf) + |= [* =rung] + %+ turn ~(tap by rus.rung) + |= [* =rede] + spill.fod.dom.rede + :: + =. marked + |- + ?~ spills + marked + =/ leaks ~(tap in i.spills) + |- + ?~ leaks + ^$(spills t.spills) + =. marked + %+ ~(put by marked) i.leaks + =/ gut (~(gut by marked) i.leaks [0 0]) + [+(-.gut) +.gut] + $(leaks t.leaks) + :: + %+ murn ~(tap by marked) + |= [=leak need=@ud have=@ud] + ?: =(need have) + ~ + `u=[need have leak] + -- :: :: We clear the ford cache by replacing it with its bunt as a literal. -:: This nests within +ford-cache without reference to +type, +hoon, or +:: This nests within +flow without reference to +type, +hoon, or :: anything else in the sample of cache objects. Otherwise we would be :: contravariant in the those types, which makes them harder to change. :: ++ stay :- ver %= ruf + fad ~ dos.rom %- ~(run by dos.rom.ruf) |= =dojo - dojo(fod.dom [~ ~ ~ ~ ~]) + dojo(fod.dom `flue`[~ ~]) :: hoy %- ~(run by hoy.ruf) @@ -4847,7 +5111,7 @@ rus %- ~(run by rus.rung) |= =rede - rede(fod.dom [~ ~ ~ ~ ~]) + rede(fod.dom `flue`[~ ~]) == == :: @@ -4907,9 +5171,8 @@ [~ ..^$] :: %lost - ~| %clay-take-lost^our - :: TODO better error handling - !! + %- (slog leaf+"clay: lost warp from {}" ~) + [~ ..^$] :: %boon =+ ;; res=(unit rand) payload.hin @@ -4924,7 +5187,7 @@ [mos ..^$] == :: - ?: ?=([%back-index @ @ @ ~] tea) + ?: ?=([%back-index @ @ @ *] tea) ?+ +<.hin ~| %clay-backfill-index-strange !! %done ?~ error.hin @@ -4936,12 +5199,11 @@ [~ ..^$] :: %lost - ~| %clay-take-backfill-lost^our - :: TODO better error handling - !! + %- (slog leaf+"clay: lost backfill from {}" ~) + [~ ..^$] :: %boon - =+ ;; =blob payload.hin + =+ ;; =fell payload.hin :: =/ her=ship (slav %p i.t.tea) =/ =desk (slav %tas i.t.t.tea) @@ -4949,7 +5211,30 @@ :: =^ mos ruf =/ den ((de now rof hen ruf) her desk) - abet:abet:(take-backfill:(foreign-update:den index) blob) + abet:abet:(take-backfill:(foreign-update:den index) fell) + [mos ..^$] + == + :: + ?: ?=([%seek @ @ ~] tea) + ?+ +<.hin ~| %clay-seek-strange !! + %done + ?~ error.hin + [~ ..^$] + %- (slog leaf+"clay: seek nack from {}" u.error.hin) + [~ ..^$] + :: + %lost + %- (slog leaf+"clay: lost boon from {}" ~) + [~ ..^$] + :: + %boon + =+ ;; =fell payload.hin + :: + =/ her=ship (slav %p i.t.tea) + =/ =desk (slav %tas i.t.t.tea) + =^ mos ruf + =/ den ((de now rof hen ruf) her desk) + abet:(take-fell:den fell) [mos ..^$] == :: @@ -5040,23 +5325,208 @@ :: ++ whey ^- (list mass) + ?: (gth mas.bug.ruf 0) + =/ domestic + %+ turn (sort ~(tap by dos.rom.ruf) aor) + |= [=desk =dojo] + :+ desk %| + :~ mime+&+mim.dom.dojo + flue+&+fod.dom.dojo + dojo+&+dojo + == + :~ :+ %object-store %| + :~ commits+&+hut.ran.ruf + :+ %pages %| + %+ turn ~(tap by lat.ran.ruf) + |= [=lobe =page] + [(scot %uv lobe) %& page] + == + domestic+|+domestic + foreign+&+hoy.ruf + ford-cache+&+fad.ruf + == =/ domestic %+ turn (sort ~(tap by dos.rom.ruf) aor) |= [=desk =dojo] :+ desk %| - :~ ankh+&+ank.dom.dojo - mime+&+mim.dom.dojo - ford-files+&+files.fod.dom.dojo - ford-naves+&+naves.fod.dom.dojo - ford-marks+&+marks.fod.dom.dojo - ford-casts+&+casts.fod.dom.dojo - ford-tubes+&+tubes.fod.dom.dojo + :~ mime+&+mim.dom.dojo + flue+&+fod.dom.dojo + dojo+&+dojo == - :~ domestic+|+domestic - foreign+&+hoy.ruf - :+ %object-store %| + :~ :+ %object-store %| :~ commits+&+hut.ran.ruf - blobs+&+lat.ran.ruf + pages+&+lat.ran.ruf == + domestic+|+domestic + foreign+&+hoy.ruf + ford-cache+&+fad.ruf == +:: +++ tomb + |% + :: +tomb-clue: safely remove objects + :: + ++ tomb-clue + |= [=duct =clue] + ^- [(list move) _..^$] + ?- -.clue + %lobe `(tomb-lobe lobe.clue &) + %all + =/ lobes=(list [=lobe =page]) ~(tap by lat.ran.ruf) + |- + ?~ lobes + `..^^$ + =. ..^^$ (tomb-lobe lobe.i.lobes &) + $(lobes t.lobes) + :: + %pick pick + %norm + =^ mos ruf + =/ den ((de now rof duct ruf) ship.clue desk.clue) + abet:(set-norm:den norm.clue) + [mos ..^$] + :: + %worn + =^ mos ruf + =/ den ((de now rof duct ruf) ship.clue desk.clue) + abet:(set-worn:den tako.clue norm.clue) + [mos ..^$] + :: + %seek + =^ mos ruf + =/ den ((de now rof duct ruf) ship.clue desk.clue) + abet:(seek:den cash.clue) + [mos ..^$] + == + :: +tomb-lobe: remove specific lobe + :: + ++ tomb-lobe + |= [lob=lobe veb=?] + ^+ ..^$ + =/ peg=(unit page) (~(get by lat.ran.ruf) lob) + ?~ peg + (noop veb leaf+"clay: file already tombstoned" ~) + :: + =/ used=(unit beam) + =/ desks=(list [=desk =dojo]) ~(tap by dos.rom.ruf) + |- + =* desk-loop $ + ?~ desks + ~ + ?: =(0 let.dom.dojo.i.desks) + desk-loop(desks t.desks) + =/ =yaki + %- ~(got by hut.ran.ruf) + %- ~(got by hit.dom.dojo.i.desks) + let.dom.dojo.i.desks + =/ paths=(list [=path =lobe]) ~(tap by q.yaki) + |- + =* path-loop $ + ?~ paths + desk-loop(desks t.desks) + ?: =(lob lobe.i.paths) + `[[our desk.i.desks ud+let.dom.dojo.i.desks] path.i.paths] + path-loop(paths t.paths) + :: + ?^ used + (noop veb leaf+"clay: file used in {<(en-beam u.used)>}" ~) + :: + =. lat.ran.ruf (~(del by lat.ran.ruf) lob) + (noop veb leaf+"clay: file successfully tombstoned" ~) + :: + ++ noop + |= [veb=? =tang] + ?. veb + ..^$ + ((slog tang) ..^$) + :: + ++ draw-raft + ^- (set [norm yaki]) + =/ room-yakis + =/ rooms=(list [=desk =dojo]) ~(tap by dos.rom.ruf) + |- ^- (set [norm yaki]) + ?~ rooms + ~ + (~(uni in $(rooms t.rooms)) (draw-dome %& dom.dojo.i.rooms)) + =/ rung-yakis + =/ rungs=(list [=ship =rung]) ~(tap by hoy.ruf) + |- ^- (set [norm yaki]) + ?~ rungs + ~ + %- ~(uni in $(rungs t.rungs)) + =/ redes=(list [=desk =rede]) ~(tap by rus.rung.i.rungs) + |- ^- (set [norm yaki]) + ?~ redes + ~ + (~(uni in $(redes t.redes)) (draw-dome %| dom.rede.i.redes)) + (~(uni in room-yakis) rung-yakis) + :: + ++ draw-dome + |= [domestic=? =dome] + ^- (set [norm yaki]) + =/ =aeon 1 + |- ^- (set [norm yaki]) + ?: (lth let.dome aeon) + ~ + =/ =tako (~(got by hit.dome) aeon) + =/ yakis=(set [norm yaki]) + ?. &(=(let.dome aeon) domestic) + ~ + [[*norm (~(got by hut.ran.ruf) tako)] ~ ~] + %- ~(uni in yakis) + %- ~(uni in (draw-tako tom.dome nor.dome tako)) + $(aeon +(aeon)) + :: + ++ draw-tako + |= [tom=(map tako norm) nor=norm =tako] + ^- (set [norm yaki]) + ~+ + =/ =norm (~(gut by tom) tako nor) + =/ =yaki (~(got by hut.ran.ruf) tako) + =/ takos + |- ^- (set [^norm ^yaki]) + ?~ p.yaki + ~ + (~(uni in $(p.yaki t.p.yaki)) ^$(tako i.p.yaki)) + (~(put in takos) norm yaki) + :: + :: +pick: copying gc based on norms + :: + ++ pick + =| lat=(map lobe page) + =| sen=(set [norm (map path lobe)]) + |^ + =. ..pick-raft pick-raft + =. lat.ran.ruf lat + `..^$ + :: + ++ pick-raft + ^+ ..pick-raft + =/ yakis=(list [=norm =yaki]) ~(tap in draw-raft) + |- ^+ ..pick-raft + ?~ yakis + ..pick-raft + :: ~& > [%picking [norm r.yaki]:i.yakis] + $(yakis t.yakis, ..pick-raft (pick-yaki i.yakis)) + :: + :: NB: recurring tree-wise with the `sen` cache provides + :: approximately a 100x speedup on a mainnet moon in 4/2022 + :: + ++ pick-yaki + |= [=norm =yaki] + ^+ ..pick-raft + |- ^+ ..pick-raft + ?~ q.yaki + ..pick-raft + ?: (~(has in sen) norm q.yaki) + ..pick-raft + =. sen (~(put in sen) norm q.yaki) + =/ peg=(unit page) (~(get by lat.ran.ruf) q.n.q.yaki) + :: ~& >> [%picking-lobe ?=(^ peg) +:(~(fit of norm) p.n.q.yaki) n.q.yaki] + =? lat &(?=(^ peg) !=([~ %|] +:(~(fit of norm) p.n.q.yaki))) + (~(uni by `(map lobe page)`[[q.n.q.yaki u.peg] ~ ~]) lat) + =. ..pick-raft $(q.yaki l.q.yaki) + $(q.yaki r.q.yaki) + -- + -- -- diff --git a/pkg/arvo/sys/vane/dill.hoon b/pkg/arvo/sys/vane/dill.hoon index 16bcf51fee..b5e2df90a5 100644 --- a/pkg/arvo/sys/vane/dill.hoon +++ b/pkg/arvo/sys/vane/dill.hoon @@ -102,19 +102,19 @@ |= kyz=task ^+ +> ?+ -.kyz ~& [%strange-kiss -.kyz] +> - %flow +> - %harm +> - %hail (send %hey ~) - %text (from %out (tuba p.kyz)) - %crud :: (send `dill-belt`[%cru p.kyz q.kyz]) - (crud p.kyz q.kyz) - %blew (send %rez p.p.kyz q.p.kyz) - %heft (pass /whey %$ whey/~) - %meld (dump kyz) - %pack (dump kyz) - %crop (dump trim+p.kyz) - %verb (pass /verb %$ kyz) - :: + %flow +> + %harm +> + %hail (send %hey ~) + %text (from %out (tuba p.kyz)) + %crud :: (send `dill-belt`[%cru p.kyz q.kyz]) + (crud p.kyz q.kyz) + %blew (send %rez p.p.kyz q.p.kyz) + %heft (pass /whey %$ whey/~) + %meld (dump kyz) + %pack (dump kyz) + %crop (dump trim+p.kyz) + %verb (pass /verb %$ kyz) + %noop +> %belt %- send ::TMP forwards compatibility with next-dill diff --git a/pkg/arvo/sys/vane/eyre.hoon b/pkg/arvo/sys/vane/eyre.hoon index 562c33b465..110c7d3a64 100644 --- a/pkg/arvo/sys/vane/eyre.hoon +++ b/pkg/arvo/sys/vane/eyre.hoon @@ -1705,13 +1705,14 @@ == :: %fact - :~ ['response' [%s 'diff']] - :: - :- 'json' - ~| [%unexpected-fact-mark p.cage.sign] - ?> =(%json p.cage.sign) - !<(json q.cage.sign) - == + :+ ['response' [%s 'diff']] + :- 'json' + ~| [%unexpected-fact-mark p.cage.sign] + ?> =(%json p.cage.sign) + !<(json q.cage.sign) + :: + ?~ from ~ + ['mark' [%s mark.u.from]]~ :: %kick ['response' [%s 'quit']]~ diff --git a/pkg/arvo/sys/vane/gall.hoon b/pkg/arvo/sys/vane/gall.hoon index af07252e2c..3ea10d64ae 100644 --- a/pkg/arvo/sys/vane/gall.hoon +++ b/pkg/arvo/sys/vane/gall.hoon @@ -1007,7 +1007,7 @@ ^+ ap-core =. stats.yak :+ +(change.stats.yak) - (shaz (mix (add dap change.stats.yak) eny)) + (shaz (mix (add dap change.stats.yak) eny)) :: TODO: so bad, use +og now =. agent-name dap =. agent-routes routes diff --git a/pkg/arvo/sys/vane/khan.hoon b/pkg/arvo/sys/vane/khan.hoon new file mode 100644 index 0000000000..62b1999b9e --- /dev/null +++ b/pkg/arvo/sys/vane/khan.hoon @@ -0,0 +1,217 @@ +:: %khan, thread runner +:: +:: this vane presents a command/response interface for running +:: threads. two modes are supported: %fard for intra-arvo +:: requests (i.e. within the same kernel space) and %fyrd for +:: external requests (e.g. from the unix control plane.) +:: +:: both modes take a thread start request consisting of a +:: namespace, thread name, and input data; they respond over the +:: same duct with either success or failure. %fard takes its +:: input arguments as a cage and produces %arow, which contains +:: a cage on success (or tang on failure). %fyrd takes an output +:: mark and input page; it produces %avow, which contains a page +:: on success. +:: +:: threads currently expect input and produce output as vase, +:: not cage. %fard/%arow use cage instead since this is the +:: eventual desired thread API; however, the input mark is +:: currently ignored, and the output mark is always %noun. (for +:: forward compatibility, it is safe to specify %noun as the +:: input mark.) +:: +:: %fyrd does mark conversion on both ends, and additionally +:: lifts its input into a $unit. this second step is done +:: because threads conventionally take their input as a unit, +:: with ~ for the case of "no arguments". +:: +:: n.b. the current convention for threads is to use !< to +:: unpack their input vase. !< imposes the requirement that the +:: input type nests within the specified type. this limits %fyrd +:: to threads with inputs for which a named mark exists; it is +:: impossible to use %noun in general since it does not nest. +:: threads written against the current vase-based API could use +:: ;; instead of !< to unpack their input, thus allowing the +:: use of %fyrd with %noun. however the eventual solution is +:: probably to make threads consume and produce cages, and do +:: mark conversion where appropriate. +!: +!? 164 +:: +=, khan +|= our=ship +=> |% :: %khan types + +$ move [p=duct q=(wite note gift)] :: + +$ note :: out request $-> + $~ [%g %deal *sock *term *deal:gall] :: + $% $: %g :: to %gall + $>(%deal task:gall) :: full transmission + == :: + $: %k :: to self + $>(%fard task) :: internal thread + == == :: + +$ sign :: in response $<- + $% $: %gall :: from %gall + $>(%unto gift:gall) :: update + == :: + $: %khan :: from self + $>(?(%arow %avow) gift) :: thread result + == == :: + +$ khan-state :: + $: %0 :: state v0 + hey=duct :: unix duct + tic=@ud :: tid counter + == :: + -- :: +=> +|% +++ get-beak + |= [=bear now=@da] + ?@(bear [our bear %da now] bear) +:: +++ get-dais + |= [=beak =mark rof=roof] + ^- dais:clay + ?~ ret=(rof ~ %cb beak /[mark]) + ~|(mark-unknown+mark !!) + ?~ u.ret + ~|(mark-invalid+mark !!) + ?> =(%dais p.u.u.ret) + !<(dais:clay q.u.u.ret) +:: +++ get-tube + |= [=beak =mark =out=mark rof=roof] + ^- tube:clay + ?~ ret=(rof ~ %cc beak /[mark]/[out-mark]) + ~|(tube-unknown+[mark out-mark] !!) + ?~ u.ret + ~|(tube-invalid+[mark out-mark] !!) + ?> =(%tube p.u.u.ret) + !<(tube:clay q.u.u.ret) +:: +++ make-wire + |= [=beak =mark] + ^- wire + [%fyrd (en-beam beak mark ~)] +:: +++ read-wire + |= =wire + ^- (pair beak mark) + ~| khan-read-wire+wire + ?> ?=([%fyrd ^] wire) + =/ =beam (need (de-beam t.wire)) + ?>(?=([@ ~] s.beam) beam(s i.s.beam)) +:: +++ start-spider + |= =vase + ^- note + [%g %deal [our our] %spider %poke %spider-start vase] +:: +++ watch-spider + |= =path + ^- note + [%g %deal [our our] %spider %watch path] +-- +=| khan-state +=* state - +|= [now=@da eny=@uvJ rof=roof] +=* khan-gate . +^? +|% +:: +call: handle a +task request +:: +++ call + |= $: hen=duct + dud=(unit goof) + wrapped-task=(hobo task) + == + ^- [(list move) _khan-gate] + :: + =/ =task ((harden task) wrapped-task) + ?^ dud + ~|(%khan-call-dud (mean tang.u.dud)) + ?+ -.task [~ khan-gate] + %born + [~ khan-gate(hey hen, tic 0)] + :: + %fard + =/ tid=@ta + %^ cat 3 + 'khan-fyrd--' + (scot %uv (sham (mix tic eny))) + =. tic +(tic) + =* fyd p.task + =/ =beak (get-beak bear.fyd now) + =/ args [~ `tid beak name.fyd q.args.fyd] + :_ khan-gate + %+ turn + :~ (watch-spider /thread-result/[tid]) + (start-spider !>(args)) + == + |=(=note ^-(move [hen %pass //g note])) + :: + %fyrd + =* fyd p.task + =/ =beak (get-beak bear.fyd now) + =/ =wire (make-wire beak p.args.fyd) + =/ =dais:clay (get-dais beak p.q.args.fyd rof) + =/ =vase + (slap (vale.dais q.q.args.fyd) !,(*hoon [~ u=.])) + =- [[hen %pass wire -]~ khan-gate] + [%k %fard bear.fyd name.fyd p.q.args.fyd vase] + == +:: +load: migrate an old state to a new khan version +:: +++ load + |= old=khan-state + ^+ khan-gate + khan-gate(state old) +:: +scry: nothing to see as yet +:: +++ scry + ^- roon + |= [lyc=gang car=term bem=beam] + ^- (unit (unit cage)) + ~ +++ stay state +:: +take: handle responses. +:: +++ take + |= [tea=wire hen=duct dud=(unit goof) hin=sign] + ^- [(list move) _khan-gate] + ?^ dud + ~|(%khan-take-dud (mean tang.u.dud)) + :_ khan-gate + ?- -.hin + %gall + ?+ -.p.hin ~ + ?(%poke-ack %watch-ack) + ?~ p.p.hin ~ + %- (slog 'khan-ack' u.p.p.hin) + [hen %give %arow %| -.p.hin u.p.p.hin]~ + :: + %fact + =* cag cage.p.hin + ?+ p.cag ~&(bad-fact+p.cag !!) + %thread-fail + =/ =tang !<(tang q.cag) + %- (slog 'khan-fact' tang) + [hen %give %arow %| p.cag tang]~ + :: + %thread-done + [hen %give %arow %& %noun q.cag]~ + == + == + :: + %khan + ?. ?=(%arow +<.hin) ~ + ?. ?=([%fyrd *] tea) ~ + =* row p.hin + ?. ?=(%& -.row) + [hen %give %avow row]~ + =/ [=beak =mark] (read-wire tea) + =/ =tube:clay (get-tube beak p.p.row mark rof) + =/ =vase (tube q.p.row) + [hen %give %avow %& mark q.vase]~ + == +-- diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 6967e68837..6c48fe74e5 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -4,7 +4,7 @@ => ..lull ~% %zuse ..part ~ |% -++ zuse %419 +++ zuse %418 :: :: :: :::: :: :: (2) engines :: :: :: @@ -3495,6 +3495,14 @@ |= jon=json ?> ?=([%n *] jon) (rash p.jon dem) + :: :: ++ns:dejs:format + ++ ns :: number as signed + |= jon=json + ^- @s + ?> ?=([%n *] jon) + %+ rash p.jon + %+ cook new:si + ;~(plug ;~(pose (cold %| (jest '-')) (easy %&)) dem) :: :: ++no:dejs:format ++ no :: number as cord |=(jon=json ?>(?=([%n *] jon) p.jon)) @@ -3844,55 +3852,6 @@ ++ new-desk |= [=desk tako=(unit tako) files=(map path page)] [%c %park desk &/[(drop tako) (~(run by files) (lead %&))] *rang] - :: +an: $ankh interface door - :: - ++ an - |_ nak=ankh - :: +dug: produce ankh at path - :: - ++ dug - |= =path - ^- (unit ankh) - ?~ path `nak - ?~ kid=(~(get by dir.nak) i.path) - ~ - $(nak u.kid, path t.path) - :: +get: produce file at path - :: - ++ get - |= =path - ^- (unit cage) - ?~ nik=(dug path) ~ - ?~ fil.u.nik ~ - `q.u.fil.u.nik - :: +mup: convert sub-tree at .pre to (map path [lobe cage]) - :: - ++ mup - |= pre=path - =- ~? =(~ -) [%oh-no-empty pre] - - - ^- (map path [lobe cage]) - =/ nek=(unit ankh) (dug pre) - ?~ nek - ~& [%oh-no-empty-pre pre ~(key by dir.nak)] - ~ - =. nak u.nek - ~? =(~ nak) [%oh-no-empty-nak pre] - =| pax=path - =| res=(map path [=lobe =cage]) - |- ^+ res - =? res ?=(^ fil.nak) (~(put by res) pax u.fil.nak) - :: =/ anz=(list [seg=@ta =ankh]) ~(tap by dir.nak) - :: |- ^+ res - :: ?~ anz res - :: %_ $ - :: anz t.anz - :: res ^$(pax (snoc pax seg.i.anz), nak ankh.i.anz) - :: == - %+ roll ~(tap by dir.nak) - |= [[seg=@ta =ankh] res=_res] - ^$(pax (snoc pax seg), nak ankh, res res) - -- -- :: :: :::: ++differ :: (2d) hunt-mcilroy diff --git a/pkg/arvo/ted/aqua/ames.hoon b/pkg/arvo/ted/aqua/ames.hoon index 80125cbc78..04c9126121 100644 --- a/pkg/arvo/ted/aqua/ames.hoon +++ b/pkg/arvo/ted/aqua/ames.hoon @@ -70,5 +70,5 @@ == [cards this] :: -++ handle-arvo-response _!! +++ handle-arvo-response |=(* !!) -- diff --git a/pkg/arvo/ted/aqua/dill.hoon b/pkg/arvo/ted/aqua/dill.hoon index 4d3b7b2e4e..e001a65dc1 100644 --- a/pkg/arvo/ted/aqua/dill.hoon +++ b/pkg/arvo/ted/aqua/dill.hoon @@ -43,5 +43,5 @@ == [cards this] :: -++ handle-arvo-response _!! +++ handle-arvo-response |=(* !!) -- diff --git a/pkg/arvo/ted/azimuth-tracker.hoon b/pkg/arvo/ted/azimuth-tracker.hoon deleted file mode 100644 index 26c0e7ee24..0000000000 --- a/pkg/arvo/ted/azimuth-tracker.hoon +++ /dev/null @@ -1,305 +0,0 @@ -/- spider -/+ strandio, *azimuthio -=, strand=strand:spider -=, jael -|% -+$ pending-udiffs (map number:block udiffs:point) -+$ app-state - $: %2 - url=@ta - =number:block - =pending-udiffs - blocks=(list block) - whos=(set ship) - == -+$ in-poke-data - $% [%listen whos=(list ship) =source:jael] - [%watch url=@ta] - == -+$ in-peer-data ~ --- -:: -:: Async helpers -:: -|% -++ topics - |= ships=(set ship) - ^- (list ?(@ux (list @ux))) - :: The first topic should be one of these event types - :: - :- => azimuth-events:azimuth - :~ broke-continuity - changed-keys - lost-sponsor - escape-accepted - == - :: If we're looking for a specific set of ships, specify them as - :: the second topic. Otherwise don't specify the second topic so - :: we will match all ships. - :: - ?: =(~ ships) - ~ - [(turn ~(tap in ships) ,@) ~] -:: -++ get-logs-by-hash - |= [url=@ta whos=(set ship) =hash:block] - =/ m (strand udiffs:point) - ^- form:m - ;< =json bind:m - %+ request-rpc url - :* `'logs by hash' - %eth-get-logs-by-hash - hash - ~[azimuth:contracts:azimuth] - (topics whos) - == - =/ event-logs=(list event-log:rpc:ethereum) - (parse-event-logs:rpc:ethereum json) - =/ =udiffs:point (event-logs-to-udiffs event-logs) - (pure:m udiffs) -:: -++ get-logs-by-range - |= [url=@ta whos=(set ship) =from=number:block =to=number:block] - =/ m (strand udiffs:point) - ^- form:m - ;< =json bind:m - %+ request-rpc url - :* `'logs by range' - %eth-get-logs - `number+from-number - `number+to-number - ~[azimuth:contracts:azimuth] - (topics whos) - == - =/ event-logs=(list event-log:rpc:ethereum) - (parse-event-logs:rpc:ethereum json) - =/ =udiffs:point (event-logs-to-udiffs event-logs) - (pure:m udiffs) -:: -++ event-logs-to-udiffs - |= event-logs=(list =event-log:rpc:ethereum) - ^- =udiffs:point - %+ murn event-logs - |= =event-log:rpc:ethereum - ^- (unit [=ship =udiff:point]) - ?~ mined.event-log - ~ - ?: removed.u.mined.event-log - ~& [%removed-log event-log] - ~ - =/ =id:block [block-hash block-number]:u.mined.event-log - =, azimuth-events:azimuth - =, abi:ethereum - ?: =(broke-continuity i.topics.event-log) - =/ who=@ (decode-topics t.topics.event-log ~[%uint]) - =/ num=@ (decode-results data.event-log ~[%uint]) - `[who id %rift num] - ?: =(changed-keys i.topics.event-log) - =/ who=@ (decode-topics t.topics.event-log ~[%uint]) - =/ [enc=octs aut=octs sut=@ud rev=@ud] - %+ decode-results data.event-log - ~[[%bytes-n 32] [%bytes-n 32] %uint %uint] - `[who id %keys rev sut (pass-from-eth:azimuth enc aut sut)] - ?: =(lost-sponsor i.topics.event-log) - =/ [who=@ pos=@] - (decode-topics t.topics.event-log ~[%uint %uint]) - `[who id %spon ~] - ?: =(escape-accepted i.topics.event-log) - =/ [who=@ wer=@] - (decode-topics t.topics.event-log ~[%uint %uint]) - `[who id %spon `wer] - ~& [%bad-topic event-log] - ~ -:: -++ jael-update - |= =udiffs:point - =/ m (strand ,~) - |- ^- form:m - =* loop $ - ?~ udiffs - (pure:m ~) - =/ =path /(scot %p ship.i.udiffs) - =/ cards - :~ [%give %fact ~[/] %azimuth-udiff !>(i.udiffs)] - [%give %fact ~[path] %azimuth-udiff !>(i.udiffs)] - == - ;< ~ bind:m (send-raw-cards:strandio cards) - loop(udiffs t.udiffs) -:: -++ handle-azimuth-tracker-poke - =/ m (strand ,in-poke-data) - ^- form:m - ;< =vase bind:m - ((handle:strandio ,vase) (take-poke:strandio %azimuth-tracker-poke)) - =/ =in-poke-data !<(in-poke-data vase) - (pure:m in-poke-data) --- -:: -:: Main loop -:: -|% -:: -:: Switch eth node -:: -++ handle-watch - |= state=app-state - =/ m (strand ,app-state) - ^- form:m - ;< =in-poke-data bind:m handle-azimuth-tracker-poke - ?. ?=(%watch -.in-poke-data) - ignore:strandio - (pure:m state(url url.in-poke-data)) -:: -:: Send %listen to jael -:: -++ handle-listen - |= state=app-state - =/ m (strand ,app-state) - ^- form:m - ;< =in-poke-data bind:m handle-azimuth-tracker-poke - ?. ?=(%listen -.in-poke-data) - ignore:strandio - =/ card - [%pass /lo %arvo %j %listen (silt whos.in-poke-data) source.in-poke-data] - ;< ~ bind:m (send-raw-card:strandio card) - (pure:m state) -:: -:: Start watching a node -:: -++ handle-peer - |= state=app-state - =/ m (strand ,app-state) - ;< =path bind:m ((handle:strandio ,path) take-watch:strandio) - =: number.state 0 - pending-udiffs.state *pending-udiffs - blocks.state *(list block) - whos.state - =/ who=(unit ship) ?~(path ~ `(slav %p i.path)) - ?~ who - ~ - (~(put in whos.state) u.who) - == - :: - ;< ~ bind:m send-cancel-request:strandio - (get-updates state) -:: -:: Get more blocks -:: -++ handle-wake - |= state=app-state - =/ m (strand ,app-state) - ^- form:m - ;< ~ bind:m ((handle:strandio ,~) (take-wake:strandio ~)) - (get-updates state) -:: -:: Get updates since last checked -:: -++ get-updates - |= state=app-state - =/ m (strand ,app-state) - ^- form:m - ;< =latest=block bind:m (get-latest-block url.state) - ;< state=app-state bind:m (zoom state number.id.latest-block) - |- ^- form:m - =* walk-loop $ - ?: (gth number.state number.id.latest-block) - ;< now=@da bind:m get-time:strandio - ;< ~ bind:m (send-wait:strandio (add now ~m5)) - (pure:m state) - ;< =block bind:m (get-block-by-number url.state number.state) - ;< [=new=pending-udiffs new-blocks=(lest ^block)] bind:m - %- take-block - [url.state whos.state pending-udiffs.state block blocks.state] - =: pending-udiffs.state new-pending-udiffs - blocks.state new-blocks - number.state +(number.id.i.new-blocks) - == - walk-loop -:: -:: Process a block, detecting and handling reorgs -:: -++ take-block - |= [url=@ta whos=(set ship) =a=pending-udiffs =block blocks=(list block)] - =/ m (strand ,[pending-udiffs (lest ^block)]) - ^- form:m - ?: &(?=(^ blocks) !=(parent-hash.block hash.id.i.blocks)) - (rewind url a-pending-udiffs block blocks) - ;< =b=pending-udiffs bind:m - (release-old-events a-pending-udiffs number.id.block) - ;< =new=udiffs:point bind:m (get-logs-by-hash url whos hash.id.block) - =. b-pending-udiffs (~(put by b-pending-udiffs) number.id.block new-udiffs) - (pure:m b-pending-udiffs block blocks) -:: -:: Release events if they're more than 30 blocks ago -:: -++ release-old-events - |= [=pending-udiffs =number:block] - =/ m (strand ,^pending-udiffs) - ^- form:m - =/ rel-number (sub number 30) - =/ =udiffs:point (~(get ja pending-udiffs) rel-number) - ;< ~ bind:m (jael-update udiffs) - (pure:m (~(del by pending-udiffs) rel-number)) -:: -:: Reorg detected, so rewind until we're back in sync -:: -++ rewind - |= [url=@ta =pending-udiffs =block blocks=(list block)] - =/ m (strand ,[^pending-udiffs (lest ^block)]) - |- ^- form:m - =* loop $ - ?~ blocks - (pure:m pending-udiffs block blocks) - ?: =(parent-hash.block hash.id.i.blocks) - (pure:m pending-udiffs block blocks) - ;< =next=^block bind:m (get-block-by-number url number.id.i.blocks) - ?: =(~ pending-udiffs) - ;< ~ bind:m (disavow block) - loop(block next-block, blocks t.blocks) - =. pending-udiffs (~(del by pending-udiffs) number.id.block) - loop(block next-block, blocks t.blocks) -:: -:: Tell subscribers there was a deep reorg -:: -++ disavow - |= =block - =/ m (strand ,~) - ^- form:m - (jael-update [*ship id.block %disavow ~]~) -:: -:: Zoom forward to near a given block number. -:: -:: Zooming doesn't go forward one block at a time. As a -:: consequence, it cannot detect and handle reorgs. Only use it -:: at a safe distance -- 500 blocks ago is probably sufficient. -:: -++ zoom - |= [state=app-state =latest=number:block] - =/ m (strand ,app-state) - ^- form:m - =/ zoom-margin=number:block 100 - ?: (lth latest-number (add number.state zoom-margin)) - (pure:m state) - =/ to-number=number:block (sub latest-number zoom-margin) - ;< =udiffs:point bind:m - (get-logs-by-range url.state whos.state number.state to-number) - ;< ~ bind:m (jael-update udiffs) - =. number.state +(to-number) - =. blocks.state ~ - (pure:m state) --- -:: -:: Main -:: -^- thread:spider -|= args=vase -=/ m (strand ,vase) -^- form:m -;< ~ bind:m - %- (main-loop:strandio ,app-state) - :~ handle-listen - handle-watch - handle-wake - handle-peer - == -(pure:m *vase) diff --git a/pkg/arvo/ted/azimuth/snap-logs.hoon b/pkg/arvo/ted/azimuth/snap-logs.hoon index 4e513440c2..044f14cdd5 100644 --- a/pkg/arvo/ted/azimuth/snap-logs.hoon +++ b/pkg/arvo/ted/azimuth/snap-logs.hoon @@ -9,7 +9,8 @@ lib=naive-transactions, ethereum, dice -/* logs %eth-logs /app/azimuth/logs/eth-logs +:: /* logs %eth-logs /app/azimuth/logs/eth-logs +=/ logs ~ =, strand=strand:spider :: => |% +$ card card:agent:gall diff --git a/pkg/arvo/ted/eth-watcher.hoon b/pkg/arvo/ted/eth-watcher.hoon index d06ace4a1f..c3e093122f 100644 --- a/pkg/arvo/ted/eth-watcher.hoon +++ b/pkg/arvo/ted/eth-watcher.hoon @@ -13,7 +13,8 @@ =/ m (strand:strandio ,vase) ^- form:m ;< =latest=block bind:m (get-latest-block:ethio url.pup) -;< pup=watchpup bind:m (zoom pup number.id.latest-block) +=+ last=number.id.latest-block +;< pup=watchpup bind:m (zoom pup last (min last (fall to.pup last))) =| vows=disavows ;< pup=watchpup bind:m (fetch-batches pup) ::?. eager.pup @@ -79,7 +80,7 @@ :: at a safe distance -- 100 blocks ago is probably sufficient. :: ++ zoom - |= [pup=watchpup =latest=number:block] + |= [pup=watchpup =latest=number:block up-to=number:block] =/ m (strand:strandio ,watchpup) ^- form:m =/ zoom-margin=number:block 30 @@ -87,7 +88,11 @@ ?: (lth latest-number (add number.pup zoom-margin)) (pure:m pup) =/ up-to-number=number:block - (min (add 10.000.000 number.pup) (sub latest-number zoom-margin)) + ;: min + (add 10.000.000 number.pup) + (sub latest-number zoom-margin) + up-to + == |- =* loop $ ?: (gth number.pup up-to-number) diff --git a/pkg/arvo/ted/eth/get-tx-receipts.hoon b/pkg/arvo/ted/eth/get-tx-receipts.hoon new file mode 100644 index 0000000000..c000628e47 --- /dev/null +++ b/pkg/arvo/ted/eth/get-tx-receipts.hoon @@ -0,0 +1,33 @@ +:: eth/get-tx-receipts +:: +:: asks an ethereum node for transaction receipts from a list of transaction +:: hashes. returns a (list [@t json]), where @t is the transaction hash in +:: hex written as a cord, and json is the receipt +:: +/+ ethereum, ethio, *strandio +=, jael +:: +|= args=vase +=+ !<([url=@t tx-hashes=(list @ux)] args) +=/ m (strand ,vase) +=| out=(list [@t json]) +|^ +^- form:m +=* loop $ +?: =(~ tx-hashes) (pure:m !>(out)) +;< res=(list [@t json]) bind:m + (request-receipts url (scag 100 tx-hashes)) +%_ loop + out (welp out res) + tx-hashes (slag 100 tx-hashes) +== +:: +++ request-receipts + |= [url=@t tx-hashes=(list @ux)] + %+ request-batch-rpc-strict:ethio url + %+ turn tx-hashes + |= txh=@ux + ^- [(unit @t) request:rpc:ethereum] + :- `(crip '0' 'x' ((x-co:co 64) txh)) + [%eth-get-transaction-receipt txh] +-- diff --git a/pkg/arvo/ted/naive-csv.hoon b/pkg/arvo/ted/naive-csv.hoon new file mode 100644 index 0000000000..3ce3029eba --- /dev/null +++ b/pkg/arvo/ted/naive-csv.hoon @@ -0,0 +1,390 @@ +:: naive-csv: produces csv file containing L2 transaction data +:: +:: takes in the network to use and the ethereum node url to grab data from. +:: it starts with the azimuth snapshot and scries the logs from %azimuth. +:: it then produces a csv file containing the following data on L2 +:: transactions: +:: +:: - block number +:: - timestamp +:: - roller address +:: - roll hash +:: - tx hash +:: - sending ship +:: - sending proxy +:: - nonce +:: - gas price +:: - length of input data +:: - success or failure +:: - function name +:: - spawning ship (^sein:title) +:: +:: A lot of the data-scrounging here is stuff that %roller already keeps track +:: of. We could just scry it from there, but then this thread needs to be run +:: on the roller ship. So we rebuild the list of historical transactions +:: ourselves so that this can run from any ship. +:: +/- dice, + spider +:: +/+ dice, + ethereum, + ethio, + naive, + naive-tx=naive-transactions, + *strandio +:: starting snapshot. this may not be the right starting point once we have +:: clay tombstoning and the snapshot may be updated +:: +/* snap %azimuth-snapshot /app/azimuth/version-0/azimuth-snapshot +:: +=, strand=strand:spider +=, jael +:: +^- thread:spider +=< process-logs +=> + |% + :: imported logs is cast as $events + +$ events (list event-log:rpc:ethereum) + +$ address address:naive :: @ux + +$ keccak @ux :: used for transaction and roll hashes + +$ blocknum number:block :: @udblocknumber + +$ net net:dice :: ?(%mainnet %ropsten %local %default) + +$ roll-dat :: all data required for each roll + [[gas=@ud sender=address] =effects:naive] + +$ block-dat :: all data required for each block + [timestamp=@da rolls=(map keccak roll-dat)] + +$ block-map (map blocknum block-dat) + +$ rolls-map (map blocknum (map keccak effects:naive)) + :: + +$ action + $? %transfer-point + %spawn + %configure-keys + %escape + %cancel-escape + %adopt + %reject + %detach + %set-management-proxy + %set-spawn-proxy + %set-transfer-proxy + == + :: + +$ tx-data + $: =blocknum + timestamp=@da + roller=address + roll-hash=keccak + tx-hash=keccak + sender=ship + proxy=proxy:naive + nonce=nonce:naive + gas=@ud + length=@ux + suc=? + =action + parent=ship + == + -- +:: +|% + :: +process-logs is the main process. it grabs the azimuth snapshop, runs + :: +naive on the logs, grabs the timestamps and gas costs for each roll, + :: then flattens them into a list of $tx-data and saves them to disk. + :: + ++ process-logs + |= arg=vase + =+ !<([~ =net node-url=@t] arg) + =/ pax=path /naive-exports/csv :: data will be saved here + =/ m (strand ,vase) + ^- form:m + ;< =events bind:m (scry events /gx/azimuth/logs/noun) + =/ [naive-contract=address chain-id=@] + [naive chain-id]:(get-network:dice net) + =/ snap=snap-state:dice snap + :: + ;< ~ bind:m + %- flog-text %+ weld "naive-csv: processing {} ethereum logs " + "with {<(lent events)>} events" + =/ =rolls-map + (compute-effects nas.snap events net naive-contract chain-id) + ;< ~ bind:m (flog-text "naive-csv: getting timestamps") + ;< tim=thread-result bind:m + %+ await-thread %eth-get-timestamps + !>([node-url ~(tap in ~(key by rolls-map))]) + =/ timestamps %- ~(gas by *(map blocknum @da)) + ?- tim + [%.y *] ;;((list [@ud @da]) q.p.tim) + [%.n *] + => (mean 'naive-csv: %eth-get-timestamps failed' p.tim) + !! + == + ;< ~ bind:m (flog-text "naive-csv: got timestamps") + ;< ~ bind:m (flog-text "naive-csv: getting tx receipts") + ;< gaz=thread-result bind:m + %+ await-thread %eth-get-tx-receipts + !>([node-url (get-roll-hashes rolls-map)]) + =/ gas-sender %- ~(gas by *(map keccak [gas=@ud sender=address])) + ?- gaz + [%.y *] (parse-gas-sender ;;((list [@t json]) q.p.gaz)) + [%.n *] + => (mean 'naive-csv: %eth-tx-receipts failed' p.gaz) + !! + == + ;< ~ bind:m (flog-text "naive-csv: got tx receipts") + =/ csv=(list cord) + (make-csv (flatten (collate-roll-data rolls-map timestamps gas-sender))) + ;< ~ bind:m (export-csv csv pax) + ;< ~ bind:m (flog-text :(weld "naive-csv: csv saved to %" (spud pax) "/")) + :: + (pure:m !>(~)) + :: +collate-roll-data throws naive:effects, timestamps, and gas costs into + :: one $block-map + :: + ++ collate-roll-data + |= $: =rolls-map + timestamps=(map blocknum @da) + roll-receipts=(map keccak [gas=@ud sender=address]) + == + =/ blocknums=(list blocknum) ~(tap in ~(key by rolls-map)) + =| =block-map + ^+ block-map + |- + ?~ blocknums block-map + =/ =blocknum i.blocknums + =/ rolls=(map keccak [[gas=@ud sender=address] =effects:naive]) + %- ~(gas by *(map keccak [[gas=@ud sender=address] =effects:naive])) + %+ turn ~(tap in ~(key by (~(got by rolls-map) blocknum))) + |= txh=keccak + :+ txh + (~(got by roll-receipts) txh) + (~(got by (~(got by rolls-map) blocknum)) txh) + %= $ + blocknums t.blocknums + block-map %+ ~(put by block-map) + blocknum + [(~(got by timestamps) blocknum) rolls] + == + :: +flatten takes a $block-map and creates a $tx-data for every transaction + :: in every roll, returned as a (list tx-data) + :: + ++ flatten + |= =block-map + =/ blocks=(list [blocknum block-dat]) ~(tap by block-map) + =| tx-list=(list tx-data) + ^+ tx-list + :: recurse through the list of blocks, getting the rolls submitted in that + :: block, their timestamp, and the gas price of that roll + :: + |- + =* block-loop $ + ?~ blocks tx-list + =/ block=[=blocknum =block-dat] i.blocks + =/ roll-list=(list [=keccak =roll-dat]) ~(tap by rolls.block-dat.block) + =| block-tx-list=(list tx-data) + :: recurse through each roll, getting the transaction data from the effects + :: + |- + =* roll-loop $ + ?~ roll-list + %= block-loop + blocks t.blocks + tx-list (welp tx-list block-tx-list) + == + =/ roll=[=keccak =roll-dat] i.roll-list + :: recurse through the list of effects, building up transaction data as we + :: go. there's a choice here to use the effects, or the submitted + :: raw-tx. the effects include whether or not a transaction failed, + :: which is important data not a part of the submitted raw-tx. we + :: could determine this ourselves, but we build the effects anyways when + :: computing the state transitions, so we may as well use them. + :: + :: an individual transaction results in up to 3 diffs: a %nonce, a %tx, and + :: a %point. they always appear in this order. successful transactions + :: always have all 3, while failed transactions only have %nonce and %tx. + :: note that the nonce listed is always the expected nonce - we can't know + :: what nonce was actually submitted without the private key of the signer. + :: + =| roll-tx-list=(list tx-data) + =| =tx-data + =| nonce-and-tx=[_| _|] + |- + =* effect-loop $ + :: if we are processing a new transaction, initialize the parts of tx-data + :: that are identical for every transaction in the roll + =? tx-data =([| |] nonce-and-tx) + :* blocknum.block timestamp.block-dat.block sender.roll-dat.roll + keccak.roll *keccak *ship *proxy:naive *nonce:naive + gas.roll-dat.roll *@ | *action *ship + == + :: if we've gotten both the %nonce and %tx diff from a transaction, add the + :: tx-data to the list of tx for the roll + :: + ?: =([& &] nonce-and-tx) + %= effect-loop + nonce-and-tx [| |] + roll-tx-list (snoc roll-tx-list tx-data) + == + :: if we've finished looping through the effects, add the tx list from the + :: roll to the list of tx for the block + :: + ?~ effects.roll-dat.roll + %= roll-loop + roll-list t.roll-list + block-tx-list (welp block-tx-list roll-tx-list) + == + :: + =/ =diff:naive i.effects.roll-dat.roll + :: we ignore %operator, %dns, %point diffs + :: + ?+ diff + $(effects.roll-dat.roll t.effects.roll-dat.roll) + :: %nonce is always the first diff from a given transaction. + :: + [%nonce *] + %= effect-loop + -.nonce-and-tx & + sender.tx-data ship.diff + nonce.tx-data nonce.diff + proxy.tx-data proxy.diff + parent.tx-data (^sein:title ship.diff) + effects.roll-dat.roll t.effects.roll-dat.roll + == + :: %tx is always the second diff from a given transaction. + :: + [%tx *] + %= effect-loop + +.nonce-and-tx & + effects.roll-dat.roll t.effects.roll-dat.roll + action.tx-data +<.tx.raw-tx.diff + suc.tx-data ?~ err.diff & | + length.tx-data `@`-.raw.raw-tx.diff + tx-hash.tx-data (hash-raw-tx:naive-tx raw-tx.diff) + == + == + :: + ++ parse-gas-sender + |= res=(list [@t json]) + ^- (list [=keccak [gas=@ud sender=address]]) + %+ turn res + |= [id=@t =json] + ^- [=keccak [gas=@ud sender=address]] + :- (hex-to-num:ethereum id) + :- %- parse-hex-result:rpc:ethereum + ~| json + ?> ?=(%o -.json) + (~(got by p.json) 'effectiveGasPrice') :: gas used in wei + %- parse-hex-result:rpc:ethereum + ~| json + ?> ?=(%o -.json) + (~(got by p.json) 'from') + :: +get-roll-hashes makes a list of hashes of all transactions from $rolls-map + :: + ++ get-roll-hashes + |= =rolls-map ^- (list keccak) + %- zing + %+ turn ~(val by rolls-map) + |= a=(map keccak effects:naive) + ~(tap in ~(key by a)) + :: +compute-effects calls +naive to compute the state transitions for all + :: logs, but it returns a map that only has the effects for L2 transactions, + :: leaving out L1 transactions. we need to compute all of them in order to + :: determine whether the transactions were valid. + :: + ++ compute-effects + |= $: nas=^state:naive + =events + =net + naive-contract=address + chain-id=@ud + == + =| out=rolls-map + ^+ out + :: + |- + ?~ events out + =/ log=event-log:rpc:ethereum i.events + ?~ mined.log + ~& >> 'naive-csv: empty log' + $(events t.events) + =/ =blocknum block-number.u.mined.log + =/ =^input:naive + :- blocknum + ?. =(naive-contract address.log) + :- %log + [address.log (data-to-hex:dice data.log) topics.log] + ?~ input.u.mined.log + ~& >> 'naive-csv: empty L2 transaction' + [%bat *@] + [%bat u.input.u.mined.log] + =^ =effects:naive nas + (%*(. naive lac |) verifier:naive-tx chain-id nas input) + %= $ + events t.events + out ?. =(%bat +<.input) + out :: skip L1 logs + =/ cur (~(get by out) blocknum) + ?~ cur + %+ ~(put by out) blocknum + (my [[transaction-hash.u.mined.log effects]~]) + %+ ~(put by out) blocknum + (~(put by u.cur) transaction-hash.u.mined.log effects) + == + :: +export-csv writes a (list cord) as csv to disk at .pax + :: + ++ export-csv + |= [in=(list cord) pax=path] + =/ m (strand ,~) + ^- form:m + ;< =bowl:spider bind:m get-bowl + =- (send-raw-card %pass / %arvo %c %info -) + %+ foal:space:userlib + ;: weld + /(scot %p our.bowl)/base/(scot %da now.bowl) + pax + /(scot %da now.bowl)/txt + == + [%txt !>(in)] + :: +make-csv takes in a (list tx-data) and makes it into a (list cord) to be + :: saved as a csv file + :: + ++ make-csv + |= in=(list tx-data) + ^- (list cord) + :- %- crip + ;: weld + "block number," + "timestamp," + "roller address," + "roll hash," + "tx hash," + "sending ship," + "sending proxy," + "nonce," + "gas price," + "length of input data," + "success or failure," + "function name," + "parent" + == + %+ turn in + |= =tx-data + %- crip + ;: weld + (scow %ud blocknum.tx-data) "," + (scow %da timestamp.tx-data) "," + (scow %ux roller.tx-data) "," + (scow %ux roll-hash.tx-data) "," + (scow %ux tx-hash.tx-data) "," + (scow %p sender.tx-data) "," + (scow %tas proxy.tx-data) "," + (scow %ud nonce.tx-data) "," + (scow %ud gas.tx-data) "," + (scow %ux length.tx-data) "," + (scow %f suc.tx-data) "," + (scow %tas action.tx-data) "," + (scow %p parent.tx-data) + == +-- diff --git a/pkg/arvo/ted/ph/all.hoon b/pkg/arvo/ted/ph/all.hoon index 9fb13636e1..34f8db8728 100644 --- a/pkg/arvo/ted/ph/all.hoon +++ b/pkg/arvo/ted/ph/all.hoon @@ -4,7 +4,7 @@ ^- thread:spider |= args=vase =/ m (strand ,vase) -=+ !<(group=(list @tas) args) +=+ !<([~ group=(list @tas)] args) ;< =bowl:spider bind:m get-bowl =/ threads=(list @tas) ?- group @@ -20,8 +20,8 @@ == :: [%all ~] - =+ .^(=arch %cy /(scot %p our.bowl)/home/(scot %da now.bowl)/ted/ph) - %+ turn (turn ~(tap by dir.arch) head) + =+ .^(=arch %cy /(scot %p our.bowl)/base/(scot %da now.bowl)/ted/ph) + %+ turn (sort (turn ~(tap by dir.arch) head) aor) |= =term (cat 3 'ph-' term) :: @@ -29,11 +29,24 @@ (turn group |=(=term (cat 3 'ph-' term))) == :: -=| results=(list [@tas thread-result]) +=| results=(list [n=@tas r=thread-result]) |- ^- form:m =* loop $ -?~ threads - (pure:m !>(results)) -;< =thread-result bind:m (await-thread i.threads *vase) -;< ~ bind:m (flog-text "ph-all: {} complete") -loop(threads t.threads, results [[i.threads thread-result] results]) +?^ threads + ?: =(%ph-all i.threads) + loop(threads t.threads) + ;< ~ bind:m (flog-text "ph-all: {} started") + ;< =thread-result bind:m (await-thread i.threads *vase) + ;< ~ bind:m (flog-text "ph-all: {} complete") + loop(threads t.threads, results [[i.threads thread-result] results]) +:: +|- +=* loop $ +?~ results (pure:m !>(~)) ::TODO maybe collate vases +?: ?=(%& -.r.i.results) loop(results t.results) +=* name n.i.results +=* mess p.r.i.results +;< ~ bind:m (flog-text "ph-all: {(trip name)} failed: {(trip -.mess)}") +;< ~ bind:m (flog-tang +.mess) +;< ~ bind:m (flog-text "") +loop(results t.results) diff --git a/pkg/arvo/ted/ph/breach-multiple.hoon b/pkg/arvo/ted/ph/breach-multiple.hoon index 33eca2ea8b..35d69b1adb 100644 --- a/pkg/arvo/ted/ph/breach-multiple.hoon +++ b/pkg/arvo/ted/ph/breach-multiple.hoon @@ -12,13 +12,13 @@ ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (init-ship ~marbud |) ;< file=@t bind:m (touch-file ~bud %kids %foo) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m (breach-and-hear ~bud ~marbud) ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (breach-and-hear ~marbud ~bud) ;< ~ bind:m (init-ship ~marbud |) ;< file=@t bind:m (touch-file ~bud %kids %bar) ;< file=@t bind:m (touch-file ~bud %kids %baz) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/breach-sudden.hoon b/pkg/arvo/ted/ph/breach-sudden.hoon index 6e1c91ece4..d50646a3ae 100644 --- a/pkg/arvo/ted/ph/breach-sudden.hoon +++ b/pkg/arvo/ted/ph/breach-sudden.hoon @@ -14,13 +14,13 @@ ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (init-ship ~marbud |) ;< file=@t bind:m (touch-file ~bud %kids %foo) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m (breach ~bud) ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m - (dojo ~bud "|merge %home ~marbud %kids, =gem %only-this") + (dojo ~bud "|merge %base ~marbud %kids, =gem %only-this") ;< file=@t bind:m (touch-file ~bud %kids %bar) ;< file=@t bind:m (touch-file ~bud %kids %baz) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/breach-sync.hoon b/pkg/arvo/ted/ph/breach-sync.hoon index e40cf9f68c..ee1021f36d 100644 --- a/pkg/arvo/ted/ph/breach-sync.hoon +++ b/pkg/arvo/ted/ph/breach-sync.hoon @@ -1,5 +1,6 @@ :: This tests that syncs are correctly restarted after a breach :: +::TODO breach tests broken by dangling bone? /- spider /+ *ph-io =, strand=strand:spider @@ -12,17 +13,17 @@ ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (init-ship ~marbud |) ;< file=@t bind:m (touch-file ~bud %kids %foo) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) :: Merge so that when we unify history with the %only-this merge later, we -:: don't get a spurious conflict in %home +:: don't get a spurious conflict in %base :: -;< ~ bind:m (dojo ~marbud "|merge %kids our %home") +;< ~ bind:m (dojo ~marbud "|merge %kids our %base") ;< ~ bind:m (breach-and-hear ~bud ~marbud) ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (dojo ~bud "|merge %kids ~marbud %kids, =gem %only-this") ;< file=@t bind:m (touch-file ~bud %kids %bar) ;< file=@t bind:m (touch-file ~bud %kids %baz) -;< ~ bind:m (check-file-touched ~marbud %home file) +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/change-file.hoon b/pkg/arvo/ted/ph/change-file.hoon index 34b3b4d4ee..7fa19faaa8 100644 --- a/pkg/arvo/ted/ph/change-file.hoon +++ b/pkg/arvo/ted/ph/change-file.hoon @@ -6,7 +6,7 @@ =/ m (strand ,vase) ;< ~ bind:m start-simple ;< ~ bind:m (init-ship ~bud &) -;< file=@t bind:m (touch-file ~bud %home %foo) -;< ~ bind:m (check-file-touched ~bud %home file) +;< file=@t bind:m (touch-file ~bud %base %foo) +;< ~ bind:m (check-file-touched ~bud %base file) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/child-sync.hoon b/pkg/arvo/ted/ph/child-sync.hoon index 1d67a4e516..bcc4c8043c 100644 --- a/pkg/arvo/ted/ph/child-sync.hoon +++ b/pkg/arvo/ted/ph/child-sync.hoon @@ -7,8 +7,8 @@ ;< ~ bind:m start-simple ;< ~ bind:m (init-ship ~bud &) ;< ~ bind:m (init-ship ~marbud &) -;< file=@t bind:m (touch-file ~bud %home %foo) -;< ~ bind:m (dojo ~bud "|merge %kids our %home") -;< ~ bind:m (check-file-touched ~marbud %home file) +;< file=@t bind:m (touch-file ~bud %base %foo) +;< ~ bind:m (dojo ~bud "|merge %kids our %base") +;< ~ bind:m (check-file-touched ~marbud %base file) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/child-update.hoon b/pkg/arvo/ted/ph/child-update.hoon index e377aed6e2..a182e7b50a 100644 --- a/pkg/arvo/ted/ph/child-update.hoon +++ b/pkg/arvo/ted/ph/child-update.hoon @@ -6,9 +6,9 @@ |^ =/ m (strand ,vase) ;< ~ bind:m start-simple -;< ~ bind:m (init-ship ~bud |) -;< ~ bind:m (init-ship ~marbud |) -;< [path @t] bind:m (modify ~bud %home) +;< ~ bind:m (init-ship ~bud &) +;< ~ bind:m (init-ship ~marbud &) +;< * bind:m (modify ~bud %base) ;< [=path file=@t] bind:m (modify ~bud %kids) ;< ~ bind:m (check-touched ~marbud %kids path file) ;< ~ bind:m end @@ -26,18 +26,16 @@ %^ cat 3 '=/ new-val 57 ' (get-val /sys/zuse/hoon) =/ mar-contents - %^ cat 3 (get-val /mar/js/hoon) - ' ~& > new-val=new-val .' - =/ js-contents - %^ cat 3 (get-val /app/landscape/js/channel/js) - 'extra' + %^ cat 3 (get-val /mar/hoon/hoon) + ::TODO doesn't get picked up somehow + :: ' ~& > new-val=new-val .' + ' ~& > %testing .' =/ files - :~ [/sys/zuse/hoon zuse-contents] - [/mar/js/hoon mar-contents] - [/app/landscape/js/channel/js js-contents] + :~ ::[/sys/zuse/hoon zuse-contents] + [/mar/hoon/hoon mar-contents] == ;< ~ bind:m (send-events (insert-files:util her desk files)) - (pure:m /app/landscape/js/channel/js js-contents) + (pure:m /mar/hoon/hoon mar-contents) :: ++ aqua-path |= =path diff --git a/pkg/arvo/ted/ph/group-rejoin.hoon b/pkg/arvo/ted/ph/group-rejoin.hoon index c2e7c272d6..4a6ab5772f 100644 --- a/pkg/arvo/ted/ph/group-rejoin.hoon +++ b/pkg/arvo/ted/ph/group-rejoin.hoon @@ -8,7 +8,7 @@ ^- form:m =* loop $ ;< [her=^ship =unix-effect] bind:m take-unix-effect - ?: (is-dojo-output:util ship her unix-effect "activated app home/{(trip agent)}") + ?: (is-dojo-output:util ship her unix-effect "activated app base/{(trip agent)}") (pure:m ~) loop :: diff --git a/pkg/arvo/ted/ph/hi.hoon b/pkg/arvo/ted/ph/hi.hoon index 02ecd1b8f2..7ae015d5be 100644 --- a/pkg/arvo/ted/ph/hi.hoon +++ b/pkg/arvo/ted/ph/hi.hoon @@ -7,7 +7,6 @@ ;< ~ bind:m start-simple ;< ~ bind:m (init-ship ~bud &) ;< ~ bind:m (init-ship ~dev &) -;< ~ bind:m (init-ship ~dev &) ;< ~ bind:m (send-hi ~bud ~dev) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/ph/migrate/end.hoon b/pkg/arvo/ted/ph/migrate/end.hoon deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pkg/arvo/ted/ph/migrate/make-groups.hoon b/pkg/arvo/ted/ph/migrate/make-groups.hoon deleted file mode 100644 index 4e814ddaeb..0000000000 --- a/pkg/arvo/ted/ph/migrate/make-groups.hoon +++ /dev/null @@ -1,49 +0,0 @@ -/- spider, - graph-store, - graph-view, - post, - *resource, - *group -/+ *ph-io, strandio -=, strand=strand:spider -=> -|% -:: -++ create-group - |= our=@p - %^ dojo-thread our %group-create - :- %group-view-action - :* %create - %group-1 - [%open ~ ~] - 'Test Group' - 'A description' - == -:: -++ join-group - |= our=@p - %^ poke-app our %group-view - :- %group-view-action - :* %join - [~zod %group-1] - ~zod - == --- -:: -^- thread:spider -|= vase -=/ m (strand ,vase) -;< ~ bind:m start-simple -;< ~ bind:m (create-group ~zod) -;< ~ bind:m (join-group ~bus) -;< ~ bind:m (join-group ~web) -;< ~ bind:m (send-hi ~zod ~bus) -;< ~ bind:m (send-hi ~zod ~web) -;< ~ bind:m (send-hi ~bus ~zod) -;< ~ bind:m (send-hi ~bus ~web) -;< ~ bind:m (send-hi ~web ~zod) -;< ~ bind:m (send-hi ~web ~bus) -(pure:m *vase) - - - diff --git a/pkg/arvo/ted/ph/migrate/setup.hoon b/pkg/arvo/ted/ph/migrate/setup.hoon deleted file mode 100644 index 71b420b903..0000000000 --- a/pkg/arvo/ted/ph/migrate/setup.hoon +++ /dev/null @@ -1,38 +0,0 @@ -/- spider, - graph-store, - graph-view, - post, - *resource, - *group -/+ *ph-io, strandio -=, strand=strand:spider -=> -|% -:: -++ create-group - |= our=@p - %^ dojo-thread our %group-create - :- %group-view-action - :* %create - %group-1 - [%open ~ ~] - 'Test Group' - 'A description' - == -:: -++ hang - =/ m (strand ,~) - ^- form:m - |= tin=strand-input:strand - `[%wait ~] --- -:: -^- thread:spider -|= vase -=/ m (strand ,vase) -;< ~ bind:m start-simple -;< ~ bind:m hang -(pure:m *vase) - - - diff --git a/pkg/arvo/ted/ph/migrate/wait.hoon b/pkg/arvo/ted/ph/migrate/wait.hoon deleted file mode 100644 index 7eda30b9cb..0000000000 --- a/pkg/arvo/ted/ph/migrate/wait.hoon +++ /dev/null @@ -1,42 +0,0 @@ -/- spider, - graph-store, - graph-view, - post, - *resource, - *group -/+ *ph-io, strandio -=, strand=strand:spider -=> -|% -:: -++ create-group - |= our=@p - %^ dojo-thread our %group-create - :- %group-view-action - :* %create - %group-1 - [%open ~ ~] - 'Test Group' - 'A description' - == -:: -++ join-group - |= our=@p - %^ poke-app our %group-view - :- %group-view-action - :* %join - [~zod %group-1] - ~zod - == --- -:: -^- thread:spider -|= vase -=/ m (strand ,vase) -;< ~ bind:m start-simple -;< ~ bind:m (sleep ~s10) -;< ~ bind:m end -(pure:m *vase) - - - diff --git a/pkg/arvo/ted/ph/moon-az.hoon b/pkg/arvo/ted/ph/moon-az.hoon index 22a077941f..870bc9819e 100644 --- a/pkg/arvo/ted/ph/moon-az.hoon +++ b/pkg/arvo/ted/ph/moon-az.hoon @@ -12,11 +12,13 @@ ;< ~ bind:m (init-ship ~bud |) ;< ~ bind:m (init-ship ~marbud |) ;< ~ bind:m (init-ship ~linnup-torsyx |) -;< ~ bind:m (init-ship ~linnup-torsyx-linnup-torsyx |) -;< ~ bind:m (send-hi ~bud ~linnup-torsyx-linnup-torsyx) -;< ~ bind:m (send-hi ~linnup-torsyx-linnup-torsyx ~marbud) +::NOTE only shortmoons supported, see also /ted/aqua/ames +lane-to-ship +;< ~ bind:m (init-moon ~torsyx-linnup-torsyx |) +;< ~ bind:m (send-hi ~bud ~torsyx-linnup-torsyx) +;< ~ bind:m (send-hi ~torsyx-linnup-torsyx ~marbud) ;< ~ bind:m (init-ship ~dev |) -;< ~ bind:m (send-hi ~linnup-torsyx-linnup-torsyx ~dev) -;< ~ bind:m (send-hi ~dev ~linnup-torsyx-linnup-torsyx) +::TODO these hi's never come through! +;< ~ bind:m (send-hi ~torsyx-linnup-torsyx ~dev) +;< ~ bind:m (send-hi ~dev ~torsyx-linnup-torsyx) ;< ~ bind:m end (pure:m *vase) diff --git a/pkg/arvo/ted/roller/send.hoon b/pkg/arvo/ted/roller/send.hoon index 6302f34f2f..eeadd7efbf 100644 --- a/pkg/arvo/ted/roller/send.hoon +++ b/pkg/arvo/ted/roller/send.hoon @@ -13,12 +13,26 @@ =/ =address:ethereum (address-from-prv:key:ethereum pk) ;< expected-nonce=@ud bind:m (get-next-nonce:ethio endpoint address) -=/ batch-data=octs - %+ cad:naive 3 - %- flop - %+ roll txs - |= [=raw-tx:naive out=(list octs)] - [raw.raw-tx 65^sig.raw-tx out] +:: Infura enforces a max calldata size (32, 64, 128 Kb?) so we calculate how +:: many txs are included in a batch of that size, and only send those +:: +=/ max-calldata=@ud 128.000 +=/ [n-txs=@ud batch-data=octs] + =| n-txs=@ud + =| size=@ud + =| out=(list octs) + |- ^- [@ud octs] + ?~ txs + [n-txs (cad:naive 3 (flop out))] + =* raw-tx i.txs + =. size :(add 65 p.raw.raw-tx size) + ?: (gth size max-calldata) + [n-txs (cad:naive 3 (flop out))] + %_ $ + n-txs +(n-txs) + txs t.txs + out [raw.raw-tx 65^sig.raw-tx out] + == :: if the batch is malformed, emit error to kick it out of sending :: ?~ (parse-roll:naive q.batch-data) @@ -26,16 +40,15 @@ :: if chain expects a different nonce, don't send this transaction :: ?. =(nonce expected-nonce) - ~& >>> [%unexpected-nonce nonce expected+expected-nonce] %- pure:m !> ^- [%.n @tas @t] :+ %.n %not-sent ?: (lth expected-nonce nonce) - :: if ahead, it will use the same next-gas-price when resending + :: if ahead, use the same next-gas-price when resending :: %ahead-nonce - :: if behind, start out-of-sync flow + :: if behind, start out-of-sync flow if batch was not sent before :: %behind-nonce :: if a gas-price of 0 was specified, fetch the recommended one @@ -49,22 +62,23 @@ :: gasLimit = G_transaction + G_txdatanonzero × dataByteLength :: where :: G_transaction = 21000 gas (base fee) -:: + G_txdatanonzero = 68 gas +:: + G_txdatanonzero = 16 gas (previously 68; see EIP-2028) :: * dataByteLength = (65 + raw) * (lent txs) bytes :: -:: TODO: enforce max number of tx in batch? +:: 1.000 gas are added to the base fee as extra, for emitting the log :: -=/ gas-limit=@ud (add 21.000 (mul 68 p.batch-data)) -:: if we cannot pay for the transaction, don't bother sending it out -:: -=/ max-cost=@ud (mul gas-limit use-gas-price) +=/ gas-limit=@ud (add 22.000 (mul 16 p.batch-data)) +=/ max-cost=@ud (mul gas-limit use-gas-price) ;< balance=@ud bind:m (get-balance:ethio endpoint address) ?: (gth max-cost balance) + :: if we cannot pay for the transaction, don't bother sending it out + :: (pure:m !>(%.n^[%not-sent %insufficient-roller-balance])) :: ::NOTE this fails the thread if sending fails, which in the app gives us :: the "retry with same gas price" behavior we want +:: ;< =response:rpc bind:m %+ send-batch endpoint =; tx=transaction:rpc:ethereum @@ -80,19 +94,23 @@ :: log batch tx-hash to getTransactionReceipt(tx-hash) :: ~? &(?=(%result -.response) ?=(%s -.res.response)) - ^- [nonce=@ud batch-hash=@t gas=@ud] - nonce^(so:dejs:format res.response)^use-gas-price + ^- [nonce=@ud batch-hash=@t gas=@ud sent-txs=@ud bytes=@ud] + :* nonce + (so:dejs:format res.response) + use-gas-price + n-txs + p.batch-data + == %- pure:m -!> ^- (each @ud [term @t]) +!> ^- (each [@ud @ud] [term @t]) :: TODO: capture if the tx fails (e.g. Runtime Error: revert) :: check that tx-hash in +.response is non-zero? -:: enforce max here, or in app? :: ?+ -.response %.n^[%error 'unexpected rpc response'] %error %.n^[%error message.response] :: add five gwei to gas price of next attempt :: - %result %.y^(add use-gas-price 5.000.000.000) + %result %.y^[n-txs (add use-gas-price 5.000.000.000)] == :: ::TODO should be distilled further, partially added to strandio? diff --git a/pkg/arvo/ted/work.hoon b/pkg/arvo/ted/work.hoon index 150e145d12..5eb76769c5 100644 --- a/pkg/arvo/ted/work.hoon +++ b/pkg/arvo/ted/work.hoon @@ -2,7 +2,7 @@ :: :: With no arguments, creates and mounts a %work desk. :: If there are arguments, each one is created and mounted. -:: All desks are begun by merging from our %home desk. +:: All desks are begun by merging from our %base desk. :: /- spider /+ strandio @@ -16,10 +16,10 @@ |- ^- form:m =* loop $ ?~ desks (pure:m !>(ok=&)) -:: |merge %work our %home +:: |merge %work our %base :: ;< [=ship =desk =case:clay] bind:m get-beak:strandio -=/ kiln-merge [i.desks ship %home case %auto] +=/ kiln-merge [i.desks ship %base case %auto] ;< ~ bind:m (poke-our:strandio %hood %kiln-merge !>(kiln-merge)) ;< ~ bind:m (trace:strandio leaf+"work: merged {}" ~) :: sleep 10ms to defer to new event diff --git a/pkg/arvo/tests/run/hints.hoon b/pkg/arvo/tests/run/hints.hoon new file mode 100644 index 0000000000..7481b105bd --- /dev/null +++ b/pkg/arvo/tests/run/hints.hoon @@ -0,0 +1,21 @@ +:: Test that these hints do not crash the runtime +:: there is no need to include the hints for dynamic %bout +:: since all hoon tests exersize dynamic %bout +|% +:: these test that the hilt-trace hints +:: are safe to run or ignore +++ test-hela-hilt + ~> %hela + ~ +++ test-nara-hilt + ~> %nara + ~ +:: these test that the hint-trace hints +:: are safe to run or ignore +++ test-hela-hint + ~> %hela.[1 leaf+"test-hela-trace-hint"] + ~ +++ test-nara-hint + ~> %nara.[1 leaf+"test-nara-trace-hint"] + ~ +-- diff --git a/pkg/arvo/tests/sys/hoon/map.hoon b/pkg/arvo/tests/sys/hoon/map.hoon index 3ea30f6cc2..5957e458cf 100644 --- a/pkg/arvo/tests/sys/hoon/map.hoon +++ b/pkg/arvo/tests/sys/hoon/map.hoon @@ -670,10 +670,6 @@ ;: weld :: +uno:by arm test :: - :: Checks with empty map (a or b) - :: - %- expect-fail - |. ((~(uno by m-nul) m-des) union-gate) %+ expect-eq !> m-des !> ((~(uno by m-des) m-nul) union-gate) diff --git a/pkg/arvo/tests/sys/vane/ames.hoon b/pkg/arvo/tests/sys/vane/ames.hoon index 16638ddc13..668ab28124 100644 --- a/pkg/arvo/tests/sys/vane/ames.hoon +++ b/pkg/arvo/tests/sys/vane/ames.hoon @@ -1,10 +1,16 @@ /+ *test /= ames /sys/vane/ames +/= jael /sys/vane/jael :: construct some test fixtures :: -=/ nec (ames ~nec) -=/ bud (ames ~bud) -=/ comet (ames ~bosrym-podwyl-magnes-dacrys--pander-hablep-masrym-marbud) +=/ nec (ames ~nec) +=/ bud (ames ~bud) +=/ marbud (ames ~marbud) +:: +=/ our-comet ~bosrym-podwyl-magnes-dacrys--pander-hablep-masrym-marbud +=/ our-comet2 ~togdut-rosled-fadlev-siddys--botmun-wictev-sapfus-marbud +=/ comet (ames our-comet) +=/ comet2 (ames our-comet2) :: =. now.nec ~1111.1.1 =. eny.nec 0xdead.beef @@ -22,8 +28,17 @@ =/ bud-pub pub:ex:crypto-core.ames-state.bud =/ bud-sec sec:ex:crypto-core.ames-state.bud :: +=. now.marbud ~1111.1.1 +=. eny.marbud 0xbeef.beef +=. life.ames-state.marbud 4 +=. rof.marbud |=(* ``[%noun !>(*(list turf))]) +=. crypto-core.ames-state.marbud (pit:nu:crub:crypto 512 (shaz 'marbud')) +=/ marbud-pub pub:ex:crypto-core.ames-state.marbud +=/ marbud-sec sec:ex:crypto-core.ames-state.marbud +:: =. now.comet ~1111.1.1 =. eny.comet 0xbeef.cafe +=. life.ames-state.comet 1 =. rof.comet |=(* ``[%noun !>(*(list turf))]) =. crypto-core.ames-state.comet %- nol:nu:crub:crypto @@ -31,12 +46,25 @@ 3q3td.T4UF0.d5sDL.JGpZq.S3A92.QUuWg.IHdw7.izyny.j9W92 =/ comet-pub pub:ex:crypto-core.ames-state.comet =/ comet-sec sec:ex:crypto-core.ames-state.comet - +:: +=. now.comet2 ~1111.1.1 +=. eny.comet2 0xcafe.cafe +=. life.ames-state.comet2 1 +=. rof.comet2 |=(* ``[%noun !>(*(list turf))]) +=. crypto-core.ames-state.comet2 (pit:nu:crub:crypto 512 0v1eb4) +=/ comet2-pub pub:ex:crypto-core.ames-state.comet2 +=/ comet2-sec sec:ex:crypto-core.ames-state.comet2 +:: =/ nec-sym (derive-symmetric-key:ames bud-pub nec-sec) =/ bud-sym (derive-symmetric-key:ames nec-pub bud-sec) ?> =(nec-sym bud-sym) +=/ nec-marbud-sym (derive-symmetric-key:ames marbud-pub nec-sec) :: -=/ comet-sym (derive-symmetric-key:ames bud-pub comet-sec) +=/ marbud-sym (derive-symmetric-key:ames marbud-pub comet-sec) +=/ marbud2-sym (derive-symmetric-key:ames marbud-pub comet2-sec) +=/ bud-marbud-sym (derive-symmetric-key:ames bud-pub marbud-sec) +:: +=/ comet-sym (derive-symmetric-key:ames bud-pub comet-sec) :: =. peers.ames-state.nec %+ ~(put by peers.ames-state.nec) ~bud @@ -44,29 +72,95 @@ =. -.peer-state :* symmetric-key=bud-sym life=3 + rift=0 public-key=bud-pub sponsor=~nec == =. route.peer-state `[direct=%.y `lane:ames`[%& ~nec]] [%known peer-state] :: +=. peers.ames-state.nec + %+ ~(put by peers.ames-state.nec) ~marbud + =| =peer-state:ames + =. -.peer-state + :* symmetric-key=nec-marbud-sym + life=5 + rift=0 + public-key=marbud-pub + sponsor=~bud + == + =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] + [%known peer-state] +:: =. peers.ames-state.bud %+ ~(put by peers.ames-state.bud) ~nec =| =peer-state:ames =. -.peer-state :* symmetric-key=nec-sym life=2 + rift=0 public-key=nec-pub sponsor=~nec == =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] [%known peer-state] +:: +=. peers.ames-state.comet + %+ ~(put by peers.ames-state.comet) ~marbud + =| =peer-state:ames + =. -.peer-state + :* symmetric-key=marbud-sym + life=5 + rift=0 + public-key=marbud-pub + sponsor=~bud + == + =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] + [%known peer-state] +=. peers.ames-state.comet + %+ ~(put by peers.ames-state.comet) ~bud + =| =peer-state:ames + =. -.peer-state + :* symmetric-key=bud-marbud-sym + life=3 + rift=0 + public-key=bud-pub + sponsor=~bud + == + =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] + [%known peer-state] +=. peers.ames-state.comet2 + %+ ~(put by peers.ames-state.comet2) ~marbud + =| =peer-state:ames + =. -.peer-state + :* symmetric-key=marbud2-sym + life=5 + rift=0 + public-key=marbud-pub + sponsor=~bud + == + =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] + [%known peer-state] +=. peers.ames-state.comet2 + %+ ~(put by peers.ames-state.comet2) ~bud + =| =peer-state:ames + =. -.peer-state + :* symmetric-key=bud-marbud-sym + life=3 + rift=0 + public-key=bud-pub + sponsor=~bud + == + =. route.peer-state `[direct=%.y `lane:ames`[%| `@`%lane-bar]] + [%known peer-state] :: metamorphose :: => .(nec +:(call:(nec) ~[//unix] ~ %born ~)) => .(bud +:(call:(bud) ~[//unix] ~ %born ~)) +=> .(comet +:(call:(comet) ~[//unix] ~ %born ~)) +=> .(comet2 +:(call:(comet2) ~[//unix] ~ %born ~)) :: helper core -:: +:: => |% ++ move-to-packet @@ -195,7 +289,7 @@ =^ moves1 bud (call bud ~[//unix] %hear lane-foo blob) =^ moves2 bud =/ =point:ames - :* rift=1 + :* rift=0 life=4 keys=[[life=4 [crypto-suite=1 `@`nec-pub]] ~ ~] sponsor=`~bus @@ -213,7 +307,7 @@ :: %+ expect-eq !> %- sy - :~ :^ ~[//unix] %pass /bone/~bus/1 + :~ :^ ~[//unix] %pass /bone/~bus/0/1 [%g %plea ~bus %g /talk [%first %post]] :: :^ ~[//unix] %pass /qos @@ -222,57 +316,6 @@ !> (sy ,.moves3) == :: -++ test-comet-encounter ^- tang - :: - =/ lane-foo=lane:ames [%| `@ux``@`%lane-foo] - :: - =/ =open-packet:ames - :* public-key=`@`comet-pub - sndr=our.comet - sndr-life=1 - rcvr=~bud - rcvr-life=3 - == - =/ packet - ~! ames - (encode-open-packet:ames open-packet crypto-core.ames-state.comet) - =/ blob (encode-packet:ames packet) - :: - =^ moves0 bud (call bud ~[//unix] %hear lane-foo blob) - :: - =/ =plea:ames [%g /talk [%first %post]] - =/ =shut-packet:ames - :* bone=1 - message-num=1 - [%& num-fragments=1 fragment-num=0 (jam plea)] - == - =/ =packet:ames - %: encode-shut-packet:ames - shut-packet - comet-sym - our.comet - ~bud - sndr-life=1 - rcvr-life=3 - == - =/ blob (encode-packet:ames packet) - =^ moves1 bud (call bud ~[//unix] %hear lane-foo blob) - :: - ;: weld - %+ expect-eq - !> ~ - !> moves0 - :: - %+ expect-eq - !> :~ :* ~[//unix] %pass /qos %d %flog %text - "; {} is your neighbor" - == - :* ~[//unix] %pass /bone/(scot %p our.comet)/1 - %g %plea our.comet plea - == == - !> moves1 - == -:: ++ test-message-flow ^- tang :: ~nec -> %plea -> ~bud :: @@ -280,11 +323,11 @@ =^ moves2 bud (call bud ~[//unix] %hear (snag-packet 0 moves1)) :: ~bud -> %done -> ~nec :: - =^ moves3 bud (take bud /bone/~nec/1 ~[//unix] %g %done ~) + =^ moves3 bud (take bud /bone/~nec/0/1 ~[//unix] %g %done ~) =^ moves4 nec (call nec ~[//unix] %hear (snag-packet 0 moves3)) :: ~bud -> %boon -> ~nec :: - =^ moves5 bud (take bud /bone/~nec/1 ~[//unix] %g %boon [%post 'first1!!']) + =^ moves5 bud (take bud /bone/~nec/0/1 ~[//unix] %g %boon [%post 'first1']) =^ moves6 nec (call nec ~[//unix] %hear (snag-packet 0 moves5)) :: ~nec -> %done -> ~bud (just make sure ~bud doesn't crash on ack) :: @@ -293,7 +336,8 @@ ;: weld %+ expect-eq !> :~ [~[//unix] %pass /qos %d %flog %text "; ~nec is your neighbor"] - [~[//unix] %pass /bone/~nec/1 %g %plea ~nec %g /talk [%get %post]] + :^ ~[//unix] %pass /bone/~nec/0/1 + [%g %plea ~nec %g /talk [%get %post]] == !> moves2 :: @@ -306,10 +350,82 @@ !> (sy ,.moves4) :: %+ expect-eq - !> [~[/g/talk] %give %boon [%post 'first1!!']] + !> [~[/g/talk] %give %boon [%post 'first1']] !> (snag 0 `(list move:ames)`moves6) == :: +++ test-comet-message-flow ^- tang + :: same as test-message-flow, but ~nec will send a sendkeys packet to request + :: comet's self-attestation directly + :: + =^ moves0 nec (call nec ~[/g/talk] %plea our-comet %g /talk [%get %post]) + =^ moves1 comet (call comet ~[//unix] %hear (snag-packet 0 moves0)) + =^ moves2 comet + =/ =point:ames + :* rift=1 + life=2 + keys=[[life=2 [crypto-suite=1 `@`nec-pub]] ~ ~] + sponsor=`~nec + == + %- take + :^ comet /public-keys ~[//unix] + ^- sign:ames + [%jael %public-keys %full [n=[~nec point] ~ ~]] + :: give comet's self-attestation to ~nec; at this point, we have established + :: a channel, and can proceed as usual + :: + =^ moves3 nec (call nec ~[//unix] %hear (snag-packet 0 moves2)) + =^ moves4 comet (call comet ~[//unix] %hear (snag-packet 0 moves3)) + =^ moves5 comet (take comet /bone/~nec/0/1 ~[//unix] %g %done ~) + =^ moves6 nec (call nec ~[//unix] %hear (snag-packet 0 moves5)) + =^ moves7 comet (take comet /bone/~nec/0/1 ~[//unix] %g %boon [%post 'first1!!']) + =^ moves8 nec (call nec ~[//unix] %hear (snag-packet 0 moves7)) + :: + ;: weld + %+ expect-eq + !> [~[//unix] %pass /qos %d %flog %text "; ~nec is your neighbor"] + !> (snag 0 `(list move:ames)`moves4) + :: + %+ expect-eq + !> [~[//unix] %pass /qos %d %flog %text "; {} is your neighbor"] + !> (snag 0 `(list move:ames)`moves6) + :: + %+ expect-eq + !> [~[/g/talk] %give %boon [%post 'first1!!']] + !> (snag 0 `(list move:ames)`moves8) + == +:: +++ test-comet-comet-message-flow ^- tang + :: same as test-message-flow, but the comets need to exchange + :: self-attestations to establish a channel + :: + =^ moves0 comet (call comet ~[/g/talk] %plea our-comet2 %g /talk [%get %post]) + =^ moves1 comet2 (call comet2 ~[//unix] %hear (snag-packet 0 moves0)) + =^ moves2 comet (call comet ~[//unix] %hear (snag-packet 0 moves1)) + :: channel is now established; comet also emitted a duplicate + :: self-attestation, which we ignore + :: + =^ moves3 comet2 (call comet2 ~[//unix] %hear (snag-packet 0 moves2)) + =^ moves4 comet2 (call comet2 ~[//unix] %hear (snag-packet 1 moves2)) + =^ moves5 comet2 (take comet2 /bone/(scot %p our-comet)/0/1 ~[//unix] %g %done ~) + =^ moves6 comet2 (take comet2 /bone/(scot %p our-comet)/0/1 ~[//unix] %g %boon [%post 'first1!!']) + =^ moves7 comet (call comet ~[//unix] %hear (snag-packet 0 moves5)) + =^ moves8 comet (call comet ~[//unix] %hear (snag-packet 0 moves6)) + :: + ;: weld + %+ expect-eq + !> [~[//unix] %pass /qos %d %flog %text "; {} is your neighbor"] + !> (snag 0 `(list move:ames)`moves4) + :: + %+ expect-eq + !> [~[//unix] %pass /qos %d %flog %text "; {} is your neighbor"] + !> (snag 0 `(list move:ames)`moves7) + :: + %+ expect-eq + !> [~[/g/talk] %give %boon [%post 'first1!!']] + !> (snag 0 `(list move:ames)`moves8) + == +:: ++ test-nack ^- tang :: ~nec -> %plea -> ~bud :: @@ -318,7 +434,7 @@ :: ~bud -> nack -> ~nec :: =/ =error:ames [%flub [%leaf "sinusoidal repleneration"]~] - =^ moves3 bud (take bud /bone/~nec/1 ~[/bud] %g %done `error) + =^ moves3 bud (take bud /bone/~nec/0/1 ~[/bud] %g %done `error) =^ moves4 nec (call nec ~[//unix] %hear (snag-packet 0 moves3)) :: ~bud -> nack-trace -> ~nec :: @@ -330,4 +446,81 @@ %+ expect-eq !> [~[/g/talk] %give %done `error] !> (snag 1 `(list move:ames)`moves5) +:: +++ test-old-ames-wire ^- tang + =^ moves0 bud (call bud ~[/g/hood] %spew [%odd]~) + =^ moves1 nec (call nec ~[/g/talk] %plea ~bud %g /talk [%get %post]) + =^ moves2 bud (call bud ~[//unix] %hear (snag-packet 0 moves1)) + =^ moves3 bud (take bud /bone/~nec/1 ~[//unix] %g %done ~) + %+ expect-eq + !> 1 + !> (lent `(list move:ames)`moves3) +:: +++ test-dangling-bone ^- tang + =^ moves0 bud (call bud ~[/g/hood] %spew [%odd]~) + :: ~nec -> %plea -> ~bud + :: + =^ moves1 nec (call nec ~[/g/talk] %plea ~bud %g /talk [%get %post]) + =^ moves2 bud (call bud ~[//unix] %hear (snag-packet 0 moves1)) + :: ~bud receives a gift from %jael with ~nec's new rift + :: + =^ moves3 bud + %- take + :^ bud /public-keys ~[//unix] + ^- sign:ames + [%jael %public-keys %diff who=~nec %rift from=0 to=1] + :: %gall has a pending wire with the old rift, so sending a gift to + :: %ames on it will drop that request, not producing any moves + :: + =^ moves3 bud (take bud /bone/~nec/0/1 ~[//unix] %g %done ~) + :: + %+ expect-eq + !> ~ + !> (sy ,.moves3) +:: +++ test-ames-flow-with-new-rift ^- tang + :: ~nec receives a gift from %jael with ~bud's new rift + :: + =^ moves1 nec + %- take + :^ nec /public-keys ~[//unix] + ^- sign:ames + [%jael %public-keys %diff who=~bud %rift from=0 to=1] + :: now we try a normal message flow using the new rift in the wire + :: ~nec -> %plea -> ~bud + :: + =^ moves2 nec (call nec ~[/g/talk] %plea ~bud %g /talk [%get %post]) + =^ moves3 bud (call bud ~[//unix] %hear (snag-packet 0 moves2)) + :: ~bud -> %done -> ~nec + :: + =^ moves4 bud (take bud /bone/~nec/1/1 ~[//unix] %g %done ~) + =^ moves5 nec (call nec ~[//unix] %hear (snag-packet 0 moves4)) + :: ~bud -> %boon -> ~nec + :: + =^ moves6 bud (take bud /bone/~nec/1/1 ~[//unix] %g %boon [%post '¡hola!']) + =^ moves7 nec (call nec ~[//unix] %hear (snag-packet 0 moves6)) + :: ~nec -> %done -> ~bud (just make sure ~bud doesn't crash on ack) + :: + =^ moves8 bud (call bud ~[//unix] %hear (snag-packet 0 moves7)) + :: + ;: weld + %+ expect-eq + !> :~ [~[//unix] %pass /qos %d %flog %text "; ~nec is your neighbor"] + :^ ~[//unix] %pass /bone/~nec/0/1 + [%g %plea ~nec %g /talk [%get %post]] + == + !> moves3 + :: + %+ expect-eq + !> %- sy + :~ [~[/ames] %pass /pump/~bud/0 %b %rest ~1111.1.1..00.00.03] + [~[//unix] %pass /qos %d %flog %text "; ~bud is your neighbor"] + [~[/g/talk] %give %done error=~] + == + !> (sy ,.moves5) + :: + %+ expect-eq + !> [~[/g/talk] %give %boon [%post '¡hola!']] + !> (snag 0 `(list move:ames)`moves7) + == -- diff --git a/pkg/arvo/tests/sys/vane/clay.hoon b/pkg/arvo/tests/sys/vane/clay.hoon index cd8951206b..6da35b2ee8 100644 --- a/pkg/arvo/tests/sys/vane/clay.hoon +++ b/pkg/arvo/tests/sys/vane/clay.hoon @@ -18,6 +18,18 @@ =/ clay-gate (clay-raw ~nul) =/ fusion fusion:clay-gate :: +=> |% + ++ leak-to-deps + |= =leak:fusion + ^- (set mist:fusion) + %- sy + |- ^- (list mist:fusion) + %- zing + %+ turn ~(tap in deps.leak) + |= l=leak:fusion + :- (pour-to-mist:fusion pour.l) + ^$(leak l) + -- |% ++ test-parse-pile ^- tang =/ src "." @@ -85,11 +97,11 @@ |. =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes=(my [/lib/self/hoon &+hoon+source]~) + files=(my [/lib/self/hoon &+hoon+source]~) file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == (build-file:ford /lib/self/hoon) :: @@ -100,29 +112,28 @@ ++ test-mar-mime ^- tang =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes=(my [/mar/mime/hoon &+hoon+mar-mime]~) + files=(my [/mar/mime/hoon &+hoon+mar-mime]~) file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-nave:ford %mime) + =/ =leak:fusion leak:(~(got by sprig.nub) file+/mar/mime/hoon) ;: weld %+ expect-eq !>(*mime) (slap res !,(*hoon *vale)) :: %+ expect-eq - !> (~(gas in *(set [? path])) |^/mar/mime/hoon ~) - !> dez:(~(got by files.cache.nub) /mar/mime/hoon) + !> (~(gas in *(set mist:fusion)) vale+/mar/mime/hoon ~) + !> (leak-to-deps leak) == :: ++ test-mar-udon ^- tang =/ ford %: ford:fusion - *ankh:clay - deletes=~ - ^= changes + ^= files %- my :~ [/mar/udon/hoon &+hoon+mar-udon] [/lib/cram/hoon &+hoon+lib-cram] @@ -130,32 +141,39 @@ [/mar/txt-diff/hoon &+hoon+mar-txt-diff] == file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-nave:ford %udon) + =/ =leak:fusion leak:(~(got by sprig.nub) file+/mar/udon/hoon) ;: weld %+ expect-eq !>(*@t) (slap res !,(*hoon *vale)) :: %+ expect-eq - !> (~(gas in *(set [? path])) |^/mar/udon/hoon |^/lib/cram/hoon ~) - !> dez:(~(got by files.cache.nub) /mar/udon/hoon) + !> %- ~(gas in *(set mist:fusion)) + :~ vale+/mar/udon/hoon + vale+/lib/cram/hoon + file+/lib/cram/hoon + == + !> (leak-to-deps leak) == :: ++ test-cast-html-mime ^- tang - =/ changes + =/ files %- my :~ [/mar/mime/hoon &+hoon+mar-mime] [/mar/html/hoon &+hoon+mar-html] == =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes + files file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-cast:ford %html %mime) %+ expect-eq @@ -163,18 +181,18 @@ !> `mime`[/text/html 13 ''] :: ++ test-fascen ^- tang - =/ changes + =/ files %- my :~ [/mar/mime/hoon &+hoon+mar-mime] [/lib/foo/hoon &+hoon+'/% moo %mime\0a*vale:moo'] == =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes + files file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-file:ford /lib/foo/hoon) %+ expect-eq @@ -182,7 +200,7 @@ !> *mime :: ++ test-fasbuc ^- tang - =/ changes + =/ files %- my :~ [/mar/mime/hoon &+hoon+mar-mime] [/mar/html/hoon &+hoon+mar-html] @@ -190,11 +208,11 @@ == =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes + files file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-file:ford /lib/foo/hoon) %+ expect-eq @@ -204,49 +222,53 @@ ++ test-gen-hello ^- tang =/ ford %: ford:fusion - *ankh:clay - deletes=~ - changes=(my [/gen/hello/hoon &+hoon+gen-hello]~) + files=(my [/gen/hello/hoon &+hoon+gen-hello]~) file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-file:ford /gen/hello/hoon) + =/ =leak:fusion leak:(~(got by sprig.nub) file+/gen/hello/hoon) ;: weld %+ expect-eq !> noun+'hello, bob' (slap res (ream '(+ [*^ [%bob ~] ~])')) :: %+ expect-eq - !> (~(gas in *(set [? path])) |^/gen/hello/hoon ~) - !> dez:(~(got by files.cache.nub) /gen/hello/hoon) + !> (~(gas in *(set mist:fusion)) vale+/gen/hello/hoon ~) + !> (leak-to-deps leak) == :: ++ test-lib-strandio ^- tang =/ ford %: ford:fusion - *ankh:clay - deletes=~ - ^= changes + ^= files %- my :~ [/lib/strand/hoon &+hoon+lib-strand] [/lib/strandio/hoon &+hoon+lib-strandio] [/sur/spider/hoon &+hoon+sur-spider] == file-store=~ - *ford-cache:fusion + 0 + *flow:fusion + *flue:fusion == =/ [res=vase nub=state:ford:fusion] (build-file:ford /lib/strandio/hoon) + =/ =leak:fusion leak:(~(got by sprig.nub) file+/lib/strandio/hoon) ;: weld %- expect !>((slab %read %get-our -.res)) :: %+ expect-eq - !> %- ~(gas in *(set [? path])) - :~ [| /lib/strandio/hoon] - [| /lib/strand/hoon] - [| /sur/spider/hoon] + !> %- ~(gas in *(set mist:fusion)) + :~ vale+/lib/strandio/hoon + file+/lib/strand/hoon + vale+/lib/strand/hoon + file+/sur/spider/hoon + vale+/sur/spider/hoon == - !> dez:(~(got by files.cache.nub) /lib/strandio/hoon) + !> (leak-to-deps leak) == :: :: |utilities: helper functions for testing diff --git a/pkg/arvo/tests/sys/vane/eyre.hoon b/pkg/arvo/tests/sys/vane/eyre.hoon index 2439258e48..f8fd9ba0f7 100644 --- a/pkg/arvo/tests/sys/vane/eyre.hoon +++ b/pkg/arvo/tests/sys/vane/eyre.hoon @@ -663,7 +663,7 @@ eyre-gate now=~1111.1.2 scry=scry-provides-code - call-args=[duct=~[/gen1] ~ [%serve [~ /] [%home /gen/handler/hoon ~]]] + call-args=[duct=~[/gen1] ~ [%serve [~ /] [%base /gen/handler/hoon ~]]] expected-moves=[duct=~[/gen1] %give %bound %.y [~ /]]~ == :: outside requests a path that app1 has bound to diff --git a/pkg/arvo/tests/sys/vane/khan.hoon b/pkg/arvo/tests/sys/vane/khan.hoon new file mode 100644 index 0000000000..f327392867 --- /dev/null +++ b/pkg/arvo/tests/sys/vane/khan.hoon @@ -0,0 +1,476 @@ +:: remaining cases to test: +:: call dud +:: take dud +:: TODO when can dud happen? +:: +/+ *test +/= khan-raw /sys/vane/khan +=/ khan-gate (khan-raw ~nul) +|% +++ test-khan-fyrd-start-args + =^ born-moves khan-gate + %- khan-call :* + khan-gate + now=~1162.1.1 + scry=scry-provides-mark + call-args=[duct=~[/initial-born-duct] ~ [%born ~]] + == + =/ results-0 (expect-eq !>(~) !>(born-moves)) + =/ fyrd=(fyrd:khan cast:khan) [%base %nonexistent %noun %noun ~] + =/ now=@da (add ~1162.1.1 ~s1) + =^ start-moves khan-gate + %- khan-call :* + khan-gate + now + scry=scry-provides-mark + ^= call-args + :* duct=~[//khan/1/0vsome.ductt] ~ + %fyrd fyrd + == == + =/ results-1 (expect !>(=(1 (lent start-moves)))) + =/ mev (head start-moves) + =/ results-2 + %+ expect-eq + !> ~[//khan/1/0vsome.ductt] + !> p.mev + ?> ?=(%pass -.q.mev) + =/ results-3 + %+ expect-eq + !> /fyrd/~nul/base/~1162.1.1..00.00.01/noun + !> wire.q.mev + =/ results-4 (expect-eq !>(%k) !>(-.note.q.mev)) + ?> ?=(%fard +<.note.q.mev) + =/ fad p.note.q.mev + ;: weld + results-0 results-1 results-2 + results-3 results-4 + (expect-eq !>(%base) !>(bear.fad)) + (expect-eq !>(%nonexistent) !>(name.fad)) + (expect-eq !>(%noun) !>(p.args.fad)) + (expect-eq !>(`~) q.args.fad) + == +++ test-khan-fard-start-args + =^ born-moves khan-gate + %- khan-call :* + khan-gate + now=~1162.1.1 + scry=scry-provides-mark + call-args=[duct=~[/initial-born-duct] ~ [%born ~]] + == + =/ fard=(fyrd:khan cage) [%base %nonexistent %noun !>(~)] + =/ now=@da (add ~1162.1.1 ~s1) + =^ start-moves khan-gate + %- khan-call :* + khan-gate + now + scry=scry-provides-mark + ^= call-args + :* duct=~[//khan/1/0vthat.ductt] ~ + %fard fard + == == + =/ results-0 (expect !>(=(2 (lent start-moves)))) + :: XX overspecified + :: + =/ expected-tid (cat 3 'khan-fyrd--' (scot %uv (sham 0xdead.beef))) + =/ results-1 + %+ expect-eq + !> :* ~[//khan/1/0vthat.ductt] + %pass //g %g %deal + [~nul ~nul] %spider %watch + /thread-result/[expected-tid] + == + !> (head start-moves) + =/ mev (rear start-moves) + =/ results-2 (expect-eq !>(~[//khan/1/0vthat.ductt]) !>(p.mev)) + ?> ?=(%pass -.q.mev) + =/ results-3 (expect-eq !>(//g) !>(wire.q.mev)) + =* not note.q.mev + =/ results-4 (expect-eq !>(%g) !>(-.not)) + ?> ?=(%deal +<.not) + =/ results-5 (expect-eq !>([~nul ~nul]) !>(p.not)) + =/ results-6 (expect-eq !>(%spider) !>(q.not)) + ?> ?=(%poke -.r.not) + =* cag cage.r.not + ?> ?=(%spider-start p.cag) + =/ rag + :: XX $start-args in %/app/spider/hoon + :: + !< [p=(unit @ta) q=(unit @ta) r=beak s=term t=vase] + q.cag + =/ results-7 + %+ expect-eq + !> :* ~ `expected-tid + [~nul %base %da now] %nonexistent ~ + == + !>(rag(t ~)) + =/ results-8 (expect-eq !>(~) t.rag) + ;: weld + results-0 results-1 results-2 + results-3 results-4 results-5 + results-6 results-7 results-8 + == +++ test-khan-take-full-run-fard + =^ born-moves khan-gate + %- khan-call :* + khan-gate + now=~1162.1.1 + scry=scry-provides-mark + call-args=[duct=~[/a] ~ [%born ~]] + == + =/ results-0 (expect-eq !>(~) !>(born-moves)) + =/ fard=(fyrd:khan cage) [%base %fake %noun !>(~)] + =^ start-moves khan-gate + %- khan-call :* + khan-gate + now=(add ~1162.1.1 ~s1) + scry=scry-provides-mark + ^= call-args + :* duct=~[//khan/2/0v0] ~ + %fard fard + == == + =^ take-moves khan-gate + %- khan-take-all :* + khan-gate now=~1162.1.2 sep=~s1 scry=scry-provides-mark + :~ [//g ~[//khan/2/0v0] ~ %gall %unto %watch-ack ~] + [//g ~[//khan/2/0v0] ~ %gall %unto %poke-ack ~] + [//g ~[//khan/2/0v0] ~ %gall %unto %fact %thread-done !>(%res)] + [//g ~[//khan/2/0v0] ~ %gall %unto %kick ~] + == + == + =/ results-1 + %- expect !>(=(1 (lent take-moves))) + =/ results-2 + %+ expect-eq + !>([~[//khan/2/0v0] %give %arow %& %noun !>(%res)]) + !>((head take-moves)) + :(weld results-0 results-1 results-2) +++ test-khan-multi-fard + =^ born-moves khan-gate + %- khan-call :* + khan-gate + now=~1162.1.1 + scry=scry-provides-mark + call-args=[duct=~[/a] ~ [%born ~]] + == + =/ fard=(fyrd:khan cage) [%base %fake %noun !>(~)] + =/ khan-call-args :* + now=(add ~1162.1.1 ~s1) + scry=scry-provides-mark + ^= call-args :* + duct=~[//khan/2/0va] ~ %fard fard + == + == + =^ start-1-moves khan-gate + %- khan-call :* + khan-gate + khan-call-args + == + =^ start-2-moves khan-gate + %- khan-call :* + khan-gate + khan-call-args + == + =/ results-1 + %+ expect-spider-start-tid + 'khan-fyrd--0vir6kv.ci3nm.a8rcs.kua3e.9sp7o' + start-1-moves + =/ results-2 + %+ expect-spider-start-tid + 'khan-fyrd--0v4.la9d1.uc5cu.ngv3f.pbo8a.mlc5f' + start-2-moves + (weld results-1 results-2) +++ test-khan-take-full-run-fyrd + =^ born-moves khan-gate + %- khan-call :* + khan-gate + now=~1162.1.1 + scry=scry-provides-mark + call-args=[duct=~[/a] ~ [%born ~]] + == + =^ fyrd-moves khan-gate + %- khan-call :* + khan-gate + now=(add ~1162.1.1 ~s1) + scry=scry-provides-mark + ^= call-args + duct=~[//khan/0v0/1/0v2] ~ + %fyrd [%base %fake %noun %noun ~] + == + =/ results-0 (expect !>(=(1 (lent fyrd-moves)))) + =/ fard-move (head fyrd-moves) + ?> ?=(%pass -.q.fard-move) + ?> ?=(%k -.note.q.fard-move) + =* wir wire.q.fard-move + :: XX may erroneously break if %khan keeps state dependent on + :: its inner %fard. + :: + =^ arow-moves khan-gate + %- khan-take :* + khan-gate + now=(add ~1162.1.1 ~s3) + scry=scry-provides-mark + ^= take-args + wire=wir + duct=~[//khan/0v0/1/0v2] + dud=~ + [%khan %arow %& %noun !>(%res)] + == + =/ results-1 (expect !>(=(1 (lent arow-moves)))) + =/ row (head arow-moves) + =/ results-2 + %+ expect-eq + !>(~[//khan/0v0/1/0v2]) + !>(p.row) + =/ results-3 + %+ expect-eq + !>([%give %avow %& %noun %res]) + !>(q.row) + :(weld results-0 results-1 results-2 results-3) +++ test-khan-fard-watch-ack-fail + =^ born-moves khan-gate + %- khan-call-all :* + khan-gate now=~1162.1.1 sep=~s1 scry=scry-provides-mark + :~ [~[/a] ~ %born ~] + [~[//khan/0v0/1/0v0] ~ %fard %base %hi %noun %noun ~] + == + == + =^ watch-ack-moves khan-gate + %- khan-take :* + khan-gate now=~1162.1.2 scry=scry-provides-mark + ^= take-args + //g ~[//khan/0v0/1/0v0] ~ + %gall %unto %watch-ack `~['fail'] + == + =/ results-0 (expect !>(=(1 (lent watch-ack-moves)))) + =/ mev (head watch-ack-moves) + =/ results-1 + %+ expect-eq + !>([~[//khan/0v0/1/0v0] %give %arow %| %watch-ack ~['fail']]) + !>(mev) + (weld results-0 results-1) +++ test-khan-fard-poke-ack-fail + =^ call-moves khan-gate + %- khan-call-all :* + khan-gate now=~1162.1.1 sep=~s1 scry=scry-provides-mark + :~ [~[/a] ~ %born ~] + [~[//khan/0v0/1/0v0] ~ %fard %base %hi %noun %noun ~] + == + == + =^ take-moves khan-gate + %- khan-take-all :* + khan-gate now=~1162.1.2 sep=~s1 scry=scry-provides-mark + :~ [//g ~[//khan/0v0/1/0v0] ~ %gall %unto %watch-ack ~] + :* //g ~[//khan/0v0/1/0v0] ~ + %gall %unto %poke-ack `~['fail'] + == + [//g ~[//khan/0v0/1/0v0] ~ %gall %unto %kick ~] + == + == + =/ results-0 (expect !>(=(1 (lent take-moves)))) + =/ mev (head take-moves) + =/ results-1 + %+ expect-eq + !>([~[//khan/0v0/1/0v0] %give %arow %| %poke-ack ~['fail']]) + !>(mev) + (weld results-0 results-1) +++ test-khan-fard-thread-fail + =^ call-moves khan-gate + %- khan-call-all :* + khan-gate now=~1162.1.1 sep=~s1 scry=scry-provides-mark + :~ [~[/a] ~ %born ~] + [~[//khan/0v0/1/0v0] ~ %fard %base %hi %noun %noun ~] + == + == + =^ take-moves khan-gate + %- khan-take-all :* + khan-gate now=~1162.1.2 sep=~s1 scry=scry-provides-mark + :~ [//g ~[//khan/0v0/1/0v0] ~ %gall %unto %watch-ack ~] + [//g ~[//khan/0v0/1/0v0] ~ %gall %unto %poke-ack ~] + :* //g ~[//khan/0v0/1/0v0] ~ + %gall %unto %fact %thread-fail + !>([%woops ~['fail']]) + == + [//g ~[//khan/0v0/1/0v0] ~ %gall %unto %kick ~] + == + == + =/ results-0 (expect !>(=(1 (lent take-moves)))) + =/ mev (head take-moves) + =/ results-1 + %+ expect-eq + !> :* ~[//khan/0v0/1/0v0] %give + %arow %| %thread-fail ~['woops' 'fail'] + == + !>(mev) + (weld results-0 results-1) +++ test-khan-fyrd-arow-fail + =^ call-moves khan-gate + %- khan-call-all :* + khan-gate now=~1162.1.1 sep=~s1 scry=scry-provides-mark + :~ [~[/a] ~ %born ~] + [~[//khan/0v0/1/0v0] ~ %fyrd %base %a %noun %noun ~] + == + == + =/ results-0 (expect !>(=(1 (lent call-moves)))) + =/ fard-move (head call-moves) + ?> ?=(%pass -.q.fard-move) + =* wir wire.q.fard-move + =^ arow-moves khan-gate + %- khan-take :* + khan-gate now=~1162.1.2 scry=scry-provides-mark + ^= take-args + wir ~[//khan/0v0/1/0v0] ~ + %khan %arow %| %watch-ack ~['fail'] + == + =/ results-1 (expect !>(=(1 (lent arow-moves)))) + =/ mev (head arow-moves) + =/ results-2 + %+ expect-eq + !>([~[//khan/0v0/1/0v0] %give %avow %| %watch-ack ~['fail']]) + !>(mev) + :(weld results-0 results-1 results-2) +++ test-khan-fyrd-no-input-mark + =^ born-moves khan-gate + %- khan-call :* + khan-gate + ~1162.1.1 + scry-provides-mark + ~[/a] ~ %born ~ + == + %- expect-fail + |. + %- khan-call :* + khan-gate + (add ~1162.1.1 ~s1) + scry-provides-mark + ~[//khan/0v0/1/0v0] ~ + %fyrd %base %a %noun %bad-mark ~ + == +++ test-khan-fyrd-no-output-mark + =^ call-moves khan-gate + %- khan-call-all :* + khan-gate ~1162.1.1 ~s1 scry-provides-mark + :~ [~[/a] ~ %born ~] + [~[//khan/0v0/1/0v0] ~ %fyrd %base %a %bad-mark %noun ~] + == + == + %- expect-fail + |. + %- khan-take :* + khan-gate + ~1162.1.2 + scry-provides-mark + /fyrd/~nul/base/da/~1162.1.1..00.00.01/bad-mark + ~[//khan/0v0/1/0v0] ~ + [%khan %arow %& %noun !>(~)] + == +++ expect-spider-start-tid + |= [tid=@ta mev=(list move:khan-gate)] + ?> ?=([^ ^ ~] mev) + =* watch-move i.mev + =* start-move i.t.mev + ?> ?=([* %pass * %g %deal * %spider %watch *] watch-move) + =/ results-1 + %+ expect-eq + !>(/thread-result/[tid]) + !>(path.r.note.q.watch-move) + ?> ?=([* %pass * %g %deal * %spider %poke %spider-start *] start-move) + =/ start-args + !< [p=(unit @ta) q=(unit @ta) r=beak s=term t=vase] + q.cage.r.note.q.start-move + =/ results-2 + %+ expect-eq + !> `tid + !> q.start-args + (weld results-1 results-2) +++ khan-call + |= $: khan-gate=_khan-gate + now=@da + scry=roof + $= call-args + $: =duct + dud=(unit goof) + wrapped-task=(hobo task:khan) + == == + ^- [(list move:khan-gate) _khan-gate] + =/ khan-core + (khan-gate now eny=`@uvJ`0xdead.beef scry=scry) + (call:khan-core [duct dud wrapped-task]:call-args) +++ khan-call-all + |= $: khan-gate=_khan-gate + now=@da + sep=@dr + scry=roof + call-list=(list [p=duct q=(unit goof) r=(hobo task:khan)]) + == + ^- [(list move:khan-gate) _khan-gate] + =+ i=0 + =/ mev=(list move:khan-gate) ~ + |- + ?~ call-list [mev khan-gate] + =^ mov khan-gate + %- khan-call :* + khan-gate + now=(add now (mul sep i)) + scry=scry + call-args=i.call-list + == + $(i +(i), call-list t.call-list, mev (weld mev mov)) +++ khan-take + |= $: khan-gate=_khan-gate + now=@da + scry=roof + $= take-args + $: =wire + =duct + dud=(unit goof) + =sign:khan-gate + == == + ^- [(list move:khan-gate) _khan-gate] + =/ khan-core + (khan-gate now eny=`@uvJ`0xdead.beef scry=scry) + (take:khan-core [wire duct dud sign]:take-args) +++ khan-take-all + |= $: khan-gate=_khan-gate + now=@da + sep=@dr + scry=roof + take-list=(list [p=wire q=duct r=(unit goof) s=sign:khan-gate]) + == + ^- [(list move:khan-gate) _khan-gate] + =+ i=0 + =/ mev=(list move:khan-gate) ~ + |- + ?~ take-list [mev khan-gate] + =^ mov khan-gate + %- khan-take :* + khan-gate + now=(add now (mul sep i)) + scry=scry + take-args=i.take-list + == + $(i +(i), take-list t.take-list, mev (weld mev mov)) +++ dais-noun ^- dais:clay + |_ sam=vase + ++ diff !! + ++ form !! + ++ join !! + ++ mash !! + ++ pact !! + ++ vale |=(=noun !>(;;(^noun noun))) + -- +++ tube-noun-noun ^- tube:clay + |= =vase + !>(!<(noun vase)) +++ scry-provides-mark ^- roof + |= [gang =view =beam] + ^- (unit (unit cage)) + ?: &(=(%cb view) =(/noun s.beam)) + :^ ~ ~ %dais + !> ^- dais:clay + dais-noun + ?: &(=(%cc view) =(/noun/noun s.beam)) + :^ ~ ~ %tube + !> ^- tube:clay + tube-noun-noun + ~ +-- diff --git a/pkg/arvo/tests/sys/zuse/format.hoon b/pkg/arvo/tests/sys/zuse/format.hoon index dddc9ef2e4..4b4db49968 100644 --- a/pkg/arvo/tests/sys/zuse/format.hoon +++ b/pkg/arvo/tests/sys/zuse/format.hoon @@ -85,8 +85,8 @@ :: path) :: ++ test-beam - =/ b=beam [[p=~zod q=%home r=[%ud p=12]] s=/sys/zuse/hoon] - =/ p=path /~zod/home/12/sys/zuse/hoon + =/ b=beam [[p=~zod q=%base r=[%ud p=12]] s=/sys/zuse/hoon] + =/ p=path /~zod/base/12/sys/zuse/hoon ;: weld :: proper encode :: @@ -107,12 +107,12 @@ :: %+ expect-eq !> ~ - !> (de-beam /~zod/home) + !> (de-beam /~zod/base) :: invalid ship :: %+ expect-eq !> ~ - !> (de-beam /'~zodisok'/home/12/sys/zuse/hoon) + !> (de-beam /'~zodisok'/base/12/sys/zuse/hoon) :: invalid desk :: %+ expect-eq @@ -122,7 +122,7 @@ :: %+ expect-eq !> ~ - !> (de-beam /~zod/home/~zod/sys/zuse/hoon) + !> (de-beam /~zod/base/~zod/sys/zuse/hoon) == :: example values used in test :: @@ -131,6 +131,7 @@ ++ nul `json`~ ++ tru `json`[%b &] ++ num `json`[%n ~.12] + ++ neg `json`[%n '-3'] ++ str `json`[%s 'hey'] ++ frond `json`(frond:enjs 'foo' num) ++ obj `json`(pairs:enjs ~[['foo' num] ['bar' str]]) @@ -228,6 +229,16 @@ !> (ni num:ex) %- expect-fail |. (ni tru:ex) + :: as @s + :: + %+ expect-eq + !> -3 + !> (ns neg:ex) + %+ expect-eq + !> --12 + !> (ns num:ex) + %- expect-fail + |. (ns tru:ex) :: as cord :: %+ expect-eq diff --git a/pkg/base-dev/lib/ethereum.hoon b/pkg/base-dev/lib/ethereum.hoon index c292eec3de..9f63062f92 100644 --- a/pkg/base-dev/lib/ethereum.hoon +++ b/pkg/base-dev/lib/ethereum.hoon @@ -948,6 +948,21 @@ %- prefix-hex (render-hex-bytes 20 `@`a) :: +++ address-to-checksum + |= a=address + ^- tape + =/ hexed (render-hex-bytes 20 `@`a) + =/ hash (keccak-256:keccak:crypto (as-octs:mimes:html (crip hexed))) + =| ret=tape + =/ pos 63 + |- + ?~ hexed (prefix-hex (flop ret)) + =/ char i.hexed + ?: (lth char 58) $(pos (dec pos), ret [char ret], hexed t.hexed) + =/ nib (cut 2 [pos 1] hash) + ?: (lth 7 nib) $(pos (dec pos), ret [(sub char 32) ret], hexed t.hexed) + $(pos (dec pos), ret [char ret], hexed t.hexed) +:: ++ transaction-to-hex |= h=@ ^- tape @@ -978,5 +993,8 @@ :: ++ hex-to-num |= a=@t - (rash (rsh [3 2] a) hex) + ~| %non-hex-cord + ?> =((end [3 2] a) '0x') + =< ?<(=(0 p) q) %- need + (de:base16:mimes:html (rsh [3 2] a)) -- diff --git a/pkg/base-dev/lib/ph/io.hoon b/pkg/base-dev/lib/ph/io.hoon index d6cbed8d72..a34c00c32d 100644 --- a/pkg/base-dev/lib/ph/io.hoon +++ b/pkg/base-dev/lib/ph/io.hoon @@ -1,5 +1,5 @@ /- *aquarium, spider -/+ libstrand=strand, *strandio, util=ph-util +/+ libstrand=strand, *strandio, util=ph-util, aqua-azimuth =, strand=strand:libstrand |% ++ send-events @@ -127,7 +127,7 @@ ;< ~ bind:m (send-azimuth-action %breach who) |- ^- form:m =* loop $ - ;< ~ bind:m (sleep ~s1) + ;< ~ bind:m (sleep ~s10) ;< =bowl:spider bind:m get-bowl =/ aqua-pax :- %i @@ -137,6 +137,18 @@ (pure:m ~) loop :: +++ init-moon ::NOTE real moon always have the same keys + |= [moon=ship fake=?] + ?> ?=(%earl (clan:title moon)) + ?: fake (init-ship moon &) + =/ m (strand ,~) + ^- form:m + ;< ~ bind:m + %+ dojo (^sein:title moon) + =/ =pass pub:ex:(get-keys:aqua-azimuth moon 1) + "|moon {(scow %p moon)}, =public-key {(scow %uw pass)}" + (init-ship moon |) +:: ++ init-ship |= [=ship fake=?] =/ m (strand ,~) diff --git a/pkg/base-dev/lib/ph/util.hoon b/pkg/base-dev/lib/ph/util.hoon index 53979b4258..eee08a2ac0 100644 --- a/pkg/base-dev/lib/ph/util.hoon +++ b/pkg/base-dev/lib/ph/util.hoon @@ -59,7 +59,7 @@ :: :: Checks whether the given event is a dojo output blit containing the :: given tape -:: +::TODO should be rename -dill-output ++ is-dojo-output |= [who=ship her=ship uf=unix-effect what=tape] ?& =(who her) diff --git a/pkg/base-dev/lib/pill.hoon b/pkg/base-dev/lib/pill.hoon index 56e01b6775..1f6993fb6e 100644 --- a/pkg/base-dev/lib/pill.hoon +++ b/pkg/base-dev/lib/pill.hoon @@ -61,10 +61,10 @@ =; hav ~& user-files+(lent hav) =/ =yuki:clay :- *(list tako:clay) - %- ~(gas by *(map path (each page:clay lobe:clay))) - (turn hav |=([=path =page:clay] [path &+page])) + %- ~(gas by *(map path (each page lobe:clay))) + (turn hav |=([=path =page] [path &+page])) [/c/sync [%park des &+yuki *rang:clay]] - =| hav=(list [path page:clay]) + =| hav=(list [path page]) |- ^+ hav ?~ sal ~ =. hav $(sal t.sal) diff --git a/pkg/base-dev/lib/ring.hoon b/pkg/base-dev/lib/ring.hoon index a7be742b7f..0490c7391c 100644 --- a/pkg/base-dev/lib/ring.hoon +++ b/pkg/base-dev/lib/ring.hoon @@ -349,15 +349,16 @@ |= [our=@p now=@da ship=@p =life] ^- @udpoint :: - =/ d=[=^life =pass] + =/ d=[=^life =pass *] =/ scry-path=path - :~ %k + :~ %j (scot %p our) + %deed (scot %da now) (scot %p ship) (scot %ud life) == - .^([^life pass] scry-path) + .^([^life pass *] scry-path) :: we have the deed which has pass, which is several numbers +cat-ed :: together; pull out the keys :: @@ -376,15 +377,15 @@ ?~ invited [participants keys] :: - =/ =life - .^(life k+/(scot %p our)/life/(scot %da now)/(scot %p i.invited)) + =/ lyfe=(unit @ud) + .^((unit @ud) j+/(scot %p our)/lyfe/(scot %da now)/(scot %p i.invited)) :: - ?: =(life 0) + ?~ lyfe $(invited t.invited) :: - =/ pubkey=@udpoint (ship-life-to-pubid our now i.invited life) + =/ pubkey=@udpoint (ship-life-to-pubid our now i.invited u.lyfe) :: - =. participants (~(put in participants) [i.invited life]) + =. participants (~(put in participants) [i.invited u.lyfe]) =. keys (~(put in keys) pubkey) :: $(invited t.invited) @@ -436,11 +437,11 @@ :: get our ships' current life :: =/ our-life=life - .^(life %k /(scot %p our)/life/(scot %da now)/(scot %p our)) + .^(life %j /(scot %p our)/life/(scot %da now)/(scot %p our)) :: get our ships' secret keyfile ring :: =/ secret-ring=ring - .^(ring %k /(scot %p our)/vein/(scot %da now)/(scot %ud our-life)) + .^(ring %j /(scot %p our)/vein/(scot %da now)/(scot %ud our-life)) :: fetch the encoded auth seed from the ring :: =/ secret-auth-seed=@ diff --git a/pkg/base-dev/lib/story.hoon b/pkg/base-dev/lib/story.hoon new file mode 100644 index 0000000000..8cb3c2a936 --- /dev/null +++ b/pkg/base-dev/lib/story.hoon @@ -0,0 +1,112 @@ +/- *story +!: +^? +|% +:: XX generalize move to hoon.hoon +++ dif-ju + |= [a=story b=story] + ^- story + :: if 0 is the empty set, + :: a \ 0 = a + :: 0 \ b = 0 :: anything in 0 but not in b is by definition 0 + :: + ?: =(~ a) ~ + :: uno := (a-b) + (merged items in both a and b) + (b-a) + :: ret := (a-b) + (merged items in both a and b) + :: ret = (~(int by a) uno) :: preserve only the entries whose keys are in a + =/ uno=story + %- (~(uno by a) b) + |= [k=tako:clay proses-a=proses proses-b=proses] + ^- proses + (~(dif in proses-a) proses-b) + :: + =/ ret=story (~(int by a) uno) + :: normalizing step, remove any keys with null sets, + :: which can occur if proses-a == proses-b above + %- ~(gas by *story) + (skip ~(tap by ret) |=([k=* v=proses] ?=(~ v))) +:: +++ uni-ju + |= [a=story b=story] + ^- story + :: 0 + b = b + ?: =(~ a) b + %- (~(uno by a) b) + |= [k=tako:clay proses-a=proses proses-b=proses] + ^- proses + (~(uni in proses-a) proses-b) +:: +:: Canonical textual representation +:: +++ tako-to-text + |= [=tako:clay] + ^- tape + "commit: {<`@uv`tako>}\0a" +:: +++ proses-to-text + |= [=proses] + ^- tape + =/ proses-list=(list prose) ~(tap in proses) + ?: ?=(~ proses-list) "" + ?: ?=([prose ~] proses-list) + (prose-to-text i.proses-list) + %- tail + %^ spin `(list prose)`t.proses-list + (prose-to-text i.proses-list) + |= [prz=prose state=tape] + ^- [prose tape] + :- prz + ;: welp + state + "|||" + "\0a" + (prose-to-text prz) + == +:: +++ prose-to-text + |= prz=prose + =/ [title=@t body=@t] prz + ^- tape + ;: welp + "{(trip title)}" + "\0a\0a" + "{(trip body)}" + "\0a" + == +:: +:: Parsers +:: +++ parse-commit-hash + ;~ sfix + ;~ pfix (jest 'commit: ') + (cook @uv ;~(pfix (jest '0v') viz:ag)) + == + :: + (just '\0a') + == +:: +++ parse-title + ;~ sfix + (cook crip (star prn)) + (jest '\0a\0a') + == +:: +++ parse-body + %+ cook of-wain:format + %- star + ;~ less + ;~(pose (jest '|||\0a') (jest '---\0a')) + (cook crip ;~(sfix (star prn) (just '\0a'))) + == +:: +++ parse-prose ;~(plug parse-title parse-body) +++ parse-rest-proses (star ;~(pfix (jest '|||\0a') parse-prose)) +++ parse-proses (cook silt ;~(plug parse-prose parse-rest-proses)) +++ parse-chapter ;~(plug parse-commit-hash parse-proses) +++ parse-story + (cook ~(gas by *story) (star ;~(sfix parse-chapter (jest '---\0a')))) +:: +:: N.B: If conflicting messages are written individually, +:: instead of under the same commit, we will overwrite previous entries +:: with later ones due to the nature of gas:by. +-- diff --git a/pkg/base-dev/lib/strandio.hoon b/pkg/base-dev/lib/strandio.hoon index a83d5ae0e0..721025ab64 100644 --- a/pkg/base-dev/lib/strandio.hoon +++ b/pkg/base-dev/lib/strandio.hoon @@ -734,7 +734,7 @@ ;< =bowl:spider bind:m get-bowl =/ tid (scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl)))) - =/ poke-vase !>([`tid.bowl `tid beak file args]) + =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid beak file args]) ;< ~ bind:m (poke-our %spider %spider-start poke-vase) ;< ~ bind:m (sleep ~s0) :: wait for thread to start (pure:m tid) @@ -748,7 +748,7 @@ ^- form:m ;< =bowl:spider bind:m get-bowl =/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl)))) - =/ poke-vase !>([`tid.bowl `tid file args]) + =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid byk.bowl file args]) ;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid]) ;< ~ bind:m (poke-our %spider %spider-start poke-vase) ;< ~ bind:m (sleep ~s0) :: wait for thread to start @@ -756,6 +756,6 @@ ;< ~ bind:m (take-kick /awaiting/[tid]) ?+ p.cage ~|([%strange-thread-result p.cage file tid] !!) %thread-done (pure:m %& q.cage) - %thread-fail (pure:m %| !<([term tang] q.cage)) + %thread-fail (pure:m %| ;;([term tang] q.q.cage)) == -- diff --git a/pkg/base-dev/lib/test.hoon b/pkg/base-dev/lib/test.hoon index 7e4eca44a5..ec97e71ddf 100644 --- a/pkg/base-dev/lib/test.hoon +++ b/pkg/base-dev/lib/test.hoon @@ -13,7 +13,7 @@ %+ weld result ^- tang :~ [%palm [": " ~ ~ ~] [leaf+"expected" (sell expected) ~]] - [%palm [": " ~ ~ ~] [leaf+"actual" (sell actual) ~]] + [%palm [": " ~ ~ ~] [leaf+"actual " (sell actual) ~]] == :: =? result !(~(nest ut p.actual) | p.expected) diff --git a/pkg/base-dev/mar/story-diff.hoon b/pkg/base-dev/mar/story-diff.hoon new file mode 100644 index 0000000000..17d417d366 --- /dev/null +++ b/pkg/base-dev/mar/story-diff.hoon @@ -0,0 +1,16 @@ +:: +:::: + :: +/- *story +|_ =story-diff +:: +++ grad %noun +++ grow + |% + ++ noun story-diff + -- +++ grab :: convert from + |% + ++ noun ^story-diff :: make from %noun + -- +-- diff --git a/pkg/base-dev/mar/story.hoon b/pkg/base-dev/mar/story.hoon new file mode 100644 index 0000000000..bf07ac742b --- /dev/null +++ b/pkg/base-dev/mar/story.hoon @@ -0,0 +1,70 @@ +/- *story +/+ *story +|_ tale=story +++ grad + |% + ++ form %story-diff + ++ diff + |= tory=story + ^- story-diff + :: Given new story (tory), old story (tale), compute the diff + :: additions = new - old + :: deletions = old - new + [(dif-ju tory tale) (dif-ju tale tory)] + ++ pact + |= dif=story-diff + :: Compute the new story after applying dif to tale. + :: + ^- story + =. tale (uni-ju tale additions.dif) + =. tale (dif-ju tale deletions.dif) + tale + ++ join + |= [ali=story-diff bob=story-diff] + ^- (unit story-diff) + =/ joined-additions (uni-ju additions.ali additions.bob) + =/ joined-deletions (uni-ju deletions.ali deletions.bob) + :: + :: In a true join, we'd do a set intersection on the keys. + :: If they're not equal, we have a conflict. + :: In this case, we'd produce null and kick the flow to +mash + :: + %- some + [joined-additions joined-deletions] + ++ mash + :: called by meld, force merge, annotating conflicts + |= $: [als=ship ald=desk ali=story-diff] + [bos=ship bod=desk bob=story-diff] + == + ^- story-diff + (need (join ali bob)) :: XX temporary, only because join doesn't fail + -- +:: +++ grow :: convert to + |% :: + ++ mime :: to %mime + [/text/x-urb-story (as-octs:mimes:html (of-wain:format txt))] + ++ txt + ^- wain + %- snoc :_ '' :: ensures terminating newline is present + %+ murn ~(tap by tale) + |= [[=tako:clay =proses]] + ^- (unit cord) + ?~ proses ~ + %- some + %- crip + ;: welp + (tako-to-text tako) + (proses-to-text proses) + "---" + == + -- +++ grab + |% :: convert from + ++ noun story :: clam from %noun + ++ mime :: retrieve from %mime + |= [p=mite q=octs] + =/ story-text `@t`q.q + `story`(rash story-text parse-story) + -- +-- diff --git a/pkg/base-dev/mar/thread-done.hoon b/pkg/base-dev/mar/thread-done.hoon new file mode 100644 index 0000000000..79b2ee08a6 --- /dev/null +++ b/pkg/base-dev/mar/thread-done.hoon @@ -0,0 +1,11 @@ +|_ res=* +++ grab + |% + ++ noun * + -- +++ grow + |% + ++ noun res + -- +++ grad %noun +-- diff --git a/pkg/base-dev/mar/thread-fail.hoon b/pkg/base-dev/mar/thread-fail.hoon new file mode 100644 index 0000000000..64b008b14d --- /dev/null +++ b/pkg/base-dev/mar/thread-fail.hoon @@ -0,0 +1,11 @@ +|_ err=* +++ grab + |% + ++ noun (pair term tang) + -- +++ grow + |% + ++ noun err + -- +++ grad %noun +-- diff --git a/pkg/base-dev/mar/udon.hoon b/pkg/base-dev/mar/udon.hoon index 72c9e6f5cf..e8bf3b5d02 100644 --- a/pkg/base-dev/mar/udon.hoon +++ b/pkg/base-dev/mar/udon.hoon @@ -28,5 +28,4 @@ ++ txt of-wain:format -- ++ grad %txt -++ garb /down -- diff --git a/pkg/base-dev/sur/aquarium.hoon b/pkg/base-dev/sur/aquarium.hoon index d71d9f5197..96b29f7001 100644 --- a/pkg/base-dev/sur/aquarium.hoon +++ b/pkg/base-dev/sur/aquarium.hoon @@ -24,7 +24,16 @@ aqua-event == :: -+$ unix-event unix-event:pill-lib ++$ unix-event ::NOTE like unix-event:pill-lib but for all tasks + %+ pair wire + $% [%wack p=@] + [%what p=(list (pair path (cask)))] + [%whom p=ship] + [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))] + [%wyrd p=vere] + [%verb p=(unit ?)] + task-arvo + == +$ pill pill:pill-lib :: +$ aqua-event diff --git a/pkg/base-dev/sur/hood.hoon b/pkg/base-dev/sur/hood.hoon index 7ef167bf1f..d1087a05b9 100644 --- a/pkg/base-dev/sur/hood.hoon +++ b/pkg/base-dev/sur/hood.hoon @@ -130,13 +130,8 @@ =/ tak (scot %uv (~(got by hit.dom) let.dom)) =/ yak .^(yaki cs/~[her syd yon %yaki tak]) =/ lob (scot %uv (~(got by q.yak) /sys/kelvin)) - =/ bob .^(blob cs/~[her syd yon %blob lob]) - :: - ;; weft - ?- -.bob - %direct q.q.bob - %delta q.r.bob - == + =/ peg .^(page cs/~[her syd yon %blob lob]) + ;;(weft q.peg) :: +read-kelvin-local: read /sys/kelvin from a local desk :: ++ read-kelvin-local @@ -164,13 +159,8 @@ =/ fil (~(get by q.yak) /desk/bill) ?~ fil ~ =/ lob (scot %uv u.fil) - =/ bob .^(blob cs/~[her syd yon %blob lob]) - :: - ;; (list dude) - ?- -.bob - %direct q.q.bob - %delta q.r.bob - == + =/ peg .^(page cs/~[her syd yon %blob lob]) + ;;((list dude) q.peg) :: +read-bill: read contents of /desk/bill manifest :: ++ read-bill diff --git a/pkg/base-dev/sur/spider.hoon b/pkg/base-dev/sur/spider.hoon index 5fe7a76268..2a6a8207e0 100644 --- a/pkg/base-dev/sur/spider.hoon +++ b/pkg/base-dev/sur/spider.hoon @@ -11,4 +11,11 @@ %nonexistent :: 404 %offline :: 504 == ++$ start-args + $: parent=(unit tid) + use=(unit tid) + =beak + file=term + =vase + == -- diff --git a/pkg/base-dev/sur/story.hoon b/pkg/base-dev/sur/story.hoon new file mode 100644 index 0000000000..1336a616ba --- /dev/null +++ b/pkg/base-dev/sur/story.hoon @@ -0,0 +1,9 @@ +^? +|% ++$ prose [title=@t body=@t] ++$ proses (set prose) ++$ story (jug tako:clay prose) :: set len > 1 means conflicting messages have been assigned ++$ chapter [tako:clay proses] :: prose entry type ++$ cash $%([%tako p=tako:clay] case) :: used in generators to accept a tako directly as well ++$ story-diff [additions=story deletions=story] +-- \ No newline at end of file diff --git a/pkg/bitcoin/sys.kelvin b/pkg/bitcoin/sys.kelvin index e68acb6a4c..e77a3de08a 100644 --- a/pkg/bitcoin/sys.kelvin +++ b/pkg/bitcoin/sys.kelvin @@ -1 +1 @@ -[%zuse 419] +[%zuse 418] diff --git a/pkg/ent/configure b/pkg/ent/configure index 8171293f3f..5eb1c0e2f9 100755 --- a/pkg/ent/configure +++ b/pkg/ent/configure @@ -1,5 +1,7 @@ #!/usr/bin/env bash +: "${MAKE:=make}" + log () { echo "$@" >&2; } @@ -14,7 +16,7 @@ do log "Trying IMPL=$IMPL" - if IMPL=$impl make >/dev/null 2>/dev/null + if IMPL=$impl ${MAKE} >/dev/null 2>/dev/null then sed -i 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile log "IMPL=$IMPL works" exit 0 diff --git a/pkg/garden/sys.kelvin b/pkg/garden/sys.kelvin index e68acb6a4c..e77a3de08a 100644 --- a/pkg/garden/sys.kelvin +++ b/pkg/garden/sys.kelvin @@ -1 +1 @@ -[%zuse 419] +[%zuse 418] diff --git a/pkg/hs/stack.yaml b/pkg/hs/stack.yaml index 0ce45ed38b..f9077a35dd 100644 --- a/pkg/hs/stack.yaml +++ b/pkg/hs/stack.yaml @@ -2,7 +2,6 @@ resolver: lts-16.15 packages: - natpmp-static - - proto - racquire - terminal-progress-bar - urbit-atom diff --git a/pkg/hs/urbit-king/lib/Urbit/King/CLI.hs b/pkg/hs/urbit-king/lib/Urbit/King/CLI.hs index b9e7fadaa4..5c1d16fb9a 100644 --- a/pkg/hs/urbit-king/lib/Urbit/King/CLI.hs +++ b/pkg/hs/urbit-king/lib/Urbit/King/CLI.hs @@ -6,12 +6,10 @@ -} module Urbit.King.CLI where -import ClassyPrelude hiding (log) +import Urbit.Prelude hiding (log, Parser) import Options.Applicative import Options.Applicative.Help.Pretty -import Data.Word (Word16) -import RIO (LogLevel(..)) import System.Environment (getProgName) -------------------------------------------------------------------------------- @@ -253,9 +251,9 @@ serfExe = optional ethNode :: Parser String ethNode = strOption $ short 'e' - <> long "eth-node" - <> value "http://eth-mainnet.urbit.org:8545" - <> help "Ethereum gateway URL" + <> long "l2-endpoint" + <> value "https://l2.urbit.org/v1/azimuth" --TODO + <> help "Azimuth Layer 2 RPC API endpoint URL" <> hidden new :: Parser New diff --git a/pkg/hs/urbit-king/lib/Urbit/King/TryJamPill.hs b/pkg/hs/urbit-king/lib/Urbit/King/TryJamPill.hs index 73ead8b8ee..539638679f 100644 --- a/pkg/hs/urbit-king/lib/Urbit/King/TryJamPill.hs +++ b/pkg/hs/urbit-king/lib/Urbit/King/TryJamPill.hs @@ -3,9 +3,8 @@ -} module Urbit.King.TryJamPill where -import ClassyPrelude import Control.Lens -import Urbit.Noun +import Urbit.Prelude -------------------------------------------------------------------------------- diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/LaneCache.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/LaneCache.hs index 519f5845d5..b7eb896edd 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/LaneCache.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/LaneCache.hs @@ -2,31 +2,63 @@ module Urbit.Vere.Ames.LaneCache (cache) where import Urbit.Prelude +import qualified Data.HashPSQ as P + import Urbit.Noun.Time expiry :: Gap expiry = (2 * 60) ^. from secs +bound :: Int +bound = 1_000 + +-- | An "upside down" time for use as a priority. +newtype New = New Wen + deriving newtype (Eq, Ord) + +new :: Wen -> New +new = New . negate + +wen :: New -> Wen +wen (New w) = negate w + +-- | Given a new, find an older new corresponding to `expiry` ago. +lag :: New -> New +lag n = new (addGap (wen n) expiry) + +trim :: (Hashable a, Ord a, Ord b) => P.HashPSQ a b c -> P.HashPSQ a b c +trim p = if P.size p > bound then P.deleteMin p else p + cache :: forall a b m n - . (Ord a, MonadIO m, MonadIO n) + . (Ord a, Hashable a, MonadIO m, MonadIO n) => (a -> m b) -> n (a -> m b) cache act = do - cas <- newTVarIO (mempty :: Map a (Wen, b)) + cas <- newTVarIO (P.empty :: P.HashPSQ a New b) - let fun x = lookup x <$> readTVarIO cas >>= \case + let fun x = P.lookup x <$> readTVarIO cas >>= \case Nothing -> thru - Just (t, v) -> do + Just (n, v) -> do + let t = wen n t' <- io now if gap t' t > expiry then thru else pure v where + -- Insert a key into the map, simultaneously removing *all* stale + -- entries. Since insertion is linear in the size of the map, + -- presumably it's not horrible to do it this way. The alternative + -- would be to have a thread doing a purge every 10s or something, and + -- then we'd have to be in RAcquire. + up :: a -> New -> b -> P.HashPSQ a New b -> P.HashPSQ a New b + up k n v ps = trim + $ P.insert k n v + $ snd $ P.atMostView (lag n) ps thru :: m b thru = do - t <- io now + n <- new <$> io now v <- act x - atomically $ modifyTVar' cas (insertMap x (t, v)) + atomically $ modifyTVar' cas $ up x n v pure v pure fun diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/Packet.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/Packet.hs index d2ddcdfc42..ea878d5331 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/Packet.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Ames/Packet.hs @@ -158,8 +158,8 @@ instance Serialize Packet where putByteString body where - putShipGetRank s@(Ship (LargeKey p q)) = case () of - _ | s < 2 ^ 16 -> (0, putWord16le $ fromIntegral s) -- lord - | s < 2 ^ 32 -> (1, putWord32le $ fromIntegral s) -- planet - | s < 2 ^ 64 -> (2, putWord64le $ fromIntegral s) -- moon - | otherwise -> (3, putWord64le p >> putWord64le q) -- comet + putShipGetRank (Ship (LargeKey p q)) = case q of + 0 | p < 2 ^ 16 -> (0, putWord16le $ fromIntegral p) -- lord + | p < 2 ^ 32 -> (1, putWord32le $ fromIntegral p) -- planet + | otherwise -> (2, putWord64le $ fromIntegral p) -- moon + _ -> (3, putWord64le p >> putWord64le q) -- comet diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Dawn.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Dawn.hs index debfb9a735..9d1475749c 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Dawn.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Dawn.hs @@ -1,5 +1,5 @@ {-| - Use etherium to access PKI information. + Use L2 to access PKI information. -} module Urbit.Vere.Dawn ( dawnVent @@ -19,12 +19,13 @@ import Urbit.Arvo.Common import Urbit.Arvo.Event hiding (Address) import Urbit.Prelude hiding (rights, to, (.=)) +import Prelude (read) + import Data.Bits (xor) import Data.List (nub) import Data.Text (splitOn) import Data.Aeson import Data.HexString -import Numeric (showHex) import qualified Crypto.Hash.SHA256 as SHA256 import qualified Crypto.Hash.SHA512 as SHA512 @@ -39,19 +40,12 @@ import qualified Urbit.Ob as Ob import qualified Network.HTTP.Client.TLS as TLS import qualified Network.HTTP.Types as HT --- The address of the azimuth contract as a string. -azimuthAddr :: Text -azimuthAddr = "0x223c067f8cf28ae173ee5cafea60ca44c335fecb" - -- Conversion Utilities -------------------------------------------------------- -passFromBS :: ByteString -> ByteString -> ByteString -> Pass -passFromBS enc aut sut - | bytesAtom sut /= 1 = Pass (Ed.PublicKey mempty) (Ed.PublicKey mempty) - | otherwise = Pass (Ed.PublicKey aut) (Ed.PublicKey enc) - -bsToBool :: ByteString -> Bool -bsToBool bs = bytesAtom bs == 1 +passFromBytes :: ByteString -> ByteString -> Int -> Pass +passFromBytes enc aut sut + | sut /= 1 = Pass (Ed.PublicKey mempty) (Ed.PublicKey mempty) + | otherwise = Pass (Ed.PublicKey aut) (Ed.PublicKey enc) clanFromShip :: Ship -> Ob.Class clanFromShip = Ob.clan . Ob.patp . fromIntegral @@ -62,10 +56,6 @@ shipSein = Ship . fromIntegral . Ob.fromPatp . Ob.sein . Ob.patp . fromIntegral renderShip :: Ship -> Text renderShip = Ob.renderPatp . Ob.patp . fromIntegral -hexStrToAtom :: Text -> Atom -hexStrToAtom = - bytesAtom . reverse . toBytes . hexString . removePrefix . encodeUtf8 - onLeft :: (a -> b) -> Either a c -> Either b c onLeft fun = bimap fun id @@ -84,18 +74,8 @@ ringToPass Ring{..} = Pass{..} -- JSONRPC Functions ----------------------------------------------------------- --- The big problem here is that we can't really use the generated web3 wrappers --- around the azimuth contracts, especially for the galaxy table request. They --- make multiple rpc invocations per galaxy request (which aren't even --- batched!), while Vere built a single batched rpc call to fetch the entire --- galaxy table. --- --- The included Network.JsonRpc.TinyClient that Network.Web3 embeds can't do --- batches, so calling that directly is out. --- --- Network.JSONRPC appears to not like something about the JSON that Infura --- returns; it's just hanging? Also no documentation. --- +-- Our use case here is simple enough. +-- Network.JSONRPC appeared fragile and has no documentation. -- So, like with Vere, we roll our own. dawnSendHTTP :: String -> L.ByteString -> RIO e (Either Int L.ByteString) @@ -122,24 +102,25 @@ dawnSendHTTP endpoint requestData = liftIO do class RequestMethod m where getRequestMethod :: m -> Text -data RawResponse = RawResponse +data RawResponse r = RawResponse { rrId :: Int - , rrResult :: Text + , rrResult :: r } deriving (Show) -instance FromJSON RawResponse where +instance FromJSON r => FromJSON (RawResponse r) where parseJSON = withObject "Response" $ \v -> do - rrId <- v .: "id" + rawId <- v .: "id" rrResult <- v .: "result" + let rrId = read rawId pure RawResponse{..} -- Given a list of methods and parameters, return a list of decoded responses. -dawnPostRequests :: forall req e resp - . (ToJSON req, RequestMethod req) +dawnPostRequests :: forall req e resp res + . (ToJSON req, RequestMethod req, FromJSON res) => String - -> (req -> Text -> resp) + -> (req -> res -> resp) -> [req] -> RIO e [resp] dawnPostRequests endpoint responseBuilder requests = do @@ -168,122 +149,114 @@ dawnPostRequests endpoint responseBuilder requests = do toFullRequest (rid, req) = object [ "jsonrpc" .= ("2.0" :: Text) , "method" .= getRequestMethod req , "params" .= req - , "id" .= rid + , "id" .= (show rid) ] -- Azimuth JSON Requests ------------------------------------------------------- --- Not a full implementation of the Ethereum ABI, but just the ability to call --- a method by encoded id (like 0x63fa9a87 for `points(uint32)`), and a single --- UIntN 32 parameter. -encodeCall :: Text -> Int -> Text -encodeCall method idx = method <> leadingZeroes <> renderedNumber - where - renderedNumber = pack $ showHex idx "" - leadingZeroes = replicate (64 - length renderedNumber) '0' +data PointResponse = PointResponse + -- NOTE also contains dominion and ownership, but not actually used here + { prNetwork :: PointNetwork + } deriving (Show, Eq, Generic) -data BlockRequest = BlockRequest - deriving (Show, Eq) +instance FromJSON PointResponse where + parseJSON = withObject "PointResponse" $ \o -> do + prNetwork <- o .: "network" + pure PointResponse{..} -instance RequestMethod BlockRequest where - getRequestMethod BlockRequest = "eth_blockNumber" +data PointNetwork = PointNetwork + { pnKeys :: PointKeys + , pnSponsor :: PointSponsor + , pnRift :: ContNum + } deriving (Show, Eq, Generic) -instance ToJSON BlockRequest where - toJSON BlockRequest = Array $ fromList [] +instance FromJSON PointNetwork where + parseJSON = withObject "PointNetwork" $ \o -> do + pnKeys <- o .: "keys" + pnSponsor <- o .: "sponsor" + pnRift <- o .: "rift" + pure PointNetwork{..} --- No need to parse, it's already in the format we'll pass as an argument to --- eth calls which take a block number. -parseBlockRequest :: BlockRequest -> Text -> TextBlockNum -parseBlockRequest _ txt = txt +data PointKeys = PointKeys + { pkLife :: Life + , pkSuite :: Int + , pkAuth :: ByteString + , pkCrypt :: ByteString + } deriving (Show, Eq, Generic) -type TextBlockNum = Text +instance FromJSON PointKeys where + parseJSON = withObject "PointKeys" $ \o -> do + pkLife <- o .: "life" + pkSuite <- o .: "suite" + rawAuth <- o .: "auth" + rawCrypt <- o .: "crypt" + let pkAuth = parseKey rawAuth + let pkCrypt = parseKey rawCrypt + pure PointKeys{..} + where + parseKey = reverse . toBytes . hexString . removePrefix . encodeUtf8 -data PointRequest = PointRequest - { grqHexBlockNum :: TextBlockNum - , grqPointId :: Int - } deriving (Show, Eq) +data PointSponsor = PointSponsor + { psHas :: Bool + , psWho :: Text + } deriving (Show, Eq, Generic) + +instance FromJSON PointSponsor where + parseJSON = withObject "PointSponsor" $ \o -> do + psHas <- o .: "has" + psWho <- o .: "who" + pure PointSponsor{..} + +data PointRequest = PointRequest Ship instance RequestMethod PointRequest where - getRequestMethod PointRequest{..} = "eth_call" + getRequestMethod PointRequest{} = "getPoint" instance ToJSON PointRequest where - -- 0x63fa9a87 is the points(uint32) call. - toJSON PointRequest{..} = - Array $ fromList [object [ "to" .= azimuthAddr - , "data" .= encodeCall "0x63fa9a87" grqPointId], - String grqHexBlockNum - ] + toJSON (PointRequest point) = object [ "ship" .= renderShip point ] -parseAndChunkResultToBS :: Text -> [ByteString] -parseAndChunkResultToBS result = - map reverse $ - chunkBytestring 32 $ - toBytes $ - hexString $ - removePrefix $ - encodeUtf8 result - --- The incoming result is a text bytestring. We need to take that text, and --- spit out the parsed data. --- --- We're sort of lucky here. After removing the front "0x", we can just chop --- the incoming text string into 10 different 64 character chunks and then --- parse them as numbers. -parseEthPoint :: PointRequest -> Text -> EthPoint -parseEthPoint PointRequest{..} result = EthPoint{..} +parseAzimuthPoint :: PointRequest -> PointResponse -> EthPoint +parseAzimuthPoint (PointRequest point) response = EthPoint{..} where - [rawEncryptionKey, - rawAuthenticationKey, - rawHasSponsor, - rawActive, - rawEscapeRequested, - rawSponsor, - rawEscapeTo, - rawCryptoSuite, - rawKeyRevision, - rawContinuityNum] = parseAndChunkResultToBS result - - escapeState = if bsToBool rawEscapeRequested - then Just $ Ship $ fromIntegral $ bytesAtom rawEscapeTo - else Nothing + net = prNetwork response + key = pnKeys net -- Vere doesn't set ownership information, neither did the old Dawn.hs -- implementation. epOwn = (0, 0, 0, 0) - epNet = if not $ bsToBool rawActive + sponsorShip = Ob.parsePatp $ psWho $ pnSponsor net + epNet = if pkLife key == 0 then Nothing - else Just - ( fromIntegral $ bytesAtom rawKeyRevision - , passFromBS rawEncryptionKey rawAuthenticationKey rawCryptoSuite - , fromIntegral $ bytesAtom rawContinuityNum - , (bsToBool rawHasSponsor, - Ship (fromIntegral $ bytesAtom rawSponsor)) - , escapeState - ) + else case sponsorShip of + Left _ -> Nothing + Right s -> Just + ( fromIntegral $ pkLife key + , passFromBytes (pkCrypt key) (pkAuth key) (pkSuite key) + , fromIntegral $ pnRift net + , (psHas $ pnSponsor net, Ship $ fromIntegral $ Ob.fromPatp s) + , Nothing -- NOTE goes unused currently, so we simply put Nothing + ) -- I don't know what this is supposed to be, other than the old Dawn.hs and -- dawn.c do the same thing. - epKid = case clanFromShip (Ship $ fromIntegral grqPointId) of + -- zero-fill spawn data + epKid = case clanFromShip (Ship $ fromIntegral point) of Ob.Galaxy -> Just (0, setToHoonSet mempty) Ob.Star -> Just (0, setToHoonSet mempty) _ -> Nothing -- Preprocess data from a point request into the form used in the galaxy table. -parseGalaxyTableEntry :: PointRequest -> Text -> (Ship, (Rift, Life, Pass)) -parseGalaxyTableEntry PointRequest{..} result = (ship, (rift, life, pass)) +parseGalaxyTableEntry :: PointRequest -> PointResponse -> (Ship, (Rift, Life, Pass)) +parseGalaxyTableEntry (PointRequest point) response = (ship, (rift, life, pass)) where - [rawEncryptionKey, - rawAuthenticationKey, - _, _, _, _, _, - rawCryptoSuite, - rawKeyRevision, - rawContinuityNum] = parseAndChunkResultToBS result + net = prNetwork response + keys = pnKeys net - ship = Ship $ fromIntegral grqPointId - rift = fromIntegral $ bytesAtom rawContinuityNum - life = fromIntegral $ bytesAtom rawKeyRevision - pass = passFromBS rawEncryptionKey rawAuthenticationKey rawCryptoSuite + ship = Ship $ fromIntegral point + rift = fromIntegral $ pnRift net + life = fromIntegral $ pkLife keys + pass = passFromBytes (pkCrypt keys) (pkAuth keys) (pkSuite keys) removePrefix :: ByteString -> ByteString removePrefix withOhEx @@ -292,54 +265,32 @@ removePrefix withOhEx where (prefix, suffix) = splitAt 2 withOhEx -chunkBytestring :: Int -> ByteString -> [ByteString] -chunkBytestring size bs - | null rest = [cur] - | otherwise = (cur : chunkBytestring size rest) - where - (cur, rest) = splitAt size bs - data TurfRequest = TurfRequest - { trqHexBlockNum :: TextBlockNum - , trqTurfId :: Int - } deriving (Show, Eq) instance RequestMethod TurfRequest where - getRequestMethod TurfRequest{..} = "eth_call" + getRequestMethod TurfRequest = "getDns" instance ToJSON TurfRequest where - -- 0xeccc8ff1 is the dnsDomains(uint32) call. - toJSON TurfRequest{..} = - Array $ fromList [object [ "to" .= azimuthAddr - , "data" .= encodeCall "0xeccc8ff1" trqTurfId], - String trqHexBlockNum - ] + toJSON TurfRequest = object [] -- NOTE getDns takes no parameters --- This is another hack instead of a full Ethereum ABI response. -parseTurfResponse :: TurfRequest -> Text -> Turf -parseTurfResponse a raw = turf - where - without0x = removePrefix $ encodeUtf8 raw - (_, blRest) = splitAt 64 without0x - (utfLenStr, utfStr) = splitAt 64 blRest - utfLen = fromIntegral $ bytesAtom $ reverse $ toBytes $ hexString utfLenStr - dnsStr = decodeUtf8 $ BS.take utfLen $ toBytes $ hexString utfStr - turf = Turf $ fmap Cord $ reverse $ splitOn "." dnsStr +parseTurfResponse :: TurfRequest -> [Text] -> [Turf] +parseTurfResponse TurfRequest = map turf + where + turf t = Turf $ fmap Cord $ reverse $ splitOn "." t -- Azimuth Functions ----------------------------------------------------------- -retrievePoint :: String -> TextBlockNum -> Ship -> RIO e EthPoint -retrievePoint endpoint block ship = - dawnPostRequests endpoint parseEthPoint - [PointRequest block (fromIntegral ship)] >>= \case +retrievePoint :: String -> Ship -> RIO e EthPoint +retrievePoint endpoint ship = + dawnPostRequests endpoint parseAzimuthPoint [PointRequest ship] + >>= \case [x] -> pure x _ -> error "JSON server returned multiple return values." validateFeedAndGetSponsor :: String - -> TextBlockNum -> Feed -> RIO e (Seed, Ship) -validateFeedAndGetSponsor endpoint block = \case +validateFeedAndGetSponsor endpoint = \case Feed0 s -> do r <- validateSeed s case r of @@ -387,7 +338,7 @@ validateFeedAndGetSponsor endpoint block = \case putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys") --TODO could cache this lookup - whoP <- retrievePoint endpoint block ship + whoP <- retrievePoint endpoint ship case epNet whoP of Nothing -> pure $ Left "ship not keyed" Just (netLife, pass, contNum, (hasSponsor, who), _) -> do @@ -396,7 +347,7 @@ validateFeedAndGetSponsor endpoint block = \case show life <> ", but Azimuth claims life " <> show netLife) else if ((ringToPass ring) /= pass) then - pure $ Left "keyfile does not match blockchain" + pure $ Left "keyfile does not match Azimuth" -- TODO: The hoon code does a breach check, but the C code never -- supplies the data necessary for it to function. else @@ -404,13 +355,13 @@ validateFeedAndGetSponsor endpoint block = \case -- Walk through the sponsorship chain retrieving the actual sponsorship chain --- as it exists on Ethereum. -getSponsorshipChain :: String -> TextBlockNum -> Ship -> RIO e [(Ship,EthPoint)] -getSponsorshipChain endpoint block = loop +-- as it exists on Azimuth. +getSponsorshipChain :: String -> Ship -> RIO e [(Ship,EthPoint)] +getSponsorshipChain endpoint = loop where loop ship = do putStrLn ("boot: retrieving keys for sponsor " <> renderShip ship) - ethPoint <- retrievePoint endpoint block ship + ethPoint <- retrievePoint endpoint ship case (clanFromShip ship, epNet ethPoint) of (Ob.Comet, _) -> error "Comets cannot be sponsors" @@ -433,32 +384,29 @@ dawnVent :: HasLogFunc e => String -> Feed -> RIO e (Either Text Dawn) dawnVent provider feed = -- The type checker can't figure this out on its own. (onLeft tshow :: Either SomeException Dawn -> Either Text Dawn) <$> try do - putStrLn ("boot: requesting ethereum information from " <> pack provider) - blockResponses - <- dawnPostRequests provider parseBlockRequest [BlockRequest] - - hexStrBlock <- case blockResponses of - [num] -> pure num - x -> error "Unexpected multiple returns from block # request" - - let dBloq = hexStrToAtom hexStrBlock - putStrLn ("boot: ethereum block #" <> tshow dBloq) + putStrLn ("boot: requesting L2 Azimuth information from " <> pack provider) (dSeed, immediateSponsor) - <- validateFeedAndGetSponsor provider hexStrBlock feed - dSponsor <- getSponsorshipChain provider hexStrBlock immediateSponsor + <- validateFeedAndGetSponsor provider feed + dSponsor <- getSponsorshipChain provider immediateSponsor putStrLn "boot: retrieving galaxy table" dCzar <- (mapToHoonMap . mapFromList) <$> - (dawnPostRequests provider parseGalaxyTableEntry $ - map (PointRequest hexStrBlock) [0..255]) + (dawnPostRequests provider parseGalaxyTableEntry (map (PointRequest . Ship . fromIntegral) [0..255])) putStrLn "boot: retrieving network domains" - dTurf <- nub <$> (dawnPostRequests provider parseTurfResponse $ - map (TurfRequest hexStrBlock) [0..2]) + dTurf <- (dawnPostRequests provider parseTurfResponse [TurfRequest]) + >>= \case + [] -> pure [] + [t] -> pure (nub t) + _ -> error "too many turf responses" let dNode = Nothing + -- NOTE blocknum of 0 is fine because jael ignores it. + -- should probably be removed from dawn event. + let dBloq = 0 + pure MkDawn{..} diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Http.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Http.hs index 51700a042d..54b926cdca 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Http.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Http.hs @@ -4,9 +4,8 @@ module Urbit.Vere.Http where -import ClassyPrelude +import Urbit.Prelude import Urbit.Arvo -import Urbit.Noun import qualified Data.CaseInsensitive as CI import qualified Network.HTTP.Types as HT diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs index 3cad0b9760..5902675703 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs @@ -278,11 +278,11 @@ pier (serf, log) vSlog startedSig injected = do -- TODO Instead of using a TMVar, pull directly from the IO driver -- event sources. - computeQ :: TMVar RunReq <- newEmptyTMVarIO - persistQ :: TQueue (Fact, FX) <- newTQueueIO - executeQ :: TQueue FX <- newTQueueIO - saveSig :: TMVar () <- newEmptyTMVarIO - kingApi :: King.King <- King.kingAPI + computeQ :: TMVar RunReq <- newEmptyTMVarIO + persistQ :: TBQueue (Fact, FX) <- newTBQueueIO 10 -- TODO tuning? + executeQ :: TBQueue FX <- newTBQueueIO 10 + saveSig :: TMVar () <- newEmptyTMVarIO + kingApi :: King.King <- King.kingAPI termApiQ :: TQueue TermConn <- atomically $ do q <- newTQueue @@ -310,8 +310,8 @@ pier (serf, log) vSlog startedSig injected = do -- the c serf code. Logging output from our haskell process must manually -- add them. let compute = putTMVar computeQ - let execute = writeTQueue executeQ - let persist = writeTQueue persistQ + let execute = writeTBQueue executeQ + let persist = writeTBQueue persistQ let sigint = Serf.sendSIGINT serf let scry = \g r -> do res <- newEmptyMVar @@ -378,7 +378,7 @@ pier (serf, log) vSlog startedSig injected = do fn (0, textToTank txt) drivz <- startDrivers - tExec <- acquireWorker "Effects" (router slog (readTQueue executeQ) drivz) + tExec <- acquireWorker "Effects" (router slog (readTBQueue executeQ) drivz) tDisk <- acquireWorkerBound "Persist" (runPersist log persistQ execute) -- Now that the Serf is configured, the IO drivers are hooked up, their @@ -667,12 +667,14 @@ runPersist :: forall e . HasPierEnv e => EventLog - -> TQueue (Fact, FX) + -> TBQueue (Fact, FX) -> (FX -> STM ()) -> RIO e () runPersist log inpQ out = do dryRun <- view dryRunL forever $ do + -- This is not a memory leak because eventually the TBQueue at out will + -- fill up, blocking the loop. writs <- atomically getBatchFromQueue events <- validateFactsAndGetBytes (fst <$> toNullable writs) unless dryRun (Log.appendEvents log events) @@ -690,9 +692,11 @@ runPersist log inpQ out = do pure $ buildLogEvent mug $ toNoun (wen, non) pure (fromList lis) + -- Read as much out of the queue as possible (i.e. the entire contents), + -- blocking if empty. getBatchFromQueue :: STM (NonNull [(Fact, FX)]) - getBatchFromQueue = readTQueue inpQ >>= go . singleton + getBatchFromQueue = readTBQueue inpQ >>= go . singleton where - go acc = tryReadTQueue inpQ >>= \case + go acc = tryReadTBQueue inpQ >>= \case Nothing -> pure (reverse acc) Just item -> go (item <| acc) diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs index dc49043fe8..0f86dd2539 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs @@ -566,7 +566,6 @@ localClient doneSignal = fst <$> mkRAcquire start stop loop rd else if w <= 26 then do case pack [BS.w2c (w + 97 - 1)] of - "d" -> atomically doneSignal c -> do sendBelt $ Ctl $ Cord c loop rd else if w == 27 then do diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs index 3765f9cb25..f0982dfbe3 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs @@ -9,7 +9,7 @@ module Urbit.Vere.Term.Render , soundBell ) where -import ClassyPrelude +import Urbit.Prelude import qualified System.Console.ANSI as ANSI diff --git a/pkg/hs/urbit-king/package.yaml b/pkg/hs/urbit-king/package.yaml index 65b932f7d2..4e91c4ccbe 100644 --- a/pkg/hs/urbit-king/package.yaml +++ b/pkg/hs/urbit-king/package.yaml @@ -79,6 +79,7 @@ dependencies: - pretty-show - primitive - process + - psqueues - QuickCheck - racquire - random diff --git a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Convert.hs b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Convert.hs index d78a097b95..d9cd3bad44 100644 --- a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Convert.hs +++ b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Convert.hs @@ -30,6 +30,7 @@ newtype Parser a = Parser { runParser :: forall r. ParseStack -> Failure r -> Success a r -> r } +{-# INLINE named #-} -- keep out of the cost centers named :: Text -> Parser a -> Parser a named nm (Parser cb) = Parser $ \path kf ks -> cb (nm:path) kf ks diff --git a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Jam.hs b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Jam.hs index e9f2a64c26..325bb4cd12 100644 --- a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Jam.hs +++ b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/Jam.hs @@ -84,15 +84,15 @@ flush = Put $ \tbl s@S{..} -> do {-# INLINE update #-} update :: (S -> S) -> Put () -update f = Put $ \tbl s@S{..} -> pure (PutResult (f s) ()) +update f = Put $ \tbl s@S{} -> pure (PutResult (f s) ()) {-# INLINE setRegOff #-} setRegOff :: Word -> Int -> Put () -setRegOff r o = update $ \s@S{..} -> (s {reg=r, off=o}) +setRegOff r o = update $ \s@S{} -> (s {reg=r, off=o}) {-# INLINE setReg #-} setReg :: Word -> Put () -setReg r = update $ \s@S{..} -> (s { reg=r }) +setReg r = update $ \s@S{} -> (s { reg=r }) {-# INLINE getS #-} getS :: Put S diff --git a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/TH.hs b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/TH.hs index 89dd760273..c619ab655f 100644 --- a/pkg/hs/urbit-noun-core/lib/Urbit/Noun/TH.hs +++ b/pkg/hs/urbit-noun-core/lib/Urbit/Noun/TH.hs @@ -110,9 +110,22 @@ deriveToNounFunc tyName = do addErrTag :: String -> Exp -> Exp addErrTag tag exp = - InfixE (Just $ AppE (VarE 'named) str) (VarE (mkName ".")) (Just exp) + -- This spurious let is inserted so we can get better cost center data + -- during heap profiling. + LetE [ValD (VarP nom) (NormalB nam) []] + $ InfixE (Just $ VarE nom) (VarE (mkName ".")) (Just exp) where + -- XX arguably we should use newName rather than mkName here + nom = mkName $ "named_" ++ filter C.isAlphaNum tag str = LitE $ StringL tag + nam = LamE [VarP $ mkName "x"] $ AppE (AppE (VarE 'named) str) + $ VarE (mkName "x") + +addCostCenter :: String -> Exp -> Exp +addCostCenter tag exp = + LetE [ValD (VarP nom) (NormalB exp) []] (VarE nom) + where + nom = mkName $ "scc_" ++ filter C.isAlphaNum tag deriveFromNoun :: Name -> Q [Dec] deriveFromNoun tyName = do @@ -124,7 +137,8 @@ deriveFromNoun tyName = do let ty = foldl' (\acc v -> AppT acc (VarT v)) (ConT tyName) params let overlap = Nothing - body = NormalB (addErrTag (nameStr tyName) exp) + body = NormalB (addCostCenter nom $ addErrTag nom exp) + nom = nameStr tyName ctx = params <&> \t -> AppT (ConT ''FromNoun) (VarT t) inst = AppT (ConT ''FromNoun) ty @@ -214,12 +228,13 @@ taggedFromNoun cons = LamE [VarP n] (DoE [getHead, getTag, examine]) matches = mkMatch <$> cons mkMatch = \(tag, (n, tys)) -> - let body = AppE (addErrTag ('%':tag) (tupFromNoun (n, tys))) + let body = addCostCenter tag + $ AppE (addErrTag ('%':tag) (tupFromNoun (n, tys))) (VarE t) in Match (LitP $ StringL tag) (NormalB body) [] fallback = Match WildP (NormalB $ AppE (VarE 'fail) matchFail) [] - matchFail = unexpectedTag (fst <$> cons) (VarE c) + matchFail = addCostCenter "matchFail" $ unexpectedTag (fst <$> cons) (VarE c) tagFail = LitE $ StringL (intercalate " " (('%':) <$> (fst <$> cons))) diff --git a/pkg/hs/urbit-noun/lib/Urbit/Noun/Conversions.hs b/pkg/hs/urbit-noun/lib/Urbit/Noun/Conversions.hs index 09dd4aa739..c8be6d0cd7 100644 --- a/pkg/hs/urbit-noun/lib/Urbit/Noun/Conversions.hs +++ b/pkg/hs/urbit-noun/lib/Urbit/Noun/Conversions.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE StrictData #-} + {-| Large Library of conversion between various types and Nouns. -} @@ -29,7 +31,7 @@ import Urbit.Noun.Convert import Urbit.Noun.Core import Urbit.Noun.TH -import Data.LargeWord (LargeKey, Word128, Word256) +import Data.LargeWord (LargeKey(..), Word128, Word256) import GHC.Exts (chr#, isTrue#, leWord#, word2Int#) import GHC.Natural (Natural) import GHC.Types (Char(C#)) @@ -600,6 +602,9 @@ newtype Ship = Ship Word128 -- @p instance Show Ship where show = show . patp . fromIntegral +instance Hashable Ship where + hashWithSalt s (Ship (LargeKey a b)) = s `hashWithSalt` a `hashWithSalt` b + -- Path ------------------------------------------------------------------------ diff --git a/pkg/landscape/sys.kelvin b/pkg/landscape/sys.kelvin index e68acb6a4c..e77a3de08a 100644 --- a/pkg/landscape/sys.kelvin +++ b/pkg/landscape/sys.kelvin @@ -1 +1 @@ -[%zuse 419] +[%zuse 418] diff --git a/pkg/urbit/Makefile b/pkg/urbit/Makefile index c079c2af3b..46b90249e5 100644 --- a/pkg/urbit/Makefile +++ b/pkg/urbit/Makefile @@ -24,7 +24,7 @@ all_srcs = $(common) $(daemon) $(worker) test_exes = $(shell echo $(tests) | sed 's/tests\//.\/build\//g' | sed 's/\.c//g') bench_exes = $(shell echo $(bench) | sed 's/bench\//.\/build\//g' | sed 's/\.c//g') -all_exes = $(test_exes) $(bench_exes) ./build/urbit ./build/urbit-worker +all_exes = $(test_exes) $(bench_exes) ./build/urbit # -Werror promotes all warnings that are enabled into errors (this is on) # -Wall issues all types of errors. This is off (for now) @@ -41,7 +41,7 @@ all: $(all_exes) test: $(test_exes) @FAIL=0; \ for x in $^; \ - do echo "\n$$x" && ./$$x; \ + do echo $$'\n'"$$x" && ./$$x; \ if [ $$? != 0 ]; then FAIL=1; fi; \ done; \ if [ $$FAIL != 0 ]; then echo "\n" && exit 1; fi; @@ -67,12 +67,7 @@ build/%_tests: $(common_objs) tests/%_tests.o @mkdir -p ./build @$(CC) $^ $(LDFLAGS) -o $@ -build/urbit: $(common_objs) $(daemon_objs) - @echo CC -o $@ - @mkdir -p ./build - @$(CC) $^ $(LDFLAGS) -o $@ - -build/urbit-worker: $(common_objs) $(worker_objs) +build/urbit: $(common_objs) $(daemon_objs) $(worker_objs) @echo CC -o $@ @mkdir -p ./build @$(CC) $^ $(LDFLAGS) -o $@ diff --git a/pkg/urbit/compat/create-include-files.sh b/pkg/urbit/compat/create-include-files.sh index ff45ef7483..34b87cb526 100755 --- a/pkg/urbit/compat/create-include-files.sh +++ b/pkg/urbit/compat/create-include-files.sh @@ -18,5 +18,5 @@ poor_mans_xxd () { echo "unsigned int $2_len = $cch;" } -[ -e include/ca-bundle.h ] || poor_mans_xxd $2 include_ca_bundle_crt >include/ca-bundle.h -[ -e include/ivory.h ] || poor_mans_xxd ../../bin/ivory.pill u3_Ivory_pill >include/ivory.h +[ -e include/ca-bundle.h ] || poor_mans_xxd $2 include_ca_bundle_crt >include/ca-bundle.h +[ -e include/ivory_impl.h ] || poor_mans_xxd ../../bin/ivory.pill u3_Ivory_pill >include/ivory_impl.h diff --git a/pkg/urbit/compat/mingw/compat.c b/pkg/urbit/compat/mingw/compat.c index 0a60b56661..ebef5041fe 100644 --- a/pkg/urbit/compat/mingw/compat.c +++ b/pkg/urbit/compat/mingw/compat.c @@ -134,6 +134,16 @@ int err_win_to_posix(DWORD winerr) return error; } +int link(const char *path1, const char *path2) +{ + if ( CreateHardLinkA(path2, path1, NULL) ) { + return 0; + } + + errno = err_win_to_posix(GetLastError()); + return -1; +} + // from msys2 mingw-packages-dev patches // ----------------------------------------------------------------------- @@ -350,6 +360,18 @@ intmax_t mdb_get_filesize(HANDLE han_u) char *realpath(const char *path, char *resolved_path) { - // TODO - return strdup(path); + // XX MAX_PATH + // + return _fullpath(resolved_path, path, MAX_PATH); +} + +long sysconf(int name) +{ + SYSTEM_INFO si; + + if ( _SC_PAGESIZE != name ) { + return -1; + } + GetNativeSystemInfo(&si); + return si.dwPageSize; } diff --git a/pkg/urbit/compat/mingw/compat.h b/pkg/urbit/compat/mingw/compat.h index 21290d7b55..56c35e90ae 100644 --- a/pkg/urbit/compat/mingw/compat.h +++ b/pkg/urbit/compat/mingw/compat.h @@ -3,16 +3,19 @@ #define mkdir(A, B) mkdir(A) +int link(const char *path1, const char *path2); char *realpath(const char *path, char *resolved_path); int fdatasync(int fd); int utimes(const char *path, const struct timeval times[2]); +long sysconf(int name); int kill(pid_t pid, int signum); -#define SIGUSR1 10 -#define SIGALRM 14 -#define SIGVTALRM 26 -#define SIGSTK 31 -#define SIG_COUNT 32 +#define SIGUSR1 10 +#define SIGALRM 14 +#define SIGVTALRM 26 +#define SIGSTK 31 +#define SIG_COUNT 32 +#define _SC_PAGESIZE 29 #endif//_MINGW_IO_H diff --git a/pkg/urbit/compat/mingw/daemon.c b/pkg/urbit/compat/mingw/daemon.c index 0220cb75ae..46e73b0ea8 100644 --- a/pkg/urbit/compat/mingw/daemon.c +++ b/pkg/urbit/compat/mingw/daemon.c @@ -10,7 +10,7 @@ _dup_std_handle(HANDLE* new_u, DWORD typ_u) HANDLE han_u = GetStdHandle(typ_u); BOOL con_u = GetConsoleMode(han_u, &dum_u); if ( con_u ) { - han_u = (HANDLE)_get_osfhandle(open(c3_dev_null, O_RDWR, 0)); + han_u = (HANDLE)_get_osfhandle(c3_open(c3_dev_null, O_RDWR, 0)); } if ( !DuplicateHandle(GetCurrentProcess(), han_u, GetCurrentProcess(), new_u, 0, TRUE, DUPLICATE_SAME_ACCESS) ) { diff --git a/pkg/urbit/compat/poor-mans-nix-shell.sh b/pkg/urbit/compat/poor-mans-nix-shell.sh index dddff0305d..493b532f63 100644 --- a/pkg/urbit/compat/poor-mans-nix-shell.sh +++ b/pkg/urbit/compat/poor-mans-nix-shell.sh @@ -9,6 +9,8 @@ markfil=.$1~ depdirs= nixpath=${NIX_STORE-../build} +: "${MAKE:=make}" + # LDFLAGS doesn't like absolute paths if [ "${nixpath:0:1}" == "/" ] then @@ -84,7 +86,7 @@ buildnixdep () { [ -e $patch ] && patch -d $dir -p 1 <$patch pushd $dir eval "$cmdprep" - eval make "$cmdmake" + eval ${MAKE} "$cmdmake" touch $markfil popd fi diff --git a/pkg/urbit/configure b/pkg/urbit/configure index ab5b3a3dfa..22958e3ed6 100755 --- a/pkg/urbit/configure +++ b/pkg/urbit/configure @@ -24,11 +24,6 @@ deps=" \ softfloat3 \ " -headers=" \ - ca-bundle.h \ - ivory.h \ -" - echo '#pragma once' >include/config.h defmacro () { @@ -36,6 +31,7 @@ defmacro () { } defmacro URBIT_VERSION "\"$URBIT_VERSION\"" +defmacro U3_VERE_PACE "\"${VERE_PACE:-once}\"" opt_debug= opt_static= @@ -93,7 +89,7 @@ case $(tr A-Z a-z <<< $cpu) in x86_64) defmacro U3_OS_ENDIAN_little 1 ;; - aarch64) + arm64|aarch64) defmacro U3_OS_ENDIAN_little 1 defmacro U3_CPU_aarch64 1 ;; @@ -114,6 +110,8 @@ case $(tr A-Z a-z <<< $os) in mpkgs=(cmake curl gcc jq make) pacman -S --needed autoconf automake-wrapper libtool patch ${mpkgs[@]/#/mingw-w64-x86_64-} + export MAKE=mingw32-make + . compat/poor-mans-nix-shell.sh mingw compat/create-include-files.sh 'stat -c %s' /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt @@ -185,10 +183,6 @@ for dep in $deps; do LDFLAGS="${LDFLAGS-} -l$dep" done -for header in $headers; do - CFLAGS="${CFLAGS-} -I$header" -done - compat="${compat-posix}" for citem in $compat; do CFLAGS="${CFLAGS-} -Icompat/$citem" diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index 6e3bbcd1d5..c91576fd98 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -4,6 +4,8 @@ #define U3_GLOBAL #define C3_GLOBAL #include "all.h" +#include "rsignal.h" +#include #include "vere/vere.h" #if !defined(U3_OS_mingw) #include @@ -15,14 +17,52 @@ #include #include #include +#include +#include #include "ca-bundle.h" +#include "whereami.h" + +// serf module state +// +static u3_serf u3V; // one serf per process +static u3_moat inn_u; // input stream +static u3_mojo out_u; // output stream +static u3_cue_xeno* sil_u; // cue handle + +#undef SERF_TRACE_JAM +#undef SERF_TRACE_CUE /* Require unsigned char */ STATIC_ASSERT(( 0 == CHAR_MIN && UCHAR_MAX == CHAR_MAX ), "unsigned char required"); +/* _main_self_path(): get binary self-path. +*/ +static void +_main_self_path(void) +{ + c3_c* pat_c; + c3_i len_i, pat_i; + + if ( 0 < (len_i = wai_getExecutablePath(NULL, 0, &pat_i)) ) { + pat_c = c3_malloc( 1 + len_i ); + wai_getExecutablePath(pat_c, len_i, &pat_i); + pat_c[len_i] = 0; + + u3_Host.dem_c = pat_c; + } + else { + fprintf(stderr, "unable to get binary self path\r\n"); + exit(1); + + // XX continue? + // + // u3_Host.dem_c = strdup(bin_c); + } +} + /* _main_readw(): parse a word from a string. */ static u3_noun @@ -54,13 +94,51 @@ _main_presig(c3_c* txt_c) return new_c; } -/* _main_getopt(): extract option map from command line. +/* _main_repath(): canonicalize path, using dirname if needed. */ -static u3_noun -_main_getopt(c3_i argc, c3_c** argv) +c3_c* +_main_repath(c3_c* pax_c) { - c3_i ch_i; - c3_w arg_w; + c3_c* rel_c; + c3_c* fas_c; + c3_c* dir_c; + c3_w len_w; + c3_i wit_i; + + c3_assert(pax_c); + if ( 0 != (rel_c = realpath(pax_c, 0)) ) { + return rel_c; + } + fas_c = strrchr(pax_c, '/'); + if ( !fas_c ) { + c3_c rec_c[2048]; + + wit_i = snprintf(rec_c, sizeof(rec_c), "./%s", pax_c); + c3_assert(sizeof(rec_c) > wit_i); + return _main_repath(rec_c); + } + c3_assert(u3_unix_cane(fas_c + 1)); + *fas_c = 0; + dir_c = realpath(pax_c, 0); + *fas_c = '/'; + if ( 0 == dir_c ) { + return 0; + } + len_w = strlen(dir_c) + strlen(fas_c) + 1; + rel_c = c3_malloc(len_w); + wit_i = snprintf(rel_c, len_w, "%s%s", dir_c, fas_c); + c3_assert(len_w == wit_i + 1); + c3_free(dir_c); + return rel_c; +} + +/* _main_init(): initialize globals +*/ +static void +_main_init(void) +{ + u3_Host.nex_o = c3n; + u3_Host.pep_o = c3n; u3_Host.ops_u.abo = c3n; u3_Host.ops_u.dem = c3n; @@ -86,9 +164,86 @@ _main_getopt(c3_i argc, c3_c** argv) u3_Host.ops_u.puf_c = "jam"; u3_Host.ops_u.hap_w = 50000; u3_Host.ops_u.kno_w = DefaultKernel; +} - while ( -1 != (ch_i=getopt(argc, argv, - "X:Y:G:J:B:b:K:A:H:I:C:w:u:e:F:k:n:p:r:i:Z:LljacdgqstvxPDRS")) ) +/* _main_pier_run(): get pier from binary path (argv[0]), if appropriate +*/ +static c3_c* +_main_pier_run(c3_c* bin_c) +{ + c3_c* dir_c = 0; + c3_w bin_w = strlen(bin_c); + c3_w len_w = strlen(U3_BIN_ALIAS); + + // no args, argv[0] == $pier/.run + // + if ( (len_w <= bin_w) + && (0 == strcmp(bin_c + (bin_w - len_w), U3_BIN_ALIAS)) ) + { + bin_c = strdup(bin_c); // dirname can modify + dir_c = _main_repath(dirname(bin_c)); + c3_free(bin_c); + } + + return dir_c; +} + +/* _main_getopt(): extract option map from command line. +*/ +static u3_noun +_main_getopt(c3_i argc, c3_c** argv) +{ + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "arvo", required_argument, NULL, 'A' }, + { "abort", no_argument, NULL, 'a' }, + { "bootstrap", required_argument, NULL, 'B' }, + { "http-ip", required_argument, NULL, 'b' }, + { "memo-cache-limit", required_argument, NULL, 'C' }, + { "pier", required_argument, NULL, 'c' }, + { "replay", no_argument, NULL, 'D' }, + { "daemon", no_argument, NULL, 'd' }, + { "ethereum", required_argument, NULL, 'e' }, + { "fake", required_argument, NULL, 'F' }, + { "key-string", required_argument, NULL, 'G' }, + { "gc", no_argument, NULL, 'g' }, + { "dns-root", required_argument, NULL, 'H' }, + { "inject", required_argument, NULL, 'I' }, + { "import", required_argument, NULL, 'i' }, + { "ivory-pill", required_argument, NULL, 'J' }, + { "json-trace", no_argument, NULL, 'j' }, + { "kernel-stage", required_argument, NULL, 'K' }, + { "key-file", required_argument, NULL, 'k' }, + { "local", no_argument, NULL, 'L' }, + { "lite-boot", no_argument, NULL, 'l' }, + { "replay-to", required_argument, NULL, 'n' }, + { "profile", no_argument, NULL, 'P' }, + { "ames-port", required_argument, NULL, 'p' }, + { "http-port", required_argument, NULL, c3__http }, + { "https-port", required_argument, NULL, c3__htls }, + { "no-conn", no_argument, NULL, c3__noco }, + { "no-dock", no_argument, NULL, c3__nodo }, + { "quiet", no_argument, NULL, 'q' }, + { "versions", no_argument, NULL, 'R' }, + { "replay-from", required_argument, NULL, 'r' }, + { "skip-battery-hashes", no_argument, NULL, 'S' }, + { "autoselect-pill", no_argument, NULL, 's' }, + { "no-tty", no_argument, NULL, 't' }, + { "bootstrap-url", required_argument, NULL, 'u' }, + { "verbose", no_argument, NULL, 'v' }, + { "name", required_argument, NULL, 'w' }, + { "scry", required_argument, NULL, 'X' }, + { "exit", no_argument, NULL, 'x' }, + { "scry-into", required_argument, NULL, 'Y' }, + { "scry-format", required_argument, NULL, 'Z' }, + { NULL, 0, NULL, 0 }, + }; + + while ( -1 != (ch_i=getopt_long(argc, argv, + "A:B:C:DF:G:H:I:J:K:LPRSX:Y:Z:ab:cde:gi:jk:ln:p:qr:stu:vw:x", + lop_u, &lid_i)) ) { switch ( ch_i ) { case 'X': { @@ -96,7 +251,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'Y': { - u3_Host.ops_u.puk_c = strdup(optarg); + u3_Host.ops_u.puk_c = _main_repath(optarg); break; } case 'Z': { @@ -104,11 +259,11 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'J': { - u3_Host.ops_u.lit_c = strdup(optarg); + u3_Host.ops_u.lit_c = _main_repath(optarg); break; } case 'B': { - u3_Host.ops_u.pil_c = strdup(optarg); + u3_Host.ops_u.pil_c = _main_repath(optarg); break; } case 'b': { @@ -120,7 +275,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'A': { - u3_Host.ops_u.arv_c = strdup(optarg); + u3_Host.ops_u.arv_c = _main_repath(optarg); break; } case 'H': { @@ -128,7 +283,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'I': { - u3_Host.ops_u.jin_c = strdup(optarg); + u3_Host.ops_u.jin_c = _main_repath(optarg); break; } case 'C': { @@ -166,7 +321,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'k': { - u3_Host.ops_u.key_c = strdup(optarg); + u3_Host.ops_u.key_c = _main_repath(optarg); break; } case 'n': { @@ -179,6 +334,26 @@ _main_getopt(c3_i argc, c3_c** argv) } else u3_Host.ops_u.por_s = arg_w; break; } + case c3__http: { + if ( c3n == _main_readw(optarg, 65536, &arg_w) ) { + return c3n; + } else u3_Host.ops_u.per_s = arg_w; + break; + } + case c3__htls: { + if ( c3n == _main_readw(optarg, 65536, &arg_w) ) { + return c3n; + } else u3_Host.ops_u.pes_s = arg_w; + break; + } + case c3__noco: { + u3_Host.ops_u.con = c3n; + break; + } + case c3__nodo: { + u3_Host.ops_u.doc = c3n; + break; + } case 'R': { u3_Host.ops_u.rep = c3y; return c3y; @@ -188,7 +363,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'i': { - u3_Host.ops_u.imp_c = strdup(optarg); + u3_Host.ops_u.imp_c = _main_repath(optarg); break; } case 'L': { u3_Host.ops_u.net = c3n; break; } @@ -234,8 +409,9 @@ _main_getopt(c3_i argc, c3_c** argv) if ( u3_Host.ops_u.who_c != 0 ) { u3_Host.dir_c = strdup(1 + u3_Host.ops_u.who_c); } - else { - // XX not sure how this might be reachable + // no trailing positional arg, argv[0] != $pier/.run, invalid command + // + else if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { return c3n; } } @@ -248,7 +424,7 @@ _main_getopt(c3_i argc, c3_c** argv) } } - u3_Host.dir_c = strdup(argv[optind]); + u3_Host.dir_c = _main_repath(argv[optind]); } // daemon mode (-d) implies disabling terminal assumptions (-t) @@ -277,9 +453,6 @@ _main_getopt(c3_i argc, c3_c** argv) } } - c3_t imp_t = ((0 != u3_Host.ops_u.who_c) && - (4 == strlen(u3_Host.ops_u.who_c))); - if ( u3_Host.ops_u.gen_c != 0 && u3_Host.ops_u.nuu == c3n ) { fprintf(stderr, "-G only makes sense when bootstrapping a new instance\n"); return c3n; @@ -321,10 +494,6 @@ _main_getopt(c3_i argc, c3_c** argv) return c3n; } - if ( u3_Host.ops_u.eth_c == 0 && imp_t ) { - u3_Host.ops_u.eth_c = "http://eth-mainnet.urbit.org:8545"; - } - if ( u3_Host.ops_u.url_c != 0 && u3_Host.ops_u.pil_c != 0 ) { fprintf(stderr, "-B and -u cannot be used together\n"); return c3n; @@ -422,6 +591,41 @@ _setup_ssl_curl(void* arg) curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, _curl_ssl_ctx_cb); } +/* _cw_usage(): print utility usage. +*/ +static void +_cw_usage(c3_c* bin_c) +{ + c3_c *use_c[] = { + "utilities:\n", + " %s cram %.*s jam state:\n", + " %s dock %.*s copy binary:\n", + " %s grab %.*s measure memory usage:\n", + " %s info %.*s print pier info:\n", + " %s meld %.*s deduplicate snapshot:\n", + " %s pack %.*s defragment snapshot:\n", + " %s prep %.*s prepare for upgrade:\n", + " %s next %.*s request upgrade:\n", + " %s queu %.*s cue state:\n", + " %s vere ARGS download binary:\n", + "\n run as a 'serf':\n", + " %s serf " +#ifdef U3_OS_mingw + " " +#endif + "\n", + 0 + }; + + c3_c* d = _main_pier_run(bin_c); + c3_i i; + + for ( i=0; use_c[i]; i++ ) { + fprintf(stderr, use_c[i], bin_c, d ? 0 : 7, " "); + } + + c3_free(d); +} /* u3_ve_usage(): print usage and exit. */ @@ -437,37 +641,46 @@ u3_ve_usage(c3_i argc, c3_c** argv) "where ship_name is a @p phonetic representation of an urbit address\n", "without the leading '~', and options is some subset of the following:\n", "\n", - "-A dir Use dir for initial clay sync\n", - "-B pill Bootstrap from this pill\n", - "-b ip Bind HTTP server to this IP address\n", - "-C limit Set memo cache max size; 0 means uncapped\n", - "-c pier Create a new urbit in pier/\n", - "-D Recompute from events\n", - "-d Daemon mode; implies -t\n", - "-e url Urbit ID (L2) gateway\n", - "-F ship Fake keys; also disables networking\n", - "-G string Private key string (see also -k)\n", - "-g Set GC flag\n", - "-i jam_file import pier state\n", - "-j Create json trace file in .urb/put/trace\n", - "-K stage Start at Hoon kernel version stage\n", - "-k file-path Private key file (see also -G)\n", - "-L local networking only\n", - "-P Profiling\n", - "-p ames_port Set the ames port to bind to\n", - "-q Quiet\n", - "-R Report urbit build info\n", - "-S Disable battery hashing\n", + "-A, --arvo DIR Use dir for initial clay sync\n", + "-a, --abort Abort aggressively\n", + "-B, --bootstrap PILL Bootstrap from this pill\n", + "-b, --http-ip IP Bind HTTP server to this IP address\n", + "-C, --memo-cache-limit LIMIT Set memo cache max size; 0 means uncapped\n", + "-c, --pier PIER Create a new urbit in pier/\n", + "-D, --replay Recompute from events\n", + "-d, --daemon Daemon mode; implies -t\n", + "-e, --ethereum URL Ethereum gateway\n", + "-F, --fake SHIP Fake keys; also disables networking\n", + "-G, --key-string STRING Private key string (@uw, see also -k)\n" + "-g, --gc Set GC flag\n", + "-I, --inject FILE Inject event from jamfile\n", + "-i, --import FILE Import pier state from jamfile\n", + "-J, --ivory-pill PILL Use custom ivory pill\n", + "-j, --json-trace Create json trace file in .urb/put/trace\n", + "-K, --kernel-stage STAGE Start at Hoon kernel version stage\n", + "-k, --key-file KEYS Private key file (see also -G)\n", + "-L, --local Local networking only\n", + "-l, --lite-boot Most-minimal startup\n", + "-n, --replay-to NUMBER Replay up to event\n", + "-P, --profile Profiling\n", + "-p, --ames-port PORT Set the ames port to bind to\n", + " --http-port PORT Set the http port to bind to\n", + " --https-port PORT Set the https port to bind to\n", + "-q, --quiet Quiet\n", + "-R, --versions Report urbit build info\n", + "-r, --replay-from NUMBER Load snapshot from event\n", + "-S, --skip-battery-hashes Disable battery hashing\n", // XX find a way to re-enable - // "-s Pill URL from arvo git hash\n", - "-t Disable terminal/tty assumptions\n", - "-u url URL from which to download pill\n", - "-v Verbose\n", - "-w name Boot as ~name\n", - "-X path Scry, write to file, then exit\n" - "-x Exit immediately\n", - "-Y file Optional name of file (for -X and -o)\n" - "-Z format Optional file format ('jam', or aura, for -X)\n" + // "-s, --autoselect-pill Pill URL from arvo git hash\n", + "-t, --no-tty Disable terminal/tty assumptions\n", + "-u, --bootstrap-url URL URL from which to download pill\n", + "-v, --verbose Verbose\n", + "-w, --name NAME Boot as ~name\n", + "-X, --scry PATH Scry, write to file, then exit\n", + "-x, --exit Exit immediately\n", + "-Y, --scry-into FILE Optional name of file (for -X)\n", + "-Z, --scry-format FORMAT Optional file format ('jam', or aura, for -X)\n", + " --no-conn Do not run control plane\n", "\n", "Development Usage:\n", " To create a development ship, use a fakezod:\n", @@ -487,6 +700,7 @@ u3_ve_usage(c3_i argc, c3_c** argv) for ( i=0; use_c[i]; i++ ) { fprintf(stderr, use_c[i], argv[0]); } + _cw_usage(argv[0]); exit(1); } @@ -554,62 +768,928 @@ _stop_on_boot_completed_cb() u3_king_exit(); } -static c3_i -_debug_db_stats(const c3_c* dir_c) +/* _cw_serf_fail(): failure stub. +*/ +static void +_cw_serf_fail(void* ptr_v, ssize_t err_i, const c3_c* err_c) { -#if defined(U3_CPU_aarch64) && defined(U3_OS_linux) - const size_t siz_i = 64424509440; -#else - const size_t siz_i = 1099511627776; -#endif - - c3_c* log_c = c3_malloc(10 + strlen(dir_c)); - - strcpy(log_c, dir_c); - strcat(log_c, "/.urb/log"); - - MDB_env* mdb_u = u3_lmdb_init(log_c, siz_i); - - if ( mdb_u ) { - u3_lmdb_stat(mdb_u, stdout); - u3_lmdb_exit(mdb_u); - return 0; + if ( UV_EOF == err_i ) { + fprintf(stderr, "serf: pier unexpectedly shut down\r\n"); } else { - return 1; + fprintf(stderr, "serf: pier error: %s\r\n", err_c); } + + exit(1); +} + +/* _cw_serf_send(): send plea back to daemon. +*/ +static void +_cw_serf_send(u3_noun pel) +{ + c3_d len_d; + c3_y* byt_y; + +#ifdef SERF_TRACE_JAM + u3t_event_trace("serf ipc jam", 'B'); +#endif + + u3s_jam_xeno(pel, &len_d, &byt_y); + +#ifdef SERF_TRACE_JAM + u3t_event_trace("serf ipc jam", 'E'); +#endif + + u3_newt_send(&out_u, len_d, byt_y); + u3z(pel); +} + +/* _cw_serf_send_slog(): send hint output (hod is [priority tank]). +*/ +static void +_cw_serf_send_slog(u3_noun hod) +{ + _cw_serf_send(u3nc(c3__slog, hod)); +} + +/* _cw_serf_send_stdr(): send stderr output (%flog) +*/ +static void +_cw_serf_send_stdr(c3_c* str_c) +{ + _cw_serf_send(u3nc(c3__flog, u3i_string(str_c))); +} + + +/* _cw_serf_step_trace(): initialize or rotate trace file. +*/ +static void +_cw_serf_step_trace(void) +{ + if ( u3C.wag_w & u3o_trace ) { + if ( u3_Host.tra_u.con_w == 0 && u3_Host.tra_u.fun_w == 0 ) { + u3t_trace_open(u3V.dir_c); + } + else if ( u3_Host.tra_u.con_w >= 100000 ) { + u3t_trace_close(); + u3t_trace_open(u3V.dir_c); + } + } +} + +/* _cw_serf_writ(): process a command from the king. +*/ +static void +_cw_serf_writ(void* vod_p, c3_d len_d, c3_y* byt_y) +{ + u3_weak jar; + u3_noun ret; + + _cw_serf_step_trace(); + +#ifdef SERF_TRACE_CUE + u3t_event_trace("serf ipc cue", 'B'); +#endif + + jar = u3s_cue_xeno_with(sil_u, len_d, byt_y); + +#ifdef SERF_TRACE_CUE + u3t_event_trace("serf ipc cue", 'E'); +#endif + + if ( (u3_none == jar) + || (c3n == u3_serf_writ(&u3V, jar, &ret)) ) + { + _cw_serf_fail(0, -1, "bad jar"); + } + else { + _cw_serf_send(ret); + + // all references must now be counted, and all roots recorded + // + u3_serf_post(&u3V); + } +} + +/* _cw_serf_stdio(): fix up std io handles +*/ +static void +_cw_serf_stdio(c3_i* inn_i, c3_i* out_i) +{ + // the serf is spawned with [FD 0] = events and [FD 1] = effects + // we dup [FD 0 & 1] so we don't accidently use them for something else + // we replace [FD 0] (stdin) with a fd pointing to /dev/null + // we replace [FD 1] (stdout) with a dup of [FD 2] (stderr) + // + c3_i nul_i = c3_open(c3_dev_null, O_RDWR, 0); + + *inn_i = dup(0); + *out_i = dup(1); + + dup2(nul_i, 0); + dup2(2, 1); + + close(nul_i); + + // set stream I/O to unbuffered because it's now a pipe not a console + // + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +} + +/* _cw_serf_stdio(): cleanup on serf exit. +*/ +static void +_cw_serf_exit(void) +{ + u3s_cue_xeno_done(sil_u); + u3t_trace_close(); +} + +/* _cw_init_io(): initialize i/o streams. +*/ +static void +_cw_init_io(uv_loop_t* lup_u) +{ + // mars is spawned with [FD 0] = events and [FD 1] = effects + // we dup [FD 0 & 1] so we don't accidently use them for something else + // we replace [FD 0] (stdin) with a fd pointing to /dev/null + // we replace [FD 1] (stdout) with a dup of [FD 2] (stderr) + // + c3_i nul_i = c3_open(c3_dev_null, O_RDWR, 0); + c3_i inn_i = dup(0); + c3_i out_i = dup(1); + + dup2(nul_i, 0); + dup2(2, 1); + + close(nul_i); + + // set stream I/O to unbuffered because it's now a pipe not a console + // + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + + // Ignore SIGPIPE signals. + // +#ifndef U3_OS_mingw + { + struct sigaction sig_s = {{0}}; + sigemptyset(&(sig_s.sa_mask)); + sig_s.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sig_s, 0); + } +#endif + + // configure pipe to daemon process + // + { + c3_i err_i; + err_i = uv_timer_init(lup_u, &inn_u.tim_u); + c3_assert(!err_i); + err_i = uv_pipe_init(lup_u, &inn_u.pyp_u, 0); + c3_assert(!err_i); + uv_pipe_open(&inn_u.pyp_u, inn_i); + err_i = uv_pipe_init(lup_u, &out_u.pyp_u, 0); + c3_assert(!err_i); + uv_pipe_open(&out_u.pyp_u, out_i); + + uv_stream_set_blocking((uv_stream_t*)&out_u.pyp_u, 1); + } +} + +#ifdef U3_OS_mingw +/* _cw_intr_win_cb(): invoked when urth signals ctrl-c. +*/ +static void +_cw_intr_win_cb(PVOID param, BOOLEAN timedOut) +{ + rsignal_raise(SIGINT); +} + +/* _cw_intr_win(): initialize ctrl-c handling. +*/ +static void +_cw_intr_win(c3_c* han_c) +{ + HANDLE h; + if ( 1 != sscanf(han_c, "%" PRIu64, &h) ) { + fprintf(stderr, "mars: ctrl-c event: bad handle %s: %s\r\n", + han_c, strerror(errno)); + } + else { + if ( !RegisterWaitForSingleObject(&h, h, _cw_intr_win_cb, + NULL, INFINITE, 0) ) + { + fprintf(stderr, + "mars: ctrl-c event: RegisterWaitForSingleObject(%u) failed (%d)\r\n", + h, GetLastError()); + } + } +} +#endif + +/* _cw_serf_commence(): initialize and run serf +*/ +static void +_cw_serf_commence(c3_i argc, c3_c* argv[]) +{ +#ifdef U3_OS_mingw + if ( 8 > argc ) { +#else + if ( 7 > argc ) { +#endif + fprintf(stderr, "serf: missing args\n"); + exit(1); + } + + c3_d eve_d = 0; + uv_loop_t* lup_u = u3_Host.lup_u = uv_default_loop(); + c3_c* dir_c = argv[2]; + c3_c* key_c = argv[3]; // XX use passkey + c3_c* wag_c = argv[4]; + c3_c* hap_c = argv[5]; + c3_c* eve_c = argv[6]; +#ifdef U3_OS_mingw + c3_c* han_c = argv[7]; + _cw_intr_win(han_c); +#endif + + _cw_init_io(lup_u); + + memset(&u3V, 0, sizeof(u3V)); + memset(&u3_Host.tra_u, 0, sizeof(u3_Host.tra_u)); + + // load passkey + // + // XX and then ... use passkey + // + { + sscanf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64, + &u3V.key_d[0], + &u3V.key_d[1], + &u3V.key_d[2], + &u3V.key_d[3]); + } + + // load runtime config + // + { + sscanf(wag_c, "%" SCNu32, &u3C.wag_w); + sscanf(hap_c, "%" SCNu32, &u3_Host.ops_u.hap_w); + + if ( 1 != sscanf(eve_c, "%" PRIu64, &eve_d) ) { + fprintf(stderr, "serf: rock: invalid number '%s'\r\n", argv[4]); + } + } + + sil_u = u3s_cue_xeno_init(); + + // set up writing + // + out_u.ptr_v = &u3V; + out_u.bal_f = _cw_serf_fail; + + // set up reading + // + inn_u.ptr_v = &u3V; + inn_u.pok_f = _cw_serf_writ; + inn_u.bal_f = _cw_serf_fail; + + // setup loom + // + { + u3V.dir_c = strdup(dir_c); + u3V.sen_d = u3V.dun_d = u3m_boot(dir_c); + + if ( eve_d ) { + // XX need not be fatal, need a u3m_reboot equivalent + // XX can spuriously fail do to corrupt memory-image checkpoint, + // need a u3m_half_boot equivalent + // workaround is to delete/move the checkpoint in case of corruption + // + if ( c3n == u3u_uncram(u3V.dir_c, eve_d) ) { + fprintf(stderr, "serf (%" PRIu64 "): rock load failed\r\n", eve_d); + exit(1); + } + } + } + + // set up logging + // + // XX must be after u3m_boot due to u3l_log + // + { + u3C.stderr_log_f = _cw_serf_send_stdr; + u3C.slog_f = _cw_serf_send_slog; + } + + u3V.xit_f = _cw_serf_exit; + +#if defined(SERF_TRACE_JAM) || defined(SERF_TRACE_CUE) + u3t_trace_open(u3V.dir_c); +#endif + + // start serf + // + { + _cw_serf_send(u3_serf_init(&u3V)); + } + + // start reading + // + u3_newt_read_sync(&inn_u); + + // enter loop + // + uv_run(lup_u, UV_RUN_DEFAULT); + u3m_stop(); +} + +/* _cw_disk_init(): open event log +*/ +static u3_disk* +_cw_disk_init(c3_c* dir_c) +{ + u3_disk_cb cb_u = {0}; + u3_disk* log_u = u3_disk_init(dir_c, cb_u); + + if ( !log_u ) { + fprintf(stderr, "unable to open event log\n"); + exit(1); + } + + return log_u; +} + +/* _cw_dock(): copy binary into pier +*/ +static void +_cw_dock(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + _main_self_path(); + + u3_king_dock(U3_VERE_PACE); +} + +/* _cw_info(): print pier info +*/ +static void +_cw_info(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + c3_d eve_d = u3m_boot(u3_Host.dir_c); + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); + + fprintf(stderr, "\r\nurbit: %s at event %" PRIu64 "\r\n", + u3_Host.dir_c, eve_d); + + u3_disk_slog(log_u); + printf("\n"); + u3_lmdb_stat(log_u->mdb_u, stdout); + u3_disk_exit(log_u); + + u3m_stop(); +} + +/* _cw_grab(): gc pier. +*/ +static void +_cw_grab(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + u3m_boot(u3_Host.dir_c); + u3C.wag_w |= u3o_hashless; + u3_serf_grab(); + u3m_stop(); +} + +/* _cw_cram(): jam persistent state (rock), and exit. +*/ +static void +_cw_cram(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + c3_d eve_d = u3m_boot(u3_Host.dir_c); + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock + c3_o ret_o; + + fprintf(stderr, "urbit: cram: preparing\r\n"); + + if ( c3n == (ret_o = u3u_cram(u3_Host.dir_c, eve_d)) ) { + fprintf(stderr, "urbit: cram: unable to jam state\r\n"); + } + else { + fprintf(stderr, "urbit: cram: rock saved at event %" PRIu64 "\r\n", eve_d); + } + + // save even on failure, as we just did all the work of deduplication + // + u3e_save(); + u3_disk_exit(log_u); + + if ( c3n == ret_o ) { + exit(1); + } + + u3m_stop(); +} + +/* _cw_queu(): cue rock, save, and exit. +*/ +static void +_cw_queu(c3_i argc, c3_c* argv[]) +{ + c3_c* eve_c; + c3_d eve_d; + + switch ( argc ) { + case 3: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + eve_c = argv[2]; + } break; + + case 4: { + u3_Host.dir_c = argv[2]; + eve_c = argv[3]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + if ( 1 != sscanf(eve_c, "%" PRIu64 "", &eve_d) ) { + fprintf(stderr, "urbit: queu: invalid number '%s'\r\n", eve_c); + exit(1); + } + else { + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock + + fprintf(stderr, "urbit: queu: preparing\r\n"); + + u3m_boot(u3_Host.dir_c); + + // XX can spuriously fail do to corrupt memory-image checkpoint, + // need a u3m_half_boot equivalent + // workaround is to delete/move the checkpoint in case of corruption + // + if ( c3n == u3u_uncram(u3_Host.dir_c, eve_d) ) { + fprintf(stderr, "urbit: queu: failed\r\n"); + exit(1); + } + + u3e_save(); + u3_disk_exit(log_u); + + fprintf(stderr, "urbit: queu: rock loaded at event %" PRIu64 "\r\n", eve_d); + u3m_stop(); + } +} + +/* _cw_uniq(): deduplicate persistent nouns +*/ +static void +_cw_meld(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock + c3_w pre_w; + + u3C.wag_w |= u3o_hashless; + u3m_boot(u3_Host.dir_c); + + pre_w = u3a_open(u3R); + u3u_meld(); + u3a_print_memory(stderr, "urbit: meld: gained", (u3a_open(u3R) - pre_w)); + + u3e_save(); + u3_disk_exit(log_u); + u3m_stop(); +} + +/* _cw_next(): request upgrade +*/ +static void +_cw_next(c3_i argc, c3_c* argv[]) +{ + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "arch", required_argument, NULL, 'a' }, + { NULL, 0, NULL, 0 } + }; + + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "a:", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case 'a': { + u3_Host.arc_c = strdup(optarg); + } break; + + case '?': { + exit(1); + } break; + } + } + + // argv[optind] is always "next" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); + exit(1); + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + u3_Host.pep_o = c3y; + u3_Host.nex_o = c3y; +} + +/* _cw_pack(): compact memory, save, and exit. +*/ +static void +_cw_pack(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock + + u3m_boot(u3_Host.dir_c); + u3a_print_memory(stderr, "urbit: pack: gained", u3m_pack()); + + u3e_save(); + u3_disk_exit(log_u); + u3m_stop(); +} + +/* _cw_prep(): prepare for upgrade +*/ +static void +_cw_prep(c3_i argc, c3_c* argv[]) +{ + switch ( argc ) { + case 2: { + if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { + fprintf(stderr, "unable to find pier\r\n"); + exit (1); + } + } break; + + case 3: { + u3_Host.dir_c = argv[2]; + } break; + + default: { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } break; + } + + u3_Host.pep_o = c3y; +} + +/* _cw_vere(): download vere +*/ +static void +_cw_vere(c3_i argc, c3_c* argv[]) +{ + c3_c* pac_c = "live"; + c3_c* arc_c = 0; + c3_c* ver_c = 0; + c3_c* dir_c; + + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "arch", required_argument, NULL, 'a' }, + { "pace", required_argument, NULL, 'p' }, + { "version", required_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } + }; + + while ( -1 != (ch_i=getopt_long(argc, argv, "a:p:v:", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case 'a': { + arc_c = strdup(optarg); + } break; + + case 'p': { + pac_c = strdup(optarg); + } break; + + case 'v': { + ver_c = strdup(optarg); + } break; + + case '?': { + exit(1); + } break; + } + } + + // argv[optind] is always "vere"/"fetch-vere" + // + + if ( optind + 1 < argc ) { + dir_c = argv[optind + 1]; + optind++; + } + else { + fprintf(stderr, "invalid command, output directory required\r\n"); + exit(1); + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + if ( !arc_c ) { +#ifdef U3_OS_ARCH + arc_c = U3_OS_ARCH; +#else + fprintf(stderr, "unknown architecture, --arch required\r\n"); + exit(1); +#endif + } + + // Initialize OpenSSL for client and server + // + { + SSL_library_init(); + SSL_load_error_strings(); + } + + // initialize curl + // + if ( 0 != curl_global_init(CURL_GLOBAL_DEFAULT) ) { + u3l_log("boot: curl initialization failed\r\n"); + exit(1); + } + + _setup_cert_store(); + u3K.ssl_curl_f = _setup_ssl_curl; + u3K.ssl_x509_f = _setup_ssl_x509; + + if ( !ver_c ) { + switch ( u3_king_next(pac_c, &ver_c) ) { + case -2: { + fprintf(stderr, "vere: unable to check for next version\n"); + exit(1); + } break; + + case -1: { + fprintf(stderr, "you're already running it!\n"); + exit(0); + } break; + + case 0: { + fprintf(stderr, "vere: next (%%%s): %s\n", pac_c, ver_c); + } break; + + default: c3_assert(0); + } + } + + + if ( u3_king_vere(pac_c, ver_c, arc_c, dir_c, 0) ) { + u3l_log("vere: download failed\r\n"); + exit(1); + } + + u3l_log("vere: download succeeded\r\n"); +} + +/* _cw_utils(): "worker" utilities and "serf" entrypoint +*/ +static c3_i +_cw_utils(c3_i argc, c3_c* argv[]) +{ + // utility commands and positional arguments, by analogy + // + // $@ ~ :: usage + // $% [%cram dir=@t] :: jam state + // [%dock dir=@t] :: copy binary + // [?(%grab %mass) dir=@t] :: gc + // [%info dir=@t] :: print + // [%meld dir=@t] :: deduplicate + // [?(%next %upgrade) dir=@t] :: upgrade + // [%pack dir=@t] :: defragment + // [%prep dir=@t] :: prep upgrade + // [%queu dir=@t eve=@ud] :: cue state + // [?(%vere %fetch-vere) dir=@t] :: download vere + // :: :: ipc: + // [%serf dir=@t key=@t wag=@t hap=@ud eve=@ud] :: compute + // == + // + // NB: don't print to anything other than stderr; + // other streams may be used for ipc. + // + c3_m mot_m = 0; + + if ( 2 <= argc ) { + if ( 4 == strlen(argv[1]) ) { + c3_c* s = argv[1]; + mot_m = c3_s4(s[0], s[1], s[2], s[3]); + } + else if ( 0 == strcmp(argv[1], "upgrade") ) { + mot_m = c3__next; + } + else if ( 0 == strcmp(argv[1], "fetch-vere") ) { + mot_m = c3__vere; + } + } + + switch ( mot_m ) { + case c3__cram: _cw_cram(argc, argv); return 1; + case c3__dock: _cw_dock(argc, argv); return 1; + + case c3__mass: + case c3__grab: _cw_grab(argc, argv); return 1; + + case c3__info: _cw_info(argc, argv); return 1; + case c3__meld: _cw_meld(argc, argv); return 1; + case c3__next: _cw_next(argc, argv); return 2; // continue on + case c3__pack: _cw_pack(argc, argv); return 1; + case c3__prep: _cw_prep(argc, argv); return 2; // continue on + case c3__queu: _cw_queu(argc, argv); return 1; + case c3__vere: _cw_vere(argc, argv); return 1; + + case c3__serf: _cw_serf_commence(argc, argv); return 1; + } + + return 0; } c3_i main(c3_i argc, c3_c** argv) { - // Parse options. + if ( argc <= 0 ) { + fprintf(stderr, "nice try, fbi\r\n"); + exit(1); + } + + _main_init(); + + c3_c* bin_c = strdup(argv[0]); + + // parse for subcommands // - if ( c3n == _main_getopt(argc, argv) ) { - if ( (3 == argc) - && (0 == strcmp("db-info", argv[1])) ) - { - return _debug_db_stats(argv[2]); + switch ( _cw_utils(argc, argv) ) { + default: c3_assert(0); + + // no matching subcommand, parse arguments + // + case 0: { + if ( c3n == _main_getopt(argc, argv) ) { + u3_ve_usage(argc, argv); + return 1; + } + } break; + + // ran subcommand + case 1: { + return 0; } - u3_ve_usage(argc, argv); - return 1; + // found subcommand, continue + // + case 2: break; } - // Set `u3_Host.wrk_c` to the worker executable path. - c3_i urbit_exe_len = strlen(argv[0]); - c3_i worker_exe_len = 1 + urbit_exe_len + strlen("-worker"); - u3_Host.wrk_c = c3_malloc(worker_exe_len); - #if defined(U3_OS_mingw) - if ( urbit_exe_len >= 4 && !strcmp(argv[0] + urbit_exe_len - 4, ".exe")) { - snprintf(u3_Host.wrk_c, worker_exe_len, "%.*s-worker.exe", urbit_exe_len - 4, argv[0]); - } else { - snprintf(u3_Host.wrk_c, worker_exe_len, "%s-worker", argv[0]); + _main_self_path(); + + // XX add argument + // + if ( !u3_Host.wrk_c ) { + u3_Host.wrk_c = bin_c; + } + else { + c3_free(bin_c); } - #else - snprintf(u3_Host.wrk_c, worker_exe_len, "%s-worker", argv[0]); - #endif if ( c3y == u3_Host.ops_u.dem ) { // In daemon mode, run the urbit as a background process, but don't @@ -663,31 +1743,7 @@ main(c3_i argc, printf("~\n"); // printf("welcome.\n"); printf("urbit %s\n", URBIT_VERSION); - - // prints the absolute path of the pier - // - c3_c* abs_c = realpath(u3_Host.dir_c, 0); - - // if the ship is being booted, we use realpath(). Otherwise, we use getcwd() - // with a memory-allocation loop - // - if (abs_c == NULL) { - c3_i mprint_i = 1000; - abs_c = c3_malloc(mprint_i); - - // allocates more memory as needed if the path is too large - // - while ( abs_c != getcwd(abs_c, mprint_i) ) { - c3_free(abs_c); - mprint_i *= 2; - abs_c = c3_malloc(mprint_i); - } - printf("boot: home is %s/%s\n", abs_c, u3_Host.dir_c); - c3_free(abs_c); - } else { - printf("boot: home is %s\n", abs_c); - c3_free(abs_c); - } + printf("boot: home is %s\n", u3_Host.dir_c); // printf("vere: hostname is %s\n", u3_Host.ops_u.nam_c); if ( c3y == u3_Host.ops_u.dem ) { @@ -756,7 +1812,7 @@ main(c3_i argc, } } - #if defined(U3_OS_mingw) +#ifdef U3_OS_mingw // Initialize event used to transmit Ctrl-C to worker process // { @@ -766,11 +1822,11 @@ main(c3_i argc, exit(1); } } - #endif +#endif // starting u3m configures OpenSSL memory functions, so we must do it // before any OpenSSL allocations - // + // u3m_boot_lite(); // Initialize OpenSSL for client and server diff --git a/pkg/urbit/daemon/whereami.c b/pkg/urbit/daemon/whereami.c new file mode 100644 index 0000000000..2900057660 --- /dev/null +++ b/pkg/urbit/daemon/whereami.c @@ -0,0 +1,673 @@ +// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +// in case you want to #include "whereami.c" in a larger compilation unit +#if !defined(WHEREAMI_H) +#include "whereami.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) +#include +#endif + +#if !defined(WAI_MALLOC) +#define WAI_MALLOC(size) malloc(size) +#endif + +#if !defined(WAI_FREE) +#define WAI_FREE(p) free(p) +#endif + +#if !defined(WAI_REALLOC) +#define WAI_REALLOC(p, size) realloc(p, size) +#endif + +#ifndef WAI_NOINLINE +#if defined(_MSC_VER) +#define WAI_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define WAI_NOINLINE __attribute__((noinline)) +#else +#error unsupported compiler +#endif +#endif + +#if defined(_MSC_VER) +#define WAI_RETURN_ADDRESS() _ReturnAddress() +#elif defined(__GNUC__) +#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) +#else +#error unsupported compiler +#endif + +#if defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) +#pragma warning(push, 3) +#endif +#include +#include +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) +{ + wchar_t buffer1[MAX_PATH]; + wchar_t buffer2[MAX_PATH]; + wchar_t* path = NULL; + int length = -1; + + for (;;) + { + DWORD size; + int length_, length__; + + size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0])); + + if (size == 0) + break; + else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0]))) + { + DWORD size_ = size; + do + { + wchar_t* path_; + + path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2); + if (!path_) + break; + size_ *= 2; + path = path_; + size = GetModuleFileNameW(module, path, size_); + } + while (size == size_); + + if (size == size_) + break; + } + else + path = buffer1; + + if (!_wfullpath(buffer2, path, MAX_PATH)) + break; + length_ = (int)wcslen(buffer2); + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL); + + if (length__ == 0) + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL); + if (length__ == 0) + break; + + if (length__ <= capacity && dirname_length) + { + int i; + + for (i = length__ - 1; i >= 0; --i) + { + if (out[i] == '\\') + { + *dirname_length = i; + break; + } + } + } + + length = length__; + + break; + } + + if (path != buffer1) + WAI_FREE(path); + + return length; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + HMODULE module; + int length = -1; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4054) +#endif + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module)) +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + { + length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length); + } + + return length; +} + +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) + +#include +#include +#include +#if defined(__linux__) +#include +#else +#include +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include + +#if !defined(WAI_PROC_SELF_EXE) +#if defined(__sun) +#define WAI_PROC_SELF_EXE "/proc/self/path/a.out" +#else +#define WAI_PROC_SELF_EXE "/proc/self/exe" +#endif +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for (;;) + { + resolved = realpath(WAI_PROC_SELF_EXE, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + + return length; +} + +#if !defined(WAI_PROC_SELF_MAPS_RETRY) +#define WAI_PROC_SELF_MAPS_RETRY 5 +#endif + +#if !defined(WAI_PROC_SELF_MAPS) +#if defined(__sun) +#define WAI_PROC_SELF_MAPS "/proc/self/map" +#else +#define WAI_PROC_SELF_MAPS "/proc/self/maps" +#endif +#endif + +#if defined(__ANDROID__) || defined(ANDROID) +#include +#include +#include +#endif + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + int length = -1; + FILE* maps = NULL; + + for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r) + { + maps = fopen(WAI_PROC_SELF_MAPS, "r"); + if (!maps) + break; + + for (;;) + { + char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; + uint64_t low, high; + char perms[5]; + uint64_t offset; + uint32_t major, minor; + char path[PATH_MAX]; + uint32_t inode; + + if (!fgets(buffer, sizeof(buffer), maps)) + break; + + if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) + { + uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS(); + if (low <= addr && addr <= high) + { + char* resolved; + + resolved = realpath(path, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); +#if defined(__ANDROID__) || defined(ANDROID) + if (length > 4 + &&buffer[length - 1] == 'k' + &&buffer[length - 2] == 'p' + &&buffer[length - 3] == 'a' + &&buffer[length - 4] == '.') + { + int fd = open(path, O_RDONLY); + char* begin; + char* p; + + begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + p = begin + offset; + + while (p >= begin) // scan backwards + { + if (*((uint32_t*)p) == 0x04034b50UL) // local file header found + { + uint16_t length_ = *((uint16_t*)(p + 26)); + + if (length + 2 + length_ < (int)sizeof(buffer)) + { + memcpy(&buffer[length], "!/", 2); + memcpy(&buffer[length + 2], p + 30, length_); + length += 2 + length_; + } + + break; + } + + p -= 4; + } + + munmap(begin, offset); + close(fd); + } +#endif + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + } + } + + fclose(maps); + maps = NULL; + + if (length != -1) + break; + } + + if (maps) + fclose(maps); + + return length; +} + +#elif defined(__APPLE__) + +#define _DARWIN_BETTER_REALPATH +#include +#include +#include +#include +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + + for (;;) + { + uint32_t size = (uint32_t)sizeof(buffer1); + if (_NSGetExecutablePath(path, &size) == -1) + { + path = (char*)WAI_MALLOC(size); + if (!_NSGetExecutablePath(path, &size)) + break; + } + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + + if (path != buffer1) + WAI_FREE(path); + + return length; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__QNXNTO__) + +#include +#include +#include +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#define WAI_PROC_SELF_EXE "/proc/self/exefile" +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* resolved = NULL; + FILE* self_exe = NULL; + int length = -1; + + for (;;) + { + self_exe = fopen(WAI_PROC_SELF_EXE, "r"); + if (!self_exe) + break; + + if (!fgets(buffer1, sizeof(buffer1), self_exe)) + break; + + resolved = realpath(buffer1, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + + fclose(self_exe); + + return length; +} + +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__) + +#include +#include +#include +#include +#include +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + + for (;;) + { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t size = sizeof(buffer1); + + if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0) + break; + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + + if (path != buffer1) + WAI_FREE(path); + + return length; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#else + +#error unsupported platform + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/pkg/urbit/daemon/whereami.h b/pkg/urbit/daemon/whereami.h new file mode 100644 index 0000000000..6c81af8187 --- /dev/null +++ b/pkg/urbit/daemon/whereami.h @@ -0,0 +1,65 @@ +// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +#ifndef WHEREAMI_H +#define WHEREAMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WAI_FUNCSPEC + #define WAI_FUNCSPEC +#endif +#ifndef WAI_PREFIX +#define WAI_PREFIX(function) wai_##function +#endif + +/** + * Returns the path to the current executable. + * + * Usage: + * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to + * retrieve the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the + * path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the executable path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); + +/** + * Returns the path to the current module + * + * Usage: + * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve + * the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the module path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef WHEREAMI_H diff --git a/pkg/urbit/include/all.h b/pkg/urbit/include/all.h index b138c6d408..ae647d865a 100644 --- a/pkg/urbit/include/all.h +++ b/pkg/urbit/include/all.h @@ -1,7 +1,3 @@ -/* include/all.h -** -** This file is in the public domain. -*/ # include "config.h" /** c3: C environment. **/ diff --git a/pkg/urbit/include/c/defs.h b/pkg/urbit/include/c/defs.h index 8dda9b126e..29198bc009 100644 --- a/pkg/urbit/include/c/defs.h +++ b/pkg/urbit/include/c/defs.h @@ -1,7 +1,6 @@ -/* include/c/defs.h -** -** This file is in the public domain. -*/ +#ifndef C3_DEFS_H +#define C3_DEFS_H + /** Loobeans - inverse booleans to match nock. **/ # define c3y 0 @@ -122,3 +121,30 @@ c3_assert(!"memory lost"); \ } \ rut;}) + + /* Asserting unix fs wrappers. + ** + ** these all crash the process if passed a non-canonical + ** path (i.e., one containing '.', '..', or the empty path + ** component), so make sure you don't pass them one. if you + ** find yourself fighting with them, then please delete them + ** and do a sed search-and-replace to remove the `c3_` from + ** their call sites; their goal is to decrease maintenance + ** burden, not increase it. + */ + // defined in vere/io/unix.c. + c3_t u3_unix_cane(const c3_c* pax_c); +# define c3_open(a, ...) ({ \ + open(a, __VA_ARGS__);}) +# define c3_opendir(a) ({ \ + opendir(a);}) +# define c3_mkdir(a, b) ({ \ + mkdir(a, b);}) +# define c3_rmdir(a) ({ \ + rmdir(a);}) +# define c3_unlink(a) ({ \ + unlink(a);}) +# define c3_fopen(a, b) ({ \ + fopen(a, b);}) + +#endif /* ifndef C3_DEFS_H */ diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index 789fd209f8..cd2668632a 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -1,7 +1,6 @@ -/* include/lib/motes.h -** -** This file is in the public domain. -*/ +#ifndef C3_MOTES_H +#define C3_MOTES_H + /** Definitions. **/ @@ -27,6 +26,8 @@ # define c3__at c3_s2('a','t') # define c3__atom c3_s4('a','t','o','m') # define c3__auth c3_s4('a','u','t','h') +# define c3__auto c3_s4('a','u','t','o') +# define c3__avow c3_s4('a','v','o','w') # define c3__ax c3_s2('a','x') # define c3__axe c3_s3('a','x','e') # define c3__axil c3_s4('a','x','i','l') @@ -35,18 +36,16 @@ # define c3__bac c3_s3('b','a','c') # define c3__bach c3_s4('b','a','c','h') # define c3__bag c3_s3('b','a','g') -# define c3__bar c3_s3('b','a','r') # define c3__bail c3_s4('b','a','i','l') # define c3__ball c3_s4('b','a','l','l') # define c3__band c3_s4('b','a','n','d') # define c3__bank c3_s4('b','a','n','k') +# define c3__bar c3_s3('b','a','r') # define c3__bark c3_s4('b','a','r','k') # define c3__barn c3_s4('b','a','r','n') # define c3__base c3_s4('b','a','s','e') # define c3__bask c3_s4('b','a','s','k') # define c3__basp c3_s4('b','a','s','p') -# define c3__bee c3_s3('b','e','e') -# define c3__bel c3_s3('b','e','l') # define c3__bbye c3_s4('b','b','y','e') # define c3__bcbn c3_s4('b','c','b','n') # define c3__bcbr c3_s4('b','c','b','r') @@ -67,7 +66,9 @@ # define c3__bean c3_s4('b','e','a','n') # define c3__bear c3_s4('b','e','a','r') # define c3__bede c3_s4('b','e','d','e') +# define c3__bee c3_s3('b','e','e') # define c3__behn c3_s4('b','e','h','n') +# define c3__bel c3_s3('b','e','l') # define c3__belt c3_s4('b','e','l','t') # define c3__bend c3_s4('b','e','n','d') # define c3__ber c3_s3('b','e','r') @@ -100,6 +101,7 @@ # define c3__bnpd c3_s4('b','n','p','d') # define c3__bnps c3_s4('b','n','p','s') # define c3__bnsp c3_s4('b','n','s','p') +# define c3__boat c3_s4('b','o','a','t') # define c3__boce c3_s4('b','o','c','e') # define c3__boil c3_s4('b','o','i','l') # define c3__boin c3_s4('b','o','i','n') @@ -109,7 +111,6 @@ # define c3__bong c3_s4('b','o','n','g') # define c3__book c3_s4('b','o','o','k') # define c3__bool c3_s4('b','o','o','l') -# define c3__boat c3_s4('b','o','a','t') # define c3__boot c3_s4('b','o','o','t') # define c3__born c3_s4('b','o','r','n') # define c3__both c3_s4('b','o','t','h') @@ -120,16 +121,16 @@ # define c3__brax c3_s4('b','r','a','x') # define c3__brbn c3_s4('b','r','b','n') # define c3__brcb c3_s4('b','r','c','b') +# define c3__brcl c3_s4('b','r','c','l') # define c3__brcn c3_s4('b','r','c','n') # define c3__brcs c3_s4('b','r','c','s') # define c3__brdg c3_s4('b','r','d','g') # define c3__brdl c3_s4('b','r','d','l') # define c3__brdp c3_s4('b','r','d','p') # define c3__brdt c3_s4('b','r','d','t') -# define c3__brkt c3_s4('b','r','k','t') # define c3__brhp c3_s4('b','r','h','p') # define c3__brip c3_s4('b','r','i','p') -# define c3__brcl c3_s4('b','r','c','l') +# define c3__brkt c3_s4('b','r','k','t') # define c3__brlc c3_s4('b','r','l','c') # define c3__brld c3_s4('b','r','l','d') # define c3__brls c3_s4('b','r','l','s') @@ -211,9 +212,9 @@ # define c3__clkt c3_s4('c','l','k','t') # define c3__clls c3_s4('c','l','l','s') # define c3__clms c3_s4('c','l','m','s') +# define c3__clr c3_s3('c','l','r') # define c3__clsg c3_s4('c','l','s','g') # define c3__clsp c3_s4('c','l','s','p') -# define c3__clr c3_s3('c','l','r') # define c3__cltr c3_s4('c','l','t','r') # define c3__cnbc c3_s4('c','n','b','c') # define c3__cnbr c3_s4('c','n','b','r') @@ -247,9 +248,9 @@ # define c3__cook c3_s4('c','o','o','k') # define c3__cool c3_s4('c','o','o','l') # define c3__core c3_s4('c','o','r','e') -# define c3__corp c3_s4('c','o','r','p') # define c3__corm c3_s4('c','o','r','m') # define c3__corp c3_s4('c','o','r','p') +# define c3__corp c3_s4('c','o','r','p') # define c3__cow c3_s3('c','o','w') # define c3__cpu c3_s3('c','p','u') # define c3__crad c3_s4('c','r','a','d') @@ -280,11 +281,11 @@ # define c3__cstg c3_s4('c','s','t','g') # define c3__cstr c3_s4('c','s','t','r') # define c3__cszp c3_s4('c','s','z','p') +# define c3__ctl c3_s3('c','t','l') # define c3__cttp c3_s4('c','t','t','p') # define c3__cube c3_s4('c','u','b','e') # define c3__cull c3_s4('c','u','l','l') # define c3__curd c3_s4('c','u','r','d') -# define c3__ctl c3_s3('c','t','l') # define c3__cut c3_s3('c','u','t') # define c3__cyl c3_s3('c','y','l') # define c3__czar c3_s4('c','z','a','r') @@ -327,6 +328,7 @@ # define c3__dmal c3_s4('d','m','a','l') # define c3__do c3_s2('d','o') # define c3__doc c3_s3('d','o','c') +# define c3__dock c3_s4('d','o','c','k') # define c3__docs c3_s4('d','o','c','s') # define c3__dogo c3_s4('d','o','g','o') # define c3__dojo c3_s4('d','o','j','o') @@ -364,13 +366,13 @@ # define c3__dtwt c3_s4('d','t','w','t') # define c3__dtzy c3_s4('d','t','z','y') # define c3__dtzz c3_s4('d','t','z','z') -# define c3__dxkt c3_s4('d','x','k','t') # define c3__dub c3_s3('d','u','b') # define c3__duct c3_s4('d','u','c','t') # define c3__duke c3_s4('d','u','k','e') # define c3__dumb c3_s4('d','u','m','b') # define c3__dump c3_s4('d','u','m','p') # define c3__dust c3_s4('d','u','s','t') +# define c3__dxkt c3_s4('d','x','k','t') # define c3__e c3_s1('e') # define c3__earl c3_s4('e','a','r','l') # define c3__east c3_s4('e','a','s','t') @@ -382,10 +384,10 @@ # define c3__emph c3_s4('e','m','p','h') # define c3__end c3_s3('e','n','d') # define c3__eq c3_s2('e','q') -# define c3__ex c3_s2('e','x') -# define c3__esh c3_s3('e','s','h') # define c3__ergo c3_s4('e','r','g','o') +# define c3__esh c3_s3('e','s','h') # define c3__etch c3_s4('e','t','c','h') +# define c3__ex c3_s2('e','x') # define c3__exit c3_s4('e','x','i','t') # define c3__eyre c3_s4('e','y','r','e') # define c3__f c3_s1('f') @@ -443,19 +445,20 @@ # define c3__free c3_s4('f','r','e','e') # define c3__frez c3_s4('f','r','e','z') # define c3__frit c3_s4('f','r','i','t') -# define c3__from c3_s4('f','r','o','m') # define c3__frog c3_s4('f','r','o','g') +# define c3__from c3_s4('f','r','o','m') # define c3__fron c3_s4('f','r','o','n') # define c3__fry c3_s3('f','r','y') # define c3__fuge c3_s4('f','u','g','e') -# define c3__fume c3_s4('f','u','m','e') # define c3__full c3_s4('f','u','l','l') +# define c3__fume c3_s4('f','u','m','e') # define c3__fun c3_s3('f','u','n') # define c3__fund c3_s4('f','u','n','d') # define c3__fung c3_s4('f','u','n','g') # define c3__funk c3_s4('f','u','n','k') # define c3__fuse c3_s4('f','u','s','e') # define c3__fuss c3_s4('f','u','s','s') +# define c3__fyrd c3_s4('f','y','r','d') # define c3__gab c3_s3('g','a','b') # define c3__galb c3_s4('g','a','l','b') # define c3__gald c3_s4('g','a','l','d') @@ -490,6 +493,7 @@ # define c3__good c3_s4('g','o','o','d') # define c3__gorm c3_s4('g','o','r','m') # define c3__goto c3_s4('g','o','t','o') +# define c3__grab c3_s4('g','r','a','b') # define c3__grad c3_s4('g','r','a','d') # define c3__gram c3_s4('g','r','a','m') # define c3__gran c3_s4('g','r','a','n') @@ -525,6 +529,7 @@ # define c3__head c3_s4('h','e','a','d') # define c3__heal c3_s4('h','e','a','l') # define c3__hear c3_s4('h','e','a','r') +# define c3__hela c3_s4('h','e','l','a') # define c3__helm c3_s4('h','e','l','m') # define c3__helo c3_s4('h','e','l','o') # define c3__help c3_s4('h','e','l','p') @@ -542,8 +547,8 @@ # define c3__hit c3_s3('h','i','t') # define c3__hmal c3_s4('h','m','a','l') # define c3__hold c3_s4('h','o','l','d') -# define c3__holt c3_s4('h','o','l','t') # define c3__hole c3_s4('h','o','l','e') +# define c3__holt c3_s4('h','o','l','t') # define c3__home c3_s4('h','o','m','e') # define c3__homp c3_s4('h','o','m','p') # define c3__hook c3_s4('h','o','o','k') @@ -571,10 +576,10 @@ # define c3__http c3_s4('h','t','t','p') # define c3__hume c3_s4('h','u','m','e') # define c3__hunk c3_s4('h','u','n','k') -# define c3__hxtr c3_s4('h','x','t','r') -# define c3__hxts c3_s4('h','x','t','s') # define c3__hxgl c3_s4('h','x','g','l') # define c3__hxgr c3_s4('h','x','g','r') +# define c3__hxtr c3_s4('h','x','t','r') +# define c3__hxts c3_s4('h','x','t','s') # define c3__i c3_s1('i') # define c3__ic c3_s2('i','c') # define c3__ice c3_s3('i','c','e') @@ -584,6 +589,7 @@ # define c3__ifix c3_s4('i','f','i','x') # define c3__in c3_s2('i','n') # define c3__inc c3_s3('i','n','c') +# define c3__info c3_s4('i','n','f','o') # define c3__init c3_s4('i','n','i','t') # define c3__ins c3_s3('i','n','s') # define c3__into c3_s4('i','n','t','o') @@ -603,6 +609,8 @@ # define c3__jet c3_s3('j','e','t') # define c3__jetd c3_s4('j','e','t','d') # define c3__just c3_s4('j','u','s','t') +# define c3__k c3_s1('k') +# define c3__khan c3_s4('k','h','a','n') # define c3__keep c3_s4('k','e','e','p') # define c3__kern c3_s4('k','e','r','n') # define c3__kgo c3_s3('k','g','o') @@ -691,6 +699,7 @@ # define c3__look c3_s4('l','o','o','k') # define c3__loop c3_s4('l','o','o','p') # define c3__lorb c3_s4('l','o','r','b') +# define c3__lord c3_s4('l','o','r','d') # define c3__lort c3_s4('l','o','r','t') # define c3__lose c3_s4('l','o','s','e') # define c3__loss c3_s4('l','o','s','s') @@ -700,8 +709,8 @@ # define c3__lt c3_s2('l','t') # define c3__lull c3_s4('l','u','l','l') # define c3__lunt c3_s4('l','u','n','t') -# define c3__mack c3_s4('m','a','c','k') # define c3__mach c3_s4('m','a','c','h') +# define c3__mack c3_s4('m','a','c','k') # define c3__main c3_s4('m','a','i','n') # define c3__make c3_s4('m','a','k','e') # define c3__malg c3_s4('m','a','l','g') @@ -711,9 +720,9 @@ # define c3__map c3_s3('m','a','p') # define c3__marg c3_s4('m','a','r','g') # define c3__mark c3_s4('m','a','r','k') -# define c3__mass c3_s4('m','a','s','s') # define c3__marn c3_s4('m','a','r','n') # define c3__mash c3_s4('m','a','s','h') +# define c3__mass c3_s4('m','a','s','s') # define c3__mast c3_s4('m','a','s','t') # define c3__mate c3_s4('m','a','t','e') # define c3__mave c3_s4('m','a','v','e') @@ -735,14 +744,15 @@ # define c3__mirt c3_s4('m','i','r','t') # define c3__miss c3_s4('m','i','s','s') # define c3__mix c3_s3('m','i','x') -# define c3__mod c3_s3('m','o','d') # define c3__moat c3_s4('m','o','a','t') +# define c3__mod c3_s3('m','o','d') # define c3__mold c3_s4('m','o','l','d') # define c3__mong c3_s4('m','o','n','g') # define c3__mono c3_s4('m','o','n','o') # define c3__mook c3_s4('m','o','o','k') # define c3__moot c3_s4('m','o','o','t') # define c3__mor c3_s3('m','o','r') +# define c3__move c3_s4('m','o','v','e') # define c3__moze c3_s4('m','o','z','e') # define c3__mtbn c3_s4('m','t','b','n') # define c3__mtbr c3_s4('m','t','b','r') @@ -768,6 +778,7 @@ # define c3__nail c3_s4('n','a','i','l') # define c3__name c3_s4('n','a','m','e') # define c3__nap c3_s3('n','a','p') +# define c3__nara c3_s4('n','a','r','a') # define c3__narv c3_s4('n','a','r','v') # define c3__ne c3_s2('n','e') # define c3__need c3_s4('n','e','e','d') @@ -775,6 +786,7 @@ # define c3__nest c3_s4('n','e','s','t') # define c3__netd c3_s4('n','e','t','d') # define c3__new c3_s3('n','e','w') +# define c3__news c3_s4('n','e','w','s') # define c3__newt c3_s4('n','e','w','t') # define c3__next c3_s4('n','e','x','t') # define c3__nich c3_s4('n','i','c','h') @@ -784,9 +796,11 @@ # define c3__no c3_s2('n','o') # define c3__noah c3_s4('n','o','a','h') # define c3__nock c3_s4('n','o','c','k') +# define c3__noco c3_s4('n','o','c','o') +# define c3__nodo c3_s4('n','o','d','o') # define c3__none c3_s4('n','o','n','e') -# define c3__nop c3_s3('n','o','p') # define c3__noop c3_s4('n','o','o','p') +# define c3__nop c3_s3('n','o','p') # define c3__norm c3_s4('n','o','r','m') # define c3__nost c3_s4('n','o','s','t') # define c3__not c3_s3('n','o','t') @@ -817,6 +831,8 @@ # define c3__outd c3_s4('o','u','t','d') # define c3__ov c3_s2('o','v') # define c3__over c3_s4('o','v','e','r') +# define c3__ovum c3_s4('o','v','u','m') +# define c3__p c3_s1('p') # define c3__pack c3_s4('p','a','c','k') # define c3__pair c3_s4('p','a','i','r') # define c3__palm c3_s4('p','a','l','m') @@ -834,6 +850,7 @@ # define c3__past c3_s4('p','a','s','t') # define c3__pawn c3_s4('p','a','w','n') # define c3__peek c3_s4('p','e','e','k') +# define c3__peel c3_s4('p','e','e','l') # define c3__peep c3_s4('p','e','e','p') # define c3__peft c3_s4('p','e','f','t') # define c3__peg c3_s3('p','e','g') @@ -863,7 +880,6 @@ # define c3__plet c3_s4('p','l','e','t') # define c3__plic c3_s4('p','l','i','c') # define c3__plin c3_s4('p','l','i','n') -# define c3__plol c3_s4('p','l','o','m') # define c3__plom c3_s4('p','l','o','m') # define c3__plov c3_s4('p','l','o','v') # define c3__plug c3_s4('p','l','u','g') @@ -898,6 +914,7 @@ # define c3__post c3_s4('p','o','s','t') # define c3__pray c3_s4('p','r','a','y') # define c3__prec c3_s4('p','r','e','c') +# define c3__prep c3_s4('p','r','e','p') # define c3__pret c3_s4('p','r','e','t') # define c3__prex c3_s4('p','r','e','x') # define c3__pril c3_s4('p','r','i','l') @@ -922,6 +939,7 @@ # define c3__quem c3_s4('q','u','e','m') # define c3__ques c3_s4('q','u','e','s') # define c3__quet c3_s4('q','u','e','t') +# define c3__queu c3_s4('q','u','e','u') # define c3__quid c3_s4('q','u','i','d') # define c3__quil c3_s4('q','u','i','l') # define c3__quix c3_s4('q','u','i','x') @@ -933,14 +951,14 @@ # define c3__ramp c3_s4('r','a','m','p') # define c3__rasp c3_s4('r','a','s','p') # define c3__raw c3_s3('r','a','w') -# define c3__ret c3_s3('r','e','t') -# define c3__rez c3_s3('r','e','z') # define c3__read c3_s4('r','e','a','d') # define c3__reck c3_s4('r','e','c','k') # define c3__reef c3_s4('r','e','e','f') # define c3__resd c3_s4('r','e','s','d') # define c3__rest c3_s4('r','e','s','t') +# define c3__ret c3_s3('r','e','t') # define c3__revo c3_s4('r','e','v','o') +# define c3__rez c3_s3('r','e','z') # define c3__rin c3_s3('r','i','n') # define c3__ring c3_s4('r','i','n','g') # define c3__ripe c3_s4('r','i','p','e') @@ -977,6 +995,7 @@ # define c3__send c3_s4('s','e','n','d') # define c3__seq c3_s3('s','e','q') # define c3__serd c3_s4('s','e','r','d') +# define c3__serf c3_s4('s','e','r','f') # define c3__set c3_s3('s','e','t') # define c3__sfix c3_s4('s','f','i','x') # define c3__sgbc c3_s4('s','g','b','c') @@ -1103,11 +1122,6 @@ # define c3__term c3_s4('t','e','r','m') # define c3__test c3_s4('t','e','s','t') # define c3__text c3_s4('t','e','x','t') -# define c3__that c3_s4('t','h','a','t') -# define c3__this c3_s4('t','h','i','s') -# define c3__thin c3_s4('t','h','i','n') -# define c3__thud c3_s4('t','h','u','d') -# define c3__time c3_s4('t','i','m','e') # define c3__tgbn c3_s4('t','g','b','n') # define c3__tgbr c3_s4('t','g','b','r') # define c3__tgdg c3_s4('t','g','d','g') @@ -1122,13 +1136,18 @@ # define c3__tgpm c3_s4('t','g','p','m') # define c3__tgps c3_s4('t','g','p','s') # define c3__tgsp c3_s4('t','g','s','p') +# define c3__that c3_s4('t','h','a','t') # define c3__thee c3_s4('t','h','e','e') # define c3__then c3_s4('t','h','e','n') # define c3__they c3_s4('t','h','e','y') -# define c3__tick c3_s4('t','i','c','k') +# define c3__thin c3_s4('t','h','i','n') +# define c3__this c3_s4('t','h','i','s') # define c3__thou c3_s4('t','h','o','u') +# define c3__thud c3_s4('t','h','u','d') # define c3__thuo c3_s4('t','h','u','o') # define c3__thus c3_s4('t','h','u','s') +# define c3__tick c3_s4('t','i','c','k') +# define c3__time c3_s4('t','i','m','e') # define c3__tip c3_s3('t','i','p') # define c3__tmbn c3_s4('t','m','b','n') # define c3__tmdg c3_s4('t','m','d','g') @@ -1197,6 +1216,7 @@ # define c3__unt c3_s3('u','n','t') # define c3__up c3_s2('u','p') # define c3__url c3_s3('u','r','l') +# define c3__urth c3_s4('u','r','t','h') # define c3__use c3_s3('u','s','e') # define c3__ut c3_s2('u','t') # define c3__uv c3_s2('u','v') @@ -1206,21 +1226,21 @@ # define c3__vamp c3_s4('v','a','m','p') # define c3__vane c3_s4('v','a','n','e') # define c3__var c3_s3('v','a','r') -# define c3__veb c3_s3('v','e','b') # define c3__veal c3_s4('v','e','a','l') +# define c3__veb c3_s3('v','e','b') # define c3__veck c3_s4('v','e','c','k') # define c3__veer c3_s4('v','e','e','r') # define c3__vega c3_s4('v','e','g','a') # define c3__velt c3_s4('v','e','l','t') # define c3__vent c3_s4('v','e','n','t') # define c3__verb c3_s4('v','e','r','b') +# define c3__vere c3_s4('v','e','r','e') # define c3__vern c3_s4('v','e','r','n') # define c3__very c3_s4('v','e','r','y') # define c3__view c3_s4('v','i','e','w') # define c3__vint c3_s4('v','i','n','t') # define c3__void c3_s4('v','o','i','d') # define c3__vorp c3_s4('v','o','r','p') -# define c3__way c3_s3('w','a','y') # define c3__wack c3_s4('w','a','c','k') # define c3__wail c3_s4('w','a','i','l') # define c3__wake c3_s4('w','a','k','e') @@ -1232,18 +1252,20 @@ # define c3__warx c3_s4('w','a','r','x') # define c3__wash c3_s4('w','a','s','h') # define c3__watt c3_s4('w','a','t','t') +# define c3__way c3_s3('w','a','y') # define c3__weak c3_s4('w','e','a','k') # define c3__web c3_s3('w','e','b') -# define c3__wet c3_s3('w','e','t') # define c3__wend c3_s4('w','e','n','d') # define c3__werp c3_s4('w','e','r','p') # define c3__west c3_s4('w','e','s','t') +# define c3__wet c3_s3('w','e','t') # define c3__what c3_s4('w','h','a','t') # define c3__whey c3_s4('w','h','e','y') +# define c3__who c3_s3('w','h','o') # define c3__whom c3_s4('w','h','o','m') -# define c3__wing c3_s4('w','i','n','g') # define c3__wild c3_s4('w','i','l','d') # define c3__win c3_s3('w','i','n') +# define c3__wing c3_s4('w','i','n','g') # define c3__wipe c3_s4('w','i','p','e') # define c3__wise c3_s4('w','i','s','e') # define c3__wish c3_s4('w','i','s','h') @@ -1273,10 +1295,9 @@ # define c3__wtts c3_s4('w','t','t','s') # define c3__wtzp c3_s4('w','t','z','p') # define c3__wyrd c3_s4('w','y','r','d') -# define c3__yew c3_s3('y','a','w') # define c3__yell c3_s4('y','e','l','l') -# define c3__z c3_s1('z') # define c3__yelp c3_s4('y','e','l','p') +# define c3__z c3_s1('z') # define c3__zact c3_s4('z','a','c','t') # define c3__zalt c3_s4('z','a','l','t') # define c3__zarb c3_s4('z','a','r','b') @@ -1297,7 +1318,6 @@ # define c3__zpdx c3_s4('z','p','d','x') # define c3__zpfs c3_s4('z','p','f','s') # define c3__zpgr c3_s4('z','p','g','r') -# define c3__zphs c3_s4('z','p','h','x') # define c3__zphx c3_s4('z','p','h','x') # define c3__zplc c3_s4('z','p','l','c') # define c3__zpmc c3_s4('z','p','m','c') @@ -1313,3 +1333,5 @@ # define c3__zpzp c3_s4('z','p','z','p') # define c3__zuse c3_s4('z','u','s','e') # define c3__zush c3_s4('z','u','s','h') + +#endif /* ifndef C3_MOTES_H */ diff --git a/pkg/urbit/include/c/portable.h b/pkg/urbit/include/c/portable.h index f3edc95b44..10c2aa7107 100644 --- a/pkg/urbit/include/c/portable.h +++ b/pkg/urbit/include/c/portable.h @@ -1,7 +1,5 @@ -/* include/c/portable.h -** -** This file is in the public domain. -*/ +#ifndef C3_PORTABLE_H +#define C3_PORTABLE_H #include "config.h" @@ -23,6 +21,7 @@ # ifndef _XOPEN_SOURCE # define _XOPEN_SOURCE 700 # endif +# include # include # include # include @@ -37,8 +36,10 @@ # include # include # include +# include # elif defined(U3_OS_osx) +# include # include # include # include @@ -55,8 +56,11 @@ # include # include # include +# include +# include # elif defined(U3_OS_bsd) +# include # include # include # include @@ -76,6 +80,7 @@ # define signal mingw_has_no_usable_signal # define raise mingw_has_no_usable_raise # define _POSIX +# include # include # include # include @@ -103,6 +108,42 @@ # define ASAN_ENABLED # endif + /** Platform string. + **/ +# if defined(U3_OS_linux) +# ifdef __LP64__ +# ifdef U3_CPU_aarch64 +// XX not yet +//# define U3_OS_ARCH "aarch64-linux" +# else +# define U3_OS_ARCH "x86_64-linux" +# endif +# endif +# elif defined(U3_OS_mingw) +# define U3_OS_ARCH "x86_64-windows" +# elif defined(U3_OS_osx) +# ifdef __LP64__ +# ifdef U3_CPU_aarch64 +// XX not yet +//# define U3_OS_ARCH "aarch64-darwin" +# else +# define U3_OS_ARCH "x86_64-darwin" +# endif +# endif +# endif + + /** Binary alias. + **/ +# ifdef U3_OS_mingw +# define U3_BIN_SUFFIX ".exe" +# else +# define U3_BIN_SUFFIX "" +# endif + + + +# define U3_BIN_ALIAS ".run" U3_BIN_SUFFIX + /** Address space layout. *** *** NB: 2^29 words == 2GB @@ -242,3 +283,5 @@ # define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) # define STATIC_ASSERT(e,m) \ ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) } + +#endif /* ifndef C3_PORTABLE_H */ diff --git a/pkg/urbit/include/c/types.h b/pkg/urbit/include/c/types.h index a7d74901cd..b333ff1158 100644 --- a/pkg/urbit/include/c/types.h +++ b/pkg/urbit/include/c/types.h @@ -1,7 +1,6 @@ -/* include/c/types.h -** -** This file is in the public domain. -*/ +#ifndef C3_TYPES_H +#define C3_TYPES_H + /** Integer typedefs. **/ /* Canonical integers. @@ -28,3 +27,5 @@ typedef int c3_i; // int - really bad typedef uintptr_t c3_p; // pointer-length uint - really really bad typedef intptr_t c3_ps; // pointer-length int - really really bad + +#endif /* ifndef C3_TYPES_H */ diff --git a/pkg/urbit/include/jets/g.h b/pkg/urbit/include/jets/g.h deleted file mode 100644 index aa0731f1c0..0000000000 --- a/pkg/urbit/include/jets/g.h +++ /dev/null @@ -1,264 +0,0 @@ -/* include/f/qjet.h -** -** This file is in the public domain. -*/ - /** Tier 1. - **/ - u3_noun u3ga_add(u3_atom, u3_atom); - u3_noun u3ga_dec(u3_atom); - u3_noun u3ga_div(u3_atom, u3_atom); - u3_noun u3ga_gte(u3_atom, u3_atom); - u3_noun u3ga_gth(u3_atom, u3_atom); - u3_noun u3ga_inc(u3_atom); - u3_noun u3ga_lte(u3_atom, u3_atom); - u3_noun u3ga_lth(u3_atom, u3_atom); - u3_noun u3ga_mod(u3_atom, u3_atom); - u3_noun u3ga_mul(u3_atom, u3_atom); - u3_noun u3ga_sub(u3_atom, u3_atom); - - /** Tier 2. - **/ - u3_noun u3gb_bind(u3_noun, u3_noun); - u3_noun u3gb_clap(u3_noun, u3_noun, u3_noun); - u3_noun u3gb_drop(u3_noun); - u3_noun u3gb_flop(u3_noun); - u3_noun u3gb_lent(u3_noun); - u3_noun u3gb_levy(u3_noun, u3_noun); - u3_noun u3gb_lien(u3_noun, u3_noun); - u3_noun u3gb_murn(u3_noun, u3_noun); - u3_noun u3gb_need(u3_noun); - u3_noun u3gb_reap(u3_atom, u3_noun); - u3_noun u3gb_reel(u3_noun, u3_noun); - u3_noun u3gb_roll(u3_noun, u3_noun); - u3_noun u3gb_skid(u3_noun, u3_noun); - u3_noun u3gb_skim(u3_noun, u3_noun); - u3_noun u3gb_skip(u3_noun, u3_noun); - u3_noun u3gb_scag(u3_atom, u3_noun); - u3_noun u3gb_slag(u3_atom, u3_noun); - u3_noun u3gb_snag(u3_atom, u3_noun); - u3_noun u3gb_sort(u3_noun, u3_noun); - u3_noun u3gb_turn(u3_noun, u3_noun); - u3_noun u3gb_weld(u3_noun, u3_noun); - - /** Tier 3. - **/ - u3_noun u3gc_bex(u3_atom); - u3_noun u3gc_xeb(u3_atom); - u3_noun u3gc_can(u3_atom, u3_noun); - u3_noun u3gc_cap(u3_atom); - u3_noun u3gc_cat(u3_atom, u3_atom, u3_atom); - u3_noun u3gc_con(u3_atom, u3_atom); - u3_noun u3gc_cut(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3gc_dis(u3_atom, u3_atom); - u3_noun u3gc_dor(u3_atom, u3_atom); - u3_noun u3gc_dvr(u3_atom, u3_atom); - u3_noun u3gc_end(u3_atom, u3_atom, u3_atom); - u3_noun u3gc_gor(u3_atom, u3_atom); - u3_noun u3gc_hor(u3_atom, u3_atom); - u3_noun u3gc_lsh(u3_atom, u3_atom, u3_atom); - u3_noun u3gc_mas(u3_atom); - u3_noun u3gc_met(u3_atom, u3_atom); - u3_noun u3gc_mix(u3_atom, u3_atom); - u3_noun u3gc_muk(u3_atom, u3_atom, u3_atom); - u3_noun u3gc_peg(u3_atom, u3_atom); - u3_noun u3gc_pow(u3_atom, u3_atom); - u3_noun u3gc_rap(u3_atom, u3_noun); - u3_noun u3gc_rep(u3_atom, u3_noun); - u3_noun u3gc_rip(u3_atom, u3_atom); - u3_noun u3gc_rsh(u3_atom, u3_atom, u3_atom); - u3_noun u3gc_sqt(u3_atom); - u3_noun u3gc_vor(u3_atom, u3_atom); - - /** Tier 4. - **/ - u3_noun u3gdb_bif(u3_noun, u3_noun); - u3_noun u3gdb_dif(u3_noun, u3_noun); - u3_noun u3gdb_gas(u3_noun, u3_noun); - u3_noun u3gdb_get(u3_noun, u3_noun); - u3_noun u3gdb_has(u3_noun, u3_noun); - u3_noun u3gdb_int(u3_noun, u3_noun); - u3_noun u3gdb_put(u3_noun, u3_noun, u3_noun); -# define u3gdb_tap u3gdi_tap - u3_noun u3gdb_uni(u3_noun, u3_noun); - - u3_noun u3gdi_bif(u3_noun, u3_noun); - u3_noun u3gdi_dif(u3_noun, u3_noun); - u3_noun u3gdi_gas(u3_noun, u3_noun); - u3_noun u3gdi_has(u3_noun, u3_noun); - u3_noun u3gdi_int(u3_noun, u3_noun); - u3_noun u3gdi_mer(u3_noun, u3_noun); - u3_noun u3gdi_put(u3_noun, u3_noun); - u3_noun u3gdi_tap(u3_noun); - u3_noun u3gdi_uni(u3_noun, u3_noun); - u3_noun u3gdi_wyt(u3_noun); - - /** Tier 5. - **/ - u3_noun u3ge_cue(u3_atom); - u3_noun u3ge_jam(u3_atom); - u3_noun u3ge_mat(u3_atom); - u3_noun u3ge_rub(u3_atom, u3_atom); - u3_noun u3ge_lore(u3_atom); - u3_noun u3ge_loss(u3_noun, u3_noun); - u3_noun u3ge_lune(u3_atom); - u3_noun u3ge_repg(u3_noun, u3_noun, u3_noun); - u3_noun u3ge_rexp(u3_noun, u3_noun); - u3_noun u3ge_trip(u3_atom); - - u3_noun u3gea_ecba_en(u3_atom, u3_atom); - u3_noun u3gea_ecba_de(u3_atom, u3_atom); - u3_noun u3gea_ecbb_en(u3_atom, u3_atom); - u3_noun u3gea_ecbb_de(u3_atom, u3_atom); - u3_noun u3gea_ecbc_en(u3_atom, u3_atom); - u3_noun u3gea_ecbc_de(u3_atom, u3_atom); - - u3_noun u3gea_cbca_en(u3_atom, u3_atom, u3_atom); - u3_noun u3gea_cbca_de(u3_atom, u3_atom, u3_atom); - u3_noun u3gea_cbcb_en(u3_atom, u3_atom, u3_atom); - u3_noun u3gea_cbcb_de(u3_atom, u3_atom, u3_atom); - u3_noun u3gea_cbcc_en(u3_atom, u3_atom, u3_atom); - u3_noun u3gea_cbcc_de(u3_atom, u3_atom, u3_atom); - - u3_noun u3gea_de(u3_atom, u3_atom); - u3_noun u3gea_en(u3_atom, u3_atom); - - u3_noun u3ges_hsh(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3ges_hsl(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom, - u3_atom, u3_atom, u3_atom); - u3_noun u3ges_pbk(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3ges_pbl(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom, u3_atom); - - u3_noun u3ge_shax(u3_atom); - u3_noun u3ge_shay(u3_atom, u3_atom); - u3_noun u3ge_shas(u3_atom, u3_atom); - u3_noun u3ge_shal(u3_atom, u3_atom); - - u3_noun u3geo_raw(u3_atom, u3_atom); - - u3_noun u3gef_drg(u3_noun, u3_atom); - u3_noun u3gef_lug(u3_noun, u3_noun, u3_atom, u3_atom); - - u3_noun u3ger_add(u3_atom, u3_atom, u3_atom); - u3_noun u3ger_sub(u3_atom, u3_atom, u3_atom); - u3_noun u3ger_mul(u3_atom, u3_atom, u3_atom); - u3_noun u3ger_div(u3_atom, u3_atom, u3_atom); - u3_noun u3ger_sqt(u3_atom, u3_atom); - u3_noun u3ger_fma(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3ger_lth(u3_atom, u3_atom); - u3_noun u3ger_lte(u3_atom, u3_atom); - u3_noun u3ger_equ(u3_atom, u3_atom); - u3_noun u3ger_gte(u3_atom, u3_atom); - u3_noun u3ger_gth(u3_atom, u3_atom); - - u3_noun u3get_add(u3_atom, u3_atom, u3_atom); - u3_noun u3get_sub(u3_atom, u3_atom, u3_atom); - u3_noun u3get_mul(u3_atom, u3_atom, u3_atom); - u3_noun u3get_div(u3_atom, u3_atom, u3_atom); - u3_noun u3get_sqt(u3_atom, u3_atom); - u3_noun u3get_fma(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3get_lth(u3_atom, u3_atom); - u3_noun u3get_lte(u3_atom, u3_atom); - u3_noun u3get_equ(u3_atom, u3_atom); - u3_noun u3get_gte(u3_atom, u3_atom); - u3_noun u3get_gth(u3_atom, u3_atom); - - u3_noun u3geq_add(u3_atom, u3_atom, u3_atom); - u3_noun u3geq_sub(u3_atom, u3_atom, u3_atom); - u3_noun u3geq_mul(u3_atom, u3_atom, u3_atom); - u3_noun u3geq_div(u3_atom, u3_atom, u3_atom); - u3_noun u3geq_sqt(u3_atom, u3_atom); - u3_noun u3geq_fma(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3geq_lth(u3_atom, u3_atom); - u3_noun u3geq_lte(u3_atom, u3_atom); - u3_noun u3geq_equ(u3_atom, u3_atom); - u3_noun u3geq_gte(u3_atom, u3_atom); - u3_noun u3geq_gth(u3_atom, u3_atom); - - u3_noun u3ges_add(u3_atom, u3_atom, u3_atom); - u3_noun u3ges_sub(u3_atom, u3_atom, u3_atom); - u3_noun u3ges_mul(u3_atom, u3_atom, u3_atom); - u3_noun u3ges_div(u3_atom, u3_atom, u3_atom); - u3_noun u3ges_sqt(u3_atom, u3_atom); - u3_noun u3ges_fma(u3_atom, u3_atom, u3_atom, u3_atom); - u3_noun u3ges_lth(u3_atom, u3_atom); - u3_noun u3ges_lte(u3_atom, u3_atom); - u3_noun u3ges_equ(u3_atom, u3_atom); - u3_noun u3ges_gte(u3_atom, u3_atom); - u3_noun u3ges_gth(u3_atom, u3_atom); - - /** Tier 6. - **/ - u3_noun u3gf_bull(u3_noun, u3_noun); - u3_noun u3gf_cell(u3_noun, u3_noun); - u3_noun u3gf_comb(u3_noun, u3_noun); - u3_noun u3gf_cons(u3_noun, u3_noun); - u3_noun u3gf_core(u3_noun, u3_noun); - u3_noun u3gf_cube(u3_noun, u3_noun); - u3_noun u3gf_face(u3_noun, u3_noun); - u3_noun u3gf_fine(u3_noun, u3_noun, u3_noun); - u3_noun u3gf_fitz(u3_noun, u3_noun); - u3_noun u3gf_flan(u3_noun, u3_noun); - u3_noun u3gf_flay(u3_noun); - u3_noun u3gf_flip(u3_noun); - u3_noun u3gf_flor(u3_noun, u3_noun); - u3_noun u3gf_forq(u3_noun, u3_noun); - u3_noun u3gf_fork(u3_noun); - u3_noun u3gf_grof(u3_noun); - u3_noun u3gf_help(u3_noun, u3_noun); - u3_noun u3gf_hike(u3_noun, u3_noun); - u3_noun u3gf_look(u3_noun, u3_noun); - u3_noun u3gf_loot(u3_noun, u3_noun); - u3_noun u3gf_slot(u3_atom, u3_noun); - u3_noun u3gf_type(u3_noun); - - u3_noun u3gfl_bunt(u3_noun, u3_noun); - u3_noun u3gfl_whip(u3_noun, u3_noun, u3_noun); - - u3_noun u3gfp_hack(u3_noun, u3_noun); - u3_noun u3gfp_late(u3_noun); - u3_noun u3gfp_open(u3_noun, u3_noun); - u3_noun u3gfp_rake(u3_noun); - -# define u3gfu_van_fan 28 -# define u3gfu_van_rib 58 -# define u3gfu_van_vrf 59 -# define u3gfu_van_vet 118 -# define u3gfu_van_fab 119 - - u3_noun u3gfu_burn(u3_noun, u3_noun); - u3_noun u3gfu_busk(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_buss(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_bust(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_crop(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_cull(u3_noun, u3_noun, u3_noun, u3_atom, u3_noun); - u3_noun u3gfu_duck(u3_noun, u3_noun); - u3_noun u3gfu_dung(u3_noun, u3_noun cap, u3_noun); - u3_noun u3gfu_dunq(u3_noun, const c3_c*, u3_noun); - void u3gfu_dump(u3_noun, const c3_c*, u3_noun); - u3_noun u3gfu_fond(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_finc(u3_noun, u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_fink(u3_noun, u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_fire(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_firm(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_fish(u3_noun, u3_noun, u3_atom); - u3_noun u3gfu_fuse(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_gain(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_heal(u3_noun, u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_lose(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_mint(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_mull(u3_noun, u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_nest(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_nost(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_orth(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_peek(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_peel(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_play(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_repo(u3_noun, u3_noun); - u3_noun u3gfu_rest(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_shep(u3_noun, const c3_c*, u3_noun, u3_noun); - u3_noun u3gfu_shew(u3_noun, u3_noun); - u3_noun u3gfu_sift(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_snub(u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_tack(u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_toss(u3_noun, u3_noun, u3_noun, u3_noun, u3_noun); - u3_noun u3gfu_wrap(u3_noun, u3_noun, u3_noun); diff --git a/pkg/urbit/include/jets/k.h b/pkg/urbit/include/jets/k.h index 1f15a3866c..f8cce61cf8 100644 --- a/pkg/urbit/include/jets/k.h +++ b/pkg/urbit/include/jets/k.h @@ -1,7 +1,6 @@ -/* include/f/kjet.h -** -** This file is in the public domain. -*/ +#ifndef U3_JETS_K_H +#define U3_JETS_K_H + /** Tier 1. **/ u3_noun u3ka_add(u3_noun a, u3_noun b); @@ -161,3 +160,5 @@ */ u3_noun u3kfu_repo(u3_noun, u3_noun); + +#endif /* ifndef U3_JETS_K_H */ diff --git a/pkg/urbit/include/jets/l.h b/pkg/urbit/include/jets/l.h deleted file mode 100644 index e242ef6712..0000000000 --- a/pkg/urbit/include/jets/l.h +++ /dev/null @@ -1,115 +0,0 @@ -/* include/f/kjet.h -** -** This file is in the public domain. -*/ - /** Tier 1. - **/ - u3_noun u3la_add(u3_noun a, u3_noun b); - u3_noun u3la_sub(u3_noun a, u3_noun b); - u3_noun u3la_mul(u3_noun a, u3_noun b); - u3_noun u3la_gth(u3_noun a, u3_noun b); - u3_noun u3la_lte(u3_noun a, u3_noun b); - - /** Tier 2. - **/ - u3_noun u3lb_lent(u3_noun a); - u3_noun u3lb_weld(u3_noun a, u3_noun b); - u3_noun u3lb_flop(u3_noun a); - -/* u3lc: tier 3 functions -*/ - /* u3lc_lsh(): left shift. - */ - u3_noun - u3lc_lsh(u3_noun a, u3_noun b, u3_noun c); - - /* u3lc_rsh(): right shift. - */ - u3_noun - u3lc_rsh(u3_noun a, u3_noun b, u3_noun c); - -/* u3ld: tier 4 functions -*/ - /* u3ldb_get(): map get for key `b` in map `a` with u3_none. - */ - u3_weak - u3ldb_get(u3_noun a, u3_noun b); - - /* u3ldb_got(): map get for key `b` in map `a` with bail. - */ - u3_noun - u3ldb_got(u3_noun a, u3_noun b); - - /* u3ldb_put(): map put for key `b`, value `c` in map `a`. - */ - u3_weak - u3ldb_put(u3_noun a, u3_noun b, u3_noun c); - - /* u3ldb_has(): test for get. - */ - u3_noun - u3ldb_has(u3_noun a, u3_noun b); - - /* u3ldb_gas(): list to map. - */ - u3_noun - u3ldb_gas(u3_noun a, u3_noun b); - - /* u3ldi_gas(): list to map. - */ - u3_noun - u3ldi_gas(u3_noun a, u3_noun b); - - /* u3ldi_has(): test for presence. - */ - u3_noun - u3ldi_has(u3_noun a, u3_noun b); - - /* u3ldi_tap(): map/set convert to list. (solves by_tap also.) - */ - u3_noun - u3ldi_tap(u3_noun a); - - /* u3ldi_put(): put in set. - */ - u3_weak - u3ldi_put(u3_noun a, u3_noun b); - - /* u3ldi_uni(): set union. - */ - u3_noun - u3ldi_uni(u3_noun a, u3_noun b); - -# define u3ldb_tap(a) u3ldi_tap(a) - -/* u3le: tier 5 functions -*/ - /* u3le_cue(): expand saved pill. - */ - u3_noun - u3le_cue(u3_atom a); - - /* u3le_jam(): pack noun as atom. - */ - u3_atom - u3le_jam(u3_noun a); - - /* u3le_trip(): atom to tape. - */ - u3_noun - u3le_trip(u3_noun a); - - /* u3lf_fork(): build %fork span. - */ - u3_noun - u3lf_fork(u3_noun yed); - - /* u3kz_fork(): build %fork span. - */ - u3_noun - u3kz_fork(u3_noun yed); - - /* u3lfu_repo(): - */ - u3_noun - u3lfu_repo(u3_noun, u3_noun); diff --git a/pkg/urbit/include/jets/q.h b/pkg/urbit/include/jets/q.h index 0f83cf3817..305164fb89 100644 --- a/pkg/urbit/include/jets/q.h +++ b/pkg/urbit/include/jets/q.h @@ -1,7 +1,6 @@ -/* include/f/qjet.h -** -** This file is in the public domain. -*/ +#ifndef U3_JETS_Q_H +#define U3_JETS_Q_H + /** Tier 1. **/ u3_noun u3qa_add(u3_atom, u3_atom); @@ -241,3 +240,5 @@ # define u3qfu_van_vet 59 void u3qf_test(const c3_c*, u3_noun); + +#endif /* ifndef U3_JETS_Q_H */ diff --git a/pkg/urbit/include/jets/w.h b/pkg/urbit/include/jets/w.h index 4cc8473433..ec66d96b3e 100644 --- a/pkg/urbit/include/jets/w.h +++ b/pkg/urbit/include/jets/w.h @@ -1,7 +1,6 @@ -/* include/f/qjet.h -** -** This file is in the public domain. -*/ +#ifndef U3_JETS_W_H +#define U3_JETS_W_H + /** Tier 1. **/ u3_noun u3wa_add(u3_noun); @@ -207,6 +206,9 @@ u3_noun u3we_sign(u3_noun); u3_noun u3we_reco(u3_noun); + u3_noun u3we_sosi(u3_noun); + u3_noun u3we_sove(u3_noun); + u3_noun u3we_en_base16(u3_noun); u3_noun u3we_de_base16(u3_noun); @@ -318,3 +320,5 @@ u3_noun u3wfu_play(u3_noun); u3_noun u3wfu_repo(u3_noun); u3_noun u3wfu_rest(u3_noun); + +#endif /* ifndef U3_JETS_W_H */ diff --git a/pkg/urbit/include/jets/y.h b/pkg/urbit/include/jets/y.h deleted file mode 100644 index de009619fd..0000000000 --- a/pkg/urbit/include/jets/y.h +++ /dev/null @@ -1,328 +0,0 @@ -/* include/f/qjet.h -** -** This file is in the public domain. -*/ - /** Tier 1. - **/ - u3_noun u3ya_add(u3_noun); - u3_noun u3ya_dec(u3_noun); - u3_noun u3ya_div(u3_noun); - u3_noun u3ya_gte(u3_noun); - u3_noun u3ya_gth(u3_noun); - u3_noun u3ya_lte(u3_noun); - u3_noun u3ya_lth(u3_noun); - u3_noun u3ya_mod(u3_noun); - u3_noun u3ya_mul(u3_noun); - u3_noun u3ya_sub(u3_noun); - - /** Tier 2. - **/ - u3_noun u3yb_bind(u3_noun); - u3_noun u3yb_clap(u3_noun); - u3_noun u3yb_drop(u3_noun); - u3_noun u3yb_flop(u3_noun); - u3_noun u3yb_lent(u3_noun); - u3_noun u3yb_levy(u3_noun); - u3_noun u3yb_lien(u3_noun); - u3_noun u3yb_murn(u3_noun); - u3_noun u3yb_need(u3_noun); - u3_noun u3yb_reap(u3_noun); - u3_noun u3yb_reel(u3_noun); - u3_noun u3yb_roll(u3_noun); - u3_noun u3yb_skid(u3_noun); - u3_noun u3yb_skim(u3_noun); - u3_noun u3yb_skip(u3_noun); - u3_noun u3yb_scag(u3_noun); - u3_noun u3yb_slag(u3_noun); - u3_noun u3yb_snag(u3_noun); - u3_noun u3yb_sort(u3_noun); - u3_noun u3yb_turn(u3_noun); - u3_noun u3yb_weld(u3_noun); - - /** Tier 3. - **/ - u3_noun u3yc_bex(u3_noun); - u3_noun u3yc_xeb(u3_noun); - u3_noun u3yc_can(u3_noun); - u3_noun u3yc_cap(u3_noun); - u3_noun u3yc_cat(u3_noun); - u3_noun u3yc_con(u3_noun); - u3_noun u3yc_cut(u3_noun); - u3_noun u3yc_dis(u3_noun); - u3_noun u3yc_dor(u3_noun); - u3_noun u3yc_dvr(u3_noun); - u3_noun u3yc_end(u3_noun); - u3_noun u3yc_gor(u3_noun); - u3_noun u3yc_hor(u3_noun); - u3_noun u3yc_lsh(u3_noun); - u3_noun u3yc_mas(u3_noun); - u3_noun u3yc_met(u3_noun); - u3_noun u3yc_mix(u3_noun); - u3_noun u3yc_mug(u3_noun); - u3_noun u3yc_muk(u3_noun); - u3_noun u3yc_peg(u3_noun); - u3_noun u3yc_pow(u3_noun); - u3_noun u3yc_rap(u3_noun); - u3_noun u3yc_rep(u3_noun); - u3_noun u3yc_rip(u3_noun); - u3_noun u3yc_rsh(u3_noun); - u3_noun u3yc_sqt(u3_noun); - u3_noun u3yc_vor(u3_noun); - - u3_noun u3ycp_ins(u3_noun); - u3_noun u3ycp_ind(u3_noun); - u3_noun u3ycp_tos(u3_noun); - u3_noun u3ycp_tod(u3_noun); - - /** Tier 4. - **/ - u3_noun u3ydb_bif(u3_noun); - u3_noun u3ydb_dif(u3_noun); - u3_noun u3ydb_gas(u3_noun); - u3_noun u3ydb_get(u3_noun); - u3_noun u3ydb_has(u3_noun); - u3_noun u3ydb_int(u3_noun); - u3_noun u3ydb_put(u3_noun); -# define u3ydb_tap u3ydi_tap - u3_noun u3ydb_uni(u3_noun); - - u3_noun u3ydi_bif(u3_noun); - u3_noun u3ydi_dif(u3_noun); - u3_noun u3ydi_gas(u3_noun); - u3_noun u3ydi_has(u3_noun); - u3_noun u3ydi_int(u3_noun); - u3_noun u3ydi_mer(u3_noun); - u3_noun u3ydi_put(u3_noun); - u3_noun u3ydi_tap(u3_noun); - u3_noun u3ydi_uni(u3_noun); - u3_noun u3ydi_wyt(u3_noun); - - /** Tier 5. - **/ - u3_noun u3ye_cue(u3_noun); - u3_noun u3ye_jam(u3_noun); - u3_noun u3ye_mat(u3_noun); - u3_noun u3ye_rub(u3_noun); - u3_noun u3ye_lore(u3_noun); - u3_noun u3ye_loss(u3_noun); - u3_noun u3ye_lune(u3_noun); - u3_noun u3ye_mink(u3_noun); - u3_noun u3ye_mule(u3_noun); - u3_noun u3ye_repg(u3_noun); - u3_noun u3ye_rexp(u3_noun); - u3_noun u3ye_trip(u3_noun); - - u3_noun u3ye_pfix(u3_noun); - u3_noun u3ye_plug(u3_noun); - u3_noun u3ye_pose(u3_noun); - u3_noun u3ye_sfix(u3_noun); - - u3_noun u3yea_ecba_en(u3_noun); - u3_noun u3yea_ecba_de(u3_noun); - u3_noun u3yea_ecbb_en(u3_noun); - u3_noun u3yea_ecbb_de(u3_noun); - u3_noun u3yea_ecbc_en(u3_noun); - u3_noun u3yea_ecbc_de(u3_noun); - - u3_noun u3yea_cbca_en(u3_noun); - u3_noun u3yea_cbca_de(u3_noun); - u3_noun u3yea_cbcb_en(u3_noun); - u3_noun u3yea_cbcb_de(u3_noun); - u3_noun u3yea_cbcc_en(u3_noun); - u3_noun u3yea_cbcc_de(u3_noun); - - u3_noun u3yea_de(u3_noun); - u3_noun u3yea_en(u3_noun); - - u3_noun u3yes_hsh(u3_noun); - u3_noun u3yes_hsl(u3_noun); - u3_noun u3yes_pbk(u3_noun); - u3_noun u3yes_pbl(u3_noun); - - u3_noun u3ye_shax(u3_noun); - u3_noun u3ye_shay(u3_noun); - u3_noun u3ye_shas(u3_noun); - u3_noun u3ye_shal(u3_noun); - - u3_noun u3yeo_raw(u3_noun); - - u3_noun u3yee_puck(u3_noun); - u3_noun u3yee_sign(u3_noun); - u3_noun u3yee_veri(u3_noun); - u3_noun u3yee_shar(u3_noun); - - u3_noun u3ye_bend_fun(u3_noun); - u3_noun u3ye_cold_fun(u3_noun); - u3_noun u3ye_cook_fun(u3_noun); - u3_noun u3ye_comp_fun(u3_noun); - u3_noun u3ye_easy_fun(u3_noun); - u3_noun u3ye_glue_fun(u3_noun); - u3_noun u3ye_here_fun(u3_noun); - u3_noun u3ye_just_fun(u3_noun); - u3_noun u3ye_mask_fun(u3_noun); - u3_noun u3ye_shim_fun(u3_noun); - u3_noun u3ye_stag_fun(u3_noun); - u3_noun u3ye_stew_fun(u3_noun); - u3_noun u3ye_stir_fun(u3_noun); - - u3_noun u3yef_drg(u3_noun); - u3_noun u3yef_lug(u3_noun); - - u3_noun u3yer_add(u3_noun); - u3_noun u3yer_sub(u3_noun); - u3_noun u3yer_mul(u3_noun); - u3_noun u3yer_div(u3_noun); - u3_noun u3yer_sqt(u3_noun); - u3_noun u3yer_fma(u3_noun); - u3_noun u3yer_lth(u3_noun); - u3_noun u3yer_lte(u3_noun); - u3_noun u3yer_equ(u3_noun); - u3_noun u3yer_gte(u3_noun); - u3_noun u3yer_gth(u3_noun); - - u3_noun u3yet_add(u3_noun); - u3_noun u3yet_sub(u3_noun); - u3_noun u3yet_mul(u3_noun); - u3_noun u3yet_div(u3_noun); - u3_noun u3yet_sqt(u3_noun); - u3_noun u3yet_fma(u3_noun); - u3_noun u3yet_lth(u3_noun); - u3_noun u3yet_lte(u3_noun); - u3_noun u3yet_equ(u3_noun); - u3_noun u3yet_gte(u3_noun); - u3_noun u3yet_gth(u3_noun); - - u3_noun u3yeq_add(u3_noun); - u3_noun u3yeq_sub(u3_noun); - u3_noun u3yeq_mul(u3_noun); - u3_noun u3yeq_div(u3_noun); - u3_noun u3yeq_sqt(u3_noun); - u3_noun u3yeq_fma(u3_noun); - u3_noun u3yeq_lth(u3_noun); - u3_noun u3yeq_lte(u3_noun); - u3_noun u3yeq_equ(u3_noun); - u3_noun u3yeq_gte(u3_noun); - u3_noun u3yeq_gth(u3_noun); - - u3_noun u3yes_add(u3_noun); - u3_noun u3yes_sub(u3_noun); - u3_noun u3yes_mul(u3_noun); - u3_noun u3yes_div(u3_noun); - u3_noun u3yes_sqt(u3_noun); - u3_noun u3yes_fma(u3_noun); - u3_noun u3yes_lth(u3_noun); - u3_noun u3yes_lte(u3_noun); - u3_noun u3yes_equ(u3_noun); - u3_noun u3yes_gte(u3_noun); - u3_noun u3yes_gth(u3_noun); - - /** Tier 6. - **/ - u3_noun u3yf_bull(u3_noun); - u3_noun u3yf_cell(u3_noun); - u3_noun u3yf_comb(u3_noun); - u3_noun u3yf_cons(u3_noun); - u3_noun u3yf_core(u3_noun); - u3_noun u3yf_cube(u3_noun); - u3_noun u3yf_face(u3_noun); - u3_noun u3yf_fine(u3_noun); - u3_noun u3yf_fitz(u3_noun); - u3_noun u3yf_flan(u3_noun); - u3_noun u3yf_flay(u3_noun); - u3_noun u3yf_flip(u3_noun); - u3_noun u3yf_flor(u3_noun); - u3_noun u3yf_forq(u3_noun); - u3_noun u3yf_fork(u3_noun); - u3_noun u3yf_help(u3_noun); - u3_noun u3yf_hike(u3_noun); - u3_noun u3yf_look(u3_noun); - u3_noun u3yf_loot(u3_noun); - - u3_noun u3yfl_bunt(u3_noun); - u3_noun u3yfl_whip(u3_noun); - - u3_noun u3yfp_hack(u3_noun); - u3_noun u3yfp_late(u3_noun); - u3_noun u3yfp_open(u3_noun); - u3_noun u3yfp_rake(u3_noun); - - u3_noun u3yfu_burn(u3_noun); - u3_noun u3yfu_busk(u3_noun); - u3_noun u3yfu_bust(u3_noun); - u3_noun u3yfu_crop(u3_noun); - u3_noun u3yfu_cull(u3_noun); - u3_noun u3yfu_duck(u3_noun); - u3_noun u3yfu_find(u3_noun); - u3_noun u3yfu_fond(u3_noun); - u3_noun u3yfu_fink(u3_noun); - u3_noun u3yfu_fire(u3_noun); - u3_noun u3yfu_firm(u3_noun); - u3_noun u3yfu_fish(u3_noun); - u3_noun u3yfu_fuse(u3_noun); - u3_noun u3yfu_heal(u3_noun); - u3_noun u3yfu_mint(u3_noun); - u3_noun u3yfu_mull(u3_noun); - u3_noun u3yfu_nest(u3_noun); - u3_noun u3yfu_peek(u3_noun); - u3_noun u3yfu_peel(u3_noun); - u3_noun u3yfu_play(u3_noun); - u3_noun u3yfu_repo(u3_noun); - u3_noun u3yfu_rest(u3_noun); - u3_noun u3yfu_snub(u3_noun); - u3_noun u3yfu_toss(u3_noun); - u3_noun u3yfu_wrap(u3_noun); - - u3_noun u3wz_bull(u3_noun); - u3_noun u3wz_cell(u3_noun); - u3_noun u3wz_comb(u3_noun); - u3_noun u3wz_cons(u3_noun); - u3_noun u3wz_core(u3_noun); - u3_noun u3wz_cube(u3_noun); - u3_noun u3wz_face(u3_noun); - u3_noun u3wz_fine(u3_noun); - u3_noun u3wz_fitz(u3_noun); - u3_noun u3wz_flan(u3_noun); - u3_noun u3wz_flay(u3_noun); - u3_noun u3wz_flip(u3_noun); - u3_noun u3wz_flor(u3_noun); - u3_noun u3wz_forq(u3_noun); - u3_noun u3wz_fork(u3_noun); - u3_noun u3wz_help(u3_noun); - u3_noun u3wz_hike(u3_noun); - u3_noun u3wz_look(u3_noun); - u3_noun u3wz_loot(u3_noun); - - u3_noun u3wzl_bunt(u3_noun); - u3_noun u3wzl_whip(u3_noun); - - u3_noun u3wzp_hack(u3_noun); - u3_noun u3wzp_late(u3_noun); - u3_noun u3wzp_open(u3_noun); - u3_noun u3wzp_rake(u3_noun); - - u3_noun u3wzu_burn(u3_noun); - u3_noun u3wzu_busk(u3_noun); - u3_noun u3wzu_bust(u3_noun); - u3_noun u3wzu_conk(u3_noun); - u3_noun u3wzu_crop(u3_noun); - u3_noun u3wzu_cull(u3_noun); - u3_noun u3wzu_duck(u3_noun); - u3_noun u3wzu_find(u3_noun); - u3_noun u3wzu_fond(u3_noun); - u3_noun u3wzu_fink(u3_noun); - u3_noun u3wzu_fire(u3_noun); - u3_noun u3wzu_firm(u3_noun); - u3_noun u3wzu_fish(u3_noun); - u3_noun u3wzu_fuse(u3_noun); - u3_noun u3wzu_heal(u3_noun); - u3_noun u3wzu_mint(u3_noun); - u3_noun u3wzu_mull(u3_noun); - u3_noun u3wzu_nest(u3_noun); - u3_noun u3wzu_peek(u3_noun); - u3_noun u3wzu_peel(u3_noun); - u3_noun u3wzu_play(u3_noun); - u3_noun u3wzu_repo(u3_noun); - u3_noun u3wzu_rest(u3_noun); - u3_noun u3wzu_snub(u3_noun); - u3_noun u3wzu_toss(u3_noun); - u3_noun u3wzu_wrap(u3_noun); diff --git a/pkg/urbit/include/noun/aliases.h b/pkg/urbit/include/noun/aliases.h index 5e98714d48..9304563a43 100644 --- a/pkg/urbit/include/noun/aliases.h +++ b/pkg/urbit/include/noun/aliases.h @@ -1,7 +1,6 @@ -/* i/n/u.h -** -** This file is in the public domain. -*/ +#ifndef U3_ALIASES_H +#define U3_ALIASES_H + /** Constants. **/ /* u3_none - u3_noun which is not a noun. @@ -112,3 +111,5 @@ # define u3tn(type, x) (x == 0) ? (void *)0 : ((type *) u3a_into(x)) # define u3of(type, x) (u3a_outa((type *)x)) + +#endif /* ifndef U3_ALIASES_H */ diff --git a/pkg/urbit/include/noun/allocate.h b/pkg/urbit/include/noun/allocate.h index b8f367d863..cc30b18fae 100644 --- a/pkg/urbit/include/noun/allocate.h +++ b/pkg/urbit/include/noun/allocate.h @@ -1,10 +1,10 @@ -/* i/n/a.h -** -** This file is in the public domain. -*/ +#ifndef U3_ALLOCATE_H +#define U3_ALLOCATE_H #include +#include "manage.h" + /** Constants. **/ /* u3a_bits: number of bits in word-addressed pointer. 29 == 2GB. @@ -199,57 +199,101 @@ c3_wiseof(u3a_box) ) ) /* Inside a noun. */ + + /* u3a_is_cat(): yes if noun [som] is direct atom. + */ # define u3a_is_cat(som) (((som) >> 31) ? c3n : c3y) + + /* u3a_is_dog(): yes if noun [som] is indirect noun. + */ # define u3a_is_dog(som) (((som) >> 31) ? c3y : c3n) -# define u3a_is_pug(som) ((2 == ((som) >> 30)) ? c3y : c3n) -# define u3a_is_pom(som) ((3 == ((som) >> 30)) ? c3y : c3n) + /* u3a_is_pug(): yes if noun [som] is indirect atom. + */ +# define u3a_is_pug(som) ((0b10 == ((som) >> 30)) ? c3y : c3n) + + /* u3a_is_pom(): yes if noun [som] is indirect cell. + */ +# define u3a_is_pom(som) ((0b11 == ((som) >> 30)) ? c3y : c3n) + + /* u3a_to_off(): mask off bits 30 and 31 from noun [som]. + */ # define u3a_to_off(som) ((som) & 0x3fffffff) + + /* u3a_to_ptr(): convert noun [som] into generic pointer into loom. + */ # define u3a_to_ptr(som) (u3a_into(u3a_to_off(som))) + + /* u3a_to_wtr(): convert noun [som] into word pointer into loom. + */ # define u3a_to_wtr(som) ((c3_w *)u3a_to_ptr(som)) + + /* u3a_to_pug(): set bit 31 of [off]. + */ # define u3a_to_pug(off) (off | 0x80000000) + + /* u3a_to_pom(): set bits 30 and 31 of [off]. + */ # define u3a_to_pom(off) (off | 0xc0000000) + /* u3a_is_atom(): yes if noun [som] is direct atom or indirect atom. + */ # define u3a_is_atom(som) c3o(u3a_is_cat(som), \ u3a_is_pug(som)) + /* u3a_is_cell: yes if noun [som] is cell. + */ # define u3a_is_cell(som) u3a_is_pom(som) + /* u3a_h(): get head of cell [som]. Bail if [som] is not cell. + */ # define u3a_h(som) \ ( _(u3a_is_cell(som)) \ ? ( ((u3a_cell *)u3a_to_ptr(som))->hed )\ : u3m_bail(c3__exit) ) + /* u3a_t(): get tail of cell [som]. Bail if [som] is not cell. + */ # define u3a_t(som) \ ( _(u3a_is_cell(som)) \ ? ( ((u3a_cell *)u3a_to_ptr(som))->tel )\ : u3m_bail(c3__exit) ) + /* u3a_into(): convert loom offset [x] into generic pointer. + */ # define u3a_into(x) ((void *)(u3_Loom + (x))) + + /* u3a_outa(): convert pointer [p] into word offset into loom. + */ # define u3a_outa(p) (((c3_w*)(void*)(p)) - u3_Loom) + /* u3a_is_north(): yes if road [r] is north road. + */ # define u3a_is_north(r) __(r->cap_p > r->hat_p) + + /* u3a_is_south(): yes if road [r] is south road. + */ # define u3a_is_south(r) !u3a_is_north(r) - /* u3a_open(): words of contiguous free space in [r] + /* u3a_open(): words of contiguous free space in road [r] */ # define u3a_open(r) ( (c3y == u3a_is_north(r)) \ ? (c3_w)(r->cap_p - r->hat_p) \ : (c3_w)(r->hat_p - r->cap_p) ) - /* u3a_full(): words of [r]; + /* u3a_full(): total words in road [r]; ** u3a_full(r) == u3a_heap(r) + u3a_temp(r) + u3a_open(r) */ # define u3a_full(r) ( (c3y == u3a_is_north(r)) \ ? (c3_w)(r->mat_p - r->rut_p) \ : (c3_w)(r->rut_p - r->mat_p) ) - /* u3a_heap(): words of heap in [r] + /* u3a_heap(): words of heap in road [r] */ # define u3a_heap(r) ( (c3y == u3a_is_north(r)) \ ? (c3_w)(r->hat_p - r->rut_p) \ : (c3_w)(r->rut_p - r->hat_p) ) - /* u3a_temp(): words of stack in [r] + /* u3a_temp(): words of stack in road [r] */ # define u3a_temp(r) ( (c3y == u3a_is_north(r)) \ ? (c3_w)(r->mat_p - r->cap_p) \ @@ -356,12 +400,6 @@ return u3a_peek(pil_u); } - // we have to forward-declare u3m_bail() here, as our - // headers don't have the necessary guards. - // - c3_i - u3m_bail(c3_m how_m) __attribute__((noreturn)); - /* u3a_pile_sane(): bail on invalid road stack state. */ inline void @@ -639,6 +677,11 @@ void u3a_lop(c3_w lab_w); + /* u3a_print_time: print microsecond time. + */ + void + u3a_print_time(c3_c* str_c, c3_c* cap_c, c3_d mic_d); + /* u3a_print_memory(): print memory amount. */ void @@ -677,3 +720,5 @@ */ c3_c* u3a_string(u3_atom a); + +#endif /* ifndef U3_ALLOCATE_H */ diff --git a/pkg/urbit/include/noun/events.h b/pkg/urbit/include/noun/events.h index bee2d8ad57..f44a94e571 100644 --- a/pkg/urbit/include/noun/events.h +++ b/pkg/urbit/include/noun/events.h @@ -1,7 +1,6 @@ -/* i/n/e.h -** -** This file is in the public domain. -*/ +#ifndef U3_EVENTS_H +#define U3_EVENTS_H + /** Data structures. **/ /* u3e_line: control line. @@ -75,11 +74,6 @@ c3_o u3e_live(c3_o nuu_o, c3_c* dir_c); - /* u3e_dirty(): count dirty pages. - */ - c3_w - u3e_dirty(void); - /* u3e_yolo(): disable dirty page tracking, read/write whole loom. */ c3_o @@ -89,3 +83,5 @@ */ void u3e_foul(void); + +#endif /* ifndef U3_EVENTS_H */ diff --git a/pkg/urbit/include/noun/hashtable.h b/pkg/urbit/include/noun/hashtable.h index e69a060d2c..8c69b13b95 100644 --- a/pkg/urbit/include/noun/hashtable.h +++ b/pkg/urbit/include/noun/hashtable.h @@ -1,7 +1,6 @@ -/* include/n/h.h -** -** This file is in the public domain. -*/ +#ifndef U3_HASHTABLE_H +#define U3_HASHTABLE_H + /** Data structures. **/ /** Straightforward implementation of the classic Bagwell @@ -182,3 +181,5 @@ */ c3_w u3h_wyt(u3p(u3h_root) har_p); + +#endif /* ifndef U3_HASHTABLE_H */ diff --git a/pkg/urbit/include/noun/imprison.h b/pkg/urbit/include/noun/imprison.h index d4d28a87e8..2123fb8136 100644 --- a/pkg/urbit/include/noun/imprison.h +++ b/pkg/urbit/include/noun/imprison.h @@ -1,7 +1,5 @@ -/* include/noun/imprison.h -** -** This file is in the public domain. -*/ +#ifndef U3_IMPRISON_H +#define U3_IMPRISON_H /** Structures. **/ @@ -129,12 +127,12 @@ /* u3i_string(): Produce an LSB-first atom from the C string [a]. */ - u3_noun + u3_atom u3i_string(const c3_c* a_c); /* u3i_tape(): from a C string, to a list of bytes. */ - u3_atom + u3_noun u3i_tape(const c3_c* txt_c); /* u3i_list(): list from `u3_none`-terminated varargs. @@ -157,3 +155,5 @@ */ u3_noun u3i_molt(u3_noun som, ...); + +#endif /* ifndef U3_IMPRISON_H */ diff --git a/pkg/urbit/include/noun/jets.h b/pkg/urbit/include/noun/jets.h index 6a9d277566..5b1c4f03c8 100644 --- a/pkg/urbit/include/noun/jets.h +++ b/pkg/urbit/include/noun/jets.h @@ -1,7 +1,6 @@ -/* include/n/j.h -** -** This file is in the public domain. -*/ +#ifndef U3_JETS_H +#define U3_JETS_H + /** Noun semantics. **/ #if 0 @@ -301,3 +300,5 @@ */ void u3j_rewrite_compact(); + +#endif /* ifndef U3_JETS_H */ diff --git a/pkg/urbit/include/noun/log.h b/pkg/urbit/include/noun/log.h index 07ab2296cb..e786eff5f8 100644 --- a/pkg/urbit/include/noun/log.h +++ b/pkg/urbit/include/noun/log.h @@ -1,6 +1,5 @@ -/* noun/log.h -** -*/ +#ifndef U3_LOG_H +#define U3_LOG_H /* u3l_log(): logs to stderr or redirects to configured function. */ @@ -17,3 +16,5 @@ */ u3_weak u3l_punt(const char* name, u3_weak pro); + +#endif /* ifndef U3_LOG_H */ diff --git a/pkg/urbit/include/noun/manage.h b/pkg/urbit/include/noun/manage.h index 4f676e6655..5c522bcd17 100644 --- a/pkg/urbit/include/noun/manage.h +++ b/pkg/urbit/include/noun/manage.h @@ -1,7 +1,6 @@ -/* i/n/m.h -** -** This file is in the public domain. -*/ +#ifndef U3_MANAGE_H +#define U3_MANAGE_H + /** System management. **/ /* u3m_boot(): start the u3 system. return next event, starting from 1. @@ -149,3 +148,5 @@ */ c3_w u3m_pack(void); + +#endif /* ifndef U3_MANAGE_H */ diff --git a/pkg/urbit/include/noun/nock.h b/pkg/urbit/include/noun/nock.h index 1e7c6430ea..561cb7585f 100644 --- a/pkg/urbit/include/noun/nock.h +++ b/pkg/urbit/include/noun/nock.h @@ -1,7 +1,6 @@ -/* i/n/n.h -** -** This file is in the public domain. -*/ +#ifndef U3_NOCK_H +#define U3_NOCK_H + /** Data structures. *** **/ @@ -136,3 +135,5 @@ */ void u3n_ream(void); + +#endif /* ifndef U3_NOCK_H */ diff --git a/pkg/urbit/include/noun/options.h b/pkg/urbit/include/noun/options.h index 5aecc17580..f73dba264d 100644 --- a/pkg/urbit/include/noun/options.h +++ b/pkg/urbit/include/noun/options.h @@ -1,7 +1,6 @@ -/* i/n/o.h -** -** This file is in the public domain. -*/ +#ifndef U3_OPTIONS_H +#define U3_OPTIONS_H + /** Data structures. **/ /* u3o_config: process / system configuration. @@ -40,3 +39,5 @@ c3_global u3o_config u3o_Config; # define u3C u3o_Config + +#endif /* ifndef U3_OPTIONS_H */ diff --git a/pkg/urbit/include/noun/retrieve.h b/pkg/urbit/include/noun/retrieve.h index f5e047ee6d..edd2275bfa 100644 --- a/pkg/urbit/include/noun/retrieve.h +++ b/pkg/urbit/include/noun/retrieve.h @@ -1,7 +1,6 @@ -/* i/n/r.h -** -** This file is in the public domain. -*/ +#ifndef U3_RETRIEVE_H +#define U3_RETRIEVE_H + /** u3r_*: read without ever crashing. **/ #if 1 @@ -462,3 +461,5 @@ */ c3_y* u3r_tape(u3_noun a); + +#endif /* ifndef U3_RETRIEVE_H */ diff --git a/pkg/urbit/include/noun/serial.h b/pkg/urbit/include/noun/serial.h index dca9e0ac77..89a835b992 100644 --- a/pkg/urbit/include/noun/serial.h +++ b/pkg/urbit/include/noun/serial.h @@ -1,6 +1,6 @@ -/* i/n/serial.h -** -*/ +#ifndef U3_SERIAL_H +#define U3_SERIAL_H + /* opaque handles */ /* u3_cue_xeno: handle for cue-ing with an off-loom dictionary. @@ -75,3 +75,5 @@ */ u3_weak u3s_sift_ud(u3_atom a); + +#endif /* ifndef U3_SERIAL_H */ diff --git a/pkg/urbit/include/noun/trace.h b/pkg/urbit/include/noun/trace.h index 28b42151d7..e887feb3a0 100644 --- a/pkg/urbit/include/noun/trace.h +++ b/pkg/urbit/include/noun/trace.h @@ -1,7 +1,6 @@ -/* i/n/t.h -** -** This file is in the public domain. -*/ +#ifndef U3_TRACE_H +#define U3_TRACE_H + /** Data structures. **/ /* u3t_trace: fast execution flags. @@ -130,6 +129,30 @@ void u3t_boot(void); + /* u3t_slog_cap(): slog a tank with a caption with + ** a given priority c3_l (assumed 0-3). + */ + void + u3t_slog_cap(c3_l pri_l, u3_noun cap, u3_noun tan); + + /* u3t_slog_trace(): given a c3_l priority pri and a raw stack tax + ** flop the order into start-to-end, render, and slog each item + ** until done. + */ + void + u3t_slog_trace(c3_l pri_l, u3_noun tax); + + /* u3t_slog_nara(): slog only the deepest road's trace with + ** c3_l priority pri + */ + void + u3t_slog_nara(c3_l pri_l); + + /* u3t_slog_hela(): join all roads' traces together into one tax + ** and pass it to slog_trace along with the given c3_l priority pri_l + */ + void + u3t_slog_hela(c3_l pri_l); /** Globals. **/ @@ -138,3 +161,5 @@ c3_global u3t_trace u3t_Trace; # define u3T u3t_Trace + +#endif /* ifndef U3_TRACE_H */ diff --git a/pkg/urbit/include/noun/urth.h b/pkg/urbit/include/noun/urth.h index d837a72291..3fe29792e5 100644 --- a/pkg/urbit/include/noun/urth.h +++ b/pkg/urbit/include/noun/urth.h @@ -1,5 +1,6 @@ -/* include/noun/urth.h -*/ +#ifndef U3_URTH_H +#define U3_URTH_H + /** Functions. **/ /* u3u_meld(): globally deduplicate memory. @@ -35,3 +36,5 @@ */ c3_o u3u_munmap(c3_d len_d, c3_y* byt_y); + +#endif /* ifndef U3_URTH_H */ diff --git a/pkg/urbit/include/noun/vortex.h b/pkg/urbit/include/noun/vortex.h index d5e261d787..3e8f014840 100644 --- a/pkg/urbit/include/noun/vortex.h +++ b/pkg/urbit/include/noun/vortex.h @@ -1,7 +1,6 @@ -/* include/g/v.h -** -** This file is in the public domain. -*/ +#ifndef U3_VORTEX_H +#define U3_VORTEX_H + /** Data structures. **/ /* u3v_arvo: modern arvo structure. @@ -68,6 +67,11 @@ void u3v_time(u3_noun now); + /* u3v_lily(): parse little atom. + */ + c3_o + u3v_lily(u3_noun fot, u3_noun txt, c3_l* tid_l); + /* u3v_peek(): query the reck namespace. */ u3_noun @@ -112,3 +116,5 @@ */ void u3v_rewrite_compact(); + +#endif /* ifndef U3_VORTEX_H */ diff --git a/pkg/urbit/include/noun/xtract.h b/pkg/urbit/include/noun/xtract.h index 5e22a90bb6..3c26e5e4ca 100644 --- a/pkg/urbit/include/noun/xtract.h +++ b/pkg/urbit/include/noun/xtract.h @@ -1,7 +1,6 @@ -/* i/n/x.h -** -** This file is in the public domain. -*/ +#ifndef U3_XTRACT_H +#define U3_XTRACT_H + /** Constants. **/ /* Conventional axes for gate call. @@ -157,3 +156,5 @@ u3_noun* e, u3_noun* f, u3_noun* g); + +#endif /* ifndef U3_XTRACT_H */ diff --git a/pkg/urbit/include/noun/zave.h b/pkg/urbit/include/noun/zave.h index dd48befba4..2f637c0eae 100644 --- a/pkg/urbit/include/noun/zave.h +++ b/pkg/urbit/include/noun/zave.h @@ -1,7 +1,6 @@ -/* i/n/z.h -** -** This file is in the public domain. -*/ +#ifndef U3_ZAVE_H +#define U3_ZAVE_H + /** Memoization. *** *** The memo cache is keyed by an arbitrary symbolic function @@ -37,3 +36,5 @@ */ u3_noun u3z_uniq(u3_noun som); + +#endif /* ifndef U3_ZAVE_H */ diff --git a/pkg/urbit/include/ur/defs.h b/pkg/urbit/include/ur/defs.h index c16a7e153e..f6c0b00cd5 100644 --- a/pkg/urbit/include/ur/defs.h +++ b/pkg/urbit/include/ur/defs.h @@ -81,4 +81,4 @@ ur_met0_bytes_unsafe(uint64_t len, uint8_t *byt) #define ur_met3_32(a) ur_bloq_up3(ur_met0_32(a)) #define ur_met3_64(a) ur_bloq_up3(ur_met0_64(a)) -#endif +#endif /* ifndef UR_DEFS_H */ diff --git a/pkg/urbit/include/ur/hashcons.h b/pkg/urbit/include/ur/hashcons.h index 01e295ddf0..f1d5b075f1 100644 --- a/pkg/urbit/include/ur/hashcons.h +++ b/pkg/urbit/include/ur/hashcons.h @@ -254,4 +254,4 @@ ur_walk_fore_with(ur_walk_fore_t *w, void ur_walk_fore_done(ur_walk_fore_t *w); -#endif +#endif /* ifndef UR_HASHCONS_H */ diff --git a/pkg/urbit/include/ur/serial.h b/pkg/urbit/include/ur/serial.h index e1cf9e39f4..6010df6b68 100644 --- a/pkg/urbit/include/ur/serial.h +++ b/pkg/urbit/include/ur/serial.h @@ -108,4 +108,4 @@ ur_cue_test_with(ur_cue_test_t *t, void ur_cue_test_done(ur_cue_test_t *t); -#endif +#endif /* ifndef UR_SERIAL_H */ diff --git a/pkg/urbit/include/ur/ur.h b/pkg/urbit/include/ur/ur.h index 5b1bb222eb..5665a3cc42 100644 --- a/pkg/urbit/include/ur/ur.h +++ b/pkg/urbit/include/ur/ur.h @@ -1,9 +1,9 @@ -#ifndef UR_UR_H -#define UR_UR_H +#ifndef UR_H +#define UR_H #include "ur/defs.h" #include "ur/bitstream.h" #include "ur/hashcons.h" #include "ur/serial.h" -#endif +#endif /* ifndef UR_H */ diff --git a/pkg/urbit/include/vere/db/lmdb.h b/pkg/urbit/include/vere/db/lmdb.h index 7476b12bea..573a68fa44 100644 --- a/pkg/urbit/include/vere/db/lmdb.h +++ b/pkg/urbit/include/vere/db/lmdb.h @@ -1,5 +1,5 @@ -/* include/vere/db/lmdb-impl.h -*/ +#ifndef U3_VERE_DB_LMDB_H +#define U3_VERE_DB_LMDB_H #include @@ -60,3 +60,5 @@ const c3_c* key_c, size_t val_i, void* val_p); + +#endif /* ifndef U3_VERE_DB_LMDB_H */ diff --git a/pkg/urbit/include/vere/ivory.h b/pkg/urbit/include/vere/ivory.h new file mode 100644 index 0000000000..8ebc94c92a --- /dev/null +++ b/pkg/urbit/include/vere/ivory.h @@ -0,0 +1,7 @@ +#ifndef U3_IVORY_H +#define U3_IVORY_H + +extern unsigned char u3_Ivory_pill[]; +extern unsigned int u3_Ivory_pill_len; + +#endif diff --git a/pkg/urbit/include/vere/serf.h b/pkg/urbit/include/vere/serf.h index 4ed63f5ea0..5808f362e7 100644 --- a/pkg/urbit/include/vere/serf.h +++ b/pkg/urbit/include/vere/serf.h @@ -1,5 +1,5 @@ -/* include/vere/serf.h -*/ +#ifndef U3_VERE_SERF_H +#define U3_VERE_SERF_H /** Data types. **/ @@ -59,3 +59,5 @@ */ void u3_serf_grab(void); + +#endif /* ifndef U3_VERE_SERF_H */ diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index a0cab581ce..d33d1ff84e 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1,5 +1,5 @@ -/* include/vere/vere.h -*/ +#ifndef U3_VERE_H +#define U3_VERE_H #include @@ -67,7 +67,7 @@ u3_mess_type sat_e; // msg type union { // struct { // awaiting header: - c3_y len_y[8]; // header bytes + c3_y hed_y[5]; // header bytes c3_y has_y; // length } hed_u; // struct { // awaiting body @@ -274,6 +274,7 @@ c3_o abo; // -a, abort aggressively c3_c* pil_c; // -B, bootstrap from c3_c* bin_c; // -b, http server bind ip + c3_w hap_w; // -C, cap memo cache c3_o nuu; // -c, new pier c3_o dry; // -D, dry compute, no checkpoint c3_o dem; // -d, daemon @@ -284,7 +285,6 @@ c3_c* dns_c; // -H, ames bootstrap domain c3_c* jin_c; // -I, inject raw event c3_c* imp_c; // -i, import pier state - c3_w hap_w; // -C, cap memo cache c3_c* lit_c; // -J, ivory (fastboot) kernel c3_o tra; // -j, json trace c3_w kno_w; // -K, kernel version @@ -293,20 +293,24 @@ c3_o lit; // -l, lite mode c3_c* til_c; // -n, play till eve_d c3_o pro; // -P, profile + c3_s per_s; // http port + c3_s pes_s; // https port c3_s por_s; // -p, ames port c3_o qui; // -q, quiet c3_o rep; // -R, report build info c3_c* roc_c; // -r, load rock by eve_d c3_o has; // -S, Skip battery hashes - c3_o tem; // -t, Disable terminal/tty assumptions c3_o git; // -s, pill url from arvo git hash + c3_o tem; // -t, Disable terminal/tty assumptions c3_c* url_c; // -u, pill url c3_o veb; // -v, verbose (inverse of -q) c3_c* who_c; // -w, begin with ticket - c3_o tex; // -x, exit after loading c3_c* pek_c; // -X, scry path (/vc/desk/path) + c3_o tex; // -x, exit after loading c3_c* puk_c; // -Y, scry result filename c3_c* puf_c; // -Z, scry result format + c3_o con; // run conn + c3_o doc; // dock binary in pier } u3_opts; /* u3_host: entire host. @@ -314,21 +318,25 @@ typedef struct _u3_host { c3_w kno_w; // current executing stage c3_c* dir_c; // pier path (no trailing /) + c3_c* dem_c; // daemon executable path c3_c* wrk_c; // worker executable path c3_d now_d; // event tick uv_loop_t* lup_u; // libuv event loop u3_usig* sig_u; // signal list - #if defined(U3_OS_mingw) +#if defined(U3_OS_mingw) HANDLE cev_u; // Ctrl-C event handle - #endif +#endif u3_utty* uty_u; // linked terminal list + c3_o nex_o; // upgrade requested + c3_c* arc_c; // upgrade to arch u3_opts ops_u; // commandline options + c3_o pep_o; // prep for upgrade c3_i xit_i; // exit code for shutdown u3_trac tra_u; // tracing information void (*bot_f)(); // call when chis is up } u3_host; // host == computer == process - /** New pier system. + /** Pier system. **/ /* u3_ovum_news: u3_ovum lifecycle events */ @@ -585,10 +593,11 @@ /* u3_auto_cb: i/o driver callbacks */ typedef struct _u3_auto_cb { - void (*talk_f)(struct _u3_auto*); - void (*info_f)(struct _u3_auto*); - c3_o (*kick_f)(struct _u3_auto*, u3_noun, u3_noun); - void (*exit_f)(struct _u3_auto*); // XX close_cb? + void (*talk_f)(struct _u3_auto*); + u3_noun (*info_f)(struct _u3_auto*); + void (*slog_f)(struct _u3_auto*); + c3_o (*kick_f)(struct _u3_auto*, u3_noun, u3_noun); + void (*exit_f)(struct _u3_auto*); // XX close_cb? } u3_auto_cb; /* u3_auto: abstract i/o driver @@ -635,7 +644,6 @@ c3_c* pax_c; // pier directory c3_w lif_w; // lifecycle barrier c3_d who_d[2]; // identity - c3_c* who_c; // identity as C string c3_o fak_o; // yes iff fake security c3_o liv_o; // fully live u3_disk* log_u; // event log @@ -653,9 +661,12 @@ void* sop_p; // slog stream data void (*sog_f) // slog stream callback (void*, c3_w, u3_noun);// - // XX remove - c3_s por_s; // UDP port + // XX remove + c3_s per_s; // http port + c3_s pes_s; // htls port + c3_s por_s; // ames port u3_save* sav_u; // autosave + // XX end remove struct _u3_pier* nex_u; // next in list } u3_pier; @@ -674,7 +685,6 @@ u3_pier_spin(u3_pier* pir_u); # define u3L u3_Host.lup_u // global event loop -# define u3Z (&(u3_Raft)) # define u3K u3_King /** Global variables. @@ -755,7 +765,7 @@ c3_d u3_time_gap_ms(u3_noun now, u3_noun wen); - /** ward: common structure lifecycle + /** Common structure lifecycle. **/ /* u3_dent_init(): initialize file record. */ @@ -840,17 +850,22 @@ c3_w u3_mcut_host(c3_c* buf_c, c3_w len_w, u3_noun hot); - /** New vere + /** IO drivers. **/ /* u3_auto_init(): initialize all drivers. */ u3_auto* u3_auto_init(u3_pier* pir_u); - /* u3_auto_info(): print status info. + /* u3_auto_info(): status info as a (list mass), all drivers. + */ + u3_noun + u3_auto_info(u3_auto* car_u); + + /* u3_auto_slog(): print status info. */ void - u3_auto_info(u3_auto* car_u); + u3_auto_slog(u3_auto* car_u); /* u3_auto_exit(): close all drivers. */ @@ -925,10 +940,15 @@ u3_disk* u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u); - /* u3_disk_info(): print status info. + /* u3_disk_info(): status info as $mass. + */ + u3_noun + u3_disk_info(u3_disk* log_u); + + /* u3_disk_slog(): print status info. */ void - u3_disk_info(u3_disk* log_u); + u3_disk_slog(u3_disk* log_u); /* u3_disk_exit(): close [log_u] and dispose. */ @@ -979,10 +999,15 @@ c3_d key_d[4], u3_lord_cb cb_u); - /* u3_lord_info(): print status info. + /* u3_lord_info(): status info as a $mass. + */ + u3_noun + u3_lord_info(u3_lord* god_u); + + /* u3_lord_slog(): print status info. */ void - u3_lord_info(u3_lord* god_u); + u3_lord_slog(u3_lord* god_u); /* u3_lord_exit(): shutdown gracefully. */ @@ -1034,41 +1059,14 @@ void u3_lord_peek(u3_lord* god_u, u3_pico* pic_u); - /** Filesystem (new api). - **/ - /* u3_walk_load(): load file or bail. - */ - u3_noun - u3_walk_load(c3_c* pas_c); - - /* u3_walk_safe(): load file or 0. - */ - u3_noun - u3_walk_safe(c3_c* pas_c); - - /* u3_walk_save(): save file or bail. - */ - void - u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax); - - /* u3_walk(): traverse `dir_c` to produce an arch, updating `old`. - */ - u3_noun - u3_walk(const c3_c* dir_c, u3_noun old); - - /* u3_path(): C unix path in computer for file or directory. - */ - c3_c* - u3_path(c3_o fyl, u3_noun pax); - - /** Filesystem (async) + /** Filesystem (async). **/ /* u3_foil_folder(): load directory, blockingly. create if nonexistent. */ u3_dire* u3_foil_folder(const c3_c* pax_c); // directory object, or 0 - /** Terminal, new style. + /** Terminal. **/ /* u3_term_start_spinner(): prepare spinner state. RETAIN. */ @@ -1166,8 +1164,18 @@ u3_save_io_exit(u3_pier *pir_u); - /** Storage, new school. + /** Storage. **/ + /* u3_unix_save(): save file undir .../.urb/put or bail. + */ + void + u3_unix_save(c3_c* pax_c, u3_atom pad); + + /* u3_unix_cane(): true iff (unix) path is canonical. + */ + c3_t + u3_unix_cane(const c3_c* pax_c); + /* u3_unix_initial_into_card(): create initial filesystem sync card. */ u3_noun @@ -1199,14 +1207,21 @@ u3_auto* u3_cttp_io_init(u3_pier* pir_u); - /** fore, first events + /** Control plane. + **/ + /* u3_conn_io_init(): initialize control plane I/O. + */ + u3_auto* + u3_conn_io_init(u3_pier* pir_u); + + /** fore, first events. **/ /* u3_hind_io_init(): initialize fore */ u3_auto* u3_fore_io_init(u3_pier* pir_u); - /** hind, defaults + /** hind, defaults. **/ /* u3_hind_io_init(): initialize hint */ @@ -1217,7 +1232,7 @@ **/ /* u3_newt_decode(): decode a (partial) length-prefixed byte buffer */ - void + c3_o u3_newt_decode(u3_moat* mot_u, c3_y* buf_y, c3_d len_d); /* u3_newt_send(): write buffer to stream. @@ -1235,10 +1250,15 @@ void u3_newt_read(u3_moat* mot_u); - /* u3_newt_moat_info(); print status info. + /* u3_newt_moat_info(): status info as $mass. + */ + u3_noun + u3_newt_moat_info(u3_moat* mot_u); + + /* u3_newt_moat_slog(); print status info. */ void - u3_newt_moat_info(u3_moat* mot_u); + u3_newt_moat_slog(u3_moat* mot_u); /* u3_newt_moat_stop(); newt stop/close input stream. */ @@ -1304,12 +1324,17 @@ void u3_pier_pack(u3_pier* pir_u); - /* u3_pier_info(): print status info. + /* u3_pier_info(): pier status info as $mass. */ - void + u3_noun u3_pier_info(u3_pier* pir_u); - /* u3_pier_boot(): start the new pier system. + /* u3_pier_slog(): print pier status info. + */ + void + u3_pier_slog(u3_pier* pir_u); + + /* u3_pier_boot(): start the pier. */ u3_pier* u3_pier_boot(c3_w wag_w, // config flags @@ -1319,7 +1344,7 @@ u3_noun pax, // path to pier u3_weak fed); // extra private keys - /* u3_pier_stay(): restart the new pier system. + /* u3_pier_stay(): restart the pier. */ u3_pier* u3_pier_stay(c3_w wag_w, u3_noun pax); @@ -1354,6 +1379,16 @@ c3_w u3_pier_mark(FILE* fil_u); + /* u3_pier_mase(): construct a $mass leaf. + */ + u3_noun + u3_pier_mase(c3_c* cod_c, u3_noun dat); + + /* u3_pier_mass(): construct a $mass branch with noun/list. + */ + u3_noun + u3_pier_mass(u3_atom cod, u3_noun lit); + /* u3_dawn_come(): mine a comet */ u3_noun @@ -1374,10 +1409,15 @@ u3_pier* u3_king_stub(void); - /* u3_king_info(): print status info. + /* u3_king_slog(): print status info. */ void - u3_king_info(void); + u3_king_slog(void); + + /* u3_king_dock(): copy binary into pier on boot. + */ + void + u3_king_dock(c3_c* pac_c); /* u3_king_done(): all piers closed */ @@ -1399,6 +1439,21 @@ void u3_king_grab(void* ptr_v); + /* u3_king_next(): get next vere version string, if it exists. + ** return: 0 is success, -1 is no-op (same version), -2 is error + */ + c3_i + u3_king_next(c3_c* pac_c, c3_c** out_c); + + /* u3_king_vere(): download binary as specified. + */ + c3_i + u3_king_vere(c3_c* pac_c, // pace + c3_c* ver_c, // version + c3_c* arc_c, // architecture + c3_c* dir_c, // output directory + c3_t lin_t); // link to $pier/.run + /* u3_daemon_init(): platform-specific daemon mode initialization. */ void @@ -1411,3 +1466,5 @@ c3_w u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); + +#endif /* ifndef U3_VERE_H */ diff --git a/pkg/urbit/jets/e/hmac.c b/pkg/urbit/jets/e/hmac.c index 0ba332cd3a..8585f57d7f 100644 --- a/pkg/urbit/jets/e/hmac.c +++ b/pkg/urbit/jets/e/hmac.c @@ -17,13 +17,17 @@ { c3_assert(_(u3a_is_cat(boq)) && _(u3a_is_cat(wik)) && _(u3a_is_cat(wid))); + // prep the hashing gate + u3j_site sit_u; + u3j_gate_prep(&sit_u, u3k(haj)); + // ensure key and message fit signaled lengths key = u3qc_end(3, wik, key); dat = u3qc_end(3, wid, dat); // keys longer than block size are shortened by hashing if (wik > boq) { - key = u3n_slam_on(u3k(haj), u3nc(wik, key)); + key = u3j_gate_slam(&sit_u, u3nc(wik, key)); wik = out; } @@ -47,12 +51,13 @@ // append inner padding to message, then hash u3_atom innmsg = u3ka_add(u3kc_lsh(3, wid, innkey), dat); - u3_atom innhaj = u3n_slam_on(u3k(haj), u3nc((wid + boq), innmsg)); + u3_atom innhaj = u3j_gate_slam(&sit_u, u3nc((wid + boq), innmsg)); // prepend outer padding to result, hash again u3_atom outmsg = u3ka_add(u3kc_lsh(3, out, outkey), innhaj); - u3_atom outhaj = u3n_slam_on(u3k(haj), u3nc((out + boq), outmsg)); + u3_atom outhaj = u3j_gate_slam(&sit_u, u3nc((out + boq), outmsg)); + u3j_gate_lose(&sit_u); return outhaj; } diff --git a/pkg/urbit/jets/e/secp.c b/pkg/urbit/jets/e/secp.c index 6a4c6ce634..21569603c5 100644 --- a/pkg/urbit/jets/e/secp.c +++ b/pkg/urbit/jets/e/secp.c @@ -208,3 +208,90 @@ u3we_make(u3_noun cor) return u3l_punt("secp-make", _cqes_make(has, prv)); } } + +/* create a schnorr signature +*/ +static u3_weak +_cqes_sosi(u3_atom sk, u3_atom m, u3_atom a) +{ + c3_y key_y[32]; + c3_y mes_y[32]; + c3_y aux_y[32]; + + if ( (0 != u3r_bytes_fit(32, key_y, sk)) || + (0 != u3r_bytes_fit(32, mes_y, m)) || + (0 != u3r_bytes_fit(32, aux_y, a)) ) + { + return u3m_bail(c3__exit); + } + else { + c3_y sig_y[64]; + + return + ( 0 == urcrypt_secp_schnorr_sign(sec_u, key_y, mes_y, aux_y, sig_y) ) + ? u3i_bytes(64, sig_y) + : u3_none; + } +} + +u3_noun +u3we_sosi(u3_noun cor) +{ + u3_noun key, mes, aux; + + if ( (c3n == u3r_mean(cor, + u3x_sam_2, &key, + u3x_sam_6, &mes, + u3x_sam_7, &aux, + 0)) || + (c3n == u3ud(key)) || + (c3n == u3ud(mes)) || + (c3n == u3ud(aux)) ) + { + return u3m_bail(c3__exit); + } + else { + return u3l_punt("secp-sosi", _cqes_sosi(key, mes, aux)); + } +} + +/* verify a schnorr signature +*/ +static u3_atom +_cqes_sove(u3_atom pk, u3_atom m, u3_atom sig) +{ + c3_y pub_y[32]; + c3_y mes_y[32]; + c3_y sig_y[64]; + + if ( (0 != u3r_bytes_fit(32, pub_y, pk)) || + (0 != u3r_bytes_fit(32, mes_y, m)) || + (0 != u3r_bytes_fit(64, sig_y, sig)) ) + { + return u3m_bail(c3__exit); + } + else { + return __(urcrypt_secp_schnorr_veri(sec_u, sig_y, mes_y, pub_y)); + } +} + +u3_noun +u3we_sove(u3_noun cor) +{ + u3_noun pub, mes, sig; + + if ( (c3n == u3r_mean(cor, + u3x_sam_2, &pub, + u3x_sam_6, &mes, + u3x_sam_7, &sig, + 0)) || + (c3n == u3ud(pub)) || + (c3n == u3ud(mes)) || + (c3n == u3ud(sig)) ) + { + return u3m_bail(c3__exit); + } + else { + return _cqes_sove(pub, mes, sig); + } +} diff --git a/pkg/urbit/jets/e/slaw.c b/pkg/urbit/jets/e/slaw.c index c82c385253..09c4700431 100644 --- a/pkg/urbit/jets/e/slaw.c +++ b/pkg/urbit/jets/e/slaw.c @@ -31,20 +31,17 @@ u3_noun get_syllable(c3_c** cur_ptr, c3_c* one, c3_c* two, c3_c* three) { } } -static -u3_noun combine(u3_noun p, u3_noun q) +static u3_noun +combine(u3_noun p, u3_noun q) { - if (_(u3a_is_atom(p))) { + if ( (c3y == u3a_is_atom(p)) || (c3y == u3a_is_atom(q)) ) { return 0; } - if (_(u3a_is_atom(q))) { - return 0; - } - - u3_noun ret = u3nc(0, u3qa_add(u3t(p), u3qa_mul(256, u3t(q)))); - u3z(p); - u3z(q); + u3_noun lef = u3qa_mul(256, u3t(q)); + u3_noun ret = u3nc(0, u3qa_add(u3t(p), lef)); + u3z(lef); + u3z(p); u3z(q); return ret; } diff --git a/pkg/urbit/jets/tree.c b/pkg/urbit/jets/tree.c index d1d33addeb..2e796035f4 100644 --- a/pkg/urbit/jets/tree.c +++ b/pkg/urbit/jets/tree.c @@ -403,6 +403,24 @@ static u3j_harm _140_hex_secp_secp256k1_sign_a[] = {{".2", u3we_sign, c3y}, {}}; static c3_c* _140_hex_secp_secp256k1_reco_ha[] = { 0 }; static u3j_harm _140_hex_secp_secp256k1_reco_a[] = {{".2", u3we_reco, c3y}, {}}; +static c3_c* _140_hex_secp_secp256k1_schnorr_sosi_ha[] = { 0 }; +static u3j_harm _140_hex_secp_secp256k1_schnorr_sosi_a[] = + {{".2", u3we_sosi}, {}}; +static c3_c* _140_hex_secp_secp256k1_schnorr_sove_ha[] = { 0 }; +static u3j_harm _140_hex_secp_secp256k1_schnorr_sove_a[] = + {{".2", u3we_sove}, {}}; + +static c3_c* _140_hex_secp_secp256k1_schnorr_ha[] = { 0 }; +static u3j_core _140_hex_secp_secp256k1_schnorr_d[] = + { { "sosi", 7, + _140_hex_secp_secp256k1_schnorr_sosi_a, 0, + _140_hex_secp_secp256k1_schnorr_sosi_ha }, + { "sove", 7, + _140_hex_secp_secp256k1_schnorr_sove_a, 0, + _140_hex_secp_secp256k1_schnorr_sove_ha }, + {} + }; + static c3_c* _140_hex_secp_secp256k1_ha[] = { "e7fc0971a970aba7ded43bd89e9c82623eb2f346c9c720c63b22f2a646927861", 0 @@ -411,6 +429,9 @@ static u3j_core _140_hex_secp_secp256k1_d[] = { { "make", 7, _140_hex_secp_secp256k1_make_a, 0, _140_hex_secp_secp256k1_make_ha }, { "sign", 7, _140_hex_secp_secp256k1_sign_a, 0, _140_hex_secp_secp256k1_sign_ha }, { "reco", 7, _140_hex_secp_secp256k1_reco_a, 0, _140_hex_secp_secp256k1_reco_ha }, + { "schnorr", 7, 0, + _140_hex_secp_secp256k1_schnorr_d, + _140_hex_secp_secp256k1_schnorr_ha }, {} }; diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index 4536069a65..ddee5451bd 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -1922,6 +1922,27 @@ u3a_discount_noun(u3_noun som) } } +/* u3a_print_time: print microsecond time. +*/ +void +u3a_print_time(c3_c* str_c, c3_c* cap_c, c3_d mic_d) +{ + c3_assert( 0 != str_c ); + + c3_w sec_w = (mic_d / 1000000); + c3_w mec_w = (mic_d % 1000000) / 1000; + c3_w mic_w = (mic_d % 1000); + + if ( sec_w ) { + sprintf(str_c, "%s s/%d.%03d.%03d", cap_c, sec_w, mec_w, mic_w); + } + else if ( mec_w ) { + sprintf(str_c, "%s ms/%d.%03d", cap_c, mec_w, mic_w); + } + else { + sprintf(str_c, "%s \xc2\xb5s/%d", cap_c, mic_w); + } +} /* u3a_print_memory: print memory amount. */ diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 1be8a5b216..e37fdf0ee2 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -1,6 +1,71 @@ -/* g/e.c -** -*/ +//! @file events.c +//! +//! incremental, orthogonal, paginated loom snapshots +//! +//! ### components +//! +//! - page: 16KB chunk of the loom. +//! - north segment (u3e_image, north.bin): low contiguous loom pages, +//! (in practice, the home road heap). indexed from low to high: +//! in-order on disk. +//! - south segment (u3e_image, south.bin): high contiguous loom pages, +//! (in practice, the home road stack). indexed from high to low: +//! reversed on disk. +//! - patch memory (memory.bin): new or changed pages since the last snapshot +//! - patch control (u3e_control control.bin): patch metadata, watermarks, +//! and indices/mugs for pages in patch memory. +//! +//! ### initialization (u3e_live()) +//! +//! - with the loom already mapped, all pages are marked dirty in a bitmap. +//! - if snapshot is missing or partial, empty segments are created. +//! - if a patch is present, it's applied (crash recovery). +//! - snapshot segments are copied onto the loom; all included pages +//! are marked clean and protected (read-only). +//! +//! #### page faults (u3e_fault()) +//! +//! - stores into protected pages generate faults (currently SIGSEGV, +//! handled outside this module). +//! - faults are handled by dirtying the page and switching protections to +//! read/write. +//! +//! ### updates (u3e_save()) +//! +//! - all updates to a snapshot are made through a patch. +//! - high/low watermarks for the north/south segments are established, +//! and dirty pages below/above them are added to the patch. +//! - modifications have been caught by the fault handler. +//! - newly-used pages are automatically included (preemptively dirtied). +//! - unused, innermost pages are reclaimed (segments are truncated to the +//! high/low watermarks; the last page in each is always adjacent to the +//! contiguous free space). +//! - patch pages are written to memory.bin, metadata to control.bin. +//! - the patch is applied to the snapshot segments, in-place. +//! - patch files are deleted. +//! +//! ### limitations +//! +//! - loom page size is fixed (16 KB), and must be a multiple of the +//! system page size. (can the size vary at runtime give south.bin's +//! reversed order? alternately, if system page size > ours, the fault +//! handler could dirty N pages at a time.) +//! - update atomicity is suspect: patch application must either +//! completely succeed or leave on-disk segments intact. unapplied +//! patches can be discarded (triggering event replay), but once +//! patch application begins it must succeed (can fail if disk is full). +//! may require integration into the overall signal-handling regime. +//! - any errors are handled with assertions; failed/partial writes are not +//! retried. +//! +//! ### enhancements +//! +//! - use platform specific page fault mechanism (mach rpc, userfaultfd, &c). +//! - implement demand paging / heuristic page-out. +//! - add a guard page in the middle of the loom to reactively handle stack overflow. +//! - parallelism +//! + #include "all.h" #include #include @@ -123,13 +188,13 @@ u3e_fault(void* adr_v, c3_i ser_i) c3_w* adr_w = (c3_w*) adr_v; if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3a_words)) ) { - fprintf(stderr, "address %p out of loom!\r\n", adr_v); + fprintf(stderr, "address %p out of loom!\r\n", adr_w); fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3a_words); c3_assert(0); return 0; } else { - c3_w off_w = (adr_w - u3_Loom); + c3_w off_w = u3a_outa(adr_w); c3_w pag_w = off_w >> u3a_page; c3_w blk_w = (pag_w >> 5); c3_w bit_w = (pag_w & 31); @@ -174,17 +239,17 @@ _ce_image_open(u3e_image* img_u) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c); - if ( -1 == (img_u->fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (img_u->fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return c3n; } else { @@ -268,20 +333,20 @@ _ce_patch_create(u3_ce_patch* pat_u) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { - fprintf(stderr, "loom: patch open control.bin: %s\r\n", strerror(errno)); + if ( -1 == (pat_u->ctl_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { + fprintf(stderr, "loom: patch c3_open control.bin: %s\r\n", strerror(errno)); c3_assert(0); } snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { - fprintf(stderr, "loom: patch open memory.bin: %s\r\n", strerror(errno)); + if ( -1 == (pat_u->mem_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { + fprintf(stderr, "loom: patch c3_open memory.bin: %s\r\n", strerror(errno)); c3_assert(0); } } @@ -294,10 +359,10 @@ _ce_patch_delete(void) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - unlink(ful_c); + c3_unlink(ful_c); } /* _ce_patch_verify(): check patch data mug. @@ -366,18 +431,18 @@ _ce_patch_open(void) c3_i ctl_i, mem_i; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) { + if ( -1 == (ctl_i = c3_open(ful_c, O_RDWR)) ) { return 0; } snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) { + if ( -1 == (mem_i = c3_open(ful_c, O_RDWR)) ) { close(ctl_i); _ce_patch_delete(); @@ -471,62 +536,6 @@ _ce_patch_save_page(u3_ce_patch* pat_u, return pgc_w; } -/* _ce_patch_junk_page(): mark a page as junk. -*/ -static void -_ce_patch_junk_page(u3_ce_patch* pat_u, - c3_w pag_w) -{ - c3_w blk_w = (pag_w >> 5); - c3_w bit_w = (pag_w & 31); - - // u3l_log("protect b: page %d\r\n", pag_w); - if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page), - (1 << (u3a_page + 2)), - PROT_READ) ) - { - c3_assert(0); - } - u3P.dit_w[blk_w] &= ~(1 << bit_w); -} - -/* u3e_dirty(): count dirty pages. -*/ -c3_w -u3e_dirty(void) -{ - c3_w pgs_w = 0; - c3_w nor_w = 0; - c3_w sou_w = 0; - - /* Calculate number of saved pages, north and south. - */ - { - c3_w nwr_w, swu_w; - - u3m_water(&nwr_w, &swu_w); - - nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page; - sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page; - } - // u3K.nor_w = nor_w; - // u3K.sou_w = sou_w; - - /* Count dirty pages. - */ - { - c3_w i_w; - - for ( i_w = 0; i_w < nor_w; i_w++ ) { - pgs_w = _ce_patch_count_page(i_w, pgs_w); - } - for ( i_w = 0; i_w < sou_w; i_w++ ) { - pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w); - } - } - return pgs_w; -} - /* _ce_patch_compose(): make and write current patch. */ static u3_ce_patch* @@ -583,9 +592,6 @@ _ce_patch_compose(void) for ( i_w = 0; i_w < sou_w; i_w++ ) { pgc_w = _ce_patch_save_page(pat_u, (u3a_pages - (i_w + 1)), pgc_w); } - for ( i_w = nor_w; i_w < (u3a_pages - sou_w); i_w++ ) { - _ce_patch_junk_page(pat_u, i_w); - } pat_u->con_u->nor_w = nor_w; pat_u->con_u->sou_w = sou_w; @@ -710,23 +716,30 @@ _ce_image_blit(u3e_image* img_u, c3_w* ptr_w, c3_ws stp_ws) { + if ( 0 == img_u->pgs_w ) { + return; + } + c3_w i_w; + c3_w siz_w = 1 << (u3a_page + 2); lseek(img_u->fid_i, 0, SEEK_SET); - for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { - if ( -1 == read(img_u->fid_i, ptr_w, (1 << (u3a_page + 2))) ) { + for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) { + if ( -1 == read(img_u->fid_i, ptr_w, siz_w) ) { fprintf(stderr, "loom: image blit read: %s\r\n", strerror(errno)); c3_assert(0); } -#if 0 - { - c3_w off_w = (ptr_w - u3_Loom); - c3_w pag_w = (off_w >> u3a_page); - u3l_log("blit: page %d, mug %x\r\n", pag_w, - u3r_mug_words(ptr_w, (1 << u3a_page))); + if ( 0 != mprotect(ptr_w, siz_w, PROT_READ) ) { + fprintf(stderr, "loom: live mprotect: %s\r\n", strerror(errno)); + c3_assert(0); } -#endif + + c3_w pag_w = u3a_outa(ptr_w) >> u3a_page; + c3_w blk_w = pag_w >> 5; + c3_w bit_w = pag_w & 31; + u3P.dit_w[blk_w] &= ~(1 << bit_w); + ptr_w += stp_ws; } } @@ -825,7 +838,7 @@ _ce_backup(void) snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); - if ( mkdir(ful_c, 0700) ) { + if ( c3_mkdir(ful_c, 0700) ) { if ( EEXIST != errno ) { fprintf(stderr, "loom: image backup: %s\r\n", strerror(errno)); } @@ -834,15 +847,15 @@ _ce_backup(void) snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); - if ( -1 == (nop_u.fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (nop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return; } snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, sop_u.nam_c); - if ( -1 == (sop_u.fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (sop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return; } @@ -850,11 +863,11 @@ _ce_backup(void) || (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) ) { - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); - rmdir(ful_c); + c3_rmdir(ful_c); } close(nop_u.fid_i); @@ -932,6 +945,10 @@ u3e_save(void) c3_o u3e_live(c3_o nuu_o, c3_c* dir_c) { + // require that our page size is a multiple of the system page size. + // + c3_assert(0 == (1 << (2 + u3a_page)) % sysconf(_SC_PAGESIZE)); + u3P.dir_c = dir_c; u3P.nor_u.nam_c = "north"; u3P.sou_u.nam_c = "south"; @@ -965,6 +982,10 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) _ce_patch_delete(); } + // mark all pages dirty (pages in the snapshot will be marked clean) + // + u3e_foul(); + /* Write image files to memory; reinstate protection. */ { @@ -976,11 +997,6 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) (u3_Loom + (1 << u3a_bits) - (1 << u3a_page)), -(1 << u3a_page)); - if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, PROT_READ) ) { - u3l_log("loom: live mprotect: %s\r\n", strerror(errno)); - c3_assert(0); - } - u3l_log("boot: protected loom\r\n"); } @@ -1018,5 +1034,5 @@ u3e_yolo(void) void u3e_foul(void) { - memset((void*)u3P.dit_w, 0xff, u3a_pages >> 3); + memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w)); } diff --git a/pkg/urbit/noun/imprison.c b/pkg/urbit/noun/imprison.c index 77feae7f67..b34b9d8849 100644 --- a/pkg/urbit/noun/imprison.c +++ b/pkg/urbit/noun/imprison.c @@ -541,7 +541,7 @@ u3i_qual(u3_noun a, u3_noun b, u3_noun c, u3_noun d) /* u3i_string(): Produce an LSB-first atom from the C string [a]. */ -u3_noun +u3_atom u3i_string(const c3_c* a_c) { return u3i_bytes(strlen(a_c), (c3_y *)a_c); @@ -549,7 +549,7 @@ u3i_string(const c3_c* a_c) /* u3i_tape(): from a C string, to a list of bytes. */ -u3_atom +u3_noun u3i_tape(const c3_c* txt_c) { if ( !*txt_c ) { diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index f6e6928246..5ac5568239 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -432,7 +432,7 @@ u3_noun u3m_file(c3_c* pas_c) { struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644); c3_w fln_w, red_w; c3_y* pad_y; @@ -864,6 +864,18 @@ u3m_fall() _print_diff("unused free", u3R->hat_p, u3R->cap_p); _print_diff("freeing", u3R->rut_p, u3R->hat_p); _print_diff("stack", u3R->cap_p, u3R->mat_p); + static c3_w wat_w = 500000000; + if (u3to(u3_road, u3R->par_p) == &u3H->rod_u) { + wat_w = 500000000; + } + else { + wat_w = c3_min(wat_w, + u3R->hat_p < u3R->cap_p ? + u3R->cap_p - u3R->hat_p : + u3R->hat_p - u3R->cap_p); + } + u3a_print_memory(stderr, "low water mark", wat_w); + #endif u3to(u3_road, u3R->par_p)->pro.nox_d += u3R->pro.nox_d; diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index f2ec04e644..6aef6e065e 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -382,125 +382,133 @@ _n_nock_on(u3_noun bus, u3_noun fol) } #endif -/* These must match the order in the section marked OPCODE TABLE, - * and several opcodes "overflow" (from byte to short index) to - * their successor, so order can matter here. */ -// general purpose -#define HALT 0 -#define BAIL 1 -#define COPY 2 -#define SWAP 3 -#define TOSS 4 -#define AUTO 5 -#define AULT 6 -#define SNOC 7 -#define SNOL 8 -#define HEAD 9 -#define HELD 10 -#define TAIL 11 -#define TALL 12 -// fragment (keep) -#define FABK 13 -#define FASK 14 -#define FIBK 15 -#define FISK 16 -// fragment (lose) -#define FABL 17 -#define FASL 18 -#define FIBL 19 -#define FISL 20 -// literal (keep) -#define LIT0 21 -#define LIT1 22 -#define LITB 23 -#define LITS 24 -#define LIBK 25 -#define LISK 26 -// literal (lose) -#define LIL0 27 -#define LIL1 28 -#define LILB 29 -#define LILS 30 -#define LIBL 31 -#define LISL 32 -// nock -#define NOLK 33 -#define NOCT 34 -#define NOCK 35 -// 3 & 4 -#define DEEP 36 -#define BUMP 37 -// equality -#define SAM0 38 -#define SAM1 39 -#define SAMB 40 -#define SAMS 41 -#define SANB 42 -#define SANS 43 -#define SAME 44 -#define SALM 45 -#define SAMC 46 -// unconditional skips -#define SBIP 47 -#define SIPS 48 -#define SWIP 49 -// conditional skips -#define SBIN 50 -#define SINS 51 -#define SWIN 52 -// nock 9 -#define KICB 53 -#define KICS 54 -#define TICB 55 -#define TICS 56 -// nock 11 -#define WILS 57 -#define WISH 58 -// hint processing -#define BUSH 59 -#define SUSH 60 -#define DROP 61 -#define HECK 62 -#define SLOG 63 -// fast (keep) -#define BAST 64 -#define SAST 65 -// fast (lose) -#define BALT 66 -#define SALT 67 -// memo (keep) -#define SKIB 68 -#define SKIS 69 -// memo (lose) -#define SLIB 70 -#define SLIS 71 -#define SAVE 72 -// before formula -#define HILB 73 // atomic, byte -#define HILS 74 // atomic, short -#define HINB 75 // arbitrary, byte -#define HINS 76 // arbitrary, short -// after formula -#define HILK 77 // atomic, keep -#define HILL 78 // atomic, lose -#define HINK 79 // arbitrary, keep -#define HINL 80 // arbitrary, lose -// nock 10 -#define MUTH 81 -#define KUTH 82 -#define MUTT 83 -#define KUTT 84 -#define MUSM 85 -#define KUSM 86 -#define MUTB 87 -#define MUTS 88 -#define MITB 89 -#define MITS 90 -#define KUTB 91 -#define KUTS 92 -#define KITB 93 -#define KITS 94 -#define LAST 95 +// Several opcodes "overflow" (from byte to short index) to their successor, so +// order can matter here. +// Note that we use an X macro (https://en.wikipedia.org/wiki/X_Macro) to unify +// the opcode's enum name, string representation, and computed goto into a +// single structure. +#define OPCODES \ + /* general purpose */ \ + X(HALT, "halt", &&do_halt), /* 0 */ \ + X(BAIL, "bail", &&do_bail), /* 1 */ \ + X(COPY, "copy", &&do_copy), /* 2 */ \ + X(SWAP, "swap", &&do_swap), /* 3 */ \ + X(TOSS, "toss", &&do_toss), /* 4 */ \ + X(AUTO, "auto", &&do_auto), /* 5 */ \ + X(AULT, "ault", &&do_ault), /* 6 */ \ + X(SNOC, "snoc", &&do_snoc), /* 7 */ \ + X(SNOL, "snol", &&do_snol), /* 8 */ \ + X(HEAD, "head", &&do_head), /* 9 */ \ + X(HELD, "held", &&do_held), /* 10 */ \ + X(TAIL, "tail", &&do_tail), /* 11 */ \ + X(TALL, "tall", &&do_tall), /* 12 */ \ + /* fragment (keep) */ \ + X(FABK, "fabk", &&do_fabk), /* 13 */ \ + X(FASK, "fask", &&do_fask), /* 14 */ \ + X(FIBK, "fibk", &&do_fibk), /* 15 */ \ + X(FISK, "fisk", &&do_fisk), /* 16 */ \ + /* fragment (lose) */ \ + X(FABL, "fabl", &&do_fabl), /* 17 */ \ + X(FASL, "fasl", &&do_fasl), /* 18 */ \ + X(FIBL, "fibl", &&do_fibl), /* 19 */ \ + X(FISL, "fisl", &&do_fisl), /* 20 */ \ + /* literal (keep) */ \ + X(LIT0, "lit0", &&do_lit0), /* 21 */ \ + X(LIT1, "lit1", &&do_lit1), /* 22 */ \ + X(LITB, "litb", &&do_litb), /* 23 */ \ + X(LITS, "lits", &&do_lits), /* 24 */ \ + X(LIBK, "libk", &&do_libk), /* 25 */ \ + X(LISK, "lisk", &&do_lisk), /* 26 */ \ + /* literal (lose) */ \ + X(LIL0, "lil0", &&do_lil0), /* 27 */ \ + X(LIL1, "lil1", &&do_lil1), /* 28 */ \ + X(LILB, "lilb", &&do_lilb), /* 29 */ \ + X(LILS, "lils", &&do_lils), /* 30 */ \ + X(LIBL, "libl", &&do_libl), /* 31 */ \ + X(LISL, "lisl", &&do_lisl), /* 32 */ \ + /* nock */ \ + X(NOLK, "nolk", &&do_nolk), /* 33 */ \ + X(NOCT, "noct", &&do_noct), /* 34 */ \ + X(NOCK, "nock", &&do_nock), /* 35 */ \ + /* 3 & 4 */ \ + X(DEEP, "deep", &&do_deep), /* 36 */ \ + X(BUMP, "bump", &&do_bump), /* 37 */ \ + /* equality */ \ + X(SAM0, "sam0", &&do_sam0), /* 38 */ \ + X(SAM1, "sam1", &&do_sam1), /* 39 */ \ + X(SAMB, "samb", &&do_samb), /* 40 */ \ + X(SAMS, "sams", &&do_sams), /* 41 */ \ + X(SANB, "sanb", &&do_sanb), /* 42 */ \ + X(SANS, "sans", &&do_sans), /* 43 */ \ + X(SAME, "same", &&do_same), /* 44 */ \ + X(SALM, "salm", &&do_salm), /* 45 */ \ + X(SAMC, "samc", &&do_samc), /* 46 */ \ + /* unconditional skips */ \ + X(SBIP, "sbip", &&do_sbip), /* 47 */ \ + X(SIPS, "sips", &&do_sips), /* 48 */ \ + X(SWIP, "swip", &&do_swip), /* 49 */ \ + /* conditional skips */ \ + X(SBIN, "sbin", &&do_sbin), /* 50 */ \ + X(SINS, "sins", &&do_sins), /* 51 */ \ + X(SWIN, "swin", &&do_swin), /* 52 */ \ + /* nock 9 */ \ + X(KICB, "kicb", &&do_kicb), /* 53 */ \ + X(KICS, "kics", &&do_kics), /* 54 */ \ + X(TICB, "ticb", &&do_ticb), /* 55 */ \ + X(TICS, "tics", &&do_tics), /* 56 */ \ + /* nock 12 */ \ + X(WILS, "wils", &&do_wils), /* 57 */ \ + X(WISH, "wish", &&do_wish), /* 58 */ \ + /* hint processing */ \ + X(BUSH, "bush", &&do_bush), /* 59 */ \ + X(SUSH, "sush", &&do_sush), /* 60 */ \ + X(DROP, "drop", &&do_drop), /* 61 */ \ + X(HECK, "heck", &&do_heck), /* 62 */ \ + X(SLOG, "slog", &&do_slog), /* 63 */ \ + /* fast (keep) */ \ + X(BAST, "bast", &&do_bast), /* 64 */ \ + X(SAST, "sast", &&do_sast), /* 65 */ \ + /* fast (lose) */ \ + X(BALT, "balt", &&do_balt), /* 66 */ \ + X(SALT, "salt", &&do_salt), /* 67 */ \ + /* memo (keep) */ \ + X(SKIB, "skib", &&do_skib), /* 68 */ \ + X(SKIS, "skis", &&do_skis), /* 69 */ \ + /* memo (lose) */ \ + X(SLIB, "slib", &&do_slib), /* 70 */ \ + X(SLIS, "slis", &&do_slis), /* 71 */ \ + X(SAVE, "save", &&do_save), /* 72 */ \ + /* before formula */ \ + X(HILB, "hilb", &&do_hilb), /* 73: atomic, byte */ \ + X(HILS, "hils", &&do_hils), /* 74: atomic, short */ \ + X(HINB, "hinb", &&do_hinb), /* 75: arbitrary, byte */ \ + X(HINS, "hins", &&do_hins), /* 76: arbitrary, short */ \ + /* after formula */ \ + X(HILK, "hilk", &&do_hilk), /* 77: atomic, keep */ \ + X(HILL, "hill", &&do_hill), /* 78: atomic, lose */ \ + X(HINK, "hink", &&do_hink), /* 79: arbitrary, keep */ \ + X(HINL, "hinl", &&do_hinl), /* 80: arbitrary, lose */ \ + /* nock 10 */ \ + X(MUTH, "muth", &&do_muth), /* 81 */ \ + X(KUTH, "kuth", &&do_kuth), /* 82 */ \ + X(MUTT, "mutt", &&do_mutt), /* 83 */ \ + X(KUTT, "kutt", &&do_kutt), /* 84 */ \ + X(MUSM, "musm", &&do_musm), /* 85 */ \ + X(KUSM, "kusm", &&do_kusm), /* 86 */ \ + X(MUTB, "mutb", &&do_mutb), /* 87 */ \ + X(MUTS, "muts", &&do_muts), /* 88 */ \ + X(MITB, "mitb", &&do_mitb), /* 89 */ \ + X(MITS, "mits", &&do_mits), /* 90 */ \ + X(KUTB, "kutb", &&do_kutb), /* 91 */ \ + X(KUTS, "kuts", &&do_kuts), /* 92 */ \ + X(KITB, "kitb", &&do_kitb), /* 93 */ \ + X(KITS, "kits", &&do_kits), /* 94 */ \ + X(LAST, NULL, NULL), /* 95 */ + +// Opcodes. Define X to select the enum name from OPCODES. +#define X(opcode, name, indirect_jump) opcode +enum { OPCODES }; +#undef X /* _n_arg(): return the size (in bytes) of an opcode's argument */ @@ -949,40 +957,10 @@ static void _n_print_stack(u3p(u3_noun) empty) { #endif #ifdef VERBOSE_BYTECODE -// match to OPCODE TABLE -static char* opcode_names[] = { - "halt", "bail", - "copy", "swap", "toss", - "auto", "ault", "snoc", "snol", - "head", "held", "tail", "tall", - "fabk", "fask", "fibk", "fisk", - "fabl", "fasl", "fibl", "fisl", - "lit0", "lit1", "litb", "lits", - "libk", "lisk", - "lil0", "lil1", "lilb", "lils", - "libl", "lisl", - "nolk", "noct", "nock", - "deep", "bump", - "sam0", "sam1", "samb", "sams", - "sanb", "sans", - "same", "salm", "samc", - "sbip", "sips", "swip", - "sbin", "sins", "swin", - "kicb", "kics", "ticb", "tics", - "wils", "wish", - "bush", "sush", - "drop", "heck", "slog", - "bast", "sast", - "balt", "salt", - "skib", "skis", "slib", "slis", - "save", - "hilb", "hils", "hinb", "hins" - "hilk", "hill", "hink", "hinl" - "muth", "kuth", "mutt", "kutt", - "musm", "kusm", - "mutb", "muts", "mitb", "mits", - "kutb", "kuts", "kitb", "kits", -}; +// Define X to select the opcode string representation from OPCODES. +# define X(opcode, name, indirect_jump) name +static c3_c* opcode_names[] = { OPCODES }; +# undef X #endif /* _n_apen(): emit the instructions contained in src to dst @@ -1020,10 +998,11 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) default: { return _n_comp(ops, nef, los_o, tel_o); } - + case c3__nara: + case c3__hela: case c3__bout: { u3_noun fen = u3_nul; - c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + c3_w nef_w = _n_comp(&fen, nef, los_o, c3n); // add appropriate hind opcode ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HILL : HILK); // skip over the cleanup opcode @@ -1055,10 +1034,11 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) ++tot_w; _n_emit(ops, TOSS); tot_w += _n_comp(ops, nef, los_o, tel_o); } break; - + case c3__nara: + case c3__hela: case c3__bout: { u3_noun fen = u3_nul; - c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + c3_w nef_w = _n_comp(&fen, nef, los_o, c3n); // add appropriate hind opcode ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HINL : HINK); // skip over the cleanup opcode @@ -1696,12 +1676,28 @@ u3n_find(u3_noun key, u3_noun fol) static c3_o _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { - if ( c3__bout == u3h(hin) ) { - u3_atom now = u3i_chub(u3t_trace_time()); - *out = u3i_cell(u3h(hin), now); - } - else { - *out = u3_nul; + u3_noun tag, fol; + u3x_cell(hin, &tag, &fol); + + switch ( tag ) { + case c3__bout: { + u3_atom now = u3i_chub(u3t_trace_time()); + *out = u3i_cell(tag, now); + } break; + + case c3__nara : { + u3t_slog_nara(0); + *out = u3_nul; + } break; + + case c3__hela : { + u3t_slog_hela(0); + *out = u3_nul; + } break; + + default: { + *out = u3_nul; + } break; } u3z(hin); @@ -1718,8 +1714,8 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) u3_noun p_tok, q_tok; if ( (c3y == u3r_cell(tok, &p_tok, &q_tok)) && (c3__bout == p_tok) ) { u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(q_tok)); - c3_c str_c[64]; - snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + c3_c str_c[64]; + u3a_print_time(str_c, "took", u3r_chub(0, delta)); u3t_slog(u3nc(0, u3i_string(str_c))); u3z(delta); } @@ -1742,13 +1738,41 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) static c3_o _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) { - if ( c3__bout == u3h(hin) ) { - u3_atom now = u3i_chub(u3t_trace_time()); - *clu = u3i_trel(u3h(hin), *clu, now); - } - else { - u3z(*clu); - *clu = u3_nul; + u3_noun tag, fol; + u3x_cell(hin, &tag, &fol); + + switch ( tag ) { + case c3__bout: { + u3_atom now = u3i_chub(u3t_trace_time()); + *clu = u3nt(u3k(tag), *clu, now); + } break; + + case c3__nara: { + u3_noun pri, tan; + if ( c3y == u3r_cell(*clu, &pri, &tan) ) { + c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0; + u3t_slog_cap(pri_l, u3i_string("trace of"), u3k(tan)); + u3t_slog_nara(pri_l); + } + u3z(*clu); + *clu = u3_nul; + } break; + + case c3__hela: { + u3_noun pri, tan; + if ( c3y == u3r_cell(*clu, &pri, &tan) ) { + c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0; + u3t_slog_cap(pri_l, u3i_string("trace of"), u3k(tan)); + u3t_slog_hela(pri_l); + } + u3z(*clu); + *clu = u3_nul; + } break; + + default: { + u3z(*clu); + *clu = u3_nul; + } break; } u3z(hin); @@ -1763,9 +1787,7 @@ static void _n_hint_hind(u3_noun tok, u3_noun pro) { u3_noun p_tok, q_tok, r_tok; - if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok)) - && (c3__bout == p_tok) ) - { + if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok)) && (c3__bout == p_tok) ) { // get the microseconds elapsed u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok)); @@ -1776,23 +1798,14 @@ _n_hint_hind(u3_noun tok, u3_noun pro) // format the timing report c3_c str_c[64]; - snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + u3a_print_time(str_c, "took", u3r_chub(0, delta)); // join the timing report with the original tank from q_q_tok like so: // "q_q_tok: report" // prepend the priority to form a cell of the same shape q_tok // send this to ut3_slog so that it can be logged out - u3t_slog( - u3nc( - u3k(p_q_tok), - u3nt( - c3__rose, - u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul), - u3nt(u3k(q_q_tok), u3i_string(str_c), u3_nul) - ) - ) - ); - + c3_l pri_l = c3y == u3a_is_cat(p_q_tok) ? p_q_tok : 0; + u3t_slog_cap(pri_l, u3k(q_q_tok), u3i_string(str_c)); u3z(delta); } else { @@ -1838,40 +1851,12 @@ typedef struct { static u3_noun _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) { - /* OPCODE TABLE */ - static void* lab[] = { - &&do_halt, &&do_bail, - &&do_copy, &&do_swap, &&do_toss, - &&do_auto, &&do_ault, &&do_snoc, &&do_snol, - &&do_head, &&do_held, &&do_tail, &&do_tall, - &&do_fabk, &&do_fask, &&do_fibk, &&do_fisk, - &&do_fabl, &&do_fasl, &&do_fibl, &&do_fisl, - &&do_lit0, &&do_lit1, &&do_litb, &&do_lits, - &&do_libk, &&do_lisk, - &&do_lil0, &&do_lil1, &&do_lilb, &&do_lils, - &&do_libl, &&do_lisl, - &&do_nolk, &&do_noct, &&do_nock, - &&do_deep, &&do_bump, - &&do_sam0, &&do_sam1, &&do_samb, &&do_sams, - &&do_sanb, &&do_sans, - &&do_same, &&do_salm, &&do_samc, - &&do_sbip, &&do_sips, &&do_swip, - &&do_sbin, &&do_sins, &&do_swin, - &&do_kicb, &&do_kics, &&do_ticb, &&do_tics, - &&do_wils, &&do_wish, - &&do_bush, &&do_sush, - &&do_drop, &&do_heck, &&do_slog, - &&do_bast, &&do_sast, - &&do_balt, &&do_salt, - &&do_skib, &&do_skis, &&do_slib, &&do_slis, - &&do_save, - &&do_hilb, &&do_hils, &&do_hinb, &&do_hins, - &&do_hilk, &&do_hill, &&do_hink, &&do_hinl, - &&do_muth, &&do_kuth, &&do_mutt, &&do_kutt, - &&do_musm, &&do_kusm, - &&do_mutb, &&do_muts, &&do_mitb, &&do_mits, - &&do_kutb, &&do_kuts, &&do_kitb, &&do_kits, - }; + + // Opcode jump table. Define X to select the opcode computed goto from + // OPCODES. +# define X(opcode, name, indirect_jump) indirect_jump + static void* lab[] = { OPCODES }; +# undef X u3j_site* sit_u; u3j_rite* rit_u; diff --git a/pkg/urbit/noun/trace.c b/pkg/urbit/noun/trace.c index 1ee8168c70..79d290930d 100644 --- a/pkg/urbit/noun/trace.c +++ b/pkg/urbit/noun/trace.c @@ -282,13 +282,13 @@ u3t_trace_open(c3_c* dir_c) struct stat st; if ( -1 == stat(fil_c, &st) ) { - mkdir(fil_c, 0700); + c3_mkdir(fil_c, 0700); } c3_c lif_c[2056]; snprintf(lif_c, 2056, "%s/%d.json", fil_c, u3_Host.tra_u.fun_w); - u3_Host.tra_u.fil_u = fopen(lif_c, "w"); + u3_Host.tra_u.fil_u = c3_fopen(lif_c, "w"); u3_Host.tra_u.nid_w = (int)getpid(); fprintf(u3_Host.tra_u.fil_u, "[ "); @@ -589,3 +589,87 @@ u3t_boff(void) #endif } } + + +/* u3t_slog_cap(): slog a tank with a caption with +** a given priority c3_l (assumed 0-3). +*/ +void +u3t_slog_cap(c3_l pri_l, u3_noun cap, u3_noun tan) +{ + u3t_slog( + u3nc( + pri_l, + u3nt( + c3__rose, + u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul), + u3nt(cap, tan, u3_nul) + ) + ) + ); +} + + +/* u3t_slog_trace(): given a c3_l priority pri and a raw stack tax +** flop the order into start-to-end, render, and slog each item +** until done. +*/ +void +u3t_slog_trace(c3_l pri_l, u3_noun tax) +{ + // render the stack + // Note: ton is a reference to a data struct + // we have just allocated + // lit is a used as a moving cursor pointer through + // that allocated struct + // once we finish lit will be null, but ton will still + // point to the whole valid allocated data structure + // and thus we can free it safely at the end of the func + // to clean up after ourselves. + // Note: flop reverses the stack trace list 'tax' + u3_noun ton = u3dc("mook", 2, u3kb_flop(tax)); + u3_noun lit = u3t(ton); + + // print the stack one stack item at a time + while ( u3_nul != lit ) { + u3t_slog(u3nc(pri_l, u3k(u3h(lit)) )); + lit = u3t(lit); + } + + u3z(ton); +} + + +/* u3t_slog_nara(): slog only the deepest road's trace with +** c3_l priority pri +*/ +void +u3t_slog_nara(c3_l pri_l) +{ + u3_noun tax = u3k(u3R->bug.tax); + u3t_slog_trace(pri_l, tax); +} + + +/* u3t_slog_hela(): join all roads' traces together into one tax +** and pass it to slog_trace along with the given c3_l priority pri_l +*/ +void +u3t_slog_hela(c3_l pri_l) +{ + // rod_u protects us from mutating the global state + u3_road* rod_u = u3R; + + // inits to the the current road's trace + u3_noun tax = u3k(rod_u->bug.tax); + + // while there is a parent road ref ... + while ( &(u3H->rod_u) != rod_u ) { + // ... point at the next road and append its stack to tax + rod_u = u3tn(u3_road, rod_u->par_p); + tax = u3kb_weld(tax, u3k(rod_u->bug.tax)); + } + + u3t_slog_trace(pri_l, tax); +} + diff --git a/pkg/urbit/noun/urth.c b/pkg/urbit/noun/urth.c index f6df4910f6..30ab448173 100644 --- a/pkg/urbit/noun/urth.c +++ b/pkg/urbit/noun/urth.c @@ -509,7 +509,7 @@ _cu_rock_path_make(c3_c* dir_c, c3_d eve_d, c3_c** out_c) return c3n; } - if ( mkdir(nam_c, 0700) + if ( c3_mkdir(nam_c, 0700) && (EEXIST != errno) ) { fprintf(stderr, "rock: directory create failed (%s, %" PRIu64 "): %s\r\n", @@ -552,8 +552,8 @@ _cu_rock_save(c3_c* dir_c, c3_d eve_d, c3_d len_d, c3_y* byt_y) return c3n; } - if ( -1 == (fid_i = open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { - fprintf(stderr, "rock: open failed (%s, %" PRIu64 "): %s\r\n", + if ( -1 == (fid_i = c3_open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { + fprintf(stderr, "rock: c3_open failed (%s, %" PRIu64 "): %s\r\n", dir_c, eve_d, strerror(errno)); c3_free(nam_c); return c3n; @@ -691,8 +691,8 @@ u3u_mmap_read(c3_c* cap_c, c3_c* pat_c, c3_d* out_d, c3_y** out_y) // open file // - if ( -1 == (fid_i = open(pat_c, O_RDONLY, 0644)) ) { - fprintf(stderr, "%s: open failed (%s): %s\r\n", + if ( -1 == (fid_i = c3_open(pat_c, O_RDONLY, 0644)) ) { + fprintf(stderr, "%s: c3_open failed (%s): %s\r\n", cap_c, pat_c, strerror(errno)); return c3n; } @@ -744,8 +744,8 @@ u3u_mmap(c3_c* cap_c, c3_c* pat_c, c3_d len_d, c3_y** out_y) // open file // - if ( -1 == (fid_i = open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { - fprintf(stderr, "%s: open failed (%s): %s\r\n", + if ( -1 == (fid_i = c3_open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { + fprintf(stderr, "%s: c3_open failed (%s): %s\r\n", cap_c, pat_c, strerror(errno)); return c3n; } @@ -895,7 +895,7 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d) // leave rocks on disk // - // if ( 0 != unlink(nam_c) ) { + // if ( 0 != c3_unlink(nam_c) ) { // fprintf(stderr, "uncram: failed to delete rock (%s, %" PRIu64 "): %s\r\n", // dir_c, eve_d, strerror(errno)); // c3_free(nam_c); diff --git a/pkg/urbit/noun/vortex.c b/pkg/urbit/noun/vortex.c index acf7eea9d2..03d174e1fc 100644 --- a/pkg/urbit/noun/vortex.c +++ b/pkg/urbit/noun/vortex.c @@ -184,6 +184,29 @@ _cv_time_bump(u3_reck* rec_u) } #endif +/* u3v_lily(): parse little atom. +*/ +c3_o +u3v_lily(u3_noun fot, u3_noun txt, c3_l* tid_l) +{ + c3_w wad_w; + u3_noun uco = u3dc("slaw", fot, u3k(txt)); + u3_noun p_uco, q_uco; + + if ( (c3n == u3r_cell(uco, &p_uco, &q_uco)) || + (u3_nul != p_uco) || + (c3n == u3r_safe_word(q_uco, &wad_w)) || + (wad_w & 0x80000000) ) + { + u3l_log("strange lily %s\n", u3r_string(txt)); + u3z(txt); u3z(uco); return c3n; + } + else { + *tid_l = (c3_l)wad_w; + u3z(txt); u3z(uco); return c3y; + } +} + /* u3v_peek(): query the reck namespace (protected). */ u3_noun @@ -193,54 +216,6 @@ u3v_peek(u3_noun sam) return u3n_slam_on(fun, sam); } -#if 0 -/* _cv_mole(): parse simple atomic mole. -*/ -static c3_o -_cv_mole(u3_noun fot, - u3_noun san, - c3_d* ato_d) -{ - u3_noun uco = u3do("slay", san); - u3_noun p_uco, q_uco, r_uco, s_uco; - - if ( (c3n == u3r_qual(uco, &p_uco, &q_uco, &r_uco, &s_uco)) || - (0 != p_uco) || - (0 != q_uco) || - (c3n == u3r_sing(fot, r_uco)) ) - { - u3l_log("strange mole %s\n", u3r_string(san))); - - u3z(fot); u3z(uco); return c3n; - } - else { - *ato_d = u3r_chub(0, s_uco); - - u3z(fot); u3z(uco); return c3y; - } -} - -/* _cv_lily(): parse little atom. -*/ -static c3_o -_cv_lily(u3_noun fot, u3_noun txt, c3_l* tid_l) -{ - c3_d ato_d; - - if ( c3n == _cv_mole(fot, txt, &ato_d) ) { - return c3n; - } else { - if ( ato_d >= 0x80000000ULL ) { - return c3n; - } else { - *tid_l = (c3_l) ato_d; - - return c3y; - } - } -} -#endif - /* u3v_poke(): insert and apply an input ovum (protected). */ u3_noun diff --git a/pkg/urbit/tests/newt_tests.c b/pkg/urbit/tests/newt_tests.c index 2c6b174a2e..043151784b 100644 --- a/pkg/urbit/tests/newt_tests.c +++ b/pkg/urbit/tests/newt_tests.c @@ -18,18 +18,18 @@ _newt_encode(u3_atom mat, c3_w* len_w) c3_w met_w = u3r_met(3, mat); c3_y* buf_y; - *len_w = 8 + met_w; + *len_w = 5 + met_w; buf_y = c3_malloc(*len_w); - // write header; c3_d is futureproofing + // write header // - buf_y[0] = ((met_w >> 0) & 0xff); - buf_y[1] = ((met_w >> 8) & 0xff); - buf_y[2] = ((met_w >> 16) & 0xff); - buf_y[3] = ((met_w >> 24) & 0xff); - buf_y[4] = buf_y[5] = buf_y[6] = buf_y[7] = 0; + buf_y[0] = 0x0; + buf_y[1] = ( met_w & 0xff); + buf_y[2] = ((met_w >> 8) & 0xff); + buf_y[3] = ((met_w >> 16) & 0xff); + buf_y[4] = ((met_w >> 24) & 0xff); - u3r_bytes(0, met_w, buf_y + 8, mat); + u3r_bytes(0, met_w, buf_y + 5, mat); u3z(mat); return buf_y; diff --git a/pkg/urbit/tests/noun_tests.c b/pkg/urbit/tests/noun_tests.c index b7233b1f49..b84b618652 100644 --- a/pkg/urbit/tests/noun_tests.c +++ b/pkg/urbit/tests/noun_tests.c @@ -1,4 +1,7 @@ #include "all.h" +#include "ur/ur.h" +#include "vere/ivory.h" +#include "vere/vere.h" #define TRUE 1 #define FALSE 0 @@ -8,8 +11,23 @@ static void _setup(void) { - u3m_init(); - u3m_pave(c3y); + c3_d len_d = u3_Ivory_pill_len; + c3_y* byt_y = u3_Ivory_pill; + u3_cue_xeno* sil_u; + u3_weak pil; + + u3C.wag_w |= u3o_hashless; + u3m_boot_lite(); + sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { + printf("*** fail _setup 1\n"); + exit(1); + } + u3s_cue_xeno_done(sil_u); + if ( c3n == u3v_boot_lite(pil) ) { + printf("*** fail _setup 2\n"); + exit(1); + } } /* _util_rand_string(): dynamically allocated len_w random string @@ -1634,6 +1652,33 @@ _test_nvm_stack() #endif } +/* _test_lily(): test small noun parsing. +*/ +static void +_test_lily() +{ + c3_l lit_l; + c3_w big_w[] = {0, 0, 1}; + u3_noun big = u3i_words(3, big_w); + u3_noun cod = u3dc("scot", c3__uv, big); + + if ( c3y == u3v_lily(c3__uv, cod, &lit_l) ) { + printf("*** fail _test_lily-1\n"); + exit(1); + } + cod = u3dc("scot", c3__ud, 0x7fffffff); + if ( (c3n == u3v_lily(c3__ud, cod, &lit_l)) || + (0x7fffffff != lit_l) ) { + printf("*** fail _test_lily-2a\n"); + exit(1); + } + cod = u3dc("scot", c3__ux, u3i_word(0x80000000)); + if ( c3y == u3v_lily(c3__ux, cod, &lit_l) ) { + printf("*** fail _test_lily-2b\n"); + exit(1); + } +} + /* main(): run all test cases. */ int @@ -1653,6 +1698,7 @@ main(int argc, char* argv[]) _test_cells_complex(); _test_u3r_at(); _test_nvm_stack(); + _test_lily(); fprintf(stderr, "test_noun: ok\n"); diff --git a/pkg/urbit/tests/unix_tests.c b/pkg/urbit/tests/unix_tests.c new file mode 100644 index 0000000000..ca247f5ef0 --- /dev/null +++ b/pkg/urbit/tests/unix_tests.c @@ -0,0 +1,65 @@ +#include "all.h" +#include "vere/vere.h" + +/* _setup(): prepare for tests. +*/ +static void +_setup(void) +{ +} + +/* _test_safe(): +*/ +static c3_i +_test_safe() +{ + c3_i ret_i = 1; + + if ( !u3_unix_cane("/") || + !u3_unix_cane("~.") || + !u3_unix_cane("a") || + !u3_unix_cane("a/b") || + !u3_unix_cane("a/b/c/defg/h/ijklmnop") ) + { + fprintf(stderr, "_safe fail 1\n"); + ret_i = 0; + } + + if ( u3_unix_cane("") || + u3_unix_cane(".") || + u3_unix_cane("..") || + u3_unix_cane("/.") || + u3_unix_cane("a/b/c//") || + u3_unix_cane("a/b/.") || + u3_unix_cane("/././../.") || + u3_unix_cane("/../etc") ) + { + fprintf(stderr, "_safe fail 2\r\n"); + ret_i = 0; + } + + if ( !u3_unix_cane(".a") || + !u3_unix_cane("/.a.b.c/..c") ) + { + fprintf(stderr, "_safe fail 3\r\n"); + ret_i = 0; + } + + return ret_i; +} + +/* main(): run all test cases. +*/ +int +main(int argc, char* argv[]) +{ + _setup(); + + if ( !_test_safe() ) { + fprintf(stderr, "test unix: failed\r\n"); + exit(1); + } + + fprintf(stderr, "test unix: ok\r\n"); + return 0; +} diff --git a/pkg/urbit/vere/auto.c b/pkg/urbit/vere/auto.c index 5a56d22bc4..c03cd93e28 100644 --- a/pkg/urbit/vere/auto.c +++ b/pkg/urbit/vere/auto.c @@ -353,10 +353,26 @@ u3_auto_exit(u3_auto* car_u) } } -/* u3_auto_info(): print status info. +/* u3_auto_info(): status info as a (list mass), all drivers. +*/ +u3_noun +u3_auto_info(u3_auto* car_u) +{ + u3_noun lit = u3_nul; + + while ( car_u ) { + if ( car_u->io.info_f ) { + lit = u3nc(u3_pier_mass(car_u->nam_m, car_u->io.info_f(car_u)), lit); + } + car_u = car_u->nex_u; + } + return u3kb_flop(lit); +} + +/* u3_auto_slog(): print status info. */ void -u3_auto_info(u3_auto* car_u) +u3_auto_slog(u3_auto* car_u) { u3_auto* nex_u; @@ -373,9 +389,9 @@ u3_auto_info(u3_auto* car_u) // XX details // - if ( car_u->io.info_f ) { + if ( car_u->io.slog_f ) { c3_l cod_l = u3a_lush(car_u->nam_m); - car_u->io.info_f(car_u); + car_u->io.slog_f(car_u); u3a_lop(cod_l); } @@ -388,7 +404,13 @@ u3_auto_info(u3_auto* car_u) static u3_auto* _auto_link(u3_auto* car_u, u3_pier* pir_u, u3_auto* nex_u) { - // assert that io callbacks are present (info_f is optional) + // skip null drivers + // + if ( !car_u ) { + return nex_u; + } + + // assert that io callbacks are present (info_f and slog_f are optional) // c3_assert( car_u->io.talk_f ); c3_assert( car_u->io.kick_f ); @@ -408,6 +430,7 @@ u3_auto_init(u3_pier* pir_u) car_u = _auto_link(u3_hind_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_behn_io_init(pir_u), pir_u, car_u); + car_u = _auto_link(u3_conn_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_ames_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_http_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_cttp_io_init(pir_u), pir_u, car_u); diff --git a/pkg/urbit/vere/dawn.c b/pkg/urbit/vere/dawn.c index 6ad2963411..ca6eb31a76 100644 --- a/pkg/urbit/vere/dawn.c +++ b/pkg/urbit/vere/dawn.c @@ -462,7 +462,7 @@ _dawn_come(u3_noun stars) c3_c pat_c[64]; snprintf(pat_c, 64, "%s.key", who_c + 1); - FILE* fil_u = fopen(pat_c, "w"); + FILE* fil_u = c3_fopen(pat_c, "w"); fprintf(fil_u, "%s\n", key_c); fclose(fil_u); } diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index 4ef09546d5..8a17b397c5 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -585,6 +585,94 @@ u3_disk_read_meta(u3_disk* log_u, return c3y; } +/* _disk_lock(): lockfile path. +*/ +static c3_c* +_disk_lock(c3_c* pax_c) +{ + c3_w len_w = strlen(pax_c) + sizeof("/.vere.lock"); + c3_c* paf_c = c3_malloc(len_w); + c3_i wit_i; + + wit_i = snprintf(paf_c, len_w, "%s/.vere.lock", pax_c); + c3_assert(wit_i + 1 == len_w); + return paf_c; +} + +/* u3_disk_acquire(): acquire a lockfile, killing anything that holds it. +*/ +static void +u3_disk_acquire(c3_c* pax_c) +{ + c3_c* paf_c = _disk_lock(pax_c); + c3_w pid_w; + FILE* loq_u; + + if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) { + if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { + u3l_log("lockfile %s is corrupt!\n", paf_c); + kill(getpid(), SIGTERM); + sleep(1); c3_assert(0); + } + else if (pid_w != getpid()) { + c3_w i_w; + + if ( -1 != kill(pid_w, SIGTERM) ) { + u3l_log("disk: stopping process %d, live in %s...\n", + pid_w, pax_c); + + for ( i_w = 0; i_w < 16; i_w++ ) { + sleep(1); + if ( -1 == kill(pid_w, SIGTERM) ) { + break; + } + } + if ( 16 == i_w ) { + for ( i_w = 0; i_w < 16; i_w++ ) { + if ( -1 == kill(pid_w, SIGKILL) ) { + break; + } + sleep(1); + } + } + if ( 16 == i_w ) { + u3l_log("disk: process %d seems unkillable!\n", pid_w); + c3_assert(0); + } + u3l_log("disk: stopped old process %u\n", pid_w); + } + } + fclose(loq_u); + c3_unlink(paf_c); + } + + if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) { + u3l_log("disk: unable to open %s\n", paf_c); + c3_assert(0); + } + + fprintf(loq_u, "%u\n", getpid()); + + { + c3_i fid_i = fileno(loq_u); + c3_sync(fid_i); + } + + fclose(loq_u); + c3_free(paf_c); +} + +/* u3_disk_release(): release a lockfile. +*/ +static void +u3_disk_release(c3_c* pax_c) +{ + c3_c* paf_c = _disk_lock(pax_c); + + c3_unlink(paf_c); + c3_free(paf_c); +} + /* u3_disk_exit(): close the log. */ void @@ -633,6 +721,8 @@ u3_disk_exit(u3_disk* log_u) } } + u3_disk_release(log_u->dir_u->pax_c); + u3_dire_free(log_u->dir_u); u3_dire_free(log_u->urb_u); u3_dire_free(log_u->com_u); @@ -644,10 +734,48 @@ u3_disk_exit(u3_disk* log_u) #endif } -/* u3_disk_info(): print status info. +/* u3_disk_info(): status info as a (list mass). +*/ +u3_noun +u3_disk_info(u3_disk* log_u) +{ + u3_read* red_u = log_u->red_u; + u3_noun red = u3_nul; + u3_noun lit = u3i_list( + u3_pier_mase("live", log_u->liv_o), + u3_pier_mase("event", u3i_chub(log_u->dun_d)), + u3_none); + + if ( log_u->put_u.ext_u ) { + lit = u3nc( + u3_pier_mass( + c3__save, + u3i_list( + u3_pier_mase("save-start", u3i_chub(log_u->put_u.ext_u->eve_d)), + u3_pier_mase("save-final", u3i_chub(log_u->put_u.ent_u->eve_d)), + u3_none)), + lit); + } + + while ( red_u ) { + red = u3nc( + u3_pier_mass( + u3dc("scot", c3__ux, u3i_chub((c3_d)red_u)), + u3i_list( + u3_pier_mase("start", u3i_chub(red_u->eve_d)), + u3_pier_mase("final", u3i_chub(red_u->eve_d + red_u->len_d - 1)), + u3_none)), + red); + red_u = red_u->nex_u; + } + lit = u3nc(u3_pier_mass(c3__read, red), lit); + return u3_pier_mass(c3__disk, lit); +} + +/* u3_disk_slog(): print status info. */ void -u3_disk_info(u3_disk* log_u) +u3_disk_slog(u3_disk* log_u) { u3l_log(" disk: live=%s, event=%" PRIu64 "\n", ( c3y == log_u->liv_o ) ? "&" : "|", @@ -660,6 +788,7 @@ u3_disk_info(u3_disk* log_u) u3l_log(" read: %" PRIu64 "-%" PRIu64 "\n", red_u->eve_d, (red_u->eve_d + red_u->len_d) - 1); + red_u = red_u->nex_u; } } @@ -697,6 +826,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } } + // acquire lockfile. + // + u3_disk_acquire(pax_c); + // create/load $pier/.urb // { @@ -721,11 +854,11 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) strcpy(dir_c, pax_c); strcat(dir_c, "/.urb/put"); - mkdir(dir_c, 0700); + c3_mkdir(dir_c, 0700); strcpy(dir_c, pax_c); strcat(dir_c, "/.urb/get"); - mkdir(dir_c, 0700); + c3_mkdir(dir_c, 0700); c3_free(dir_c); } @@ -751,10 +884,11 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // "[..] on 64-bit there is no penalty for making this huge (say 1TB)." // { + const size_t siz_i = #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) || defined(U3_OS_mingw) - const size_t siz_i = 64424509440; + 0xf00000000; #else - const size_t siz_i = 1099511627776; + 0x10000000000; #endif if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 1773e02ed1..400bca7ad3 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1488,15 +1488,41 @@ _ames_io_exit(u3_auto* car_u) uv_close(&sam_u->had_u, _ames_exit_cb); } -/* _ames_io_info(): print status info. +/* _ames_io_info(): produce status info. +*/ +static u3_noun +_ames_io_info(u3_auto* car_u) +{ + u3_ames* sam_u = (u3_ames*)car_u; + + return u3i_list( + u3_pier_mase("filtering", sam_u->fig_u.fit_o), + u3_pier_mase("can-send", sam_u->fig_u.net_o), + u3_pier_mase("can-scry", sam_u->fig_u.see_o), + u3_pier_mase("dropped", u3i_chub(sam_u->sat_u.dop_d)), + u3_pier_mase("forwards-dropped", u3i_chub(sam_u->sat_u.fod_d)), + u3_pier_mase("forwards-pending", u3i_chub(sam_u->sat_u.foq_d)), + u3_pier_mase("forwarded", u3i_chub(sam_u->sat_u.fow_d)), + u3_pier_mase("filtered-hed", u3i_chub(sam_u->sat_u.hed_d)), + u3_pier_mase("filtered-ver", u3i_chub(sam_u->sat_u.vet_d)), + u3_pier_mase("filtered-mug", u3i_chub(sam_u->sat_u.mut_d)), + u3_pier_mase("filtered-bod", u3i_chub(sam_u->sat_u.bod_d)), + u3_pier_mase("crashed", u3i_chub(sam_u->sat_u.fal_d)), + u3_pier_mase("cached-lanes", u3i_word(u3h_wyt(sam_u->lax_p))), + u3_none); +} + +/* _ames_io_slog(): print status info. */ static void -_ames_io_info(u3_auto* car_u) +_ames_io_slog(u3_auto* car_u) { u3_ames* sam_u = (u3_ames*)car_u; # define FLAG(a) ( (c3y == a) ? "&" : "|" ) + // TODO rewrite in terms of info_f + // u3l_log(" config:\n"); u3l_log(" filtering: %s\n", FLAG(sam_u->fig_u.fit_o)); u3l_log(" can send: %s\n", FLAG(sam_u->fig_u.net_o)); @@ -1559,6 +1585,7 @@ u3_ames_io_init(u3_pier* pir_u) car_u->liv_o = c3n; car_u->io.talk_f = _ames_io_talk; car_u->io.info_f = _ames_io_info; + car_u->io.slog_f = _ames_io_slog; car_u->io.kick_f = _ames_io_kick; car_u->io.exit_f = _ames_io_exit; diff --git a/pkg/urbit/vere/io/behn.c b/pkg/urbit/vere/io/behn.c index c9394564e1..45a4347738 100644 --- a/pkg/urbit/vere/io/behn.c +++ b/pkg/urbit/vere/io/behn.c @@ -189,7 +189,8 @@ _behn_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) if ( (c3n == u3r_cell(wir, &i_wir, 0)) || (c3n == u3r_cell(cad, &tag, &dat)) - || (c3__behn != i_wir) ) + || (c3__behn != i_wir) + || (c3__doze != tag) ) { ret_o = c3n; } diff --git a/pkg/urbit/vere/io/conn.c b/pkg/urbit/vere/io/conn.c new file mode 100644 index 0000000000..ab717dd1ea --- /dev/null +++ b/pkg/urbit/vere/io/conn.c @@ -0,0 +1,920 @@ +/* vere/conn.c +** +** implements the control plane: a socket that can be used to +** query and interact with an urbit ship from earth. +** +** the control plane nominally consumes input described by: +** +** $: request-id=@ :: id for response +** $% [%fyrd fyrd-args=*] :: run a thread +** [%peek peek-args=*] :: scry +** [%peel peel-args=*] :: runtime peek +** [%ovum ovum-args=*] :: inject raw ovum +** [%urth urth-args=*] :: runtime command +** == == :: +** +** request-id is a client-supplied atomic identifier that will +** be returned along with the response, to allow correlating +** responses with requests. +** +** responses are [request-id=@ data=*]. if the driver encounters +** an error, then it will try to send a %bail response with +** request-id set to 0, i.e.: +** +** [0 %bail error-code=@ error-string=@t] +** +** and subsequently close the connection. +** +** %fyrd is a request to run a thread. its arguments are +** described in the ++khan section of sys/lull.hoon. to +** summarize: +** +** +$ task $%(... [%fyrd p=(fyrd cast)]) :: +** +$ bear $@(desk beak) :: partial $beak +** +$ cast (pair mark page) :: output mark +input +** ++ fyrd |$ [a] [=bear name=term args=a] :: thread run request +** +** the cast's mark is applied to the output. the page (untyped +** cage, or pair of mark and noun) in args contains the input +** mark. e.g. to run -hi with the ship ~zod as input, receiving +** output as a tape, with request-id set to 32, send the +jam of +** this noun over the socket with newt framing: +** +** [32 %fyrd [%base %hi %tape [%ship ~zod]]] +** +** responses to %fyrd are: +** +** +$ gift $%(... [%avow p=(avow page)]) :: +** ++ avow |$ [a] (each a goof) :: +** +** %peek is a namespace read request (aka scry), and will be +** forwarded directly to arvo. its arguments are the nom of the +** external peek interface in arvo, at arm 22. (lyc is always +** `~, i.e. request from self.) that is: +** +** $+ each path +** $% [%once vis=view syd=desk tyl=spur] +** [%beam vis=view bem=beam] +** == +** +** %peel is a runtime "peek". it exposes an unprincipled +** scry-like namespace allowing querying of various metrics +** about the state of vere. it accepts $path-like arguments, +** i.e. nul-terminated lists of $knot. it responds with a +** (unit). +** +** the %peel path /help produces a list of available commands. +** /info produces runtime metrics at the moment in time that the +** request was received. the type produced by /info is $mass: +** +** +$ mass (pair cord (each * (list mass))) +** +** where the leaves are conventionally @ud, but the +** precise interpretation depends on the metric (e.g. +** loobean settings or integer counters.) it is acceptable +** to flatten the list by prepending the parent cord +** to each child element with a separator, e.g.: +** [%pier %| [%ames %| [%packets-sent %& 37] ~] ~] could be +** rendered as 'pier-ames-packets-sent'. this transformation is +** guaranteed to result in unique names. +** +** %ovum is a raw kernel move, to be injected directly into +** arvo. needless to say this will void your warranty. usually +** you want to use %fyrd instead. an update will be sent: %done +** on successful completion, %bail with a stack trace on error, +** or %drop if the ovum is dropped. +** +** %urth is a command for the runtime. these are acked with %.y +** on receipt. no further updates are provided. +** +** messages use newt framing. because the framing begins with +** a tag byte, any messages that do not contain that byte are +** reserved for future use. +** +*/ +#include +#include +#include +#include +#include +#include + +#include "all.h" +#include "vere/vere.h" + +/* u3_cran: control plane request. +*/ + typedef struct _u3_cran { + u3_atom rid; // client-supplied request id + struct _u3_chan* can_u; // connection backpointer + struct _u3_cran* nex_u; // next pointer + } u3_cran; + +/* u3_chan: incoming control plane connection. +*/ + typedef struct _u3_chan { + struct _u3_moor mor_u; // message handler + c3_l coq_l; // connection number + c3_o liv_o; // connection live + struct _u3_shan* san_u; // server backpointer + struct _u3_cran* ran_u; // request list + } u3_chan; + +/* u3_shan: control plane server. +*/ + typedef struct _u3_shan { + uv_pipe_t pyp_u; // server stream handler + c3_l nex_l; // next connection number + struct _u3_conn* con_u; // device backpointer + struct _u3_chan* can_u; // connection list + } u3_shan; + +/* u3_conn: control plane device. +*/ + typedef struct _u3_conn { + u3_auto car_u; // driver + c3_l sev_l; // instance number + struct _u3_shan* san_u; // server reference + u3_cue_xeno* sil_u; // cue handle + c3_o kan_o; // %khan present? + } u3_conn; + +static const c3_c URB_SOCK_PATH[] = ".urb/conn.sock"; + +/* _conn_close_cb(): socket close callback. +*/ +static void +_conn_close_cb(uv_handle_t* had_u) +{ + c3_free(had_u); +} + +/* _conn_mote_free(): u3_moat-shaped close callback. +*/ +static void +_conn_moat_free(void* ptr_v, ssize_t err_i, const c3_c* err_c) +{ + c3_free(ptr_v); +} + +/* _conn_send_noun(): jam and send noun over chan. +*/ +static void +_conn_send_noun(u3_chan* can_u, u3_noun nun) +{ + c3_y* byt_y; + c3_d len_d; + + u3s_jam_xeno(nun, &len_d, &byt_y); + u3z(nun); + u3_newt_send((u3_mojo*)&can_u->mor_u, len_d, byt_y); +} + +/* _conn_find_chan(): lookup channel by connection number. +*/ +static u3_chan* +_conn_find_chan(u3_conn* con_u, c3_l sev_l, c3_l coq_l) +{ + u3_chan* ret_u; + + for ( ret_u = con_u->san_u->can_u; + ret_u; + ret_u = (u3_chan*)ret_u->mor_u.nex_u ) { + if ( coq_l == ret_u->coq_l ) { + return ret_u; + } + } + return 0; +} + +/* _conn_read_wire(): check tag, decompose wire into /sev/coq/rid +*/ +static c3_o +_conn_read_wire(u3_noun wir, + c3_l tag_l, + c3_l* sev_l, + c3_l* coq_l, + u3_atom* rid) +{ + u3_noun i_wir, t_wir; + + if ( (c3n == u3r_cell(wir, &i_wir, &t_wir)) || + (tag_l != i_wir) ) + { + u3z(wir); return c3n; + } + else { + u3_noun pud = t_wir; + u3_noun p_pud, t_pud, tt_pud, q_pud, r_pud, s_pud, + uco, p_uco, q_uco; + + if ( (c3n == u3r_cell(pud, &p_pud, &t_pud)) || + (c3n == u3v_lily(c3__uv, u3k(p_pud), sev_l)) ) + { + u3z(wir); return c3n; + } + if ( u3_nul == t_pud ) { + *coq_l = 0; *rid = 0; + } + else { + if ( (c3n == u3r_cell(t_pud, &q_pud, &tt_pud)) || + (c3n == u3v_lily(c3__ud, u3k(q_pud), coq_l)) ) + { + u3z(wir); return c3n; + } + if ( u3_nul == tt_pud ) { + *rid = 0; + } + else { + if ( (c3n == u3r_cell(tt_pud, &r_pud, &s_pud)) || + (u3_nul != s_pud) || + (c3n == u3ud(r_pud)) ) + { + u3z(wir); return c3n; + } + uco = u3dc("slaw", c3__uv, u3k(r_pud)); + if ( (c3n == u3r_cell(uco, &p_uco, &q_uco)) || + (u3_nul != p_uco) ) + { + u3z(uco); u3z(wir); return c3n; + } + *rid = u3k(q_uco); + u3z(uco); + } + } + u3z(wir); return c3y; + } +} + +/* _conn_poke_bail(): error function on failed %fyrd. +*/ +static void +_conn_poke_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3_conn* con_u = (u3_conn*)egg_u->car_u; + u3_chan* can_u; + u3_noun wir = egg_u->wir; + c3_l sev_l, coq_l; + u3_atom rid; + + u3_auto_bail_slog(egg_u, u3k(lud)); + if ( (c3n == _conn_read_wire(u3k(wir), c3__khan, &sev_l, &coq_l, &rid)) || + (con_u->sev_l != sev_l) ) + { + // wtf? + // + c3_assert(!"not reached"); + u3z(lud); return; + } + can_u = _conn_find_chan(con_u, sev_l, coq_l); + if ( can_u ) { + _conn_send_noun(can_u, u3nt(rid, c3__bail, lud)); + } + else { + u3z(rid); u3z(lud); + } + u3_ovum_free(egg_u); +} + +/* _conn_close_chan(): close given channel, freeing. +*/ +static void +_conn_close_chan(u3_shan* san_u, u3_chan* can_u) +{ + u3_conn* con_u = san_u->con_u; + u3_chan* inn_u; + u3_cran* ran_u; + + // unset chan on all pending requests. + // + for ( ran_u = can_u->ran_u; ran_u; ran_u = ran_u->nex_u ) { + ran_u->can_u = 0; + } + + // remove chan from server's connection list. + // + if ( san_u->can_u == can_u ) { + san_u->can_u = (u3_chan*)can_u->mor_u.nex_u; + } + else { + for ( inn_u = san_u->can_u; inn_u; inn_u = (u3_chan*)inn_u->mor_u.nex_u ) { + if ( (u3_chan*)inn_u->mor_u.nex_u == can_u ) { + inn_u->mor_u.nex_u = can_u->mor_u.nex_u; + break; + } + } + } + can_u->mor_u.nex_u = NULL; + + // send a close event to arvo and stop reading. + // + if ( _(con_u->kan_o) ) { + u3_noun wir, cad; + + wir = u3nq(c3__khan, + u3dc("scot", c3__uv, con_u->sev_l), + u3dc("scot", c3__ud, can_u->coq_l), + u3_nul); + cad = u3nc(c3__done, u3_nul); + u3_auto_peer( + u3_auto_plan(&con_u->car_u, + u3_ovum_init(0, c3__k, wir, cad)), + 0, 0, _conn_poke_bail); + } + u3_newt_moat_stop((u3_moat*)&can_u->mor_u, _conn_moat_free); +} + +/* _conn_moor_bail(): error callback for u3_moor. +*/ +static void +_conn_moor_bail(void* ptr_v, ssize_t err_i, const c3_c* err_c) +{ + u3_chan* can_u = (u3_chan*)ptr_v; + u3_shan* san_u = can_u->san_u; + + if ( err_i != UV_EOF ) { + u3l_log("conn: moor bail %zd %s\n", err_i, err_c); + if ( _(can_u->liv_o) ) { + _conn_send_noun(can_u, u3nq(0, c3__bail, u3i_word(err_i), + u3i_string(err_c))); + can_u->liv_o = c3n; + } + } + _conn_close_chan(san_u, can_u); +} + +/* _conn_drop_cran(): finalize/remove request from chan (does not u3z rid.) +*/ +static void +_conn_drop_cran(u3_chan* can_u, u3_cran* ran_u) +{ + u3_cran* inn_u; + + // remove from pending list, special-case for head. + // + if ( ran_u == can_u->ran_u ) { + can_u->ran_u = ran_u->nex_u; + } + else { + for ( inn_u = can_u->ran_u; inn_u; inn_u = inn_u->nex_u ) { + if ( ran_u == inn_u->nex_u ) { + inn_u->nex_u = ran_u->nex_u; + break; + } + } + } + c3_free(ran_u); +} + +/* _conn_peek_cb(): scry result handler. +*/ +static void +_conn_peek_cb(void* ptr_v, u3_noun res) +{ + u3_cran* ran_u = (u3_cran*)ptr_v; + u3_chan* can_u = ran_u->can_u; + + if ( !can_u ) { + // chan was closed; noop. + // + u3z(ran_u->rid); c3_free(ran_u); + u3z(res); return; + } + _conn_send_noun(can_u, u3nt(ran_u->rid, c3__peek, res)); + _conn_drop_cran(can_u, ran_u); +} + +/* _conn_ovum_bail(): bail callback on injected event. +*/ +static void +_conn_ovum_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3_cran* ran_u = egg_u->ptr_v; + u3_chan* can_u = ran_u->can_u; + + u3_auto_bail_slog(egg_u, u3k(lud)); + if ( !can_u ) { + // chan was closed; noop. + // + u3z(ran_u->rid); c3_free(ran_u); + u3z(lud); return; + } + _conn_send_noun(can_u, u3nt(ran_u->rid, c3__bail, lud)); + _conn_drop_cran(can_u, ran_u); + u3_ovum_free(egg_u); +} + +/* _conn_ovum_news(): lifecycle callback for injected events. +*/ +static void +_conn_ovum_news(u3_ovum* egg_u, u3_ovum_news new_e) +{ + u3_cran* ran_u = egg_u->ptr_v; + u3_chan* can_u = ran_u->can_u; + + if ( u3_ovum_done == new_e || + u3_ovum_drop == new_e ) + { + if ( can_u ) { + _conn_send_noun(can_u, + u3nt(ran_u->rid, c3__news, + ( u3_ovum_done == new_e + ? c3__done + : c3__drop ))); + _conn_drop_cran(can_u, ran_u); + } + else { + u3z(ran_u->rid); c3_free(ran_u); + } + } +} + +/* _conn_read_peel(): response to a %peel request, sans rid. +*/ +static u3_noun +_conn_read_peel(u3_conn* con_u, u3_noun dat) +{ + u3_pier* pir_u = con_u->car_u.pir_u; + u3_noun i_dat, t_dat, it_dat, tt_dat; + u3_noun res; + + if ( c3n == u3r_cell(dat, &i_dat, &t_dat) ) { + res = u3_nul; + } + else if ( u3_nul == t_dat ) { + // zero-argument requests. + // + switch (i_dat) { + default: { + res = u3_nul; + } break; + // command list. + // + case c3__help: { + res = u3nc( + u3_nul, + u3i_list(u3nc(c3__help, u3_nul), u3nc(c3__info, u3_nul), + u3nc(c3__khan, u3_nul), u3nc(c3__live, u3_nul), + u3nc(c3__mass, u3_nul), + u3nc(c3__port, + u3i_list(c3__ames, c3__htls, c3__http, u3_none)), + u3nc(c3__v, u3_nul), u3nc(c3__who, u3_nul), + u3_none)); + } break; + // simple health check. + // + case c3__live: { + res = u3nc(u3_nul, pir_u->liv_o); + } break; + // true iff the %khan vane is live (meaning %fyrd is supported.) + // + case c3__khan: { + res = u3nc(u3_nul, con_u->kan_o); + } break; + // |mass output + // + case c3__mass: { + // TODO |mass + // + res = u3_nul; + } break; + // runtime metrics. + // + case c3__info: { + res = u3nc(u3_nul, u3_pier_info(pir_u)); + } break; + // vere version. + // + case c3__v: { + res = u3nc(u3_nul, u3i_string(URBIT_VERSION)); + } break; + // current ship. + // + case c3__who: { + res = u3nc(u3_nul, u3i_chubs(2, pir_u->who_d)); + } + } + } + else if ( c3n == u3r_cell(t_dat, &it_dat, &tt_dat) ) { + res = u3_nul; + } + else if ( u3_nul == tt_dat ) { + // one-argument requests. + // + switch (i_dat) { + default: { + res = u3_nul; + } break; + case c3__port: { + switch (it_dat) { + default: { + res = u3_nul; + } break; + case c3__ames: { + res = u3nc(u3_nul, pir_u->por_s); + } break; + case c3__htls: { + res = u3nc(u3_nul, pir_u->pes_s); + } break; + case c3__http: { + res = u3nc(u3_nul, pir_u->per_s); + } break; + } + } break; + } + } + else { + res = u3_nul; + } + u3z(dat); return res; +} + +/* _conn_make_cran(): alloc/init new request. +*/ +static u3_cran* +_conn_make_cran(u3_chan* can_u, u3_atom rid) +{ + u3_cran* ran_u = c3_calloc(sizeof(*ran_u)); + + ran_u->rid = rid; + ran_u->can_u = can_u; + ran_u->nex_u = can_u->ran_u; + can_u->ran_u = ran_u; + return ran_u; +} + +/* _conn_moor_poke(): called on message read from u3_moor. +*/ +static void +_conn_moor_poke(void* ptr_v, c3_d len_d, c3_y* byt_y) +{ + u3_weak jar; + u3_noun can, rid, tag, dat, rud = u3_nul, tar, wir, cad; + u3_chan* can_u = (u3_chan*)ptr_v; + u3_conn* con_u = can_u->san_u->con_u; + c3_i err_i = 0; + c3_c* err_c; + c3_c* tag_c; + c3_c* rid_c; + + jar = u3s_cue_xeno_with(con_u->sil_u, len_d, byt_y); + if ( u3_none == jar ) { + can_u->mor_u.bal_f(can_u, -1, "cue-none"); + return; + } + if ( (c3n == u3r_cell(jar, &rid, &can)) || + (c3n == u3r_cell(can, &tag, &dat)) || + (c3n == u3ud(rid)) ) + { + err_i = -2; err_c = "jar-bad"; + goto _moor_poke_out; + } + + rud = u3dc("scot", c3__uv, u3k(rid)); + tag_c = u3r_string(tag); + rid_c = u3r_string(rud); + u3l_log("conn: %s %s\n", tag_c, rid_c); + c3_free(tag_c); c3_free(rid_c); + + switch (tag) { + default: { + err_i = -3; err_c = "tag-unknown"; + goto _moor_poke_out; + } break; + + case c3__fyrd: { + if ( c3n == con_u->kan_o ) { + err_i = -8; err_c = "khan-miss"; + goto _moor_poke_out; + } + wir = u3nc(c3__khan, + u3nq(u3dc("scot", c3__uv, con_u->sev_l), + u3dc("scot", c3__ud, can_u->coq_l), u3k(rud), u3_nul)); + u3_auto_peer( + u3_auto_plan(&con_u->car_u, + u3_ovum_init(0, c3__k, wir, u3k(can))), + 0, 0, _conn_poke_bail); + } break; + + case c3__peek: { + u3_pier_peek(con_u->car_u.pir_u, u3nc(u3_nul, u3_nul), u3k(dat), + _conn_make_cran(can_u, u3k(rid)), _conn_peek_cb); + } break; + + case c3__peel: { + _conn_send_noun( + can_u, u3nc(u3k(rid), _conn_read_peel(con_u, u3k(dat)))); + } break; + + case c3__ovum: { + if ( (c3n == u3r_trel(dat, &tar, &wir, &cad)) ) { + err_i = -6; err_c = "ovum-bad"; + goto _moor_poke_out; + } + u3_auto_peer( + u3_auto_plan(&con_u->car_u, + u3_ovum_init(0, u3k(tar), u3k(wir), u3k(cad))), + _conn_make_cran(can_u, u3k(rid)), _conn_ovum_news, _conn_ovum_bail); + } break; + + case c3__urth: { + switch (dat) { + default: { + err_i = -7; err_c = "urth-bad"; + goto _moor_poke_out; + } break; + case c3__meld: { + _conn_send_noun(can_u, u3nc(u3k(rid), c3y)); + u3_pier_meld(con_u->car_u.pir_u); + } break; + case c3__pack: { + _conn_send_noun(can_u, u3nc(u3k(rid), c3y)); + u3_pier_pack(con_u->car_u.pir_u); + } break; + } + } break; + } +_moor_poke_out: + u3z(rud); u3z(jar); + if ( 0 != err_i ) { + can_u->mor_u.bal_f(can_u, err_i, err_c); + } +} + +/* _conn_sock_cb(): socket connection callback. +*/ +static void +_conn_sock_cb(uv_stream_t* sem_u, c3_i tas_i) +{ + u3_shan* san_u = (u3_shan*)sem_u; + u3_conn* con_u = san_u->con_u; + u3_chan* can_u; + c3_i err_i; + + can_u = c3_calloc(sizeof(u3_chan)); + can_u->mor_u.ptr_v = can_u; + can_u->mor_u.pok_f = _conn_moor_poke; + can_u->mor_u.bal_f = _conn_moor_bail; + can_u->coq_l = san_u->nex_l++; + can_u->san_u = san_u; + err_i = uv_timer_init(u3L, &can_u->mor_u.tim_u); + c3_assert(!err_i); + err_i = uv_pipe_init(u3L, &can_u->mor_u.pyp_u, 0); + c3_assert(!err_i); + err_i = uv_accept(sem_u, (uv_stream_t*)&can_u->mor_u.pyp_u); + c3_assert(!err_i); + u3_newt_read((u3_moat*)&can_u->mor_u); + can_u->mor_u.nex_u = (u3_moor*)san_u->can_u; + san_u->can_u = can_u; +} + +/* _conn_init_sock(): initialize socket device. +*/ +static void +_conn_init_sock(u3_shan* san_u) +{ +#ifdef _WIN32 + u3_pier* pir_u = san_u->con_u->car_u.pir_u; + u3_atom who = u3dc("scot", c3__p, u3i_chubs(2, pir_u->who_d)); + c3_c* who_c = u3r_string(who); + c3_c pip_c[256]; + c3_i ret_i; + + u3z(who); + ret_i = snprintf(pip_c, sizeof(pip_c), "\\\\.\\pipe\\urbit-conn-%s", who_c + 1); + c3_assert(19 + strlen(who_c) == ret_i); + c3_free(who_c); + ret_i = uv_pipe_init(u3L, &san_u->pyp_u, 0); + c3_assert(!ret_i); + ret_i = uv_pipe_bind(&san_u->pyp_u, pip_c); + c3_assert(!ret_i); + ret_i = uv_listen((uv_stream_t*)&san_u->pyp_u, 0, _conn_sock_cb); + c3_assert(!ret_i); + u3l_log("conn: listening on %s\n", pip_c); + +#else // _WIN32 + // the full socket path is limited to about 108 characters, + // and we want it to be relative to the pier. save our current + // path, chdir to the pier, open the socket at the desired + // path, then chdir back. hopefully there aren't any threads. + // + c3_c pax_c[2048]; + c3_i err_i; + + if ( NULL == getcwd(pax_c, sizeof(pax_c)) ) { + u3l_log("conn: getcwd: %s\n", uv_strerror(errno)); + u3_king_bail(); + } + if ( 0 != chdir(u3_Host.dir_c) ) { + u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + u3_king_bail(); + } + if ( 0 != unlink(URB_SOCK_PATH) && errno != ENOENT ) { + u3l_log("conn: unlink: %s\n", uv_strerror(errno)); + goto _conn_sock_err_chdir; + } + if ( 0 != (err_i = uv_pipe_init(u3L, &san_u->pyp_u, 0)) ) { + u3l_log("conn: uv_pipe_init: %s\n", uv_strerror(err_i)); + goto _conn_sock_err_chdir; + } + if ( 0 != (err_i = uv_pipe_bind(&san_u->pyp_u, URB_SOCK_PATH)) ) { + u3l_log("conn: uv_pipe_bind: %s\n", uv_strerror(err_i)); + goto _conn_sock_err_chdir; + } + if ( 0 != (err_i = uv_listen((uv_stream_t*)&san_u->pyp_u, 0, + _conn_sock_cb)) ) { + u3l_log("conn: uv_listen: %s\n", uv_strerror(err_i)); + goto _conn_sock_err_unlink; + } + if ( 0 != chdir(pax_c) ) { + u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + goto _conn_sock_err_close; + } + u3l_log("conn: listening on %s/%s\n", u3_Host.dir_c, URB_SOCK_PATH); + return; + +_conn_sock_err_close: + uv_close((uv_handle_t*)&san_u->pyp_u, _conn_close_cb); +_conn_sock_err_unlink: + if ( 0 != unlink(URB_SOCK_PATH) ) { + u3l_log("conn: unlink: %s\n", uv_strerror(errno)); + } +_conn_sock_err_chdir: + if ( 0 != chdir(pax_c) ) { + u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + } + u3_king_bail(); +#endif // _WIN32 +} + +/* _conn_born_news(): initialization complete; %khan available. +*/ +static void +_conn_born_news(u3_ovum* egg_u, u3_ovum_news new_e) +{ + u3_conn* con_u = (u3_conn*)egg_u->car_u; + + if ( u3_ovum_done == new_e ) { + con_u->kan_o = c3y; + } +} + +/* _conn_born_bail(): nonessential failure; log it and keep going. +*/ +static void +_conn_born_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3l_log("conn: %%born failure; %%fyrd not supported\n"); + u3z(lud); + u3_ovum_free(egg_u); +} + +/* _conn_io_talk(): open socket and notify %khan that we're live. +*/ +static void +_conn_io_talk(u3_auto* car_u) +{ + u3_conn* con_u = (u3_conn*)car_u; + u3_shan* san_u; + u3_noun wir = u3nt(c3__khan, + u3dc("scot", c3__uv, con_u->sev_l), + u3_nul); + u3_noun cad = u3nc(c3__born, u3_nul); + + u3_auto_peer( + u3_auto_plan(car_u, u3_ovum_init(0, c3__k, wir, cad)), + 0, + _conn_born_news, + _conn_born_bail); + + // initialize server, opening socket. + // + c3_assert(!con_u->san_u); + san_u = c3_calloc(sizeof(*san_u)); + san_u->nex_l = 1; + san_u->con_u = con_u; + con_u->san_u = san_u; + _conn_init_sock(san_u); + car_u->liv_o = c3y; +} + +/* _conn_ef_handle(): handle result. +*/ +static void +_conn_ef_handle(u3_conn* con_u, + c3_l sev_l, + c3_l coq_l, + u3_atom rid, + u3_noun tag, + u3_noun dat) +{ + u3_chan* can_u; + + if ( 0 != (can_u = _conn_find_chan(con_u, sev_l, coq_l)) ) { + if ( c3__avow == tag ) { + _conn_send_noun(can_u, u3nt(u3k(rid), c3__avow, u3k(dat))); + } + else { + can_u->mor_u.bal_f(can_u, -4, "handle-unknown"); + u3_king_bail(); + } + } + else { + u3l_log("conn: handle-no-coq %" PRIx32 " %" PRIu32 "\n", + sev_l, coq_l); + } + u3z(rid); u3z(tag); u3z(dat); +} + +/* _conn_io_kick(): apply effects. +*/ +static c3_o +_conn_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) +{ + u3_conn* con_u = (u3_conn*)car_u; + u3_noun tag, dat; + c3_l sev_l, coq_l; + u3_atom rid; + + if ( c3n == _conn_read_wire(wir, c3__khan, &sev_l, &coq_l, &rid) ) { + u3z(cad); return c3n; + } + if ( (con_u->sev_l != sev_l) || + (c3n == u3r_cell(cad, &tag, &dat)) ) + { + u3z(rid); u3z(cad); return c3n; + } + + _conn_ef_handle(con_u, sev_l, coq_l, rid, u3k(tag), u3k(dat)); + u3z(cad); return c3y; +} + +/* _conn_io_exit(): unlink socket, shut down connections. +*/ +static void +_conn_io_exit(u3_auto* car_u) +{ + u3_conn* con_u = (u3_conn*)car_u; + c3_c* pax_c = u3_Host.dir_c; + c3_w len_w = strlen(pax_c) + 1 + sizeof(URB_SOCK_PATH); + c3_c* paf_c = c3_malloc(len_w); + c3_i wit_i; + + wit_i = snprintf(paf_c, len_w, "%s/%s", pax_c, URB_SOCK_PATH); + c3_assert(wit_i > 0); + c3_assert(len_w == (c3_w)wit_i + 1); + + if ( 0 != unlink(paf_c) ) { + if ( ENOENT != errno ) { + u3l_log("conn: failed to unlink socket: %s\n", uv_strerror(errno)); + } + } + else { + // u3l_log("conn: unlinked %s\n", paf_c); + } + c3_free(paf_c); + + { + u3_shan* san_u = con_u->san_u; + + if ( san_u ) { + while ( san_u->can_u ) { + _conn_close_chan(san_u, san_u->can_u); + } + uv_close((uv_handle_t*)&san_u->pyp_u, _conn_close_cb); + } + } + + u3s_cue_xeno_done(con_u->sil_u); + c3_free(con_u); +} + +/* u3_conn(): initialize control plane socket. +*/ +u3_auto* +u3_conn_io_init(u3_pier* pir_u) +{ + u3_conn* con_u; + u3_auto* car_u; + u3_noun now; + struct timeval tim_u; + + if ( c3n == u3_Host.ops_u.con ) { + return NULL; + } + con_u = c3_calloc(sizeof(*con_u)); + con_u->sil_u = u3s_cue_xeno_init(); + con_u->kan_o = c3n; + car_u = &con_u->car_u; + car_u->nam_m = c3__conn; + car_u->liv_o = c3n; + car_u->io.talk_f = _conn_io_talk; + car_u->io.kick_f = _conn_io_kick; + car_u->io.exit_f = _conn_io_exit; + + gettimeofday(&tim_u, 0); + now = u3_time_in_tv(&tim_u); + con_u->sev_l = u3r_mug(now); + u3z(now); + return car_u; +} diff --git a/pkg/urbit/vere/io/fore.c b/pkg/urbit/vere/io/fore.c index 81476d92a1..7354a8225d 100644 --- a/pkg/urbit/vere/io/fore.c +++ b/pkg/urbit/vere/io/fore.c @@ -48,7 +48,7 @@ _fore_inject(u3_auto* car_u, c3_c* pax_c) u3l_log("pier: invalid wire in -I ovum\n"); } else if ( (c3n == u3a_is_atom(tar)) - || (1 < u3r_met(3, tar)) ) + || (4 < u3r_met(3, tar)) ) { u3l_log("pier: invalid target in -I wire\n"); } diff --git a/pkg/urbit/vere/io/http.c b/pkg/urbit/vere/io/http.c index f0d2f0ea23..403a9c35ee 100644 --- a/pkg/urbit/vere/io/http.c +++ b/pkg/urbit/vere/io/http.c @@ -59,6 +59,7 @@ typedef struct _u3_h2o_serv { c3_w sev_l; // server number c3_w coq_l; // next connection number c3_s por_s; // running port + c3_o dis; // manually-configured port c3_o sec; // logically secure c3_o lop; // loopback-only c3_o liv; // c3n == shutdown @@ -793,19 +794,29 @@ typedef struct _h2o_uv_sock { // see private st_h2o_uv_socket_t uv_stream_t* han_u; // client stream handler (u3_hcon) } h2o_uv_sock; +/* _http_rec_sock(): u3 http connection from h2o request; hacky. +*/ +static u3_hcon* +_http_rec_sock(h2o_req_t* rec_u) +{ + h2o_uv_sock* suv_u = (h2o_uv_sock*)rec_u->conn-> + callbacks->get_socket(rec_u->conn); + u3_hcon* hon_u = (u3_hcon*)suv_u->han_u; + + // sanity check + // + c3_assert( hon_u->sok_u == &suv_u->sok_u ); + + return hon_u; +} + /* _http_req_prepare(): creates u3 req from h2o req and initializes its timer */ static u3_hreq* _http_req_prepare(h2o_req_t* rec_u, u3_hreq* (*new_f)(u3_hcon*, h2o_req_t*)) { - h2o_uv_sock* suv_u = (h2o_uv_sock*)rec_u->conn-> - callbacks->get_socket(rec_u->conn); - u3_hcon* hon_u = (u3_hcon*)suv_u->han_u; - - // sanity check - c3_assert( hon_u->sok_u == &suv_u->sok_u ); - + u3_hcon* hon_u = _http_rec_sock(rec_u); u3_hreq* seq_u = new_f(hon_u, rec_u); seq_u->tim_u = c3_malloc(sizeof(*seq_u->tim_u)); @@ -869,7 +880,7 @@ _http_seq_continue(void* vod_p, u3_noun nun) /* _http_seq_accept(): handle incoming http request on slogstream endpoint */ -static int +static c3_i _http_seq_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) { // try to find a cookie header @@ -893,9 +904,7 @@ _http_seq_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) // if there is a cookie, scry to see if it constitutes authentication // else { - h2o_uv_sock* suv_u = (h2o_uv_sock*)rec_u->conn-> - callbacks->get_socket(rec_u->conn); - u3_hcon* hon_u = (u3_hcon*)suv_u->han_u; + u3_hcon* hon_u = _http_rec_sock(rec_u); u3_noun pax = u3nq(u3i_string("authenticated"), u3i_string("cookie"), @@ -908,6 +917,34 @@ _http_seq_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) return 0; } +/* _http_sat_accept(): handle incoming http request on status endpoint +*/ +static c3_i +_http_sat_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) +{ + c3_o bus_o; + { + u3_hcon* hon_u = _http_rec_sock(rec_u); + u3_httd* htd_u = hon_u->htp_u->htd_u; + u3_pier* pir_u = htd_u->car_u.pir_u; + bus_o = pir_u->god_u->pin_o; + } + + if ( c3y == bus_o ) { + rec_u->res.status = 429; + rec_u->res.reason = "busy"; + } + else { + rec_u->res.status = 204; + rec_u->res.reason = "no content"; + } + + rec_u->res.content_length = 0; + h2o_send_inline(rec_u, NULL, 0); + + return 0; +} + /* _http_rec_accept(); handle incoming http request from h2o. */ static c3_i @@ -917,7 +954,7 @@ _http_rec_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) if ( u3_none == req ) { if ( (u3C.wag_w & u3o_verbose) ) { - u3l_log("strange %.*s request\n", (int)rec_u->method.len, + u3l_log("strange %.*s request\n", (c3_i)rec_u->method.len, rec_u->method.base); } c3_c* msg_c = "bad request"; @@ -1306,12 +1343,13 @@ _http_serv_close(u3_http* htp_u) /* _http_serv_new(): create new http server. */ static u3_http* -_http_serv_new(u3_httd* htd_u, c3_s por_s, c3_o sec, c3_o lop) +_http_serv_new(u3_httd* htd_u, c3_s por_s, c3_o dis, c3_o sec, c3_o lop) { u3_http* htp_u = c3_malloc(sizeof(*htp_u)); htp_u->coq_l = 1; htp_u->por_s = por_s; + htp_u->dis = dis; htp_u->sec = sec; htp_u->lop = lop; htp_u->liv = c3y; @@ -1409,11 +1447,24 @@ _http_serv_init_h2o(SSL_CTX* tls_u, c3_o log, c3_o red) h2o_u->han_u->on_req = _http_rec_accept; } - // register slog stream endpoint + // register runtime endpoints // - h2o_pathconf_t* pac_u = h2o_config_register_path(h2o_u->hos_u, "/~_~/slog", 0); - h2o_handler_t* han_u = h2o_create_handler(pac_u, sizeof(*han_u)); - han_u->on_req = _http_seq_accept; + { + h2o_pathconf_t* pac_u; + h2o_handler_t* han_u; + + // slog stream + // + pac_u = h2o_config_register_path(h2o_u->hos_u, "/~_~/slog", 0); + han_u = h2o_create_handler(pac_u, sizeof(*han_u)); + han_u->on_req = _http_seq_accept; + + // status (per spinner) + // + pac_u = h2o_config_register_path(h2o_u->hos_u, "/~_~/healthz", 0); + han_u = h2o_create_handler(pac_u, sizeof(*han_u)); + han_u->on_req = _http_sat_accept; + } if ( c3y == log ) { // XX move this to post serv_start and put the port in the name @@ -1450,9 +1501,10 @@ _http_serv_init_h2o(SSL_CTX* tls_u, c3_o log, c3_o red) static void _http_serv_start(u3_http* htp_u) { - struct sockaddr_in adr_u; - memset(&adr_u, 0, sizeof(adr_u)); + u3_pier* pir_u = htp_u->htd_u->car_u.pir_u; + struct sockaddr_in adr_u; + memset(&adr_u, 0, sizeof(adr_u)); adr_u.sin_family = AF_INET; adr_u.sin_addr.s_addr = ( c3y == htp_u->lop ) ? htonl(INADDR_LOOPBACK) : @@ -1479,6 +1531,11 @@ _http_serv_start(u3_http* htp_u) u3l_log("http: ip address not available\n"); u3_king_bail(); } + if ( c3y == htp_u->dis ) { + u3l_log("http: listen (%" PRIu16 "): %s\n", htp_u->por_s, + uv_strerror(sas_i)); + u3_king_bail(); + } if ( (UV_EADDRINUSE == sas_i) || (UV_EACCES == sas_i) ) { if ( (c3y == htp_u->sec) && (443 == htp_u->por_s) ) { htp_u->por_s = 8443; @@ -1488,6 +1545,16 @@ _http_serv_start(u3_http* htp_u) } else { htp_u->por_s++; + // XX + // + if ( c3n == htp_u->lop ) { + if ( c3y == htp_u->sec ) { + pir_u->pes_s = htp_u->por_s; + } + else { + pir_u->per_s = htp_u->por_s; + } + } } continue; @@ -1608,10 +1675,11 @@ _http_write_ports_file(u3_httd* htd_u, c3_c *pax_c) c3_c* paf_c = c3_malloc(len_w); snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c); - c3_i por_i = open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + c3_i por_i = c3_open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); c3_free(paf_c); u3_http* htp_u = htd_u->htp_u; + u3_pier* pir_u = htd_u->car_u.pir_u; c3_c temp[32]; while ( 0 != htp_u ) { @@ -1635,11 +1703,14 @@ _http_release_ports_file(c3_c *pax_c) { c3_c* nam_c = ".http.ports"; c3_w len_w = 1 + strlen(pax_c) + 1 + strlen(nam_c); - c3_c* paf_c = c3_malloc(len_w); - snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c); + c3_i wit_i; - unlink(paf_c); + wit_i = snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c); + c3_assert(wit_i > 0); + c3_assert(len_w == (c3_w)wit_i + 1); + + c3_unlink(paf_c); c3_free(paf_c); } @@ -1682,13 +1753,13 @@ _http_search_req(u3_httd* htd_u, static void _http_serv_start_all(u3_httd* htd_u) { - u3_http* htp_u; - c3_s por_s; - - u3_noun sec = u3_nul; - u3_noun non = u3_none; - - u3_form* for_u = htd_u->fig_u.for_u; + u3_http* htp_u; + u3_pier* pir_u = htd_u->car_u.pir_u; + c3_s por_s; + u3_noun sec = u3_nul; + u3_noun non = u3_none; + u3_noun dis; + u3_form* for_u = htd_u->fig_u.for_u; c3_assert( 0 != for_u ); @@ -1703,8 +1774,15 @@ _http_serv_start_all(u3_httd* htd_u) // its reference count must be incremented with SSL_CTX_up_ref if ( 0 != htd_u->tls_u ) { - por_s = ( c3y == for_u->pro ) ? 8443 : 443; - htp_u = _http_serv_new(htd_u, por_s, c3y, c3n); + if ( 0 == pir_u->pes_s ) { + por_s = ( c3y == for_u->pro ) ? 8443 : 443; + dis = c3n; + } + else { + por_s = pir_u->pes_s; + dis = c3y; + } + htp_u = _http_serv_new(htd_u, por_s, dis, c3y, c3n); htp_u->h2o_u = _http_serv_init_h2o(htd_u->tls_u, for_u->log, for_u->red); _http_serv_start(htp_u); @@ -1714,8 +1792,15 @@ _http_serv_start_all(u3_httd* htd_u) // HTTP server. { - por_s = ( c3y == for_u->pro ) ? 8080 : 80; - htp_u = _http_serv_new(htd_u, por_s, c3n, c3n); + if ( 0 == pir_u->per_s ) { + por_s = ( c3y == for_u->pro ) ? 8080 : 80; + dis = c3n; + } + else { + por_s = pir_u->per_s; + dis = c3y; + } + htp_u = _http_serv_new(htd_u, por_s, dis, c3n, c3n); htp_u->h2o_u = _http_serv_init_h2o(0, for_u->log, for_u->red); _http_serv_start(htp_u); @@ -1725,7 +1810,7 @@ _http_serv_start_all(u3_httd* htd_u) // Loopback server. { por_s = 12321; - htp_u = _http_serv_new(htd_u, por_s, c3n, c3y); + htp_u = _http_serv_new(htd_u, por_s, c3n, c3n, c3y); htp_u->h2o_u = _http_serv_init_h2o(0, for_u->log, for_u->red); _http_serv_start(htp_u); @@ -2015,50 +2100,6 @@ _http_seq_heartbeat_cb(uv_timer_t* tim_u) HEARTBEAT_TIMEOUT, 0); } -/* _reck_mole(): parse simple atomic mole. -*/ -static u3_noun -_reck_mole(u3_noun fot, - u3_noun san, - c3_d* ato_d) -{ - u3_noun uco = u3dc("slaw", fot, san); - u3_noun p_uco, q_uco; - - if ( (c3n == u3r_cell(uco, &p_uco, &q_uco)) || - (u3_nul != p_uco) ) - { - u3l_log("strange mole %s\n", u3r_string(san)); - - u3z(fot); u3z(uco); return c3n; - } - else { - *ato_d = u3r_chub(0, q_uco); - - u3z(fot); u3z(uco); return c3y; - } -} - -/* _reck_lily(): parse little atom. -*/ -static u3_noun -_reck_lily(u3_noun fot, u3_noun txt, c3_l* tid_l) -{ - c3_d ato_d; - - if ( c3n == _reck_mole(fot, txt, &ato_d) ) { - return c3n; - } else { - if ( ato_d >= 0x80000000ULL ) { - return c3n; - } else { - *tid_l = (c3_l) ato_d; - - return c3y; - } - } -} - /* _http_io_kick(): apply effects. */ static c3_o @@ -2085,7 +2126,7 @@ _http_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) if ( (c3n == u3r_cell(pud, &p_pud, &t_pud)) || - (c3n == _reck_lily(c3__uv, u3k(p_pud), &sev_l)) ) + (c3n == u3v_lily(c3__uv, u3k(p_pud), &sev_l)) ) { u3z(wir); u3z(cad); return c3n; @@ -2096,7 +2137,7 @@ _http_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) } else { if ( (c3n == u3r_cell(t_pud, &q_pud, &tt_pud)) || - (c3n == _reck_lily(c3__ud, u3k(q_pud), &coq_l)) ) + (c3n == u3v_lily(c3__ud, u3k(q_pud), &coq_l)) ) { u3z(wir); u3z(cad); return c3n; @@ -2107,7 +2148,7 @@ _http_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) } else { if ( (c3n == u3r_cell(tt_pud, &r_pud, &s_pud)) || (u3_nul != s_pud) || - (c3n == _reck_lily(c3__ud, u3k(r_pud), &seq_l)) ) + (c3n == u3v_lily(c3__ud, u3k(r_pud), &seq_l)) ) { u3z(wir); u3z(cad); return c3n; @@ -2154,10 +2195,49 @@ _http_io_exit(u3_auto* car_u) _http_release_ports_file(u3_Host.dir_c); } -/* _http_io_info(): print status info. +/* _http_io_info(): produce status info. +*/ +static u3_noun +_http_io_info(u3_auto* car_u) +{ + u3_httd* htd_u = (u3_httd*)car_u; + u3_http* htp_u = htd_u->htp_u; + c3_w sec_w = 0; + u3_hreq* seq_u = htd_u->fig_u.seq_u; + u3_noun res; + + // XX review: metrics + // + while ( 0 != seq_u ) { + sec_w++; + seq_u = seq_u->nex_u; + } + res = u3i_list( + u3_pier_mase("instance", htd_u->sev_l), + u3_pier_mase("open-slogstreams", u3i_word(sec_w)), + u3_none); + + while ( 0 != htp_u ) { + res = u3nc( + u3_pier_mass( + u3dc("scot", c3__uv, htp_u->sev_l), + u3i_list( + u3_pier_mase("secure", htp_u->sec), + u3_pier_mase("loopback", htp_u->lop), + u3_pier_mase("live", htp_u->liv), + u3_pier_mase("port", htp_u->por_s), + u3_pier_mase("connections", htp_u->coq_l), + u3_none)), + res); + htp_u = htp_u->nex_u; + } + return u3kb_flop(res); +} + +/* _http_io_slog(): print status info. */ static void -_http_io_info(u3_auto* car_u) +_http_io_slog(u3_auto* car_u) { u3_httd* htd_u = (u3_httd*)car_u; c3_y sec_y = 0; @@ -2181,6 +2261,7 @@ u3_http_io_init(u3_pier* pir_u) car_u->liv_o = c3n; car_u->io.talk_f = _http_io_talk; car_u->io.info_f = _http_io_info; + car_u->io.slog_f = _http_io_slog; car_u->io.kick_f = _http_io_kick; car_u->io.exit_f = _http_io_exit; diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index fcccf748a6..0dbf2b1dc3 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -549,14 +549,13 @@ _term_it_show_more(u3_utty* uty_u) /* _term_it_path(): path for console file. */ static c3_c* -_term_it_path(c3_o fyl, u3_noun pax) +_term_it_path(u3_noun pax) { - c3_w len_w; + c3_w len_w = 0; c3_c *pas_c; // measure // - len_w = strlen(u3_Host.dir_c); { u3_noun wiz = pax; @@ -569,16 +568,15 @@ _term_it_path(c3_o fyl, u3_noun pax) // cut // pas_c = c3_malloc(len_w + 1); - strncpy(pas_c, u3_Host.dir_c, len_w); pas_c[len_w] = '\0'; { u3_noun wiz = pax; - c3_c* waq_c = (pas_c + strlen(pas_c)); + c3_c* waq_c = pas_c; while ( u3_nul != wiz ) { c3_w tis_w = u3r_met(3, u3h(wiz)); - if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) { + if ( (u3_nul == u3t(wiz)) ) { *waq_c++ = '.'; } else *waq_c++ = '/'; @@ -598,27 +596,10 @@ _term_it_path(c3_o fyl, u3_noun pax) static void _term_it_save(u3_noun pax, u3_noun pad) { - c3_c* pax_c; - c3_c* bas_c = 0; - c3_w xap_w = u3kb_lent(u3k(pax)); - u3_noun xap = u3_nul; - u3_noun urb = c3_s4('.','u','r','b'); - u3_noun put = c3_s3('p','u','t'); - - // directory base and relative path - if ( 2 < xap_w ) { - u3_noun bas = u3nt(urb, put, u3_nul); - bas_c = _term_it_path(c3n, bas); - xap = u3qb_scag(xap_w - 2, pax); - } - - pax = u3nt(urb, put, pax); - pax_c = _term_it_path(c3y, pax); - - u3_walk_save(pax_c, 0, pad, bas_c, xap); + c3_c* pax_c = _term_it_path(pax); + u3_unix_save(pax_c, pad); c3_free(pax_c); - c3_free(bas_c); } /* _term_ovum_plan(): plan term ovums, configuring spinner. diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 4526298bcd..f9e175b5d2 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -1,5 +1,36 @@ /* vere/unix.c ** +** this file is responsible for maintaining a bidirectional +** mapping between the contents of a clay desk and a directory +** in a unix filesystem. +** +** TODO this driver is crufty and overdue for a rewrite. +** aspirationally, the rewrite should do sanity checking and +** transformations at the noun level to convert messages from +** arvo into sets of fs operations on trusted inputs, and +** inverse transformations and checks for fs contents to arvo +** messages. +** +** the two relevant transformations to apply are: +** +** 1. bidirectionally map file contents to atoms +** 2. bidirectionally map arvo $path <-> unix relative paths +** +** the first transform is trivial. the second poses some +** challenges: an arvo $path is a list of $knot, and the $knot +** space intersects with invalid unix paths in the three cases +** of: %$ (the empty knot), '.', and '..'. we escape these by +** prepending a '!' to the filename corresponding to the $knot, +** yielding unix files named '!', '!.', and '!..'. +** +** there is also the case of the empty path. we elide empty +** paths from this wrapper, which always uses the last path +** component as the file extension/mime-type. +** +** these transforms are implemented, but they ought to be +** implemented in one place, prior to any fs calls; as-is, they +** are sprinkled throughout the file updating code. +** */ #include "all.h" #include @@ -58,6 +89,7 @@ struct _u3_ufil; c3_c* pax_c; // pier directory c3_o alm; // timer set c3_o dyr; // ready to update + u3_noun sat; // (sane %ta) handle #ifdef SYNCLOG c3_w lot_w; // sync-slot struct _u3_sylo { @@ -72,6 +104,50 @@ struct _u3_ufil; void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all); +/* u3_unix_cane(): true iff (unix) path is canonical. +*/ +c3_t +u3_unix_cane(const c3_c* pax_c) +{ + if ( 0 == pax_c ) { + return 0; + } + // allow absolute paths. + // + if ( '/' == *pax_c ) { + pax_c++; + // allow root. + // + if ( 0 == *pax_c ) { + return 1; + } + } + do { + if ( 0 == *pax_c + || 0 == strcmp(".", pax_c) + || 0 == strcmp("..", pax_c) + || 0 == strncmp("/", pax_c, 1) + || 0 == strncmp("./", pax_c, 2) + || 0 == strncmp("../", pax_c, 3) ) + { + return 0; + } + pax_c = strchr(pax_c, '/'); + } while ( 0 != pax_c++ ); + return 1; +} + +/* _unix_sane_ta(): true iff pat is a valid @ta +** +** %ta is parsed by: +** (star ;~(pose nud low hep dot sig cab)) +*/ +static c3_t +_unix_sane_ta(u3_unix* unx_u, u3_atom pat) +{ + return _(u3n_slam_on(u3k(unx_u->sat), pat)); +} + /* u3_readdir_r(): */ c3_w @@ -91,6 +167,56 @@ u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) return(0); } +/* _unix_string_to_knot(): convert c unix path component to $knot +*/ +static u3_atom +_unix_string_to_knot(c3_c* pax_c) +{ + c3_assert(pax_c); + // XX this can happen if we encounter a file without an extension. + // + // c3_assert(*pax_c); + c3_assert(!strchr(pax_c, '/')); + // XX horrible + // +# ifdef _WIN32 + c3_assert(!strchr(pax_c, '\\')); +# endif + if ( '!' == *pax_c ) { + pax_c++; + } + return u3i_string(pax_c); +} + +/* _unix_knot_to_string(): convert $knot to c unix path component. RETAIN. +*/ +static c3_c* +_unix_knot_to_string(u3_atom pon) +{ + c3_c* ret_c; + + if ( u3_nul != pon + && c3_s1('.') != pon + && c3_s2('.','.') != pon + && '!' != u3r_byte(0, pon) ) + { + ret_c = u3r_string(pon); + } + else { + c3_w met_w = u3r_met(3, pon); + + ret_c = c3_malloc(met_w + 2); + *ret_c = '!'; + u3r_bytes(0, met_w, (c3_y*)ret_c + 1, pon); + ret_c[met_w + 1] = 0; + } + c3_assert(!strchr(ret_c, '/')); +# ifdef _WIN32 + c3_assert(!strchr(ret_c, '\\')); +# endif + return ret_c; +} + /* _unix_down(): descend path. */ static c3_c* @@ -108,29 +234,34 @@ _unix_down(c3_c* pax_c, c3_c* sub_c) return don_c; } -/* _unix_string_to_path(): convert c string to u3_noun path - * - * c string must begin with the pier path plus mountpoint +/* _unix_string_to_path(): convert c string to u3_noun $path +** +** c string must begin with the pier path plus mountpoint */ static u3_noun _unix_string_to_path_helper(c3_c* pax_c) { + u3_noun not; + c3_assert(pax_c[-1] == '/'); - c3_c* end_w = strchr(pax_c, '/'); - if ( !end_w ) { - end_w = strrchr(pax_c, '.'); - if ( !end_w ) { - return u3nc(u3i_string(pax_c), u3_nul); + c3_c* end_c = strchr(pax_c, '/'); + if ( !end_c ) { + end_c = strrchr(pax_c, '.'); + if ( !end_c ) { + return u3nc(_unix_string_to_knot(pax_c), u3_nul); } else { - return u3nt(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), - u3i_string(end_w + 1), - u3_nul); + *end_c = 0; + not = _unix_string_to_knot(pax_c); + *end_c = '.'; + return u3nt(not, _unix_string_to_knot(end_c + 1), u3_nul); } } else { - return u3nc(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), - _unix_string_to_path_helper(end_w + 1)); + *end_c = 0; + not = _unix_string_to_knot(pax_c); + *end_c = '/'; + return u3nc(not, _unix_string_to_path_helper(end_c + 1)); } } static u3_noun @@ -144,7 +275,7 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c) return u3_nul; } else { - return u3nc(u3i_string(pox_c + 1), u3_nul); + return u3nc(_unix_string_to_knot(pox_c + 1), u3_nul); } } else { @@ -152,6 +283,77 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c) } } +/* _unix_mkdirp(): recursive mkdir of dirname of pax_c. +*/ +static void +_unix_mkdirp(c3_c* pax_c) +{ + c3_c* fas_c = strchr(pax_c + 1, '/'); + + while ( fas_c ) { + *fas_c = 0; + if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) { + u3l_log("unix: mkdir %s: %s\n", pax_c, strerror(errno)); + u3m_bail(c3__fail); + } + *fas_c++ = '/'; + fas_c = strchr(fas_c, '/'); + } +} + +/* u3_unix_save(): save file under .../.urb/put or bail. +** +** XX this is quite bad, and doesn't share much in common with +** the rest of unix.c. a refactor would probably share common +** logic with _unix_sync_change, perhaps using openat, making +** unx_u optional, and/or having a flag to not track the file +** for future changes. +*/ +void +u3_unix_save(c3_c* pax_c, u3_atom pad) +{ + c3_i fid_i; + c3_w lod_w, len_w, fln_w, rit_w; + c3_y* pad_y; + c3_c* ful_c; + + if ( !u3_unix_cane(pax_c) ) { + u3l_log("%s: non-canonical path\n", pax_c); + u3z(pad); u3m_bail(c3__fail); + } + if ( '/' == *pax_c) { + pax_c++; + } + lod_w = strlen(u3_Host.dir_c); + len_w = lod_w + sizeof("/.urb/put/") + strlen(pax_c); + ful_c = c3_malloc(len_w); + rit_w = snprintf(ful_c, len_w, "%s/.urb/put/%s", u3_Host.dir_c, pax_c); + c3_assert(len_w == rit_w + 1); + + _unix_mkdirp(ful_c); + fid_i = c3_open(ful_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if ( fid_i < 0 ) { + u3l_log("%s: %s\n", ful_c, strerror(errno)); + c3_free(ful_c); + u3z(pad); u3m_bail(c3__fail); + } + + fln_w = u3r_met(3, pad); + pad_y = c3_malloc(fln_w); + u3r_bytes(0, fln_w, pad_y, pad); + u3z(pad); + rit_w = write(fid_i, pad_y, fln_w); + close(fid_i); + c3_free(pad_y); + + if ( rit_w != fln_w ) { + u3l_log("%s: %s\n", ful_c, strerror(errno)); + c3_free(ful_c); + u3m_bail(c3__fail); + } + c3_free(ful_c); +} + /* _unix_rm_r_cb(): callback to delete individual files/directories */ static c3_i @@ -165,7 +367,7 @@ _unix_rm_r_cb(const c3_c* pax_c, u3l_log("bad file type in rm_r: %s\r\n", pax_c); break; case FTW_F: - if ( 0 != unlink(pax_c) && ENOENT != errno ) { + if ( 0 != c3_unlink(pax_c) && ENOENT != errno ) { u3l_log("error unlinking (in rm_r) %s: %s\n", pax_c, strerror(errno)); c3_assert(0); @@ -181,7 +383,7 @@ _unix_rm_r_cb(const c3_c* pax_c, u3l_log("couldn't stat path: %s\r\n", pax_c); break; case FTW_DP: - if ( 0 != rmdir(pax_c) && ENOENT != errno ) { + if ( 0 != c3_rmdir(pax_c) && ENOENT != errno ) { u3l_log("error rmdiring %s: %s\n", pax_c, strerror(errno)); c3_assert(0); } @@ -213,7 +415,7 @@ _unix_rm_r(c3_c* pax_c) static void _unix_mkdir(c3_c* pax_c) { - if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno) { + if ( 0 != c3_mkdir(pax_c, 0755) && EEXIST != errno) { u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); c3_assert(0); } @@ -224,7 +426,7 @@ _unix_mkdir(c3_c* pax_c) static c3_w _unix_write_file_hard(c3_c* pax_c, u3_noun mim) { - c3_i fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + c3_i fid_i = c3_open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); c3_w len_w, rit_w, siz_w, mug_w = 0; c3_y* dat_y; @@ -267,7 +469,7 @@ static void _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) { struct stat buf_u; - c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_w old_w; c3_y* old_y; @@ -339,7 +541,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon) return NULL; } - c3_c* nam_c = u3r_string(mon); + c3_c* nam_c = _unix_knot_to_string(mon); u3_umon* mon_u; for ( mon_u = unx_u->mon_u; @@ -374,7 +576,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon) static void _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) { - DIR* rid_u = opendir(mon_u->dir_u.pax_c); + DIR* rid_u = c3_opendir(mon_u->dir_u.pax_c); if ( !rid_u ) { u3l_log("error opening pier directory: %s: %s\r\n", mon_u->dir_u.pax_c, strerror(errno)); @@ -425,12 +627,11 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) } } else { - if ( '.' != out_u->d_name[len_w] - || '\0' == out_u->d_name[len_w + 1] - || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || ('#' == out_u->d_name[0] && - '#' == out_u->d_name[strlen(out_u->d_name) - 1]) - ) { + if ( '.' != out_u->d_name[len_w] + || '\0' == out_u->d_name[len_w + 1] + || '~' == out_u->d_name[strlen(out_u->d_name) - 1] + || !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) ) + { c3_free(pax_c); continue; } @@ -452,7 +653,7 @@ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u); static void _unix_free_file(u3_ufil *fil_u) { - if ( 0 != unlink(fil_u->pax_c) && ENOENT != errno ) { + if ( 0 != c3_unlink(fil_u->pax_c) && ENOENT != errno ) { u3l_log("error unlinking %s: %s\n", fil_u->pax_c, strerror(errno)); c3_assert(0); } @@ -482,8 +683,8 @@ _unix_free_dir(u3_udir *dir_u) } /* _unix_free_node(): free node, deleting everything within - * - * also deletes from parent list if in it +** +** also deletes from parent list if in it */ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) @@ -526,12 +727,12 @@ _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) } /* _unix_free_mount_point(): free mount point - * - * this process needs to happen in a very careful order. in particular, - * we must recurse before we get to the callback, so that libuv does all - * the child directories before it does us. - * - * tread carefully +** +** this process needs to happen in a very careful order. in +** particular, we must recurse before we get to the callback, so +** that libuv does all the child directories before it does us. +** +** tread carefully */ static void _unix_free_mount_point(u3_unix* unx_u, u3_umon* mon_u) @@ -559,7 +760,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) return; } - c3_c* nam_c = u3r_string(mon); + c3_c* nam_c = _unix_knot_to_string(mon); u3_umon* mon_u; u3_umon* tem_u; @@ -651,7 +852,7 @@ _unix_watch_dir(u3_udir* dir_u, u3_udir* par_u, c3_c* pax_c) static void _unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam) { - c3_c* nam_c = u3r_string(nam); + c3_c* nam_c = _unix_knot_to_string(nam); c3_w nam_w = strlen(nam_c); c3_w pax_w = strlen(par_u->pax_c); c3_c* pax_c = c3_malloc(pax_w + 1 + nam_w + 1); @@ -671,12 +872,13 @@ _unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam) static u3_noun _unix_update_node(u3_unix* unx_u, u3_unod* nod_u); /* _unix_update_file(): update file, producing list of changes - * - * when scanning through files, if dry, do nothing. otherwise, mark as - * dry, then check if file exists. if not, remove self from node list - * and add path plus sig to %into event. otherwise, read the file and - * get a mug checksum. if same as gum_w, move on. otherwise, overwrite - * add path plus data to %into event. +** +** when scanning through files, if dry, do nothing. otherwise, +** mark as dry, then check if file exists. if not, remove +** self from node list and add path plus sig to %into event. +** otherwise, read the file and get a mug checksum. if same as +** gum_w, move on. otherwise, overwrite add path plus data to +** %into event. */ static u3_noun _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) @@ -690,7 +892,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) fil_u->dry = c3n; struct stat buf_u; - c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; @@ -745,9 +947,9 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) } /* _unix_update_dir(): update directory, producing list of changes - * - * when changing this, consider whether to also change - * _unix_initial_update_dir() +** +** when changing this, consider whether to also change +** _unix_initial_update_dir() */ static u3_noun _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) @@ -773,7 +975,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { if ( c3y == nod_u->dir ) { - DIR* red_u = opendir(nod_u->pax_c); + DIR* red_u = c3_opendir(nod_u->pax_c); if ( 0 == red_u ) { u3_unod* nex_u = nod_u->nex_u; can = u3kb_weld(_unix_free_node(unx_u, nod_u), can); @@ -786,7 +988,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { struct stat buf_u; - c3_i fid_i = open(nod_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(nod_u->pax_c, O_RDONLY, 0644); if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { if ( ENOENT != errno ) { @@ -813,7 +1015,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) // Check for new nodes - DIR* rid_u = opendir(dir_u->pax_c); + DIR* rid_u = c3_opendir(dir_u->pax_c); if ( !rid_u ) { u3l_log("error opening directory %s: %s\r\n", dir_u->pax_c, strerror(errno)); @@ -869,11 +1071,10 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( !nod_u ) { if ( !S_ISDIR(buf_u.st_mode) ) { - if ( !strchr(out_u->d_name,'.') - || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || ('#' == out_u->d_name[0] && - '#' == out_u->d_name[strlen(out_u->d_name) - 1]) - ) { + if ( !strchr(out_u->d_name,'.') + || '~' == out_u->d_name[strlen(out_u->d_name) - 1] + || !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) ) + { c3_free(pax_c); continue; } @@ -942,7 +1143,8 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all) u3_noun wir = u3nt(c3__sync, u3dc("scot", c3__uv, unx_u->sev_l), u3_nul); - u3_noun cad = u3nq(c3__into, u3i_string(mon_u->nam_c), all, can); + u3_noun cad = u3nq(c3__into, _unix_string_to_knot(mon_u->nam_c), all, + can); u3_auto_plan(&unx_u->car_u, u3_ovum_init(0, c3__c, wir, cad)); } @@ -950,13 +1152,13 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all) } /* _unix_initial_update_file(): read file, but don't watch -** XX deduplicate with _unix_update_file() +** XX deduplicate with _unix_update_file() */ static u3_noun _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) { struct stat buf_u; - c3_i fid_i = open(pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; @@ -1006,14 +1208,14 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) } /* _unix_initial_update_dir(): read directory, but don't watch -** XX deduplicate with _unix_update_dir() +** XX deduplicate with _unix_update_dir() */ static u3_noun _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) { u3_noun can = u3_nul; - DIR* rid_u = opendir(pax_c); + DIR* rid_u = c3_opendir(pax_c); if ( !rid_u ) { u3l_log("error opening initial directory: %s: %s\r\n", pax_c, strerror(errno)); @@ -1089,8 +1291,8 @@ _unix_sync_file(u3_unix* unx_u, u3_udir* par_u, u3_noun nam, u3_noun ext, u3_nou // form file path - c3_c* nam_c = u3r_string(nam); - c3_c* ext_c = u3r_string(ext); + c3_c* nam_c = _unix_knot_to_string(nam); + c3_c* ext_c = _unix_knot_to_string(ext); c3_w par_w = strlen(par_u->pax_c); c3_w nam_w = strlen(nam_c); c3_w ext_w = strlen(ext_c); @@ -1174,7 +1376,7 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) _unix_sync_file(unx_u, dir_u, u3k(i_pax), u3k(it_pax), mim); } else { - c3_c* nam_c = u3r_string(i_pax); + c3_c* nam_c = _unix_knot_to_string(i_pax); c3_w pax_w = strlen(dir_u->pax_c); u3_unod* nod_u; @@ -1207,7 +1409,7 @@ static void _unix_sync_ergo(u3_unix* unx_u, u3_umon* mon_u, u3_noun can) { u3_noun nac = can; - u3_noun nam = u3i_string(mon_u->nam_c); + u3_noun nam = _unix_string_to_knot(mon_u->nam_c); while ( u3_nul != nac) { _unix_sync_change(unx_u, &mon_u->dir_u, @@ -1263,98 +1465,24 @@ u3_unix_ef_hill(u3_unix* unx_u, u3_noun hil) u3z(hil); } -/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it. -*/ -static void -u3_unix_acquire(c3_c* pax_c) -{ - c3_c* paf_c = _unix_down(pax_c, ".vere.lock"); - c3_w pid_w; - FILE* loq_u; - - if ( NULL != (loq_u = fopen(paf_c, "r")) ) { - if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { - u3l_log("lockfile %s is corrupt!\n", paf_c); - kill(getpid(), SIGTERM); - sleep(1); c3_assert(0); - } - else if (pid_w != getpid()) { - c3_w i_w; - - if ( -1 != kill(pid_w, SIGTERM) ) { - u3l_log("unix: stopping process %d, live in %s...\n", - pid_w, pax_c); - - for ( i_w = 0; i_w < 16; i_w++ ) { - sleep(1); - if ( -1 == kill(pid_w, SIGTERM) ) { - break; - } - } - if ( 16 == i_w ) { - for ( i_w = 0; i_w < 16; i_w++ ) { - if ( -1 == kill(pid_w, SIGKILL) ) { - break; - } - sleep(1); - } - } - if ( 16 == i_w ) { - u3l_log("unix: process %d seems unkillable!\n", pid_w); - c3_assert(0); - } - u3l_log("unix: stopped old process %u\n", pid_w); - } - } - fclose(loq_u); - unlink(paf_c); - } - - if ( NULL == (loq_u = fopen(paf_c, "w")) ) { - u3l_log("unix: unable to open %s\n", paf_c); - c3_assert(0); - } - - fprintf(loq_u, "%u\n", getpid()); - - { - c3_i fid_i = fileno(loq_u); - c3_sync(fid_i); - } - - fclose(loq_u); - c3_free(paf_c); -} - -/* u3_unix_release(): release a lockfile. -*/ -static void -u3_unix_release(c3_c* pax_c) -{ - c3_c* paf_c = _unix_down(pax_c, ".vere.lock"); - - unlink(paf_c); - c3_free(paf_c); -} - /* u3_unix_ef_look(): update the root of a specific mount point. */ void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all) { if ( c3y == unx_u->dyr ) { + c3_c* nam_c = _unix_knot_to_string(mon); + unx_u->dyr = c3n; u3_umon* mon_u = unx_u->mon_u; - - while ( mon_u && ( c3n == u3r_sing_c(mon_u->nam_c, mon) ) ) { + while ( mon_u && 0 != strcmp(nam_c, mon_u->nam_c) ) { mon_u = mon_u->nex_u; } - + c3_free(nam_c); if ( mon_u ) { _unix_update_mount(unx_u, mon_u, all); } } - u3z(mon); } @@ -1431,10 +1559,7 @@ _unix_io_exit(u3_auto* car_u) { u3_unix* unx_u = (u3_unix*)car_u; - // XX move to disk.c? - // - u3_unix_release(unx_u->pax_c); - + u3z(unx_u->sat); c3_free(unx_u->pax_c); c3_free(unx_u); } @@ -1449,10 +1574,7 @@ u3_unix_io_init(u3_pier* pir_u) unx_u->pax_c = strdup(pir_u->pax_c); unx_u->alm = c3n; unx_u->dyr = c3n; - - // XX move to disk.c? - // - u3_unix_acquire(unx_u->pax_c); + unx_u->sat = u3do("sane", c3__ta); u3_auto* car_u = &unx_u->car_u; car_u->nam_m = c3__unix; diff --git a/pkg/urbit/vere/ivory.c b/pkg/urbit/vere/ivory.c new file mode 100644 index 0000000000..370f8c4abc --- /dev/null +++ b/pkg/urbit/vere/ivory.c @@ -0,0 +1,3 @@ +#include "vere/ivory.h" + +#include "ivory_impl.h" diff --git a/pkg/urbit/vere/king.c b/pkg/urbit/vere/king.c index e857d60401..d441ad2a1c 100644 --- a/pkg/urbit/vere/king.c +++ b/pkg/urbit/vere/king.c @@ -3,12 +3,13 @@ ** the main loop of the daemon process */ #include "all.h" -#include "vere/vere.h" #include "ur/ur.h" +#include "vere/ivory.h" +#include "vere/vere.h" #include #include -#include "ivory.h" +static const c3_c* ver_hos_c = "https://bootstrap.urbit.org/vere"; // stash config flags for worker // @@ -232,54 +233,167 @@ _king_curl_alloc(void* dat_v, size_t uni_t, size_t mem_t, void* buf_v) return siz_t; } -/* _king_get_atom(): HTTP GET url_c, produce the response body as an atom. +/* _king_curl_bytes(): HTTP GET url_c, produce response body bytes. ** XX deduplicate with dawn.c */ -static u3_noun -_king_get_atom(c3_c* url_c) +static c3_i +_king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t) { - CURL *curl; - CURLcode result; - long cod_l; - + c3_i ret_i = 0; + CURL *cul_u; + CURLcode res_i; + long cod_i; uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); - if ( !(curl = curl_easy_init()) ) { + if ( !(cul_u = curl_easy_init()) ) { u3l_log("failed to initialize libcurl\n"); exit(1); } - u3K.ssl_curl_f(curl); - curl_easy_setopt(curl, CURLOPT_URL, url_c); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _king_curl_alloc); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&buf_u); + u3K.ssl_curl_f(cul_u); + curl_easy_setopt(cul_u, CURLOPT_URL, url_c); + curl_easy_setopt(cul_u, CURLOPT_WRITEFUNCTION, _king_curl_alloc); + curl_easy_setopt(cul_u, CURLOPT_WRITEDATA, (void*)&buf_u); - result = curl_easy_perform(curl); - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &cod_l); + res_i = curl_easy_perform(cul_u); + curl_easy_getinfo(cul_u, CURLINFO_RESPONSE_CODE, &cod_i); // XX retry? // - if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", - url_c, curl_easy_strerror(result)); - u3_king_bail(); - exit(1); + if ( CURLE_OK != res_i ) { + if ( veb_t ) { + u3l_log("curl: failed %s: %s\n", url_c, curl_easy_strerror(res_i)); + } + ret_i = -1; } - if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + if ( 300 <= cod_i ) { + if ( veb_t ) { + u3l_log("curl: error %s: HTTP %ld\n", url_c, cod_i); + } + ret_i = -2; + } + + curl_easy_cleanup(cul_u); + + *len_w = buf_u.len; + *hun_y = (c3_y*)buf_u.base; + + return ret_i; +} + +/* _king_get_atom(): HTTP GET url_c, produce response body as atom. +*/ +static u3_noun +_king_get_atom(c3_c* url_c) +{ + c3_w len_w; + c3_y* hun_y; + u3_noun pro; + + if ( _king_curl_bytes(url_c, &len_w, &hun_y, 1) ) { u3_king_bail(); exit(1); } - curl_easy_cleanup(curl); + pro = u3i_bytes(len_w, hun_y); + c3_free(hun_y); + return pro; +} - { - u3_noun pro = u3i_bytes(buf_u.len, (const c3_y*)buf_u.base); +/* _king_get_pace(): get "pace" (release channel name). +*/ +static c3_c* +_king_get_pace(void) +{ + struct stat buf_u; + c3_c* pat_c; + c3_w red_w, len_w; + c3_i ret_i, fid_i; - c3_free(buf_u.base); + ret_i = asprintf(&pat_c, "%s/.bin/pace", u3_Host.dir_c); + c3_assert( ret_i > 0 ); - return pro; + fid_i = c3_open(pat_c, O_RDONLY, 0644); + + if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { + c3_free(pat_c); + return strdup("live"); } + + c3_free(pat_c); + + len_w = buf_u.st_size; + pat_c = c3_malloc(len_w + 1); + red_w = read(fid_i, pat_c, len_w); + close(fid_i); + + if ( len_w != red_w ) { + c3_free(pat_c); + u3l_log("unable to read pace file, " + "falling back to default (\"live\")\n"); + return strdup("live"); + } + + pat_c[len_w] = 0; + + while ( len_w-- && isspace(pat_c[len_w]) ) { + pat_c[len_w] = 0; + } + + return pat_c; +} + +/* u3_king_next(): get next vere version string, if it exists. +** return: 0 is success, -1 is no-op (same version), -2 is error +*/ +c3_i +u3_king_next(c3_c* pac_c, c3_c** out_c) +{ + c3_c* ver_c; + c3_c* url_c; + c3_w len_w; + c3_y* hun_y; + c3_i ret_i; + + ret_i = asprintf(&url_c, "%s/%s/%s/next", ver_hos_c, pac_c, URBIT_VERSION); + c3_assert( ret_i > 0 ); + + // skip printfs on failed requests (/next is usually not present) + // + if ( _king_curl_bytes(url_c, &len_w, &hun_y, 0) ) { + c3_free(url_c); + + ret_i = asprintf(&url_c, "%s/%s/last", ver_hos_c, pac_c); + c3_assert( ret_i > 0 ); + + // enable printfs on failed requests (/last must be present) + // XX support channel redirections + // + if ( _king_curl_bytes(url_c, &len_w, &hun_y, 1) ) + { + c3_free(url_c); + return -2; + } + } + + c3_free(url_c); + + // null-terminate + // + hun_y = c3_realloc(hun_y, 1 + len_w); + hun_y[len_w] = 0; + + ver_c = (c3_c*)hun_y; + + // XX trim ver_c ? + // + if ( 0 == strcmp(ver_c, URBIT_VERSION) ) { + c3_free(ver_c); + return -1; + } + + *out_c = ver_c; + return 0; } /* _get_cmd_output(): Run a shell command and capture its output. @@ -604,9 +718,9 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) u3l_log("\r\ninterrupt\r\n"); u3_term_ef_ctlc(); - #if defined(U3_OS_mingw) +#ifdef U3_OS_mingw PulseEvent(u3_Host.cev_u); - #endif +#endif break; } @@ -621,7 +735,7 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) case SIGINFO: #endif case SIGUSR1: { - u3_king_info(); + u3_king_slog(); break; } } @@ -827,12 +941,12 @@ _king_forall(void (*pir_f)(u3_pier*)) } } -/* u3_king_info(): print status info. +/* u3_king_slog(): print status info. */ void -u3_king_info(void) +u3_king_slog(void) { - _king_forall(u3_pier_info); + _king_forall(u3_pier_slog); } /* _king_forall_unlink(): run on all piers, unlinking from king. @@ -849,6 +963,527 @@ _king_forall_unlink(void (*pir_f)(u3_pier*)) } } +/* _king_curl_file(): HTTP GET [url_c], write response body to [fil_u]. +*/ +static c3_i +_king_save_file(c3_c* url_c, FILE* fil_u) +{ + c3_i ret_i = 0; + CURL *cul_u; + CURLcode res_i; + long cod_i; + + if ( !(cul_u = curl_easy_init()) ) { + u3l_log("failed to initialize libcurl\n"); + exit(1); + } + + u3K.ssl_curl_f(cul_u); + curl_easy_setopt(cul_u, CURLOPT_URL, url_c); + curl_easy_setopt(cul_u, CURLOPT_WRITEDATA, (void*)fil_u); + + res_i = curl_easy_perform(cul_u); + curl_easy_getinfo(cul_u, CURLINFO_RESPONSE_CODE, &cod_i); + + // XX retry? + // + if ( CURLE_OK != res_i ) { + u3l_log("curl: failed %s: %s\n", url_c, curl_easy_strerror(res_i)); + ret_i = -1; + } + if ( 300 <= cod_i ) { + u3l_log("curl: error %s: HTTP %ld\n", url_c, cod_i); + ret_i = -2; + } + + curl_easy_cleanup(cul_u); + return ret_i; +} + +/* _king_make_pace(): mkdir -p $pier/.bin/[pace] +*/ +static c3_i +_king_make_pace(c3_c* pac_c) +{ + c3_c* bin_c; + c3_i ret_i; + + ret_i = asprintf(&bin_c, "%s/.bin", u3_Host.dir_c); + c3_assert( ret_i > 0 ); + + ret_i = c3_mkdir(bin_c, 0700); + + if ( ret_i && (EEXIST != errno) ) { + fprintf(stderr, "vere: mkdir %s failed: %s\n", bin_c, strerror(errno)); + c3_free(bin_c); + return -1; + } + + c3_free(bin_c); + + ret_i = asprintf(&bin_c, "%s/.bin/%s/", u3_Host.dir_c, pac_c); + c3_assert( ret_i > 0 ); + + // XX asserting wrapper conflicts here (and is bypassed for .urb) + // + ret_i = mkdir(bin_c, 0700); + + if ( ret_i && (EEXIST != errno) ) { + fprintf(stderr, "vere: mkdir %s failed: %s\n", bin_c, strerror(errno)); + c3_free(bin_c); + return -1; + } + + c3_free(bin_c); + return 0; +} + +static c3_i +_king_write_raw(c3_i fid_i, c3_y* buf_y, size_t len_i); + +/* _king_init_pace(): save pace file if not present +*/ +static c3_i +_king_init_pace(c3_c* pac_c) +{ + c3_c* bin_c; + c3_i fid_i, ret_i = asprintf(&bin_c, "%s/.bin/pace", u3_Host.dir_c); + c3_assert( ret_i > 0 ); + + if ( (-1 == (fid_i = open(bin_c, O_WRONLY | O_CREAT | O_EXCL, 0644))) ) { + if ( EEXIST == errno ) { + c3_free(bin_c); + // XX print something here? + // + return 0; + } + else { + u3l_log("dock: init pace (%s): open %s\n", pac_c, strerror(errno)); + c3_free(bin_c); + return -1; + } + } + + if ( _king_write_raw(fid_i, (c3_y*)pac_c, strlen(pac_c)) ) { + u3l_log("dock: init pace (%s): write %s\n", pac_c, strerror(errno)); + close(fid_i); + c3_free(bin_c); + return -1; + } + // XX sync first? + // + else if ( close(fid_i) ) { + u3l_log("dock: init pace (%s): close %s\n", pac_c, strerror(errno)); + c3_free(bin_c); + return 1; + } + + u3l_log("dock: pace (%s): configured at %s/.bin/pace\r\n", + pac_c, u3_Host.dir_c); + + return 0; +} + +/* _king_link_run(): ln [bin_c] $pier/.run +*/ +static c3_i +_king_link_run(c3_c* bin_c) +{ + c3_c* lin_c; + c3_i ret_i; + + ret_i = asprintf(&lin_c, "%s/%s", u3_Host.dir_c, U3_BIN_ALIAS); + c3_assert( ret_i > 0 ); + + ret_i = unlink(lin_c); + + if ( ret_i && (ENOENT != errno) ) { + fprintf(stderr, "vere: unlink %s failed: %s\n", lin_c, strerror(errno)); + c3_free(lin_c); + return -1; + } + + ret_i = link(bin_c, lin_c); + + if ( ret_i ) { + fprintf(stderr, "vere: link %s -> %s failed: %s\n", + lin_c, bin_c, strerror(errno)); + c3_free(lin_c); + return -1; + } + + c3_free(lin_c); + return 0; +} + +/* u3_king_vere(): download binary as specified. +*/ +c3_i +u3_king_vere(c3_c* pac_c, // pace + c3_c* ver_c, // version + c3_c* arc_c, // architecture + c3_c* dir_c, // output directory + c3_t lin_t) // link to $pier/.run +{ + c3_c* bin_c; + c3_c* url_c; + FILE* fil_u; + c3_i fid_i, ret_i; + + ret_i = asprintf(&bin_c, "%s/vere-v%s-%s" U3_BIN_SUFFIX, + dir_c, ver_c, arc_c); + c3_assert( ret_i > 0 ); + + if ( (-1 == (fid_i = open(bin_c, O_WRONLY | O_CREAT | O_EXCL, 0755))) + || !(fil_u = fdopen(fid_i, "wb")) ) + { + if ( EEXIST == errno ) { + u3l_log("already installed\n"); + c3_free(bin_c); + return 0; + } + else { + u3l_log("unable to open %s: %s\r\n", bin_c, strerror(errno)); + c3_free(bin_c); + return -1; + } + } + + ret_i = asprintf(&url_c, "%s/%s/%s/vere-v%s-%s", + ver_hos_c, pac_c, ver_c, ver_c, arc_c); + c3_assert( ret_i > 0 ); + + if ( (ret_i = _king_save_file(url_c, fil_u)) ) { + u3l_log("unable to save %s to %s: %d\r\n", url_c, bin_c, ret_i); + c3_free(url_c); + fclose(fil_u); + unlink(bin_c); + c3_free(bin_c); + return -1; // XX + } + + // XX sync unnecessary here? + // + if ( fflush(fil_u) || c3_sync(fid_i) ) { + fprintf(stderr, "vere: sync %s failed: %s\n", bin_c, strerror(errno)); + c3_free(url_c); + fclose(fil_u); + unlink(bin_c); + c3_free(bin_c); + return -1; + } + + fclose(fil_u); + + // XX if link fails wat do? + // XX set via cli option + // + if ( lin_t ) { + if ( _king_link_run(bin_c) ) { + fprintf(stderr, "vere: link %s/%s failed\n", u3_Host.dir_c, U3_BIN_ALIAS); + c3_free(url_c); + c3_free(bin_c); + return -1; + } + } + + u3l_log("vere: saved to %s\n", bin_c); + + c3_free(url_c); + c3_free(bin_c); + + return 0; +} + +/* _king_do_upgrade(): get arch-appropriate binary at [ver_c]. +*/ +static void +_king_do_upgrade(c3_c* pac_c, c3_c* ver_c) +{ + c3_c* dir_c; + c3_c* arc_c; + +#ifdef U3_OS_ARCH + arc_c = U3_OS_ARCH; +#else + if ( u3_Host.arc_c ) { + arc_c = u3_Host.arc_c; + } + else { + u3l_log("vere: --arch required\r\n"); + return; + } +#endif + + if ( _king_make_pace(pac_c) ) { + u3l_log("vere: unable to make pace (%s) directory in pier\n", pac_c); + u3_king_bail(); + exit(1); + } + + { + c3_i ret_i = asprintf(&dir_c, "%s/.bin/%s", u3_Host.dir_c, pac_c); + c3_assert( ret_i > 0 ); + } + + // XX get link option + // + if ( u3_king_vere(pac_c, ver_c, arc_c, dir_c, 1) ) { + u3l_log("vere: upgrade failed\r\n"); + u3_king_bail(); + exit(1); + } + + c3_free(dir_c); + u3l_log("vere: upgrade succeeded\r\n"); + // XX print restart instructions +} + +/* _king_read_raw: read (up to) [len_i] from [fid_i] to [buf_y] +*/ +static ssize_t +_king_read_raw(c3_i fid_i, c3_y* buf_y, size_t len_i) +{ + ssize_t ret_i; + + do { + ret_i = read(fid_i, buf_y, len_i); + } + while ( (ret_i < 0) && (errno == EINTR) ); + + return ret_i; +} + +/* _king_read_raw: write [len_i] from [buf_y] to [fid_i]. +*/ +static c3_i +_king_write_raw(c3_i fid_i, c3_y* buf_y, size_t len_i) +{ + ssize_t ret_i; + + while ( len_i ) { + + do { + ret_i = write(fid_i, buf_y, len_i); + } + while ( (ret_i < 0) && (errno == EINTR) ); + + if ( ret_i < 0 ) { + return -1; + } + else { + len_i -= ret_i; + buf_y += ret_i; + } + } + + return 0; +} + +static c3_i +_king_copy_raw(c3_i src_i, c3_i dst_i, c3_y* buf_y, size_t pag_i) +{ + ssize_t red_i; + + do { + if ( 0 > (red_i = _king_read_raw(src_i, buf_y, pag_i)) ) { + return -1; + } + + if ( _king_write_raw(dst_i, buf_y, (size_t)red_i) ) { + return -1; + } + } + while ( red_i ); + + return 0; +} + +#if defined(U3_OS_mingw) +int err_win_to_posix(DWORD winerr); +#endif + +static c3_i +_king_copy_file(c3_c* src_c, c3_c* dst_c) +{ +#if defined(U3_OS_mingw) + // XX try FSCTL_DUPLICATE_EXTENTS_TO_FILE + // + if ( CopyFileA(src_c, dst_c, TRUE) ) { + return 0; + } + + // XX fallback on any? + // + errno = err_win_to_posix(GetLastError()); + return -1; +#elif defined(U3_OS_osx) + if ( !clonefile(src_c, dst_c, 0) ) { + return 0; + } + // fallthru to copying bytes on some errors + // + else if ( (ENOTSUP != errno) && (EXDEV != errno) ) { + return -1; + } +#endif + + { + c3_i src_i, dst_i, ret_i = 0, err_i = 0; + + if ( -1 == (src_i = open(src_c, O_RDONLY, 0644)) ) { + err_i = errno; + ret_i = -1; + goto done1; + } + + if ( -1 == (dst_i = open(dst_c, O_RDWR | O_CREAT, 0755)) ) { + err_i = errno; + ret_i = -1; + goto done2; + } + + // XX try clone_file_range ? + // +#if defined(U3_OS_linux) + #if defined(FICLONE) + if ( !ioctl(dst_i, FICLONE, src_i) ) { + ret_i = 0; + goto done3; + } + // fallthru to copying bytes on some errors + // + else if ( (EOPNOTSUPP != errno) && (EXDEV != errno) ) { + err_i = errno; + ret_i = -1; + goto done3; + } + #endif + + { + off_t off_i = 0; + ssize_t sen_i; + size_t len_i; + { + struct stat sat_u; + if ( -1 == fstat(src_i, &sat_u) ) { + err_i = errno; + ret_i = -1; + goto done3; + } + len_i = sat_u.st_size; + } + + do { + // XX fallback on any errors? + // + if ( 0 > (sen_i = sendfile64(dst_i, src_i, &off_i, len_i)) ) { + err_i = errno; + ret_i = -1; + goto done3; + } + + len_i -= off_i; + } + while ( len_i ); + + ret_i = 0; + goto done3; + } +#elif defined(U3_OS_osx) + if ( !fcopyfile(src_i, dst_i, NULL, COPYFILE_ALL) ) { + ret_i = 0; + goto done3; + } + + // XX fallback on any errors? + // +#endif + + { + size_t pag_i = 1 << 14;; + c3_y* buf_y = c3_malloc(pag_i); + ret_i = _king_copy_raw(src_i, dst_i, buf_y, pag_i); + err_i = errno; + c3_free(buf_y); + } + +done3: + close(dst_i); +done2: + close(src_i); +done1: + errno = err_i; + return ret_i; + } +} + +/* _king_copy_vere(): copy current binary into $pier/.bin (COW if possible) +*/ +static c3_i +_king_copy_vere(c3_c* pac_c, c3_c* ver_c, c3_c* arc_c, c3_t lin_t) +{ + c3_c* bin_c; + c3_i ret_i; + + if ( _king_make_pace(pac_c) ) { + return -1; // XX + } + + ret_i = asprintf(&bin_c, "%s/.bin/%s/vere-v%s-%s" U3_BIN_SUFFIX, + u3_Host.dir_c, pac_c, ver_c, arc_c); + c3_assert( ret_i > 0 ); + + ret_i = _king_copy_file(u3_Host.dem_c, bin_c); + + if ( ret_i ) { + fprintf(stderr, "vere: copy %s -> %s failed: %s\r\n", + bin_c, u3_Host.dem_c, strerror(errno)); + c3_free(bin_c); + return -1; + } + + // XX option + // + if ( lin_t ) { + if ( _king_link_run(bin_c) ) { + fprintf(stderr, "vere: link %s/%s failed\n", u3_Host.dir_c, U3_BIN_ALIAS); + c3_free(bin_c); + return -1; + } + } + + c3_free(bin_c); + return 0; +} + +/* u3_king_dock(): copy binary into pier on boot. +*/ +void +u3_king_dock(c3_c* pac_c) +{ + c3_c* arc_c = "unknown"; + +#ifdef U3_OS_ARCH + arc_c = U3_OS_ARCH; +#endif + + // XX get link option + // + if ( _king_copy_vere(pac_c, URBIT_VERSION, arc_c, 1) ) { + u3l_log("vere: binary copy failed\r\n"); + u3_king_bail(); + exit(1); + } + else { + // NB: failure ignored + // + _king_init_pace(pac_c); + u3l_log("vere: binary copy succeeded\r\n"); + // XX print restart instructions + } +} + /* _king_done_cb(): */ static void @@ -872,6 +1507,53 @@ u3_king_done(void) { uv_handle_t* han_u = (uv_handle_t*)&u3K.tim_u; + // get next binary + // + if ( c3y == u3_Host.nex_o ) { + c3_c* pac_c; + c3_c* ver_c; + + // hack to ensure we only try once + // + u3_Host.nex_o = c3n; + + pac_c = _king_get_pace(); + + switch ( u3_king_next(pac_c, &ver_c) ) { + case -2: { + u3l_log("vere: unable to check for next version\n"); + } break; + + case -1: { + u3l_log("vere: up to date\n"); + } break; + + case 0: { + u3l_log("vere: next (%%%s): %s\n", pac_c, ver_c); + _king_do_upgrade(pac_c, ver_c); + c3_free(ver_c); + } break; + + default: c3_assert(0); + } + + c3_free(pac_c); + } + else if ( c3y == u3_Host.pep_o ) { + u3l_log("vere: ready for upgrade\n"); + } + + // copy binary into pier on boot + // + if ( (c3y == u3_Host.ops_u.nuu) + && (c3y == u3_Host.ops_u.doc) ) + { + // hack to ensure we only try once + // + u3_Host.ops_u.nuu = c3n; + u3_king_dock(U3_VERE_PACE); + } + // XX hack, if pier's are still linked, we're not actually done // if ( !u3K.pir_u && !uv_is_closing(han_u) ) { @@ -881,6 +1563,10 @@ u3_king_done(void) u3_term_log_exit(); fflush(stdout); } + + // XX remove move + // + exit(0); } /* u3_king_exit(): shutdown gracefully @@ -924,13 +1610,13 @@ u3_king_grab(void* vod_p) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2048]; snprintf(man_c, 2048, "%s/%s-daemon.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); fprintf(fil_u, "%s\r\n", wen_c); c3_free(wen_c); diff --git a/pkg/urbit/vere/lord.c b/pkg/urbit/vere/lord.c index 25ffe60962..cc7af14f6b 100644 --- a/pkg/urbit/vere/lord.c +++ b/pkg/urbit/vere/lord.c @@ -19,7 +19,7 @@ [%meld ~] [%pack ~] == == - [%peek mil=@ sam=*] :: gang (each path $%([%once @tas @tas path] [beam @tas beam])) + [%peek mil=@ sam=*] :: gang (each path $%([%once @tas @tas path] [%beam @tas beam])) [%play eve=@ lit=(list ?((pair @da ovum) *))] [%work mil=@ job=(pair @da ovum)] == @@ -1107,17 +1107,33 @@ _lord_on_serf_bail(void* ptr_v, _lord_bail(god_u); } -/* u3_lord_info(): print status info. +/* u3_lord_info(): status info as $mass. +*/ +u3_noun +u3_lord_info(u3_lord* god_u) +{ + return u3_pier_mass( + c3__lord, + u3i_list( + u3_pier_mase("live", god_u->liv_o), + u3_pier_mase("event", u3i_chub(god_u->eve_d)), + u3_pier_mase("mug", god_u->mug_l), + u3_pier_mase("queue", u3i_word(god_u->dep_w)), + u3_newt_moat_info(&god_u->out_u), + u3_none)); +} + +/* u3_lord_slog(): print status info. */ void -u3_lord_info(u3_lord* god_u) +u3_lord_slog(u3_lord* god_u) { u3l_log(" lord: live=%s, event=%" PRIu64 ", mug=%x, queue=%u\n", ( c3y == god_u->liv_o ) ? "&" : "|", god_u->eve_d, god_u->mug_l, god_u->dep_w); - u3_newt_moat_info(&god_u->out_u); + u3_newt_moat_slog(&god_u->out_u); } /* u3_lord_init(): instantiate child process. @@ -1174,13 +1190,13 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) arg_c[6] = "0"; } - #if defined(U3_OS_mingw) - sprintf(cev_c, "%u", u3_Host.cev_u); +#ifdef U3_OS_mingw + sprintf(cev_c, "%" PRIu64, u3_Host.cev_u); arg_c[7] = cev_c; arg_c[8] = 0; - #else +#else arg_c[7] = 0; - #endif +#endif uv_pipe_init(u3L, &god_u->inn_u.pyp_u, 0); uv_timer_init(u3L, &god_u->out_u.tim_u); diff --git a/pkg/urbit/vere/newt.c b/pkg/urbit/vere/newt.c index 6325f0ef90..02dd23b10a 100644 --- a/pkg/urbit/vere/newt.c +++ b/pkg/urbit/vere/newt.c @@ -2,9 +2,11 @@ ** ** implements noun blob messages with trivial framing. ** -** a message is a 64-bit little-endian byte count, followed -** by the indicated number of bytes. the bytes are the -** the +jam of of a noun. +** framing is 5 bytes long. first byte is a version tag; a +** character that should never otherwise appear in a message +** intended for urbit. right now we use 0x0. next 32 bits are +** little-endian byte count. after that is the indicated number +** of bytes, which are the +jam of a noun. ** ** the implementation is relatively inefficient and could ** lose a few copies, mallocs, etc. @@ -109,7 +111,7 @@ _newt_meat_next_cb(uv_timer_t* tim_u) /* u3_newt_decode(): decode a (partial) length-prefixed byte buffer */ -void +c3_o u3_newt_decode(u3_moat* mot_u, c3_y* buf_y, c3_d len_d) { u3_mess* mes_u = &mot_u->mes_u; @@ -117,15 +119,15 @@ u3_newt_decode(u3_moat* mot_u, c3_y* buf_y, c3_d len_d) while ( len_d ) { switch( mes_u->sat_e ) { - // read up to 8 length bytes as needed + // read up to 5 bytes as needed // case u3_mess_head: { - c3_y* len_y = mes_u->hed_u.len_y; + c3_y* hed_y = mes_u->hed_u.hed_y; c3_y has_y = mes_u->hed_u.has_y; - c3_y ned_y = 8 - has_y; + c3_y ned_y = sizeof(mes_u->hed_u.hed_y) - has_y; c3_y cop_y = c3_min(ned_y, len_d); - memcpy(len_y + has_y, buf_y, cop_y); + memcpy(hed_y + has_y, buf_y, cop_y); buf_y += cop_y; len_d -= cop_y; ned_y -= cop_y; @@ -138,19 +140,16 @@ u3_newt_decode(u3_moat* mot_u, c3_y* buf_y, c3_d len_d) // length known, allocate message // else { - c3_d met_d = (((c3_d)len_y[0]) << 0) - | (((c3_d)len_y[1]) << 8) - | (((c3_d)len_y[2]) << 16) - | (((c3_d)len_y[3]) << 24) - | (((c3_d)len_y[4]) << 32) - | (((c3_d)len_y[5]) << 40) - | (((c3_d)len_y[6]) << 48) - | (((c3_d)len_y[7]) << 56); + c3_d met_d = (((c3_d)hed_y[1]) << 0) + | (((c3_d)hed_y[2]) << 8) + | (((c3_d)hed_y[3]) << 16) + | (((c3_d)hed_y[4]) << 24); - // must be non-zero, only 32 bits supported + // check for version tag and nonzero length // - c3_assert( met_d ); - c3_assert( 0xFFFFFFFFULL > met_d ); + if ( 0x0 != hed_y[0] || !met_d ) { + return c3n; + } // await body // @@ -183,6 +182,7 @@ u3_newt_decode(u3_moat* mot_u, c3_y* buf_y, c3_d len_d) } break; } } + return c3y; } /* _newt_read(): handle async read result. @@ -210,7 +210,11 @@ _newt_read(u3_moat* mot_u, return c3n; } else { - u3_newt_decode(mot_u, (c3_y*)buf_u->base, (c3_d)len_i); + if ( c3n == u3_newt_decode(mot_u, (c3_y*)buf_u->base, (c3_d)len_i) ) { + mot_u->bal_f(mot_u->ptr_v, -1, "newt-decode"); + c3_free(buf_u->base); + return c3n; + } c3_free(buf_u->base); return c3y; } @@ -348,10 +352,28 @@ u3_newt_read(u3_moat* mot_u) _newt_read_init(mot_u, _newt_read_cb); } -/* u3_newt_moat_info(); print status info. +/* u3_newt_moat_info(): status info as $mass. +*/ +u3_noun +u3_newt_moat_info(u3_moat* mot_u) +{ + u3_meat* met_u = mot_u->ext_u; + c3_w len_w = 0; + + while ( met_u ) { + len_w++; + met_u = met_u->nex_u; + } + return u3_pier_mass( + c3__moat, + u3i_list(u3_pier_mase("pending-inbound", u3i_word(len_w)), + u3_none)); +} + +/* u3_newt_moat_slog(); print status info. */ void -u3_newt_moat_info(u3_moat* mot_u) +u3_newt_moat_slog(u3_moat* mot_u) { u3_meat* met_u = mot_u->ext_u; c3_w len_w = 0; @@ -372,7 +394,7 @@ typedef struct _n_req { uv_write_t wri_u; u3_mojo* moj_u; c3_y* buf_y; - c3_y len_y[8]; + c3_y hed_y[5]; } n_req; /* _newt_write_cb(): generic write callback. @@ -431,18 +453,15 @@ u3_newt_send(u3_mojo* moj_u, c3_d len_d, c3_y* byt_y) // write header // - req_u->len_y[0] = ( len_d & 0xff); - req_u->len_y[1] = ((len_d >> 8) & 0xff); - req_u->len_y[2] = ((len_d >> 16) & 0xff); - req_u->len_y[3] = ((len_d >> 24) & 0xff); - req_u->len_y[4] = ((len_d >> 32) & 0xff); - req_u->len_y[5] = ((len_d >> 40) & 0xff); - req_u->len_y[6] = ((len_d >> 48) & 0xff); - req_u->len_y[7] = ((len_d >> 56) & 0xff); + req_u->hed_y[0] = 0x0; + req_u->hed_y[1] = ( len_d & 0xff); + req_u->hed_y[2] = ((len_d >> 8) & 0xff); + req_u->hed_y[3] = ((len_d >> 16) & 0xff); + req_u->hed_y[4] = ((len_d >> 24) & 0xff); { uv_buf_t buf_u[2] = { - uv_buf_init((c3_c*)req_u->len_y, 8), + uv_buf_init((c3_c*)req_u->hed_y, sizeof(req_u->hed_y)), uv_buf_init((c3_c*)req_u->buf_y, len_d) }; diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 9aad54105f..fbc3c84635 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -469,14 +469,14 @@ static void _pier_on_scry_done(void* ptr_v, u3_noun nun) { u3_pier* pir_u = ptr_v; - u3_weak res = u3r_at(7, nun); + u3_weak res = u3r_at(7, nun); if (u3_none == res) { u3l_log("pier: scry failed\n"); } else { - u3_weak out, pad; - c3_c *ext_c, *pac_c; + u3_weak out; + c3_c *ext_c, *pac_c; u3l_log("pier: scry succeeded\n"); @@ -506,32 +506,14 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) u3z(puf); } - // try to build export target path - // - { - u3_noun pro = u3m_soft(0, _pier_stab, u3i_string(pac_c)); - if ( 0 == u3h(pro) ) { - c3_w len_w = u3kb_lent(u3k(u3t(pro))); - pad = u3nt(c3_s4('.', 'u', 'r', 'b'), - c3_s3('p', 'u', 't'), - u3qb_scag(len_w - 1, u3t(pro))); - } - else { - u3l_log("pier: invalid export path %s\n", pac_c); - pad = u3_none; - } - u3z(pro); - } - // if serialization and export path succeeded, write to disk // - if ( (u3_none != out) && (u3_none != pad) ) { - c3_c fil_c[2048]; - snprintf(fil_c, 2048, "%s/.urb/put/%s.%s", - pir_u->pax_c, pac_c+1, ext_c); + if ( u3_none != out ) { + c3_c fil_c[256]; + snprintf(fil_c, 256, "%s.%s", pac_c + 1, ext_c); - u3_walk_save(fil_c, 0, out, pir_u->pax_c, pad); - u3l_log("pier: scry result in %s\n", fil_c); + u3_unix_save(fil_c, out); + u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c); } } @@ -687,7 +669,8 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 419 +#define VERE_ZUSE 418 +#define VERE_LULL 329 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ @@ -823,7 +806,7 @@ _pier_wyrd_card(u3_pier* pir_u) u3dc("scot", c3__ta, u3i_string(URBIT_VERSION)), u3_nul); u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX from both king and serf? - u3nc(c3__lull, 330), // XX define + u3nc(c3__lull, VERE_LULL), // XX from both king and serf? u3nc(c3__arvo, 240), // XX from both king and serf? u3nc(c3__hoon, 140), // god_u->hon_y u3nc(c3__nock, 4), // god_u->noc_y @@ -1049,7 +1032,17 @@ _pier_play(u3_play* pay_u) } else if ( pay_u->eve_d == log_u->dun_d ) { u3_lord_save(pir_u->god_u); - _pier_wyrd_init(pir_u); + + // early exit, preparing for upgrade + // + // XX check kelvins? + // + if ( c3y == u3_Host.pep_o ) { + u3_pier_exit(pir_u); + } + else { + _pier_wyrd_init(pir_u); + } } } else { @@ -1431,15 +1424,109 @@ _pier_on_lord_live(void* ptr_v) _pier_play_init(pir_u, eve_d); } else { - _pier_wyrd_init(pir_u); + // early exit, preparing for upgrade + // + // XX check kelvins? + // + if ( c3y == u3_Host.pep_o ) { + u3_pier_exit(pir_u); + } + else { + _pier_wyrd_init(pir_u); + } } } } -/* u3_pier_info(): print status info. +/* u3_pier_mass(): construct a $mass branch with noun/list. +*/ +u3_noun +u3_pier_mass(u3_atom cod, u3_noun lit) +{ + return u3nt(cod, c3n, lit); +} + +/* u3_pier_mase(): construct a $mass leaf. +*/ +u3_noun +u3_pier_mase(c3_c* cod_c, u3_noun dat) +{ + return u3nt(u3i_string(cod_c), c3y, dat); +} + +/* u3_pier_info(): pier status info as noun. +*/ +u3_noun +u3_pier_info(u3_pier* pir_u) +{ + u3_noun nat; + + switch (pir_u->sat_e) { + default: { + nat = u3_pier_mass(u3i_string("state-unknown"), u3_nul); + } break; + + case u3_psat_init: { + nat = u3_pier_mass(c3__init, u3_nul); + } break; + + case u3_psat_boot: { + nat = u3_pier_mass(c3__boot, u3_nul); + } break; + + case u3_psat_play: { + u3_play* pay_u = pir_u->pay_u; + + nat = u3_pier_mass(c3__play, + u3i_list( + u3_pier_mase("target", u3i_chub(pay_u->eve_d)), + u3_pier_mase("sent", u3i_chub(pay_u->sen_d)), + u3_pier_mase("read", u3i_chub(pay_u->req_d)), + u3_none)); + } break; + + case u3_psat_work: { + u3_work* wok_u = pir_u->wok_u; + + nat = u3_pier_mass(c3__work, + u3i_list( + u3_pier_mase("effects-released", u3i_chub(wok_u->fec_u.rel_d)), + u3_pier_mase("pending-any", __(wok_u->fec_u.ext_u)), + u3_pier_mase("pending-start", + ( wok_u->fec_u.ext_u + ? u3i_chub(wok_u->fec_u.ext_u->eve_d) + : 0 )), + u3_pier_mase("pending-final", + ( wok_u->fec_u.ent_u + ? u3i_chub(wok_u->fec_u.ent_u->eve_d) + : 0 )), + u3_pier_mase("wall-any", __(wok_u->wal_u)), + u3_pier_mase("wall-event", + ( wok_u->wal_u + ? u3i_chub(wok_u->wal_u->eve_d) + : 0)), + u3_pier_mass(c3__auto, u3_auto_info(wok_u->car_u)), + u3_none)); + } break; + + case u3_psat_done: { + nat = u3_pier_mass(c3__done, u3_nul); + } break; + } + + return u3_pier_mass( + c3__pier, + u3i_list( + nat, + u3_disk_info(pir_u->log_u), + u3_lord_info(pir_u->god_u), + u3_none)); +} + +/* u3_pier_slog(): print status info. */ void -u3_pier_info(u3_pier* pir_u) +u3_pier_slog(u3_pier* pir_u) { switch ( pir_u->sat_e ) { default: { @@ -1491,7 +1578,7 @@ u3_pier_info(u3_pier* pir_u) } if ( wok_u->car_u ) { - u3_auto_info(wok_u->car_u); + u3_auto_slog(wok_u->car_u); } } } break; @@ -1502,11 +1589,11 @@ u3_pier_info(u3_pier* pir_u) } if ( pir_u->log_u ) { - u3_disk_info(pir_u->log_u); + u3_disk_slog(pir_u->log_u); } if ( pir_u->god_u ) { - u3_lord_info(pir_u->god_u); + u3_lord_slog(pir_u->god_u); } } @@ -1525,6 +1612,8 @@ _pier_init(c3_w wag_w, c3_c* pax_c) // XX remove // + pir_u->per_s = u3_Host.ops_u.per_s; + pir_u->pes_s = u3_Host.ops_u.pes_s; pir_u->por_s = u3_Host.ops_u.por_s; pir_u->sav_u = c3_calloc(sizeof(u3_save)); diff --git a/pkg/urbit/vere/walk.c b/pkg/urbit/vere/walk.c deleted file mode 100644 index 5c113cbac7..0000000000 --- a/pkg/urbit/vere/walk.c +++ /dev/null @@ -1,326 +0,0 @@ -/* vere/walk.c -** -*/ -#include "all.h" -#include "vere/vere.h" - - /* |% - ** ++ arch :: fs node - ** $% [& p=@uvI q=*] :: file, hash/data - ** [| p=(map ,@ta arch)] :: directory - ** == :: - ** -- - */ - -#if 0 -static u3_noun -_walk_ok(u3_noun nod) -{ - u3_noun don = u3n_mung(u3k(u2A->toy.arch), u3k(nod)); - - if ( c3n == u3_sing(nod, don) ) { - c3_assert(0); - } - u3z(don); - return nod; -} -#endif - -/* u3_walk_safe(): load file or 0. -*/ -u3_noun -u3_walk_safe(c3_c* pas_c) -{ - struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); - c3_w fln_w, red_w; - c3_y* pad_y; - - if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - // u3l_log("%s: %s\n", pas_c, strerror(errno)); - return 0; - } - fln_w = buf_b.st_size; - pad_y = c3_malloc(buf_b.st_size); - - red_w = read(fid_i, pad_y, fln_w); - close(fid_i); - - if ( fln_w != red_w ) { - c3_free(pad_y); - return 0; - } - else { - u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y); - c3_free(pad_y); - - return pad; - } -} - -/* u3_walk_load(): load file or bail. -*/ -u3_noun -u3_walk_load(c3_c* pas_c) -{ - struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); - c3_w fln_w, red_w; - c3_y* pad_y; - - if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); - return u3m_bail(c3__fail); - } - fln_w = buf_b.st_size; - pad_y = c3_malloc(buf_b.st_size); - - red_w = read(fid_i, pad_y, fln_w); - close(fid_i); - - if ( fln_w != red_w ) { - c3_free(pad_y); - u3l_log("u3_walk_load failed"); - return u3m_bail(c3__fail); - } - else { - u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y); - c3_free(pad_y); - - return pad; - } -} - -/* _walk_mkdirp(): recursively make directories in pax at bas_c (RETAIN) -*/ -static void -_walk_mkdirp(c3_c* bas_c, u3_noun pax) -{ - c3_c* pax_c; - c3_y* waq_y; - c3_w pax_w, fas_w, len_w; - - if ( u3_nul == pax ) { - return; - } - - pax_w = u3r_met(3, u3h(pax)); - fas_w = strlen(bas_c); - len_w = 1 + fas_w + pax_w; - - pax_c = c3_malloc(1 + len_w); - strcpy(pax_c, bas_c); - - pax_c[fas_w] = '/'; - waq_y = (void*)(1 + pax_c + fas_w); - u3r_bytes(0, pax_w, waq_y, u3h(pax)); - pax_c[len_w] = '\0'; - - if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno ) { - u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); - u3m_bail(c3__fail); - } - - _walk_mkdirp(pax_c, u3t(pax)); - c3_free(pax_c); -} - -/* u3_walk_save(): save file or bail. -*/ -void -u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) -{ - c3_i fid_i = open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); - c3_w fln_w, rit_w; - c3_y* pad_y; - - if ( fid_i < 0 ) { - if ( ENOENT == errno && u3_nul != pax ) { - _walk_mkdirp(bas_c, pax); - return u3_walk_save(pas_c, tim, pad, 0, u3_nul); - } - - u3l_log("%s: %s\n", pas_c, strerror(errno)); - u3m_bail(c3__fail); - } - - fln_w = u3r_met(3, pad); - pad_y = c3_malloc(fln_w); - u3r_bytes(0, fln_w, pad_y, pad); - u3z(pad); - u3z(pax); - - rit_w = write(fid_i, pad_y, fln_w); - close(fid_i); - c3_free(pad_y); - - if ( rit_w != fln_w ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); - u3m_bail(c3__fail); - } - - if ( 0 != tim ) { - struct timeval tim_tv[2]; - - u3_time_out_tv(&tim_tv[0], u3k(tim)); - u3_time_out_tv(&tim_tv[1], tim); - - utimes(pas_c, tim_tv); - } -} - -/* _walk_in(): inner loop of _walk(), producing map. -*/ -static u3_noun -_walk_in(const c3_c* dir_c, c3_w len_w) -{ - DIR* dir_d = opendir(dir_c); - u3_noun map = u3_nul; - - if ( !dir_d ) { - return u3_nul; - } - else while ( 1 ) { - struct dirent ent_n; - struct dirent* out_n; - - if ( u3_readdir_r(dir_d, &ent_n, &out_n) != 0 ) { - u3l_log("%s: %s\n", dir_c, strerror(errno)); - break; - } - else if ( !out_n ) { - break; - } - else if ( !strcmp(out_n->d_name, ".") || - !strcmp(out_n->d_name, "..") || - ('~' == out_n->d_name[0]) || - ('.' == out_n->d_name[0]) ) // XX restricts some spans - { - continue; - } - else { - c3_c* fil_c = out_n->d_name; - c3_w lef_w = len_w + 1 + strlen(fil_c); - c3_c* pat_c = c3_malloc(lef_w + 1); - struct stat buf_b; - - strncpy(pat_c, dir_c, lef_w); - pat_c[len_w] = '/'; - strncpy(pat_c + len_w + 1, fil_c, lef_w); - pat_c[lef_w] = '\0'; - - if ( 0 != stat(pat_c, &buf_b) ) { - c3_free(pat_c); - } else { - u3_noun tim = c3_stat_mtime(&buf_b); - - if ( !S_ISDIR(buf_b.st_mode) ) { - c3_c* dot_c = strrchr(fil_c, '.'); - c3_c* nam_c = strdup(fil_c); - c3_c* ext_c = strdup(dot_c + 1); - - nam_c[dot_c - fil_c] = 0; - { - u3_noun nam = u3i_string(nam_c); - u3_noun ext = u3i_string(ext_c); - u3_noun get = u3kdb_get(u3k(map), u3k(nam)); - u3_noun dat = u3_walk_load(pat_c); - u3_noun hax; - - if ( !strcmp("noun", ext_c) ) { - dat = u3ke_cue(dat); - } - hax = u3do("sham", u3k(dat)); - if ( u3_none == get ) { get = u3_nul; } - - get = u3kdb_put(get, ext, u3nt(c3y, hax, dat)); - map = u3kdb_put(map, nam, u3nc(c3n, get)); - } - c3_free(nam_c); - c3_free(ext_c); - } - else { - u3_noun dir = _walk_in(pat_c, lef_w); - - if ( u3_nul != dir ) { - map = u3kdb_put - (map, u3i_string(fil_c), u3nc(c3n, dir)); - } - else u3z(tim); - } - c3_free(pat_c); - } - } - } - closedir(dir_d); - return map; -} - -/* u3_walk(): traverse `dir_c` to produce an arch, updating `old`. -*/ -u3_noun -u3_walk(const c3_c* dir_c, u3_noun old) -{ - // XX - obviously, cheaper to update old data. - u3z(old); - { - struct stat buf_b; - - if ( 0 != stat(dir_c, &buf_b) ) { - u3l_log("can't stat %s\n", dir_c); - // return u3m_bail(c3__fail); - c3_assert(0); - } - else { - return u3nc(c3n, - _walk_in(dir_c, strlen(dir_c))); - } - } -} - -/* u3_path(): C unix path in computer for file or directory. -*/ -c3_c* -u3_path(c3_o fyl, u3_noun pax) -{ - c3_w len_w; - c3_c *pas_c; - - // measure - // - len_w = strlen(u3_Local); - { - u3_noun wiz = pax; - - while ( u3_nul != wiz ) { - len_w += (1 + u3r_met(3, u3h(wiz))); - wiz = u3t(wiz); - } - } - - // cut - // - pas_c = c3_malloc(len_w + 1); - strncpy(pas_c, u3_Local, len_w); - pas_c[len_w] = '\0'; - { - u3_noun wiz = pax; - c3_c* waq_c = (pas_c + strlen(pas_c)); - - while ( u3_nul != wiz ) { - c3_w tis_w = u3r_met(3, u3h(wiz)); - - if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) { - *waq_c++ = '.'; - } else *waq_c++ = '/'; - - u3r_bytes(0, tis_w, (c3_y*)waq_c, u3h(wiz)); - waq_c += tis_w; - - wiz = u3t(wiz); - } - *waq_c = 0; - } - u3z(pax); - return pas_c; -} diff --git a/pkg/urbit/version b/pkg/urbit/version index 4684374946..872765e5f2 100644 --- a/pkg/urbit/version +++ b/pkg/urbit/version @@ -1 +1 @@ -1.8 \ No newline at end of file +1.9 \ No newline at end of file diff --git a/pkg/urbit/worker/main.c b/pkg/urbit/worker/main.c deleted file mode 100644 index 428e22a9a3..0000000000 --- a/pkg/urbit/worker/main.c +++ /dev/null @@ -1,533 +0,0 @@ -/* worker/main.c -** -** the main loop of a serf process. -*/ -#include "all.h" -#include "rsignal.h" -#include -#include - -#include "ur/hashcons.h" - -static u3_serf u3V; // one serf per process -static u3_moat inn_u; // input stream -static u3_mojo out_u; // output stream -static u3_cue_xeno* sil_u; // cue handle - -#undef SERF_TRACE_JAM -#undef SERF_TRACE_CUE - -/* _cw_serf_fail(): failure stub. -*/ -static void -_cw_serf_fail(void* ptr_v, ssize_t err_i, const c3_c* err_c) -{ - if ( UV_EOF == err_i ) { - fprintf(stderr, "serf: pier unexpectedly shut down\r\n"); - } - else { - fprintf(stderr, "serf: pier error: %s\r\n", err_c); - } - - exit(1); -} - -/* _cw_serf_send(): send plea back to daemon. -*/ -static void -_cw_serf_send(u3_noun pel) -{ - c3_d len_d; - c3_y* byt_y; - -#ifdef SERF_TRACE_JAM - u3t_event_trace("serf ipc jam", 'B'); -#endif - - u3s_jam_xeno(pel, &len_d, &byt_y); - -#ifdef SERF_TRACE_JAM - u3t_event_trace("serf ipc jam", 'E'); -#endif - - u3_newt_send(&out_u, len_d, byt_y); - u3z(pel); -} - -/* _cw_serf_send_slog(): send hint output (hod is [priority tank]). -*/ -static void -_cw_serf_send_slog(u3_noun hod) -{ - _cw_serf_send(u3nc(c3__slog, hod)); -} - -/* _cw_serf_send_stdr(): send stderr output (%flog) -*/ -static void -_cw_serf_send_stdr(c3_c* str_c) -{ - _cw_serf_send(u3nc(c3__flog, u3i_string(str_c))); -} - - -/* _cw_serf_step_trace(): initialize or rotate trace file. -*/ -static void -_cw_serf_step_trace(void) -{ - if ( u3C.wag_w & u3o_trace ) { - if ( u3_Host.tra_u.con_w == 0 && u3_Host.tra_u.fun_w == 0 ) { - u3t_trace_open(u3V.dir_c); - } - else if ( u3_Host.tra_u.con_w >= 100000 ) { - u3t_trace_close(); - u3t_trace_open(u3V.dir_c); - } - } -} - -/* _cw_serf_writ(): process a command from the king. -*/ -static void -_cw_serf_writ(void* vod_p, c3_d len_d, c3_y* byt_y) -{ - u3_weak jar; - u3_noun ret; - - _cw_serf_step_trace(); - -#ifdef SERF_TRACE_CUE - u3t_event_trace("serf ipc cue", 'B'); -#endif - - jar = u3s_cue_xeno_with(sil_u, len_d, byt_y); - -#ifdef SERF_TRACE_CUE - u3t_event_trace("serf ipc cue", 'E'); -#endif - - if ( (u3_none == jar) - || (c3n == u3_serf_writ(&u3V, jar, &ret)) ) - { - _cw_serf_fail(0, -1, "bad jar"); - } - else { - _cw_serf_send(ret); - - // all references must now be counted, and all roots recorded - // - u3_serf_post(&u3V); - } -} - -/* _cw_serf_stdio(): fix up std io handles -*/ -static void -_cw_serf_stdio(c3_i* inn_i, c3_i* out_i) -{ - // the serf is spawned with [FD 0] = events and [FD 1] = effects - // we dup [FD 0 & 1] so we don't accidently use them for something else - // we replace [FD 0] (stdin) with a fd pointing to /dev/null - // we replace [FD 1] (stdout) with a dup of [FD 2] (stderr) - // - c3_i nul_i = open(c3_dev_null, O_RDWR, 0); - - *inn_i = dup(0); - *out_i = dup(1); - - dup2(nul_i, 0); - dup2(2, 1); - - close(nul_i); - - // set stream I/O to unbuffered because it's now a pipe not a console - // - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); -} - -/* _cw_serf_stdio(): cleanup on serf exit. -*/ -static void -_cw_serf_exit(void) -{ - u3s_cue_xeno_done(sil_u); - u3t_trace_close(); -} - -#if defined(U3_OS_mingw) -/* _mingw_ctrlc_cb(): invoked when the lord signals the Ctrl-C event -*/ -static void -_mingw_ctrlc_cb(PVOID param, BOOLEAN timedOut) -{ - rsignal_raise(SIGINT); -} -#endif - -/* _cw_serf_commence(); initialize and run serf -*/ -static void -_cw_serf_commence(c3_i argc, c3_c* argv[]) -{ - c3_i inn_i, out_i; - _cw_serf_stdio(&inn_i, &out_i); - - #if defined(U3_OS_mingw) - c3_assert( 8 == argc ); - - // Initialize serf's end of Ctrl-C handling - // - { - HANDLE h; - if ( 1 != sscanf(argv[7], "%u", &h) ) { - fprintf(stderr, "serf: Ctrl-C event: bad handle %s: %s\r\n", argv[7], strerror(errno)); - } else - if ( !RegisterWaitForSingleObject(&h, h, _mingw_ctrlc_cb, NULL, INFINITE, 0) ) { - fprintf(stderr, "serf: Ctrl-C event: RegisterWaitForSingleObject(%u) failed (%d)\r\n", h, GetLastError()); - } - } - #else - c3_assert( 7 == argc ); - #endif - - uv_loop_t* lup_u = uv_default_loop(); - c3_c* dir_c = argv[2]; - c3_c* key_c = argv[3]; - c3_c* wag_c = argv[4]; - c3_c* hap_c = argv[5]; - c3_d eve_d = 0; - - if ( 1 != sscanf(argv[6], "%" PRIu64 "", &eve_d) ) { - fprintf(stderr, "serf: rock: invalid number '%s'\r\n", argv[4]); - } - - memset(&u3V, 0, sizeof(u3V)); - memset(&u3_Host.tra_u, 0, sizeof(u3_Host.tra_u)); - - // load passkey - // - // XX and then ... use passkey - // - { - sscanf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64 "", - &u3V.key_d[0], - &u3V.key_d[1], - &u3V.key_d[2], - &u3V.key_d[3]); - } - - // load runtime config - // - { - sscanf(wag_c, "%" SCNu32, &u3C.wag_w); - sscanf(hap_c, "%" SCNu32, &u3_Host.ops_u.hap_w); - } - - // Ignore SIGPIPE signals. - // - #ifndef U3_OS_mingw - { - struct sigaction sig_s = {{0}}; - sigemptyset(&(sig_s.sa_mask)); - sig_s.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sig_s, 0); - } - #endif - - // configure pipe to daemon process - // - { - c3_i err_i; - - err_i = uv_timer_init(lup_u, &inn_u.tim_u); - c3_assert(!err_i); - err_i = uv_pipe_init(lup_u, &inn_u.pyp_u, 0); - c3_assert(!err_i); - uv_pipe_open(&inn_u.pyp_u, inn_i); - - err_i = uv_pipe_init(lup_u, &out_u.pyp_u, 0); - c3_assert(!err_i); - uv_pipe_open(&out_u.pyp_u, out_i); - - uv_stream_set_blocking((uv_stream_t*)&out_u.pyp_u, 1); - } - - sil_u = u3s_cue_xeno_init(); - - // set up writing - // - out_u.ptr_v = &u3V; - out_u.bal_f = _cw_serf_fail; - - // set up reading - // - inn_u.ptr_v = &u3V; - inn_u.pok_f = _cw_serf_writ; - inn_u.bal_f = _cw_serf_fail; - - // setup loom - // - { - u3V.dir_c = strdup(dir_c); - u3V.sen_d = u3V.dun_d = u3m_boot(dir_c); - - if ( eve_d ) { - // XX need not be fatal, need a u3m_reboot equivalent - // XX can spuriously fail do to corrupt memory-image checkpoint, - // need a u3m_half_boot equivalent - // workaround is to delete/move the checkpoint in case of corruption - // - if ( c3n == u3u_uncram(u3V.dir_c, eve_d) ) { - fprintf(stderr, "serf (%" PRIu64 "): rock load failed\r\n", eve_d); - exit(1); - } - } - } - - // set up logging - // - // XX must be after u3m_boot due to u3l_log - // - { - u3C.stderr_log_f = _cw_serf_send_stdr; - u3C.slog_f = _cw_serf_send_slog; - } - - u3V.xit_f = _cw_serf_exit; - -#if defined(SERF_TRACE_JAM) || defined(SERF_TRACE_CUE) - u3t_trace_open(u3V.dir_c); -#endif - - // start serf - // - { - _cw_serf_send(u3_serf_init(&u3V)); - } - - // start reading - // - u3_newt_read_sync(&inn_u); - - // enter loop - // - uv_run(lup_u, UV_RUN_DEFAULT); - u3m_stop(); -} - -/* _cw_info(); print pier info -*/ -static void -_cw_info(c3_i argc, c3_c* argv[]) -{ - c3_assert( 3 <= argc ); - - c3_c* dir_c = argv[2]; - c3_d eve_d = u3m_boot(dir_c); - - fprintf(stderr, "urbit-worker: %s at event %" PRIu64 "\r\n", dir_c, eve_d); - u3m_stop(); -} - -/* _cw_grab(); gc pier. -*/ -static void -_cw_grab(c3_i argc, c3_c* argv[]) -{ - c3_assert( 3 <= argc ); - - c3_c* dir_c = argv[2]; - u3m_boot(dir_c); - u3C.wag_w |= u3o_hashless; - u3_serf_grab(); - u3m_stop(); -} - -/* _cw_cram(); jam persistent state (rock), and exit. -*/ -static void -_cw_cram(c3_i argc, c3_c* argv[]) -{ - c3_assert( 3 <= argc ); - - c3_c* dir_c = argv[2]; - c3_d eve_d = u3m_boot(dir_c); - c3_o ret_o; - - fprintf(stderr, "urbit-worker: cram: preparing\r\n"); - - if ( c3n == (ret_o = u3u_cram(dir_c, eve_d)) ) { - fprintf(stderr, "urbit-worker: cram: unable to jam state\r\n"); - } - else { - fprintf(stderr, "urbit-worker: cram: rock saved at event %" PRIu64 "\r\n", eve_d); - } - - // save even on failure, as we just did all the work of deduplication - // - u3e_save(); - - if ( c3n == ret_o ) { - exit(1); - } - - u3m_stop(); -} - -/* _cw_queu(); cue rock, save, and exit. -*/ -static void -_cw_queu(c3_i argc, c3_c* argv[]) -{ - c3_assert( 4 <= argc ); - - c3_c* dir_c = argv[2]; - c3_c* eve_c = argv[3]; - c3_d eve_d; - - if ( 1 != sscanf(eve_c, "%" PRIu64 "", &eve_d) ) { - fprintf(stderr, "urbit-worker: queu: invalid number '%s'\r\n", eve_c); - exit(1); - } - else { - fprintf(stderr, "urbit-worker: queu: preparing\r\n"); - - memset(&u3V, 0, sizeof(u3V)); - u3V.dir_c = strdup(dir_c); - u3V.sen_d = u3V.dun_d = u3m_boot(dir_c); - - // XX can spuriously fail do to corrupt memory-image checkpoint, - // need a u3m_half_boot equivalent - // workaround is to delete/move the checkpoint in case of corruption - // - if ( c3n == u3u_uncram(dir_c, eve_d) ) { - fprintf(stderr, "urbit-worker: queu: failed\r\n"); - exit(1); - } - - u3e_save(); - - fprintf(stderr, "urbit-worker: queu: rock loaded at event %" PRIu64 "\r\n", eve_d); - u3m_stop(); - } -} - -/* _cw_uniq(); deduplicate persistent nouns -*/ -static void -_cw_meld(c3_i argc, c3_c* argv[]) -{ - c3_assert( 3 <= argc ); - - c3_c* dir_c = argv[2]; - - u3C.wag_w |= u3o_hashless; - u3m_boot(dir_c); - - u3_serf_grab(); - - u3u_meld(); - - u3_serf_grab(); - - u3e_save(); -} - -/* _cw_pack(); compact memory, save, and exit. -*/ -static void -_cw_pack(c3_i argc, c3_c* argv[]) -{ - c3_assert( 3 <= argc ); - - c3_c* dir_c = argv[2]; - - u3m_boot(dir_c); - u3a_print_memory(stderr, "urbit-worker: pack: gained", u3m_pack()); - - u3e_save(); - u3m_stop(); -} - -/* _cw_usage(): print urbit-worker usage. -*/ -static void -_cw_usage(c3_i argc, c3_c* argv[]) -{ - fprintf(stderr, - "\rurbit-worker usage:\n" - " print pier info:\n" - " %s info \n\n" - " gc persistent state:\n" - " %s grab \n\n" - " compact persistent state:\n" - " %s pack \n\n" - " deduplicate persistent state:\n" - " %s meld \n\n" - " jam persistent state:\n" - " %s cram \n\n" - " cue persistent state:\n" - " %s queu \n\n" - " run as a 'serf':\n" - " %s serf " - #if defined(U3_OS_mingw) - " " - #endif - "\n", - argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0]); -} - -/* main(): main() when run as urbit-worker -*/ -c3_i -main(c3_i argc, c3_c* argv[]) -{ - // urbit-worker commands and positional arguments, by analogy - // - // $@ ~ ;; usage - // $% [%cram dir=@t] - // [%queu dir=@t eve=@ud] - // [%pack dir=@t] - // [%serf dir=@t key=@t wag=@t hap=@ud eve=@ud] - // == - // - // NB: don't print to anything other than stderr; - // other streams may have special requirements (in the case of "serf") - // - if ( 2 > argc ) { - _cw_usage(argc, argv); - exit(1); - } - else { - if ( 0 == strcmp("serf", argv[1]) ) { - _cw_serf_commence(argc, argv); - } - else if ( 0 == strcmp("info", argv[1]) ) { - _cw_info(argc, argv); - } - else if ( 0 == strcmp("grab", argv[1]) ) { - _cw_grab(argc, argv); - } - else if ( 0 == strcmp("cram", argv[1]) ) { - _cw_cram(argc, argv); - } - else if ( 0 == strcmp("queu", argv[1]) ) { - _cw_queu(argc, argv); - } - else if ( 0 == strcmp("meld", argv[1]) ) { - _cw_meld(argc, argv); - } - else if ( 0 == strcmp("pack", argv[1]) ) { - _cw_pack(argc, argv); - } - else { - fprintf(stderr, "unknown command '%s'\r\n", argv[1]); - _cw_usage(argc, argv); - exit(1); - } - } - - return 0; -} diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 55cb3ad7d8..982cb8ec96 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -204,13 +204,13 @@ _serf_grab(u3_noun sac) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2054]; snprintf(man_c, 2053, "%s/%s-serf.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); fprintf(fil_u, "%s\r\n", wen_c); c3_free(wen_c); @@ -835,13 +835,13 @@ _serf_writ_live_exit(u3_serf* sef_u, c3_w cod_w) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2054]; snprintf(man_c, 2053, "%s/%s.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); c3_free(wen_c); u3z(wen); diff --git a/pkg/urcrypt/configure.ac b/pkg/urcrypt/configure.ac index bfafbc0243..bdf78c10ff 100644 --- a/pkg/urcrypt/configure.ac +++ b/pkg/urcrypt/configure.ac @@ -58,6 +58,8 @@ AC_PROG_CC PKG_CHECK_MODULES([LIBSECP256K1], [libsecp256k1]) AC_CHECK_HEADER([secp256k1_recovery.h], [], [AC_MSG_ERROR([libsecp256k1 must have recovery enabled.])]) +AC_CHECK_HEADER([secp256k1_schnorrsig.h], [], + [AC_MSG_ERROR([libsecp256k1 must have Schnorr signatures enabled.])]) PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto]) AS_IF([test "$enable_shared" == "yes"], diff --git a/pkg/urcrypt/urcrypt/secp256k1.c b/pkg/urcrypt/urcrypt/secp256k1.c index 0e8a05caf3..8c599b6c32 100644 --- a/pkg/urcrypt/urcrypt/secp256k1.c +++ b/pkg/urcrypt/urcrypt/secp256k1.c @@ -2,8 +2,10 @@ #include "util.h" #include #include +#include #include #include +#include #define SECP_FLAGS SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN @@ -196,3 +198,48 @@ urcrypt_secp_reco(urcrypt_secp_context* context, } } } + +int +urcrypt_secp_schnorr_sign(urcrypt_secp_context* context, + uint8_t key[32], + uint8_t msg[32], + uint8_t aux[32], + uint8_t out_sig[64]) +{ + secp256k1_keypair keypair; + + urcrypt__reverse(32, key); + urcrypt__reverse(32, msg); + urcrypt__reverse(32, aux); + + if ( 1 != secp256k1_keypair_create(context->secp, &keypair, key) ) { + return -1; + } + if ( 1 != secp256k1_schnorrsig_sign(context->secp, out_sig, msg, &keypair, aux) ) { + return -1; + } + + urcrypt__reverse(64, out_sig); + return 0; +} + +bool +urcrypt_secp_schnorr_veri(urcrypt_secp_context* context, + uint8_t sig[64], + uint8_t msg[32], + uint8_t pub[32]) +{ + secp256k1_xonly_pubkey pubkey; + + urcrypt__reverse(64, sig); + urcrypt__reverse(32, msg); + urcrypt__reverse(32, pub); + + if ( 1 != secp256k1_xonly_pubkey_parse(context->secp, &pubkey, pub) ) { + return false; + } + if ( 1 != secp256k1_schnorrsig_verify(context->secp, sig, msg, 32, &pubkey) ) { + return false; + } + return true; +} diff --git a/pkg/urcrypt/urcrypt/urcrypt.h b/pkg/urcrypt/urcrypt/urcrypt.h index 33870f2c3d..682531b948 100644 --- a/pkg/urcrypt/urcrypt/urcrypt.h +++ b/pkg/urcrypt/urcrypt/urcrypt.h @@ -39,8 +39,8 @@ void urcrypt_ed_sign(const uint8_t *message, // return value means the signature was (not) verified bool urcrypt_ed_veri(const uint8_t *message, size_t length, - const uint8_t signature[64], - const uint8_t public[32]); + const uint8_t public[32], + const uint8_t signature[64]); int urcrypt_aes_ecba_en(uint8_t key[16], uint8_t block[16], uint8_t out[16]); int urcrypt_aes_ecba_de(uint8_t key[16], uint8_t block[16], uint8_t out[16]); @@ -202,6 +202,16 @@ int urcrypt_secp_reco(urcrypt_secp_context* context, const uint8_t key_s[32], uint8_t out_x[32], uint8_t out_y[32]); +int urcrypt_secp_schnorr_sign(urcrypt_secp_context* context, + uint8_t key[32], + uint8_t msg[32], + uint8_t aux[32], + uint8_t out_sig[64]); +// return value means signature was (not) verified +bool urcrypt_secp_schnorr_veri(urcrypt_secp_context* context, + uint8_t sig[64], + uint8_t msg[32], + uint8_t pub[32]); void urcrypt_scrypt_pbkdf_sha256(const uint8_t *passwd, size_t passwdlen, diff --git a/pkg/webterm/sys.kelvin b/pkg/webterm/sys.kelvin index e68acb6a4c..e77a3de08a 100644 --- a/pkg/webterm/sys.kelvin +++ b/pkg/webterm/sys.kelvin @@ -1 +1 @@ -[%zuse 419] +[%zuse 418]