Merge branch 'release/next-userspace' into lf/grid-leap-ally

This commit is contained in:
Jake Miller 2021-10-06 18:10:43 -04:00 committed by GitHub
commit ff81f00ec3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
342 changed files with 107825 additions and 4307 deletions

View File

@ -116,3 +116,24 @@ jobs:
- run: nix-build -A hs.urbit-king.components.exes.urbit-king --arg enableStatic true
- run: nix-build -A hs-checks
- run: nix-build shell.nix
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

4
.gitignore vendored
View File

@ -55,7 +55,11 @@ release/
dist/
out/
work/
pkg/*/*.a
*.o
*.so
*.dll
*.dylib
# Landscape Dev
urbitrc

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0af91e5c51359719aaa943f37a1e953989c786412616b18fbaa0addb2cf0740
size 10272514
oid sha256:9a56f675d2a6c5dafa92a9e2d55040d994f3d3d27a1ed827bd87d1158b1e69d0
size 3749183

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:23d8235b19a3404e0bfbed54aa56a018255beb1f33457e37f521bc0763b4d0eb
size 6245506
oid sha256:f50aee74e4f3dd6685d36520bbc924ab94d3d47a7bc86e649882e58ab069e7dd
size 991930

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5159d6516c0b3d12b3c7f39f434ab769e99392dc94aa43add32bb2a91455c73a
size 6121099
oid sha256:8229a2dc1908d4bb322a3300e68f79e79e3352507b8ef68d40e802bcbdb19550
size 5437325

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4427b6e4a925502fe2e63087e190dfe0c77f75644dfe31a306de64d269b128f2
size 14661883
oid sha256:618a74c199baa6d52ae9eea8c40f4f5b15e95b441e743d0f989275321e5b0703
size 7299622

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8baf284490d8c7cfbad2481f1ef0d17a6bb05200bc179b78c1a8718461756a06
size 12941119
oid sha256:d8d387759fe4830fcc09a1fc7b80d52e61327d518f7eb0713697aec1819eacf7
size 5608210

View File

@ -86,19 +86,11 @@ let
# Local vendored packages defined in ./pkg.
# For non-vendored nixpkgs specific package overrides, see ./nix/overlays.
pkgsLocal = {
argon2u = callPackage ./nix/pkgs/argon2u { };
ca-bundle = callPackage ./nix/pkgs/ca-bundle { };
ed25519 = callPackage ./nix/pkgs/ed25519 { };
ent = callPackage ./nix/pkgs/ent { };
ge-additions = callPackage ./nix/pkgs/ge-additions { };
libaes_siv = callPackage ./nix/pkgs/libaes_siv { };
libscrypt = callPackage ./nix/pkgs/libscrypt { };
libaes_siv = callPackage ./nix/pkgs/libaes_siv { inherit (pkgsNative) cmake; };
murmur3 = callPackage ./nix/pkgs/murmur3 { };
@ -118,6 +110,8 @@ let
urbit = callPackage ./nix/pkgs/urbit { inherit enableStatic; };
urcrypt = callPackage ./nix/pkgs/urcrypt { inherit enableStatic; };
docker-image = callPackage ./nix/pkgs/docker-image { };
hs = callPackage ./nix/pkgs/hs {

View File

@ -11,6 +11,11 @@ in {
outputs = [ "out" "dev" "lib" ];
});
secp256k1 = prev.secp256k1.overrideAttrs (_attrs: {
version = final.sources.secp256k1.rev;
src = final.sources.secp256k1;
});
libsigsegv = prev.libsigsegv.overrideAttrs (attrs: {
patches = optionalList attrs.patches ++ [
../pkgs/libsigsegv/disable-stackvma_fault-linux-arm.patch

View File

@ -1,30 +0,0 @@
{ stdenv, sources, enableParallelBuilding ? true }:
stdenv.mkDerivation {
pname = "argon2u";
version = sources.argon2u.rev;
src = sources.argon2u;
postPatch = ''
substituteInPlace Makefile --replace 'ar rcs' '$(AR) rcs'
'';
buildPhase = ''
make libargon2.a
'';
installPhase = ''
mkdir -p $out/{lib,include}
cp libargon2.a $out/lib/
cp include/argon2.h $out/include/
cp ./src/blake2/*.h $out/include/
'';
makeFlags = [
"AR=${stdenv.cc.targetPrefix}ar" # Fix cross-compilation
];
NO_THREADS = true;
inherit enableParallelBuilding;
}

View File

@ -1,21 +0,0 @@
{ stdenv, sources }:
stdenv.mkDerivation {
pname = "ed25519";
version = sources.ed25519.rev;
src = sources.ed25519;
buildPhase = ''
CFLAGS="-O3 -Wall -I$src/src"
for f in $(find src -type f -name '*.c'); do
$CC $CFLAGS -c $f -o "''${f//\//_}.o"
done
'';
installPhase = ''
mkdir -p $out/{lib,include}
$AR rcs $out/lib/libed25519.a *.o
cp $src/src/*.h $out/include/
'';
}

View File

@ -1,13 +0,0 @@
{ lib, stdenv, ed25519, enableParallelBuilding ? true }:
stdenv.mkDerivation {
name = "ge-additions";
src = lib.cleanSource ../../../pkg/ge-additions;
buildInputs = [ ed25519 ];
installFlags = [ "PREFIX=$(out)" ];
inherit enableParallelBuilding;
}

View File

@ -0,0 +1,34 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,6 +5,8 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
endif("${CMAKE_BUILD_TYPE}" STREQUAL "")
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+
include(GNUInstallDirs)
# Warning: don't use the UB sanitizer in production builds. It can introduce timing side-channels
@@ -31,10 +33,12 @@ endif(NOT DISABLE_DOCS)
configure_file(config.h.in config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
+if(BUILD_SHARED_LIBS)
add_library(aes_siv SHARED aes_siv.c)
target_include_directories(aes_siv PUBLIC ${OPENSSL_INCLUDE_DIR})
target_link_libraries(aes_siv ${OPENSSL_CRYPTO_LIBRARY})
set_target_properties(aes_siv PROPERTIES VERSION "1.0.1" SOVERSION 1)
+endif()
add_library(aes_siv_static STATIC aes_siv.c)
target_include_directories(aes_siv_static PUBLIC ${OPENSSL_INCLUDE_DIR})
@@ -63,7 +67,9 @@ endif(ENABLE_SANITIZER)
add_executable(bench EXCLUDE_FROM_ALL bench.c)
target_link_libraries(bench aes_siv_static)
+if(BUILD_SHARED_LIBS)
install(TARGETS aes_siv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+endif()
install(TARGETS aes_siv_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES aes_siv.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@ -1,12 +1,17 @@
{ lib, stdenv, openssl, enableParallelBuilding ? true }:
{ stdenv, sources, cmake, openssl, enableParallelBuilding ? true }:
stdenv.mkDerivation {
name = "libaes_siv";
src = lib.cleanSource ../../../pkg/libaes_siv;
version = sources.libaes_siv.rev;
src = sources.libaes_siv;
patches = [ ./cmakefiles_static.patch ];
nativeBuildInputs = [ cmake ];
buildInputs = [ openssl ];
installFlags = [ "PREFIX=$(out)" ];
cmakeFlags = [
"-DBUILD_SHARED_LIBS=OFF"
];
inherit enableParallelBuilding;
}

View File

@ -1,35 +0,0 @@
{ stdenv, sources }:
stdenv.mkDerivation {
pname = "libscrypt";
version = sources.libscrypt.rev;
src = sources.libscrypt;
buildPhase = ''
sources=" \
crypto_scrypt-check \
crypto_scrypt-hash \
crypto_scrypt-hexconvert \
crypto_scrypt-nosse \
crypto-mcf \
crypto-scrypt-saltgen \
slowequals \
sha256 \
b64 \
"
CFLAGS="-I$src -Wall -ffast-math -O3 -D_FORTIFY_SOURCE=2 -fstack-protector"
for s in $sources; do
$CC $CFLAGS -c $src/$s.c -o $s.o
done
$AR rcs libscrypt.a *.o
'';
installPhase = ''
mkdir -p $out/{lib,include}
cp libscrypt.a $out/lib
cp $src/*.h $out/include/
'';
}

View File

@ -1,8 +1,12 @@
{ lib, stdenv, coreutils, pkgconfig, argon2u, cacert, ca-bundle, curlMinimal
, ed25519, ent, ge-additions, gmp, h2o, herb, ivory, libaes_siv, libscrypt
, libsigsegv, libuv, lmdb, murmur3, openssl, secp256k1, softfloat3, zlib
, enableStatic ? stdenv.hostPlatform.isStatic, enableDebug ? false
, doCheck ? true, enableParallelBuilding ? true, dontStrip ? true }:
{ lib, stdenv, coreutils, pkgconfig # build/env
, cacert, ca-bundle, ivory # codegen
, curlMinimal, ent, gmp, h2o, libsigsegv, libuv, lmdb # libs
, murmur3, openssl, softfloat3, urcrypt, zlib #
, enableStatic ? stdenv.hostPlatform.isStatic # opts
, enableDebug ? false
, doCheck ? true
, enableParallelBuilding ? true
, dontStrip ? true }:
let
@ -19,30 +23,23 @@ in stdenv.mkDerivation {
nativeBuildInputs = [ pkgconfig ];
buildInputs = [
argon2u
cacert
ca-bundle
curlMinimal
ed25519
ent
ge-additions
gmp
h2o
ivory.header
libaes_siv
libscrypt
libsigsegv
libuv
lmdb
murmur3
openssl
secp256k1
softfloat3
urcrypt
zlib
];
checkInputs = [ herb ];
# Ensure any `/usr/bin/env bash` shebang is patched.
postPatch = ''
patchShebangs ./configure
@ -56,9 +53,14 @@ in stdenv.mkDerivation {
cp ./build/urbit-worker $out/bin/urbit-worker
'';
dontDisableStatic = enableStatic;
configureFlags = if enableStatic
then [ "--disable-shared" "--enable-static" ]
else [];
CFLAGS = [ (if enableDebug then "-O0" else "-O3") "-g" ]
++ lib.optionals (!enableDebug) [ "-Werror" ]
++ lib.optionals enableStatic [ "-static" ];
++ lib.optionals (!enableDebug) [ "-Werror" ];
MEMORY_DEBUG = enableDebug;
CPU_DEBUG = enableDebug;

View File

@ -0,0 +1,21 @@
{ stdenv, autoreconfHook, pkgconfig
, libaes_siv, openssl, secp256k1
, enableStatic ? stdenv.hostPlatform.isStatic }:
stdenv.mkDerivation rec {
name = "urcrypt";
src = ../../../pkg/urcrypt;
# XX why are these required for darwin?
dontDisableStatic = enableStatic;
configureFlags = if enableStatic
then [ "--disable-shared" "--enable-static" ]
else [];
nativeBuildInputs =
[ autoreconfHook pkgconfig ];
propagatedBuildInputs =
[ openssl secp256k1 libaes_siv ];
}

65
nix/sources-pmnsh.json Normal file
View File

@ -0,0 +1,65 @@
{
"curl": {
"branch": "master",
"description": "A command line tool and library for transferring data with URL syntax",
"homepage": "http://curl.se/",
"pmnsh": {
"include": "include",
"lib": "lib/.libs",
"prepare": "autoreconf -vfi && ./configure --disable-shared --disable-ldap --disable-rtsp --without-brotli --without-libidn2 --without-libpsl --without-nghttp2 --with-openssl",
"make": "-C lib libcurl.la"
},
"owner": "curl",
"repo": "curl",
"rev": "curl-7_77_0",
"type": "tarball",
"url": "https://github.com/curl/curl/archive/curl-7_77_0.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"lmdb": {
"branch": "mdb.master",
"description": "LMDB library",
"homepage": "http://www.lmdb.tech/",
"pmnsh": {
"strip": 2,
"make": "liblmdb.a"
},
"owner": "LMDB",
"repo": "lmdb",
"rev": "48a7fed59a8aae623deff415dda27097198ca0c1",
"type": "tarball",
"url": "https://github.com/LMDB/lmdb/archive/48a7fed59a8aae623deff415dda27097198ca0c1.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"uv": {
"branch": "v1.x",
"description": "Cross-platform asynchronous I/O",
"homepage": "http://libuv.org/",
"pmnsh": {
"include": "include",
"lib": ".libs",
"prepare": "./autogen.sh && ./configure --disable-shared",
"make": "libuv.la",
"compat": {
"m1brew": false
}
},
"owner": "libuv",
"repo": "libuv",
"rev": "v1.40.0",
"type": "tarball",
"url": "https://github.com/libuv/libuv/archive/v1.40.0.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"ent": {
"pmnsh": {
"prepare": "./configure"
}
},
"urcrypt": {
"pmnsh": {
"prepare": "./autogen.sh && ./configure --disable-shared PKG_CONFIG_PATH=../secp256k1 CFLAGS=\"-I../secp256k1/include -I../libaes_siv\" LDFLAGS=-L../libaes_siv",
"make": "install"
}
}
}

View File

@ -1,38 +1,24 @@
{
"argon2u": {
"branch": "master",
"description": "With argon2u. Based off https://github.com/P-H-C/phc-winner-argon2",
"homepage": "",
"owner": "urbit",
"repo": "argon2",
"rev": "4da94a611ee62bad87ab2b131ffda3bcc0723d9c",
"sha256": "0bqq1hg367l4jkb6cqhxlblpvdbwz3l586qsfakwzfd9wdvnm3yc",
"type": "tarball",
"url": "https://github.com/urbit/argon2/archive/4da94a611ee62bad87ab2b131ffda3bcc0723d9c.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"ed25519": {
"branch": "master",
"description": "Submodule included by Urbit",
"homepage": null,
"owner": "urbit",
"repo": "ed25519",
"rev": "76385f2ebbbc9580a9c236952d68d11d73a6135c",
"sha256": "0s1spif4s9lgcwcny3fl2fvpbw6acqn3s8r6qxnrmkd9icgyw4cp",
"type": "tarball",
"url": "https://github.com/urbit/ed25519/archive/76385f2ebbbc9580a9c236952d68d11d73a6135c.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"h2o": {
"branch": "master",
"description": "H2O - the optimized HTTP/1, HTTP/2, HTTP/3 server",
"homepage": "https://h2o.examp1e.net",
"pmnsh": {
"include": "include",
"prepare": "cmake .",
"make": "libh2o",
"compat": {
"mingw": {
"prepare": "cmake -G\"MSYS Makefiles\" -DCMAKE_INSTALL_PREFIX=. ."
}
}
},
"owner": "h2o",
"repo": "h2o",
"rev": "v2.2.4",
"sha256": "0176x0bzjry19zs074a9i5vhncc842xikmx43wj61jky318nq4w4",
"rev": "v2.2.6",
"sha256": "0qni676wqvxx0sl0pw9j0ph7zf2krrzqc1zwj73mgpdnsr8rsib7",
"type": "tarball",
"url": "https://github.com/h2o/h2o/archive/v2.2.4.tar.gz",
"url": "https://github.com/h2o/h2o/archive/v2.2.6.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"hackage.nix": {
@ -59,22 +45,37 @@
"url": "https://github.com/input-output-hk/haskell.nix/archive/bbb34dcdf7b90d478002f91713531f418ddf1b53.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"libscrypt": {
"libaes_siv": {
"branch": "master",
"description": null,
"homepage": null,
"owner": "urbit",
"repo": "libscrypt",
"rev": "029693ff1cbe4f69d3a2da87d0f4f034f92cc0c2",
"sha256": "17pcxypzjmmrvacw45cacvibm6mlr9ip30hy30l1appsnywx679n",
"pmnsh": {
"compat": {
"m1brew": {
"prepare": "cmake .",
"make": "install CFLAGS=$(pkg-config --cflags openssl)"
},
"mingw": {
"prepare": "cmake -G\"MSYS Makefiles\" -DDISABLE_DOCS:BOOL=ON .",
"make": "aes_siv_static"
}
}
},
"owner":"dfoxfranke",
"repo": "libaes_siv",
"rev": "9681279cfaa6e6399bb7ca3afbbc27fc2e19df4b",
"sha256": "1g4wy0m5wpqx7z6nillppkh5zki9fkx9rdw149qcxh7mc5vlszzi",
"type": "tarball",
"url": "https://github.com/urbit/libscrypt/archive/029693ff1cbe4f69d3a2da87d0f4f034f92cc0c2.tar.gz",
"url": "https://github.com/dfoxfranke/libaes_siv/archive/9681279cfaa6e6399bb7ca3afbbc27fc2e19df4b.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"murmur3": {
"branch": "master",
"description": null,
"homepage": null,
"pmnsh": {
"make": "static"
},
"owner": "urbit",
"repo": "murmur3",
"rev": "71a75d57ca4e7ca0f7fc2fd84abd93595b0624ca",
@ -111,6 +112,19 @@
"branch": "master",
"description": null,
"homepage": null,
"pmnsh": {
"include": "source/include",
"compat": {
"m1brew": {
"lib": "build/template-FAST_INT64",
"make": "-C build/template-FAST_INT64 libsoftfloat3.a"
},
"mingw": {
"lib": "build/Win64-MinGW-w64",
"make": "-C build/Win64-MinGW-w64 libsoftfloat3.a"
}
}
},
"owner": "urbit",
"repo": "berkeley-softfloat-3",
"rev": "ec4c7e31b32e07aad80e52f65ff46ac6d6aad986",
@ -119,6 +133,24 @@
"url": "https://github.com/urbit/berkeley-softfloat-3/archive/ec4c7e31b32e07aad80e52f65ff46ac6d6aad986.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"secp256k1": {
"branch": "master",
"description": "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1.",
"homepage": null,
"pmnsh": {
"include": "include",
"lib": ".libs",
"prepare": "./autogen.sh && ./configure --disable-shared --enable-module-recovery CFLAGS=-DSECP256K1_API=",
"make": "libsecp256k1.la"
},
"owner": "bitcoin-core",
"repo": "secp256k1",
"rev": "26de4dfeb1f1436dae1fcf17f57bdaa43540f940",
"sha256": "03i3nv8d3ci7q9y98q11rrp3rvwdqc0hc0ss0pr6xckybvizsmbb",
"type": "tarball",
"url": "https://github.com/bitcoin-core/secp256k1/archive/26de4dfeb1f1436dae1fcf17f57bdaa43540f940.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"stackage.nix": {
"branch": "master",
"description": "Automatically generated Nix expressions of Stackage snapshots",

View File

@ -12,7 +12,7 @@
=> |% :: external structures
+$ id @tasession :: session id
+$ house :: all state
$: %7
$: %8
egg=@u :: command count
hoc=(map id session) :: conversations
acl=(set ship) :: remote access whitelist
@ -65,7 +65,7 @@
$~ [%ex *hoon]
$% [%ur p=@t] :: http GET request
[%ge p=dojo-model] :: generator
[%te p=term q=(list dojo-source)] :: thread
[%te p=[=desk =term] q=(list dojo-source)] :: thread
[%dv p=beak q=path] :: core from source
[%ex p=hoon] :: hoon expression
[%sa p=mark] :: example mark value
@ -224,7 +224,7 @@
;~ pose
;~(plug (cold %ur lus) parse-url)
;~(plug (cold %ge lus) parse-model)
;~(plug (cold %te hep) sym (star ;~(pfix ace parse-source)))
;~(plug (cold %te hep) parse-thread (star ;~(pfix ace parse-source)))
;~(plug (cold %as pam) sym ;~(pfix ace parse-source))
;~(plug (cold %do cab) parse-hoon ;~(pfix ace parse-source))
parse-value
@ -278,6 +278,12 @@
(most fas sym)
==
::
++ parse-thread
;~ plug
;~(pose ;~(sfix sym zap) (easy q.dir))
sym
==
::
++ parse-hoon tall:hoon-parser
::
++ parse-rood
@ -693,7 +699,7 @@
[%sa mark]
[%as mark dy-shown]
[%do hoon dy-shown]
[%te term (list dy-shown)]
[%te [desk term] (list dy-shown)]
[%ge [desk path] (list dy-shown) (map term (unit dy-shown))]
[%dv beak path]
==
@ -870,7 +876,7 @@
(dy-hand %noun q.cag)
::
++ dy-wool-poke
|= [fil=term src=(list dojo-source)]
|= [[=desk =term] src=(list dojo-source)]
^+ +>+>
?> ?=(~ pux)
=/ tid (scot %ta (cat 3 'dojo_' (scot %uv (sham eny.hid))))
@ -880,8 +886,9 @@
[%pass /wool %agent [our.hid %spider] %watch /thread-result/[tid]]
%- he-card
=/ =cage :: also sub
:: TODO: support threads on other desks
[%spider-start !>([~ `tid he-beak fil (dy-some src)])]
::TODO would be nice if spider supported starting from paths,
:: for semantics/abilities/code closer to generators.
[%spider-start !>([~ `tid he-beak(q.dir desk) term (dy-some src)])]
[%pass /wool %agent [our.hid %spider] %poke cage]
::
++ dy-make :: build step
@ -1522,16 +1529,17 @@
|^ =+ old=!<(house-any ole)
=? old ?=(%5 -.old)
(house-5-to-6 old)
=? old ?=(%6 -.old)
(house-6-to-7 old)
?> ?=(%7 -.old)
=? old ?=(?(%6 %7) -.old)
(house-6-7-to-8 +.old)
?> ?=(%8 -.old)
`..on-init(state old)
::
+$ house-any $%(house house-6 house-5)
+$ house-any $%(house house-7 house-6 house-5)
::
+$ house-6 :: all state
$: %6
egg=@u :: command count
+$ house-7 [%7 house-6-7]
+$ house-6 [%6 house-6-7]
+$ house-6-7
$: egg=@u :: command count
hoc=(map id session-6) :: conversations
acl=(set ship) :: remote access whitelist
== ::
@ -1550,10 +1558,10 @@
old=(set term) :: used TLVs
buf=tape :: multiline buffer
== ::
++ house-6-to-7
|= old=house-6
[%7 egg.old (~(run by hoc.old) session-6-to-7) acl.old]
++ session-6-to-7
++ house-6-7-to-8
|= old=house-6-7
[%8 egg.old (~(run by hoc.old) session-6-to-8) acl.old]
++ session-6-to-8
|= old=session-6
~? ?=(^ poy.old) [dap.hid %cancelling-for-load]
old(poy ~, -.dir [our.hid %base ud+0])

View File

@ -1 +0,0 @@
../../base-dev/lib/azimuth.hoon

454
pkg/arvo/lib/azimuth.hoon Normal file
View File

@ -0,0 +1,454 @@
:: azimuth: constants and utilities
::
/+ ethereum
::
=> => [azimuth-types ethereum-types .]
|%
+$ complete-ship
$: state=point
history=(list diff-point) ::TODO maybe block/event nr? :: newest first
keys=(map life pass)
==
::
++ fleet (map @p complete-ship)
::
++ eth-type
|%
++ point
:~ [%bytes-n 32] :: encryptionKey
[%bytes-n 32] :: authenticationKey
%bool :: hasSponsor
%bool :: active
%bool :: escapeRequested
%uint :: sponsor
%uint :: escapeRequestedTo
%uint :: cryptoSuiteVersion
%uint :: keyRevisionNumber
%uint :: continuityNumber
==
++ deed
:~ %address :: owner
%address :: managementProxy
%address :: spawnProxy
%address :: votingProxy
%address :: transferProxy
==
--
::
++ eth-noun
|%
+$ point
$: encryption-key=octs
authentication-key=octs
has-sponsor=?
active=?
escape-requested=?
sponsor=@ud
escape-to=@ud
crypto-suite=@ud
key-revision=@ud
continuity-number=@ud
==
+$ deed
$: owner=address
management-proxy=address
spawn-proxy=address
voting-proxy=address
transfer-proxy=address
==
--
::
++ function
|%
++ azimuth
$% [%points who=@p]
[%rights who=@p]
[%get-spawned who=@p]
[%dns-domains ind=@ud]
==
--
::
:: # diffs
::
++ update
$% [%full ships=(map ship point) dns=dnses heard=events]
[%difs dis=(list (pair event-id diff-azimuth))]
==
::
:: # constants
::
:: contract addresses
++ contracts mainnet-contracts
++ mainnet-contracts
|%
:: azimuth: data contract
::
++ azimuth
0x223c.067f.8cf2.8ae1.73ee.5caf.ea60.ca44.c335.fecb
::
++ ecliptic
0xa5b6.109a.d2d3.5191.b3bc.32c0.0e45.26be.56fe.321f
::
++ linear-star-release
0x86cd.9cd0.992f.0423.1751.e376.1de4.5cec.ea5d.1801
::
++ conditional-star-release
0x8c24.1098.c3d3.498f.e126.1421.633f.d579.86d7.4aea
::
++ delegated-sending
0xf790.8ab1.f1e3.52f8.3c5e.bc75.051c.0565.aeae.a5fb
::
:: launch: block number of azimuth deploy
::
++ launch 6.784.800
::
:: public: block number of azimuth becoming independent
::
++ public 7.033.765
--
::
:: Testnet contract addresses
::
++ ropsten-contracts
|%
++ azimuth
0x308a.b6a6.024c.f198.b57e.008d.0ac9.ad02.1988.6579
::
++ ecliptic
0x8b9f.86a2.8921.d9c7.05b3.113a.755f.b979.e1bd.1bce
::
++ linear-star-release
0x1f8e.dd03.1ee4.1474.0aed.b39b.84fb.8f2f.66ca.422f
::
++ conditional-star-release
0x0
::
++ delegated-sending
0x3e8c.a510.354b.c2fd.bbd6.1502.52d9.3105.c9c2.7bbe
::
++ launch 4.601.630
++ public launch
--
::
:: Local contract addresses
::
:: These addresses are only reproducible if you use the deploy
:: script in bridge
::
++ local-contracts
|%
++ ecliptic
0x56db.68f2.9203.ff44.a803.faa2.404a.44ec.bb7a.7480
++ azimuth
0x863d.9c2e.5c4c.1335.96cf.ac29.d552.55f0.d0f8.6381
++ delegated-sending
0xb71c.0b6c.ee1b.cae5.6dfe.95cd.9d3e.41dd.d7ea.fc43
++ linear-star-release
0x3c3.dc12.be65.8158.d1d7.f9e6.6e08.ec40.99c5.68e4
++ conditional-star-release
0x35eb.3b10.2d9c.1b69.ac14.69c1.b1fe.1799.850c.d3eb
++ launch 0
++ public 0
--
::
:: ++ azimuth 0x863d.9c2e.5c4c.1335.96cf.ac29.d552.55f0.d0f8.6381 :: local bridge
:: hashes of ship event signatures
++ azimuth-events
|%
::
:: OwnerChanged(uint32,address)
++ owner-changed
0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1.
cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda
::
:: Activated(uint32)
++ activated
0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c.
d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f
::
:: Spawned(uint32,uint32)
++ spawned
0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010.
a854.1070.f374.4a24.7090.9644.1508.1546
::
:: EscapeRequested(uint32,uint32)
++ escape-requested
0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5.
3e9b.b015.b51e.8d93.4be7.0210.aead.874a
::
:: EscapeCanceled(uint32,uint32)
++ escape-canceled
0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd.
a590.2c83.28ed.0cd0.9988.f368.90d9.932a
::
:: EscapeAccepted(uint32,uint32)
++ escape-accepted
0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34.
ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5
::
:: LostSponsor(uint32,uint32)
++ lost-sponsor
0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff.
a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5
::
:: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32)
++ changed-keys
0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be.
bb3a.988e.8957.70e3.5198.7e01.ff54.23d5
::
:: BrokeContinuity(uint32,uint32)
++ broke-continuity
0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b.
cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e
::
:: ChangedSpawnProxy(uint32,address)
++ changed-spawn-proxy
0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e.
35c8.4095.122b.2505.1a20.ead8.866f.006d
::
:: ChangedTransferProxy(uint32,address)
++ changed-transfer-proxy
0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1.
3583.fecb.ed2f.78df.a14d.1f10.796b.847c
::
:: ChangedManagementProxy(uint32,address)
++ changed-management-proxy
0xab9c.9327.cffd.2acc.168f.afed.be06.139f.
5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf
::
:: ChangedVotingProxy(uint32,address)
++ changed-voting-proxy
0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6.
c5a2.eae3.795e.d730.0db5.1768.0c61.c805
::
:: ChangedDns(string,string,string)
++ changed-dns
0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f.
d424.063e.d5c9.2120.e67e.0730.53b9.4898
--
--
::
:: logic
::
|%
++ pass-from-eth
|= [enc=octs aut=octs sut=@ud]
^- pass
%^ cat 3 'b'
?. &(=(1 sut) =(p.enc 32) =(p.aut 32))
(cat 8 0 0)
(cat 8 q.aut q.enc)
::
++ point-from-eth
|= [who=@p point:eth-noun deed:eth-noun]
^- point
::
:: ownership
::
:+ :* owner
management-proxy
voting-proxy
transfer-proxy
==
::
:: network state
::
?. active ~
:- ~
:* key-revision
::
(pass-from-eth encryption-key authentication-key crypto-suite)
::
continuity-number
::
[has-sponsor `@p`sponsor]
::
?. escape-requested ~
``@p`escape-to
==
::
:: spawn state
::
?. ?=(?(%czar %king) (clan:title who)) ~
:- ~
:* spawn-proxy
~ ::TODO call getSpawned to fill this
==
::
++ event-log-to-point-diff
=, azimuth-events
=, abi:ethereum
|= log=event-log:rpc:ethereum
^- (unit (pair ship diff-point))
~? ?=(~ mined.log) %processing-unmined-event
::
?: =(i.topics.log owner-changed)
=/ [who=@ wer=address]
(decode-topics t.topics.log ~[%uint %address])
`[who %owner wer]
::
?: =(i.topics.log activated)
=/ who=@
(decode-topics t.topics.log ~[%uint])
`[who %activated who]
::
?: =(i.topics.log spawned)
=/ [pre=@ who=@]
(decode-topics t.topics.log ~[%uint %uint])
`[pre %spawned who]
::
?: =(i.topics.log escape-requested)
=/ [who=@ wer=@]
(decode-topics t.topics.log ~[%uint %uint])
`[who %escape `wer]
::
?: =(i.topics.log escape-canceled)
=/ who=@ (decode-topics t.topics.log ~[%uint])
`[who %escape ~]
::
?: =(i.topics.log escape-accepted)
=/ [who=@ wer=@]
(decode-topics t.topics.log ~[%uint %uint])
`[who %sponsor & wer]
::
?: =(i.topics.log lost-sponsor)
=/ [who=@ pos=@]
(decode-topics t.topics.log ~[%uint %uint])
`[who %sponsor | pos]
::
?: =(i.topics.log changed-keys)
=/ who=@ (decode-topics t.topics.log ~[%uint])
=/ [enc=octs aut=octs sut=@ud rev=@ud]
%+ decode-results data.log
~[[%bytes-n 32] [%bytes-n 32] %uint %uint]
`[who %keys rev (pass-from-eth enc aut sut)]
::
?: =(i.topics.log broke-continuity)
=/ who=@ (decode-topics t.topics.log ~[%uint])
=/ num=@ (decode-results data.log ~[%uint])
`[who %continuity num]
::
?: =(i.topics.log changed-management-proxy)
=/ [who=@ sox=address]
(decode-topics t.topics.log ~[%uint %address])
`[who %management-proxy sox]
::
?: =(i.topics.log changed-voting-proxy)
=/ [who=@ tox=address]
(decode-topics t.topics.log ~[%uint %address])
`[who %voting-proxy tox]
::
?: =(i.topics.log changed-spawn-proxy)
=/ [who=@ sox=address]
(decode-topics t.topics.log ~[%uint %address])
`[who %spawn-proxy sox]
::
?: =(i.topics.log changed-transfer-proxy)
=/ [who=@ tox=address]
(decode-topics t.topics.log ~[%uint %address])
`[who %transfer-proxy tox]
::
:: warn about unimplemented events, but ignore
:: the ones we know are harmless.
~? ?! .= i.topics.log
:: OwnershipTransferred(address,address)
0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284.
1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0
[%unimplemented-event i.topics.log]
~
::
++ apply-point-diff
|= [pot=point dif=diff-point]
^- point
?- -.dif
%full new.dif
::
%activated
%_ pot
net `[0 0 0 &^(^sein:title who.dif) ~]
kid ?. ?=(?(%czar %king) (clan:title who.dif)) ~
`[0x0 ~]
==
::
:: ownership
::
%owner pot(owner.own new.dif)
%transfer-proxy pot(transfer-proxy.own new.dif)
%management-proxy pot(management-proxy.own new.dif)
%voting-proxy pot(voting-proxy.own new.dif)
::
:: networking
::
?(%keys %continuity %sponsor %escape)
?> ?=(^ net.pot)
?- -.dif
%keys
pot(life.u.net life.dif, pass.u.net pass.dif)
::
%sponsor
%= pot
sponsor.u.net new.dif
escape.u.net ?:(has.new.dif ~ escape.u.net.pot)
==
::
%continuity pot(continuity-number.u.net new.dif)
%escape pot(escape.u.net new.dif)
==
::
:: spawning
::
?(%spawned %spawn-proxy)
?> ?=(^ kid.pot)
?- -.dif
%spawned
=- pot(spawned.u.kid -)
(~(put in spawned.u.kid.pot) who.dif)
::
%spawn-proxy pot(spawn-proxy.u.kid new.dif)
==
==
::
++ parse-id
|= id=@t
^- azimuth:function
|^
~| id
%+ rash id
;~ pose
(function %points 'points' shipname)
(function %get-spawned 'getSpawned' shipname)
(function %dns-domains 'dnsDomains' dem:ag)
==
::
++ function
|* [tag=@tas fun=@t rul=rule]
;~(plug (cold tag (jest fun)) (ifix [pal par] rul))
::
++ shipname
;~(pfix sig fed:ag)
--
::
++ function-to-call
|%
++ azimuth
|= cal=azimuth:function
^- [id=@t dat=call-data:rpc:ethereum]
?- -.cal
%points
:- (crip "points({(scow %p who.cal)})")
['points(uint32)' ~[uint+`@`who.cal]]
::
%rights
:- (crip "rights({(scow %p who.cal)})")
['rights(uint32)' ~[uint+`@`who.cal]]
::
%get-spawned
:- (crip "getSpawned({(scow %p who.cal)})")
['getSpawned(uint32)' ~[uint+`@`who.cal]]
::
%dns-domains
:- (crip "dnsDomains({(scow %ud ind.cal)})")
['dnsDomains(uint256)' ~[uint+ind.cal]]
==
--
--

View File

@ -947,7 +947,7 @@
=/ onto ?>(?=([%gall %onto *] syn) p.syn)
?- -.onto
%& kiln
%| (mean >p.onto< p.onto)
%| (mean p.onto)
==
::
++ update-running-dudes

View File

@ -1587,14 +1587,15 @@
:::: ++keccak:crypto :: (2b7) keccak family
:: ::::
++ keccak
~% %kecc ..part ~
|%
::
:: keccak
::
++ keccak-224 |=(a=octs (keccak 1.152 448 224 a))
++ keccak-256 |=(a=octs (keccak 1.088 512 256 a))
++ keccak-384 |=(a=octs (keccak 832 768 384 a))
++ keccak-512 |=(a=octs (keccak 576 1.024 512 a))
++ keccak-224 ~/ %k224 |=(a=octs (keccak 1.152 448 224 a))
++ keccak-256 ~/ %k256 |=(a=octs (keccak 1.088 512 256 a))
++ keccak-384 ~/ %k384 |=(a=octs (keccak 832 768 384 a))
++ keccak-512 ~/ %k512 |=(a=octs (keccak 576 1.024 512 a))
::
++ keccak (cury (cury hash keccak-f) padding-keccak)
::

View File

@ -21,10 +21,7 @@
!> `@ux`(hsh pw salt n r p 64)
::
++ vectors
:: TODO: until scrypt has been jetted, we can only test the
:: first vector; the others do not finish in a reasonable
:: amount of time.
%+ scag 1 ^- (list vector)
^- (list vector)
:~
:*
0x0
@ -37,8 +34,8 @@
==
::
:*
0x7061.7373.776f.7264
0x4e61.436c
`@ux`'password'
`@ux`'NaCl'
1.024 8 16
0xfdba.be1c.9d34.7200.7856.e719.0d01.e9fe.
7c6a.d7cb.c823.7830.e773.7663.4b37.3162.
@ -47,8 +44,8 @@
==
::
:*
0x70.6c65.6173.656c.6574.6d65.696e
0x536f.6469.756d.4368.6c6f.7269.6465
`@ux`'pleaseletmein'
`@ux`'SodiumChloride'
16.384 8 1
0x7023.bdcb.3afd.7348.461c.06cd.81fd.38eb.
fda8.fbba.904f.8e3e.a9b5.43f6.545d.a1f2.
@ -57,8 +54,8 @@
==
::
:*
0x70.6c65.6173.656c.6574.6d65.696e
0x536f.6469.756d.4368.6c6f.7269.6465
`@ux`'pleaseletmein'
`@ux`'SodiumChloride'
1.048.576 8 1
0x2101.cb9b.6a51.1aae.addb.be09.cf70.f881.
ec56.8d57.4a2f.fd4d.abe5.ee98.20ad.aa47.

View File

@ -156,7 +156,7 @@
::
:- ~
:+ %agent wire.in
[%fact (validate-mark q.cage.sign.in p.cage.sign.in bowl.strand-input)]
[%fact (validate-mark q.q.cage.sign.in p.cage.sign.in bowl.strand-input)]
:: run the strand callback
::
=/ =output (form.eval-form strand-input)

View File

@ -65,6 +65,7 @@
=+ .^ raz=(list vat)
%gx /(scot %p our)/hood/(scot %da now)/kiln/vats/noun
==
:- (report-kids our now)
(turn raz |=(v=vat (report-vat our now v)))
:: +report-vat: report on a single desk installation
::
@ -103,6 +104,18 @@
leaf/"source aeon: {?~(rail.arak <~> <aeon.u.rail.arak>)}"
leaf/"pending updates: {pen}"
==
:: +report-kids: non-vat cz hash report for kids desk
::
++ report-kids
|= [our=ship now=@da]
^- tank
=/ dek %kids
=/ ego (scot %p our)
=/ wen (scot %da now)
?. (~(has in .^((set desk) %cd /[ego]//[wen])) dek)
leaf/"no %kids desk"
=+ .^(hash=@uv %cz /[ego]/[dek]/[wen])
leaf/"%kids %cz hash: {<hash>}"
:: +read-kelvin-foreign: read /sys/kelvin from a foreign desk
::
++ read-kelvin-foreign

1
pkg/ent/configure vendored
View File

@ -7,6 +7,7 @@ log () {
for impl in ENT_GETENTROPY_UNISTD \
ENT_GETENTROPY_SYSRANDOM \
ENT_GETRANDOM_SYSCALL \
ENT_GETENTROPY_BCRYPTGENRANDOM \
ENT_DEV_URANDOM
do
export IMPL=$impl

View File

@ -57,6 +57,16 @@ int ent_getentropy(void* buf, size_t len) {
return 0;
}
// Use `BCryptGenRandom` on Windows ////////////////////////////////////////////
#elif defined(ENT_GETENTROPY_BCRYPTGENRANDOM)
#include <windows.h>
#include <bcrypt.h>
int ent_getentropy(void* buf, size_t len) {
return BCryptGenRandom(NULL, (PUCHAR)buf, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
}
#else
#error "One of these must be set: ENT_DEV_URANDOM, ENT_GETENTROPY_UNISTD, ENT_GETENTROPY_SYSRANDOM, ENT_GETRANDOM_SYSCALL"
#error "One of these must be set: ENT_GETENTROPY_BCRYPTGENRANDOM, ENT_DEV_URANDOM, ENT_GETENTROPY_UNISTD, ENT_GETENTROPY_SYSRANDOM, ENT_GETRANDOM_SYSCALL"
#endif

View File

@ -391,7 +391,7 @@
++ cg
|%
++ glob |=(g=^glob glob-0+!>(g))
++ docket |=(d=^docket docket-0+!>(docket))
++ docket |=(d=^docket docket-0+!>(d))
++ charge-update |=(u=^charge-update charge-update+!>(u))
++ kiln-uninstall |=(=desk kiln-uninstall+!>(desk))
++ kiln-install

View File

@ -32,6 +32,6 @@
;< =bowl:spider bind:m get-bowl:strandio
;< =cage bind:m
(watch-one:strandio /glob/(scot %da now.bowl) [ship %docket] /glob/[base]/(scot %uv hash))
?> ?=(%glob p.cage)
?> ?=(%glob-0 p.cage)
(pure:m q.cage)
--

View File

@ -1,20 +0,0 @@
CC ?= cc
AR ?= ar
PREFIX ?= ./out
################################################################################
.PHONY: all test install clean
all: ge-additions.c ge-additions.h
$(CC) $(CFLAGS) -O3 -Wall -Werror -pedantic -std=gnu99 -c ge-additions.c
$(AR) rcs libge-additions.a ge-additions.o
install: all
@mkdir -p $(PREFIX)/lib/
@mkdir -p $(PREFIX)/include/
cp libge-additions.a $(PREFIX)/lib/
cp ge-additions.h $(PREFIX)/include/
clean:
rm -rf ./out

View File

@ -1,8 +0,0 @@
let
pkgs = import ../../default.nix { };
in pkgs.shellFor {
name = "ge-additions";
packages = ps: [ ps.ge-additions ];
}

View File

@ -10,7 +10,7 @@ export const AppPrefs = ({ match }: RouteComponentProps<{ desk: string }>) => {
const charge = useCharge(desk);
const vat = useVat(desk);
const tracking = !!vat?.arak.rail;
const otasEnabled = vat?.arak.rail?.paused;
const otasEnabled = !vat?.arak.rail?.paused;
const otaSource = vat?.arak.rail?.ship;
const toggleOTAs = useKilnState((s) => s.toggleOTAs);
@ -21,7 +21,7 @@ export const AppPrefs = ({ match }: RouteComponentProps<{ desk: string }>) => {
<h2 className="h3 mb-7">{charge?.title} Settings</h2>
<div className="space-y-3">
{tracking ? (
<Setting on={!!otasEnabled} toggle={toggleUpdates} name="Automatic Updates">
<Setting on={otasEnabled} toggle={toggleUpdates} name="Automatic Updates">
<p>Automatically download and apply updates to keep {charge?.title} up to date.</p>
{otaSource && (
<p>

View File

@ -85,7 +85,7 @@ instance FromNoun Pass where
-- seed. These aren't actually private keys, but public/private keypairs which
-- can be derived from these seeds.
data Ring = Ring { ringSign :: BS.ByteString, ringCrypt :: BS.ByteString }
deriving (Eq)
deriving (Eq, Ord)
instance ToNoun Ring where
toNoun Ring{..} =
@ -117,6 +117,36 @@ data Seed = Seed
}
deriving (Eq, Show)
data Germs = Germs
{ gShip :: Ship
, gFeed :: [Germ]
}
deriving (Eq, Show)
data Germ = Germ
{ gLife :: Life
, gRing :: Ring
}
deriving (Eq, Ord, Show)
data Feed
= Feed0 Seed
| Feed1 Germs
deriving (Eq, Show)
-- NOTE reify type environment
$(pure [])
instance ToNoun Feed where
toNoun = \case
Feed0 s -> $(deriveToNounFunc ''Seed) s
Feed1 s -> C (C (A 1) (A 0)) $ $(deriveToNounFunc ''Germs) s
instance FromNoun Feed where
parseNoun = \case
(C (C (A 1) (A 0)) s) -> Feed1 <$> $(deriveFromNounFunc ''Germs) s
n -> Feed0 <$> $(deriveFromNounFunc ''Seed) n
type Public = (Life, HoonMap Life Pass)
data Dnses = Dnses { dPri::Cord, dSec::Cord, dTer::Cord }
@ -145,6 +175,7 @@ data Dawn = MkDawn
deriveNoun ''Dnses
deriveNoun ''EthPoint
deriveNoun ''Seed
deriveNoun ''Germ
deriveNoun ''Dawn
@ -239,6 +270,16 @@ data BoatEv
deriveNoun ''BoatEv
-- Jael Events -----------------------------------------------------------------
data JaelEv
= JaelEvRekey () (Life, Ring)
| JaelEvCrud Path Noun
deriving (Eq, Show)
deriveNoun ''JaelEv
-- Timer Events ----------------------------------------------------------------
data BehnEv
@ -313,6 +354,7 @@ data BlipEv
| BlipEvBoat BoatEv
| BlipEvHttpClient HttpClientEv
| BlipEvHttpServer HttpServerEv
| BlipEvJael JaelEv
| BlipEvNewt NewtEv
| BlipEvSync SyncEv
| BlipEvTerm TermEv
@ -335,6 +377,7 @@ instance ToNoun Ev where
EvBlip v@BlipEvBoat{} -> reorgThroughNoun ("clay", v)
EvBlip v@BlipEvHttpClient{} -> reorgThroughNoun ("iris", v)
EvBlip v@BlipEvHttpServer{} -> reorgThroughNoun ("eyre", v)
EvBlip v@BlipEvJael{} -> reorgThroughNoun ("jael", v)
EvBlip v@BlipEvNewt{} -> reorgThroughNoun ("ames", v)
EvBlip v@BlipEvSync{} -> reorgThroughNoun ("clay", v)
EvBlip v@BlipEvTerm{} -> reorgThroughNoun ("dill", v)
@ -362,6 +405,7 @@ getSpinnerNameForEvent = \case
BlipEvBoat _ -> Just "boat"
BlipEvHttpClient _ -> Just "iris"
BlipEvHttpServer _ -> Just "eyre"
BlipEvJael _ -> Just "jael"
BlipEvNewt _ -> Just "newt"
BlipEvSync _ -> Just "clay"
BlipEvTerm t | isRet t -> Nothing

View File

@ -184,8 +184,9 @@ tryBootFromPill
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO PierEnv ()
tryBootFromPill oExit pill lite ship boot = do
tryBootFromPill oExit pill lite ship boot feed = do
mStart <- newEmptyMVar
vSlog <- logSlogs
runOrExitImmediately vSlog (bootedPier vSlog) oExit mStart []
@ -193,7 +194,7 @@ tryBootFromPill oExit pill lite ship boot = do
bootedPier vSlog = do
view pierPathL >>= lockFile
rio $ logInfo "Starting boot"
sls <- Pier.booted vSlog pill lite ship boot
sls <- Pier.booted vSlog pill lite ship boot feed
rio $ logInfo "Completed boot"
pure sls
@ -395,7 +396,12 @@ testPill pax showPil showSeq = do
pill <- fromNounErr pillNoun & either (throwIO . uncurry ParseErr) pure
logInfo "Using pill to generate boot sequence."
bootSeq <- genBootSeq (Ship 0) pill False (Fake (Ship 0))
bootSeq <- genBootSeq
(Ship 0)
pill
False
(Fake (Ship 0))
(Feed1 $ Germs (Ship 0) [])
logInfo "Validate jam/cue and toNoun/fromNoun on pill value"
reJam <- validateNounVal pill
@ -500,12 +506,12 @@ newShip CLI.New{..} opts = do
let seed = mineComet (Set.fromList starList) eny
putStrLn ("boot: found comet " ++ renderShip (sShip seed))
putStrLn ("code: " ++ (tshow $ deriveCode $ sRing seed))
bootFromSeed pill seed
bootFromFeed pill $ Feed0 seed
CLI.BootFake name -> do
pill <- pillFrom nPillSource
ship <- shipFrom name
runTryBootFromPill pill name ship (Fake ship)
runTryBootFromPill pill name ship (Fake ship) (Feed1 $ Germs ship [])
CLI.BootFromKeyfile keyFile -> do
text <- readFileUtf8 keyFile
@ -514,13 +520,13 @@ newShip CLI.New{..} opts = do
Just (UW a) -> pure a
asNoun <- cueExn asAtom
seed :: Seed <- case fromNoun asNoun of
feed :: Feed <- case fromNoun asNoun of
Nothing -> error "Keyfile does not seem to contain a seed."
Just s -> pure s
pill <- pillFrom nPillSource
bootFromSeed pill seed
bootFromFeed pill feed
where
shipFrom :: Text -> RIO HostEnv Ship
@ -541,16 +547,16 @@ newShip CLI.New{..} opts = do
Nothing -> error "Urbit.ob didn't produce string with ~"
Just x -> pure x
bootFromSeed :: Pill -> Seed -> RIO HostEnv ()
bootFromSeed pill seed = do
ethReturn <- dawnVent nEthNode seed
bootFromFeed :: Pill -> Feed -> RIO HostEnv ()
bootFromFeed pill feed = do
ethReturn <- dawnVent nEthNode feed
case ethReturn of
Left x -> error $ unpack x
Right dawn -> do
let ship = sShip $ dSeed dawn
name <- nameFromShip ship
runTryBootFromPill pill name ship (Dawn dawn)
runTryBootFromPill pill name ship (Dawn dawn) feed
-- Now that we have all the information for running an application with a
-- PierConfig, do so.
@ -558,13 +564,14 @@ newShip CLI.New{..} opts = do
-> Text
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO HostEnv ()
runTryBootFromPill pill name ship bootEvent = do
runTryBootFromPill pill name ship bootEvent feed = do
vKill <- view (kingEnvL . kingEnvKillSignal)
let pierConfig = toPierConfig (pierPath name) nSerfExe opts
let networkConfig = toNetworkConfig opts
runPierEnv pierConfig networkConfig vKill $
tryBootFromPill True pill nLite ship bootEvent
tryBootFromPill True pill nLite ship bootEvent feed
runShipEnv :: Maybe Text -> CLI.Run -> CLI.Opts -> TMVar () -> RIO PierEnv a
-> RIO HostEnv a
@ -642,13 +649,13 @@ checkDawn provider keyfilePath = do
Just (UW a) -> pure a
asNoun <- cueExn asAtom
seed :: Seed <- case fromNoun asNoun of
feed :: Feed <- case fromNoun asNoun of
Nothing -> error "Keyfile does not seem to contain a seed."
Just s -> pure s
print $ show seed
print $ show feed
e <- dawnVent provider seed
e <- dawnVent provider feed
print $ show e

View File

@ -335,45 +335,72 @@ retrievePoint endpoint block ship =
[x] -> pure x
_ -> error "JSON server returned multiple return values."
validateShipAndGetSponsor :: String -> TextBlockNum -> Seed -> RIO e Ship
validateShipAndGetSponsor endpoint block (Seed ship life ring oaf) =
case clanFromShip ship of
Ob.Comet -> validateComet
Ob.Moon -> validateMoon
_ -> validateRest
validateFeedAndGetSponsor :: String
-> TextBlockNum
-> Feed
-> RIO e (Seed, Ship)
validateFeedAndGetSponsor endpoint block = \case
Feed0 s -> do
r <- validateSeed s
case r of
Left e -> error e
Right r -> pure (s, r)
Feed1 s -> validateGerms s
where
validateComet = do
-- A comet address is the fingerprint of the keypair
let shipFromPass = cometFingerprint $ ringToPass ring
when (ship /= shipFromPass) $
error ("comet name doesn't match fingerprint " <> show ship <> " vs " <>
show shipFromPass)
when (life /= 1) $
error ("comet can never be re-keyed")
pure (shipSein ship)
validateGerms Germs{..} =
case gFeed of
[] -> error "no usable keys in keyfile"
(Germ{..}:f) -> do
let seed = Seed gShip gLife gRing Nothing
r :: Either String Ship
<- validateSeed seed
case r of
Left _ -> validateGerms $ Germs gShip f
Right r -> pure (seed, r)
validateMoon = do
-- TODO: The current code in zuse does nothing, but we should be able to
-- try to validate the oath against the current as exists planet on
-- chain.
pure $ shipSein ship
validateSeed (Seed ship life ring oaf) = do
case clanFromShip ship of
Ob.Comet -> pure validateComet
Ob.Moon -> pure validateMoon
_ -> validateRest
where
cometFromPass = cometFingerprint $ ringToPass ring
validateComet
-- A comet address is the fingerprint of the keypair
| (ship /= cometFromPass) =
Left ("comet name doesn't match fingerprint " <>
show ship <> " vs " <>
show cometFromPass)
| (life /= 1) =
Left "comet can never be re-keyed"
| otherwise =
Right (shipSein ship)
validateRest = do
putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys")
validateMoon =
-- TODO: The current code in zuse does nothing, but we should be able
-- to try to validate the oath against the current as exists planet
-- on chain.
Right $ shipSein ship
whoP <- retrievePoint endpoint block ship
case epNet whoP of
Nothing -> error "ship not keyed"
Just (netLife, pass, contNum, (hasSponsor, who), _) -> do
when (netLife /= life) $
error ("keyfile life mismatch; keyfile claims life " <>
show life <> ", but Azimuth claims life " <>
show netLife)
when ((ringToPass ring) /= pass) $
error "keyfile does not match blockchain"
-- TODO: The hoon code does a breach check, but the C code never
-- supplies the data necessary for it to function.
pure who
validateRest = do
putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys")
--TODO could cache this lookup
whoP <- retrievePoint endpoint block ship
case epNet whoP of
Nothing -> pure $ Left "ship not keyed"
Just (netLife, pass, contNum, (hasSponsor, who), _) -> do
if (netLife /= life) then
pure $ Left ("keyfile life mismatch; keyfile claims life " <>
show life <> ", but Azimuth claims life " <>
show netLife)
else if ((ringToPass ring) /= pass) then
pure $ Left "keyfile does not match blockchain"
-- TODO: The hoon code does a breach check, but the C code never
-- supplies the data necessary for it to function.
else
pure $ Right who
-- Walk through the sponsorship chain retrieving the actual sponsorship chain
@ -402,8 +429,8 @@ getSponsorshipChain endpoint block = loop
pure $ chain <> [(ship, ethPoint)]
-- Produces either an error or a validated boot event structure.
dawnVent :: HasLogFunc e => String -> Seed -> RIO e (Either Text Dawn)
dawnVent provider dSeed@(Seed ship life ring oaf) =
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)
@ -417,7 +444,8 @@ dawnVent provider dSeed@(Seed ship life ring oaf) =
let dBloq = hexStrToAtom hexStrBlock
putStrLn ("boot: ethereum block #" <> tshow dBloq)
immediateSponsor <- validateShipAndGetSponsor provider hexStrBlock dSeed
(dSeed, immediateSponsor)
<- validateFeedAndGetSponsor provider hexStrBlock feed
dSponsor <- getSponsorshipChain provider hexStrBlock immediateSponsor
putStrLn "boot: retrieving galaxy table"
@ -431,7 +459,7 @@ dawnVent provider dSeed@(Seed ship life ring oaf) =
let dNode = Nothing
pure $ MkDawn{..}
pure MkDawn{..}
-- Comet List ------------------------------------------------------------------

View File

@ -79,12 +79,17 @@ genEntropy :: MonadIO m => m Entropy
genEntropy = Entropy . fromIntegral . bytesAtom <$> io (Ent.getEntropy 64)
genBootSeq :: HasKingEnv e
=> Ship -> Pill -> Bool -> LegacyBootEvent -> RIO e BootSeq
genBootSeq _ PillIvory {} _ _ = throwIO CannotBootFromIvoryPill
genBootSeq ship PillPill {..} lite boot = do
=> Ship -> Pill -> Bool -> LegacyBootEvent -> Feed -> RIO e BootSeq
genBootSeq _ PillIvory {} _ _ _ = throwIO CannotBootFromIvoryPill
genBootSeq ship PillPill {..} lite boot feed = do
ent <- io genEntropy
wyr <- wyrd
let ova = preKern ent <> [wyr] <> pKernelOva <> postKern <> pUserspaceOva
let ova = preKern ent
<> [wyr]
<> pKernelOva
<> postKern
<> extraKeys
<> pUserspaceOva
pure $ BootSeq ident pBootFormulae ova
where
ident = LogIdentity ship isFake (fromIntegral $ length pBootFormulae)
@ -96,6 +101,10 @@ genBootSeq ship PillPill {..} lite boot = do
isFake = case boot of
Fake _ -> True
_ -> False
extraKeys = case feed of
Feed0 _ -> []
Feed1 Germs{..} -> fmap rekey gFeed
rekey Germ{..} = EvBlip $ BlipEvJael $ JaelEvRekey () (gLife, gRing)
-- Write to the log. -----------------------------------------------------------
@ -160,9 +169,10 @@ booted
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RAcquire PierEnv (Serf, EventLog)
booted vSlog pill lite ship boot = do
rio $ bootNewShip pill lite ship boot
booted vSlog pill lite ship boot feed = do
rio $ bootNewShip pill lite ship boot feed
resumed vSlog Nothing
bootSeqJobs :: Time.Wen -> BootSeq -> [Job]
@ -183,9 +193,10 @@ bootNewShip
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO e ()
bootNewShip pill lite ship bootEv = do
seq@(BootSeq ident x y) <- genBootSeq ship pill lite bootEv
bootNewShip pill lite ship bootEv feed = do
seq@(BootSeq ident x y) <- genBootSeq ship pill lite bootEv feed
logInfo "BootSeq Computed"
pierPath <- view pierPathL

View File

@ -1,5 +1,5 @@
name: urbit-king
version: 1.5
version: 1.6
license: MIT
license-file: LICENSE
data-files:

View File

@ -1,7 +1,7 @@
{-|
Template Haskell Code to Generate FromNoun and ToNoun Instances
-}
module Urbit.Noun.TH (deriveNoun, deriveToNoun, deriveFromNoun) where
module Urbit.Noun.TH (deriveNoun, deriveToNoun, deriveFromNoun, deriveToNounFunc, deriveFromNounFunc) where
import ClassyPrelude hiding (fromList)
import Control.Monad.Fail (fail)
@ -83,13 +83,9 @@ deriveNoun n = (<>) <$> deriveToNoun n <*> deriveFromNoun n
deriveToNoun :: Name -> Q [Dec]
deriveToNoun tyName = do
(params, shape) <- typeShape tyName
let exp = case shape of Vod -> vodToNoun
Tup con -> tupToNoun con
-- Enu cons -> enumToAtom cons
Sum atoms cells -> sumToNoun atoms cells
(params, _) <- typeShape tyName
exp <- deriveToNounFunc tyName
params <- pure $ zip ['a' ..] params <&> \(n,_) -> mkName (singleton n)
let ty = foldl' (\acc v -> AppT acc (VarT v)) (ConT tyName) params
@ -101,6 +97,15 @@ deriveToNoun tyName = do
pure [InstanceD overlap ctx inst [ValD (VarP 'toNoun) body []]]
deriveToNounFunc :: Name -> Q Exp
deriveToNounFunc tyName = do
(_, shape) <- typeShape tyName
pure case shape of
Vod -> vodToNoun
Tup con -> tupToNoun con
-- Enu cons -> enumToAtom cons
Sum atoms cells -> sumToNoun atoms cells
--------------------------------------------------------------------------------
addErrTag :: String -> Exp -> Exp
@ -111,13 +116,9 @@ addErrTag tag exp =
deriveFromNoun :: Name -> Q [Dec]
deriveFromNoun tyName = do
(params, shape) <- typeShape tyName
let exp = case shape of Vod -> vodFromNoun
Tup con -> tupFromNoun con
-- Enu cons -> enumFromAtom cons
Sum atoms cells -> sumFromNoun atoms cells
(params, _) <- typeShape tyName
exp <- deriveFromNounFunc tyName
params <- pure $ zip ['a' ..] params <&> \(n,_) -> mkName (singleton n)
let ty = foldl' (\acc v -> AppT acc (VarT v)) (ConT tyName) params
@ -129,6 +130,15 @@ deriveFromNoun tyName = do
pure [InstanceD overlap ctx inst [ValD (VarP 'parseNoun) body []]]
deriveFromNounFunc :: Name -> Q Exp
deriveFromNounFunc tyName = do
(_, shape) <- typeShape tyName
pure case shape of
Vod -> vodFromNoun
Tup con -> tupFromNoun con
-- Enu cons -> enumFromAtom cons
Sum atoms cells -> sumFromNoun atoms cells
sumFromNoun :: [(String, Name)] -> [(String, ConInfo)] -> Exp
sumFromNoun [] cl = taggedFromNoun cl
sumFromNoun at [] = enumFromAtom at

View File

@ -31,6 +31,9 @@ export async function bootstrapApi() {
useLocalState.setState({ subscription: 'connected' });
};
[useGraphState].map(s => s.getState()?.clear?.());
useGraphState.getState().getShallowChildren(`~${window.ship}`, 'dm-inbox');
const promises = [
useHarkState,
useMetadataState,

View File

@ -1,7 +1,7 @@
import urbitOb from 'urbit-ob';
import { parsePermalink, permalinkToReference } from '~/logic/lib/permalinks';
const URL_REGEX = new RegExp(String(/^([^[\]]*?)(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+[-a-zA-Z0-9:@;?&=\/%\+\*!'\(\)\$_\{\}\^~\[\]`#|])([\s\S]*)/.source));
const URL_REGEX = new RegExp(String(/^([\s\S]*?)(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+[-a-zA-Z0-9:@;?&=\/%\+\*!'\(\)\$_\{\}\^~\[\]`#|])([\s\S]*)/.source));
const PATP_REGEX = /^([\s\S]*?)(~[a-z_-]+)([\s\S]*)/;
@ -18,7 +18,15 @@ export const isUrl = (str) => {
};
const raceRegexes = (str) => {
const link = str.match(URL_REGEX);
let link = str.match(URL_REGEX);
while(link?.[1]?.endsWith('(')) {
const resumePos = link[1].length + link[2].length;
const resume = str.slice(resumePos);
link = resume.match(URL_REGEX);
if(link) {
link[1] = str.slice(0, resumePos) + link[1];
}
}
const groupRef = str.match(GROUP_REGEX);
const mention = str.match(PATP_REGEX);
let pfix = str;

View File

@ -127,5 +127,15 @@ describe('tokenizeMessage', () => {
expect(text).toBe('oh no, ');
expect(reference.group).toBe('/ship/~sampel/group-123-abc');
});
it('should handle permalinks after inline urls', () => {
const example = 'test [test](https://tlon.io) web+urbitgraph://group/~middev/the-forge/graph/~littel-wolfur/writs-7082/170141184505164612398001831549075456000/2/170141184505164722986064231401764421632';
const [{ text }, { reference: { graph } }] = tokenizeMessage(example);
expect(text).toBe('test [test](https://tlon.io) ');
expect(graph.group).toBe('/ship/~middev/the-forge');
expect(graph.graph).toBe('/ship/~littel-wolfur/writs-7082');
expect(graph.index).toBe('/170141184505164612398001831549075456000/2/170141184505164722986064231401764421632');
});
});

View File

@ -56,8 +56,11 @@ export function parentPath(path: string) {
* string -> enabled feed
*/
export function getFeedPath(association: Association): string | null | undefined {
const { metadata = { config: {} } } = association;
if (metadata.config && 'group' in metadata?.config && metadata.config?.group) {
const metadata = association?.metadata;
if(!metadata) {
return undefined;
}
if (metadata?.config && 'group' in metadata?.config && metadata.config?.group) {
if ('resource' in metadata.config.group) {
return metadata.config.group.resource;
}

View File

@ -102,6 +102,9 @@ const emptyStats = () => ({
});
function updateNotificationStats(state: HarkState, place: HarkPlace, f: (s: HarkStats) => Partial<HarkStats>) {
if(place.desk !== (window as any).desk) {
return;
}
const old = state.unreads?.[place.path] || emptyStats();
state.unreads[place.path] = { ...old, ...f(old) };
}
@ -109,7 +112,8 @@ function updateNotificationStats(state: HarkState, place: HarkPlace, f: (s: Hark
function seenIndex(json: any, state: HarkState): HarkState {
const data = _.get(json, 'saw-place');
if(data) {
updateNotificationStats(state, data, s => ({ last: Date.now() }));
const last = data?.time || Date.now();
updateNotificationStats(state, data.place, s => ({ last }));
}
return state;
}
@ -135,7 +139,6 @@ function readSince(json: any, state: HarkState): HarkState {
function unreadSince(json: any, state: HarkState): HarkState {
const data = _.get(json, 'unread-count');
if (data) {
console.log(data);
const { inc, count, place } = data;
updateNotificationStats(state, place, s => ({ count: inc ? s.count + count : s.count - count }));
}
@ -154,8 +157,10 @@ function unreadEach(json: any, state: HarkState): HarkState {
function allStats(json: any, state: HarkState): HarkState {
if('all-stats' in json) {
const data = json['all-stats'];
console.log(data);
data.forEach(({ place, stats }) => {
if(place.desk !== (window as any).desk) {
return;
}
state.unreads[place.path] = stats;
});
}

View File

@ -1,4 +1,4 @@
import { MetadataUpdate } from '@urbit/api/metadata';
import { MetadataUpdate, Associations, ResourceAssociations } from '@urbit/api/metadata';
import _ from 'lodash';
import { Cage } from '~/types/cage';
import { BaseState } from '../state/base';
@ -12,24 +12,32 @@ export default class MetadataReducer {
}
}
function normalizeAssociations(assocs: ResourceAssociations): Associations {
return _.reduce(assocs, (acc, val) => {
const appName = val['app-name'];
const rid = val.resource;
const old = acc[appName];
return {
...acc,
[appName]: {
...old,
[rid]: val
}
};
}, {
groups: {},
graph: {}
} as Associations);
}
function removeGroup(group: string, assocs: Associations): Associations {
return _.mapValues(assocs, (val): any => _.omitBy(val, assoc => assoc.group === group));
}
const associations = (json: MetadataUpdate, state: MetadataState): MetadataState => {
const data = _.get(json, 'associations', false);
if (data) {
const metadata = state.associations;
Object.keys(data).forEach((key) => {
const val = data[key];
const appName = val['app-name'];
const rid = val.resource;
if (!(appName in metadata)) {
metadata[appName] = {};
}
if (!(rid in metadata[appName])) {
metadata[appName][rid] = {};
}
metadata[appName][rid] = val;
});
state.associations = metadata;
state.associations = normalizeAssociations(data);
state.loaded = true;
}
return state;
@ -58,7 +66,10 @@ const add = (json: MetadataUpdate, state: MetadataState): MetadataState => {
const groupInitial = (json: MetadataUpdate, state: MetadataState): MetadataState => {
const data = _.get(json, 'initial-group', false);
if(data) {
associations(data, state);
state.associations = removeGroup(data.group, state.associations);
const { groups, graph } = normalizeAssociations(data.associations);
state.associations.graph = { ...state.associations.graph, ...graph };
state.associations.groups = { ...state.associations.groups, ...groups };
}
return state;
};

View File

@ -3,7 +3,7 @@ import { compose } from 'lodash/fp';
import _ from 'lodash';
import create, { GetState, SetState, UseStore } from 'zustand';
import { persist } from 'zustand/middleware';
import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api';
import Urbit, { SubscriptionRequestInterface, FatalError } from '@urbit/http-api';
import { Poke } from '@urbit/api';
import airlock from '~/logic/api';
@ -94,6 +94,7 @@ export interface BaseState<StateType extends {}> {
removePatch: (id: string) => void;
optSet: (fn: (state: StateType & BaseState<StateType>) => void) => string;
initialize: (api: Urbit) => Promise<void>;
clear: () => void;
}
export function createSubscription(app: string, path: string, e: (data: any) => void): SubscriptionRequestInterface {
@ -102,7 +103,9 @@ export function createSubscription(app: string, path: string, e: (data: any) =>
path,
event: e,
err: () => {},
quit: () => {}
quit: () => {
throw new FatalError('subscription clogged');
}
};
// TODO: err, quit handling (resubscribe?)
return request;
@ -112,8 +115,12 @@ export const createState = <T extends {}>(
name: string,
properties: T | ((set: SetState<T & BaseState<T>>, get: GetState<T & BaseState<T>>) => T),
blacklist: (keyof BaseState<T> | keyof T)[] = [],
subscriptions: ((set: SetState<T & BaseState<T>>, get: GetState<T & BaseState<T>>) => SubscriptionRequestInterface)[] = []
subscriptions: ((set: SetState<T & BaseState<T>>, get: GetState<T & BaseState<T>>) => SubscriptionRequestInterface)[] = [],
clearedState?: Partial<T>
): UseStore<T & BaseState<T>> => create<T & BaseState<T>>(persist<T & BaseState<T>>((set, get) => ({
clear: () => {
set(clearedState as T & BaseState<T>);
},
initialize: async (api: Urbit) => {
await Promise.all(subscriptions.map(sub => api.subscribe(sub(set, get))));
},

View File

@ -25,6 +25,7 @@ export interface GraphState {
pendingDms: Set<string>;
screening: boolean;
graphTimesentMap: Record<number, string>;
getShallowChildren: (ship: string, name: string, index?: string) => Promise<void>;
getDeepOlderThan: (ship: string, name: string, count: number, start?: string) => Promise<void>;
getNewest: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
getOlderSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
@ -256,9 +257,17 @@ const useGraphState = createState<GraphState>('Graph', (set, get) => ({
if(j) {
reduceStateN(get(), j, reduceDm);
}
})
})],
{
graphs: {},
looseNodes: {},
graphTimesentMap: {},
flatGraphs: {},
threadGraphs: {},
pendingDms: new Set<string>()
}
]);
);
export function useGraph(ship: string, name: string) {
return useGraphState(

View File

@ -1,4 +1,4 @@
import { Association, Associations, MetadataUpdatePreview } from '@urbit/api';
import { Association, Associations, MetadataUpdatePreview } from '@urbit/api/metadata';
import _ from 'lodash';
import { useCallback, useEffect, useState } from 'react';
import {

View File

@ -38,10 +38,10 @@ export interface RemoteContentProps {
}
export const IMAGE_REGEX = new RegExp(
/(jpg|img|png|gif|tiff|jpeg|webp|webm|svg)$/i
/(\.jpg|\.img|\.png|\.gif|\.tiff|\.jpeg|\.webp|\.webm|\.svg)$/i
);
export const AUDIO_REGEX = new RegExp(/(mp3|wav|ogg|m4a)$/i);
export const VIDEO_REGEX = new RegExp(/(mov|mp4|ogv)$/i);
export const AUDIO_REGEX = new RegExp(/(\.mp3|\.wav|\.ogg|\.m4a)$/i);
export const VIDEO_REGEX = new RegExp(/(\.mov|\.mp4|\.ogv)$/i);
const emptyRef = () => {};
export function RemoteContent(props: RemoteContentProps) {

View File

@ -1,5 +1,5 @@
import { LoadingSpinner, Button } from '@tlon/indigo-react';
import React from 'react';
import React from 'react';
import { Box, Row, Col, Text } from '@tlon/indigo-react';
import { PropFunc } from '~/types';
import _ from 'lodash';
@ -40,8 +40,8 @@ function Elbow(
export function StatusBarJoins() {
const pendingJoin = useGroupState(s => s.pendingJoin);
if (
Object.keys(_.omitBy(pendingJoin, j => j.progress === 'done')).length ===
0
Object.keys(_.omitBy(pendingJoin, j => j.hidden || j.progress === 'done'))
.length === 0
) {
return null;
}
@ -63,9 +63,9 @@ export function StatusBarJoins() {
borderRadius="1"
backgroundColor="white"
>
{Object.keys(pendingJoin).map(g => (
<JoinStatus key={g} group={g} join={pendingJoin[g]} />
))}
{Object.keys(pendingJoin).map(g => (
<JoinStatus key={g} group={g} join={pendingJoin[g]} />
))}
</Col>
}
alignX="left"
@ -101,21 +101,19 @@ export function JoinStatus({
};
return (
<Row alignItems="center" gapX="3">
<Col gapY="2">
<Row alignItems="center" gapX="2">
{preview ? (
<MetadataIcon height={4} width={4} metadata={preview.metadata} />
) : null}
<Text>{preview?.metadata.title || group.slice(6)}</Text>
</Row>
<Row ml="2" alignItems="center" gapX="2">
<Elbow />
<Text>{desc}</Text>
</Row>
</Col>
<Button onClick={onHide}>
Hide
</Button>
</Row>
<Col gapY="2">
<Row alignItems="center" gapX="2">
{preview ? (
<MetadataIcon height={4} width={4} metadata={preview.metadata} />
) : null}
<Text>{preview?.metadata.title || group.slice(6)}</Text>
</Row>
<Row ml="2" alignItems="center" gapX="2">
<Elbow />
<Text>{desc}</Text>
</Row>
</Col>
<Button onClick={onHide}>Hide</Button>
</Row>
);
}

View File

@ -36,7 +36,7 @@ export function GroupifyForm(props: GroupifyFormProps) {
name,
values.group?.toString() || undefined
));
let mod = association['app-name'];
let mod: string = association['app-name'];
if (association?.metadata?.config && 'graph' in association.metadata.config) {
mod = association.metadata.config.graph as AppName;
}

View File

@ -2,6 +2,7 @@ import { Col, ColProps } from '@tlon/indigo-react';
import { Post } from '@urbit/api';
import React, { ReactElement, useCallback, useState } from 'react';
import styled, { css } from 'styled-components';
import { useResize } from '~/logic/lib/useResize';
import { GraphContent } from '~/views/landscape/components/Graph/GraphContent';
type TruncateProps = ColProps & {
@ -12,6 +13,7 @@ const TruncatedBox = styled(Col)<TruncateProps>`
display: -webkit-box;
-webkit-box-orient: vertical;
${p => p.truncate && css`
margin-bottom: ${p.theme.space[2]}px;
max-height: 300px;
mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 60%, transparent 100%);
`}
@ -27,15 +29,13 @@ const PostContent = ({ post, isParent }: PostContentProps): ReactElement => {
const [height, setHeight] = useState(0);
const showFade = !isParent && height >= 300;
const measuredRef = useCallback((node) => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}, []);
const resizer = useResize<HTMLDivElement>(useCallback((entry) => {
setHeight(entry.target.getBoundingClientRect().height);
}, []));
return (
<TruncatedBox
ref={measuredRef}
ref={resizer.ref}
truncate={showFade}
display="-webkit-box"
width="90%"

View File

@ -26,7 +26,7 @@ export function Resource(props: ResourceProps): ReactElement {
const notificationsCount = useHarkState(state => state.notificationsCount);
const associations = useMetadataState(state => state.associations);
const contacts = useContactState(state => state.contacts);
let app = association['app-name'];
let app: string = association['app-name'];
if (association?.metadata?.config && 'graph' in association.metadata.config) {
app = association.metadata.config.graph as AppName;
}

View File

@ -65,7 +65,7 @@ type ResourceSkeletonProps = {
export function ResourceSkeleton(props: ResourceSkeletonProps): ReactElement {
const { association, baseUrl, children } = props;
let app = association['app-name'];
let app: string = association['app-name'];
if (association?.metadata?.config && 'graph' in association.metadata.config) {
app = association.metadata.config.graph as AppName;
}

View File

@ -2,7 +2,7 @@ import _ from 'lodash';
import React, { useRef, ReactNode } from 'react';
import urbitOb from 'urbit-ob';
import { Icon, Row, Box, Text, BaseImage } from '@tlon/indigo-react';
import { Association, cite, AppName } from '@urbit/api';
import { Association, cite } from '@urbit/api';
import { HoverBoxLink } from '~/views/components/HoverBox';
import { Sigil } from '~/logic/lib/sigil';
import { useTutorialModal } from '~/views/components/useTutorialModal';
@ -177,9 +177,9 @@ export const SidebarAssociationItem = React.memo((props: {
const { association, selected } = props;
const title = getItemTitle(association) || '';
const appName = association?.['app-name'];
let mod = appName;
let mod: string = appName;
if (association?.metadata?.config && 'graph' in association.metadata.config) {
mod = association.metadata.config.graph as AppName;
mod = association.metadata.config.graph ;
}
const rid = association?.resource;
const groupPath = association?.group;

View File

@ -651,7 +651,7 @@
:- ~ :- ~ :- %noun
!>
?+ t.t.t.t.path (on-peek:def path)
~
~
^- update-log:store
?~(update-log *update-log:store u.update-log)
::
@ -681,7 +681,7 @@
=* graph p.u.marked-graph
=* mark q.u.marked-graph
?+ t.t.t.t.path (on-peek:def path)
~
~
:- ~ :- ~ :- mar
!>(`update:store`[now.bowl [%add-graph [ship term] graph mark %.y]])
::

View File

@ -246,15 +246,32 @@
|= [group=resource =associations:store]
=/ assocs=(list [=md-resource:store grp=resource =metadatum:store])
~(tap by associations)
:- (send-diff:mc %initial-group group associations)
=/ old-resources=(set md-resource:store) (~(get ju group-indices) group)
=/ cur-resources=(set md-resource:store) ~(key by associations)
=. state (remove-gone group (~(dif in old-resources) cur-resources))
|-
?~ assocs
state
:_ state
(send-diff:mc %initial-group group associations)
=, assocs
?> =(group grp.i)
=^ cards state
(handle-add group [md-resource metadatum]:i)
$(assocs t)
::
++ remove-gone
|= [group=resource gone=(set md-resource:store)]
^+ state
%+ roll ~(tap in gone)
|= [=md-resource:store out=_state]
%_ out
associations (~(del by associations.out) md-resource)
group-indices (~(del ju group-indices.out) group md-resource)
resource-indices (~(del by resource-indices.out) md-resource)
::
app-indices
(~(del ju app-indices.out) app-name.md-resource group resource.md-resource)
==
--
::
++ poke-import

View File

@ -69,7 +69,7 @@
%_ $
-.old %1
::
cards
cards
%+ welp cards
:~ (~(leave-our pass:io /hark) %hark-store)
(~(watch-our pass:io /hark) %hark-store /notes)
@ -121,18 +121,23 @@
?. (is-whitelisted:do src.bowl u.entry)
~|("permission denied" !!)
=. clients.u.entry (~(put by clients.u.entry) src.bowl ~)
:_ state(provider-state (~(put by provider-state) service.act u.entry))
:~ %: register-binding:do
service.act
u.entry
binding-endpoint.u.entry
src.bowl
address.act
==
%+ watch:pass
[src.bowl %notify]
/notify/(scot %p src.bowl)/[service.act]
==
=/ cards=(list card)
:_ ~
%: register-binding:do
service.act
u.entry
binding-endpoint.u.entry
src.bowl
address.act
==
=/ =wire /agentio-watch/notify/(scot %p src.bowl)/[service.act]
=? cards !(~(has by wex.bowl) wire src.bowl %notify)
:_ cards
%+ watch:pass
[src.bowl %notify]
/notify/(scot %p src.bowl)/[service.act]
:- cards
state(provider-state (~(put by provider-state) service.act u.entry))
::
%client-leave
=/ entry=(unit provider-entry) (~(get by provider-state) service.act)

View File

@ -117,7 +117,7 @@
::
++ check-all
=> (lib-hooks-desync %group scry-groups)
=> (lib-hooks-desync %graph get-keys:gra)
=> (lib-hooks-desync %graph scry-graphs)
=> (lib-hooks-desync %metadata scry-groups)
=> contacts
metadata
@ -241,6 +241,19 @@
,(set resource)
/x/[hook]/sharing/noun
::
++ scry-graphs
=+ .^ app-indices=(jug term [resource resource])
%gy
(scot %p our.bowl)
%metadata-store
(scot %da now.bowl)
/app-indices
==
=/ resources=(set [resource resource])
(~(get ju app-indices) %graph)
%- ~(int in get-keys:gra)
(~(gas in *(set resource)) (turn ~(tap in resources) |=([resource r=resource] r)))
::
++ md-group-indices
(scry (jug resource md-resource) /y/metadata-store/group-indices)
::

View File

@ -1,7 +1,7 @@
:~ title+'Groups'
info+'A suite of applications to communicate on Urbit'
color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v7.597ab.3d6qj.b7a9l.5no45.9dq2g.glob' 0v7.597ab.3d6qj.b7a9l.5no45.9dq2g]
glob-http+['https://bootstrap.urbit.org/glob-0v4d800.vqmrl.r0js2.ip98v.dd8sh.glob' 0v4d800.vqmrl.r0js2.ip98v.dd8sh]
base+'landscape'
version+[1 3 5]
website+'https://tlon.io'

View File

@ -1,20 +0,0 @@
CC ?= cc
AR ?= ar
PREFIX ?= ./out
################################################################################
.PHONY: all test install clean
all: aes_siv.c aes_siv.h
$(CC) $(CFLAGS) -Wall -Wextra -Wstrict-prototypes -Wconversion -O3 -fomit-frame-pointer -funroll-loops -ftree-vectorize -DNDEBUG -c aes_siv.c
$(AR) rcs libaes_siv.a aes_siv.o
install: all
@mkdir -p $(PREFIX)/lib/
@mkdir -p $(PREFIX)/include/
cp libaes_siv.a $(PREFIX)/lib/
cp aes_siv.h $(PREFIX)/include/
clean:
rm -rf ./out

View File

@ -1,197 +0,0 @@
# libaes_siv
This is an [RFC5297](https://tools.ietf.org/html/rfc5297)-compliant C
implementation of AES-SIV written by Daniel Franke on behalf of
[Akamai Technologies](https://www.akamai.com). It is published under
the [Apache License
(v2.0)](https://www.apache.org/licenses/LICENSE-2.0). It uses OpenSSL
for the underlying
[AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and
[CMAC](https://en.wikipedia.org/wiki/One-key_MAC) implementations and
follows a similar interface style.
An AES_SIV implementation forked from libaes_siv has been [merged into
the OpenSSL master branch](https://github.com/openssl/openssl/pull/3540).
However, the two implementations are not API-compatible; see section
"OpenSSL API Comparison" below.
## Overview of SIV mode
Synthetic Initialization Vector (SIV) mode is a [block cipher mode of
operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
for [authenticated encryption with associated
data](https://en.wikipedia.org/wiki/Authenticated_encryption) designed
to be maximally resistant to accidental
[nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) reuse. If
two messages are accidentally encrypted using the same nonce and the
same associated data, the attacker learns nothing except whether or
not the plaintexts of the two messages are identical to each other.
SIV mode also permits the nonce to be intentionally omitted, resulting
in a [deterministic encryption
scheme](https://en.wikipedia.org/wiki/Deterministic_encryption).
Here are a couple common situations where AES-SIV may be an
appropriate choice of AEAD scheme:
1. You can't count on the system doing the encrypting to reliably
generate a unique nonce for every message. For example, the system
may be an embedded device with no good entropy source, or may be a
VM subject to be snapshotted and restored.
2. You want your encryption to be deterministic so that an
intermediating party such as a caching proxy, provided only with
ciphertext, can perform deduplication.
The drawback to SIV mode is that it requires two passes over its
input. This makes it potentially clumsy for use with large messages
since the entire message must be held in memory at one time. SIV mode
is also a bit slower than most widely-used block cipher modes (but
can still be quite fast — see performance numbers below).
Be aware that with *any* encryption scheme, including SIV, repeating
or omitting a nonce can still be [fatal to
security](https://xkcd.com/257) if your plaintexts have low entropy,
e.g., if each message consists only of a single bit.
Keys for SIV mode are twice the length of the keys for the underlying
block cipher. For example, keys for AES-128-SIV are 256 bits long,
and keys for AES-256-SIV are 512 bits long.
## Build instructions
Build dependencies:
* Any ISO C89 compiler (GCC or Clang recommended). No C99 language
features are required, however `<stdint.h>` must be available and
must define `uint64_t`. `char` must be 8 bits and arithmetic must be
two's complement.
* [CMake](https://cmake.org) >= 3.1
* [OpenSSL](https://openssl.org) >=1.0.1 (libcrypto only). A recent
release from the 1.0.2 branch or later is strongly recommended since
1.0.1 was EOL'ed at the end of 2016. Furthermore, OpenSSL versions prior
to 1.0.1n and 1.0.2b have known bugs which impact `libaes_siv` and
will cause failures in its test suite. LibreSSL is not supported.
* [Asciidoc](http://asciidoc.org) (only required for building man pages)
Running benchmarks requires a POSIX.1-2001 compliant OS, including
the `clock_gettime` system call.
To build and install on POSIX-like platforms:
```
cmake . &&
make &&
make test &&
sudo make install
```
NOTE: Out-of-source builds are allowed, but out-of-source manpage builds
require a2x's -D option, which may provoke an apparently bogus warning from a2x.
If you want to build on an OS X machine, install the Xcode development
environment and the command line tools, then use either the Homebrew package
manager or the MacPorts package manager to install cmake and OpenSSL.
Homebrew (https://brew.sh/):
```
brew install cmake openssl &&
cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/openssl . &&
make &&
make test &&
sudo make install
```
MacPorts (https://www.macports.org/):
```
sudo port install cmake openssl &&
cmake . &&
make &&
make test &&
sudo make install
```
To create a native Windows build, you will first need to build
OpenSSL. Install Visual Studio, CMake, ActiveState Perl, and NASM, and
ensure that `nasm.exe` is somewhere in your `%PATH%`. From a VS developer
command prompt, unpack the OpenSSL sources and run
```
perl Configure VC-WIN64A
nmake
```
Then to build `libaes_siv`, run
```
cmake -G "NMake Makefiles" -DOPENSSL_ROOT_DIR=\path\to\openssl .
nmake
nmake test
```
## Usage
See the manual pages for API documentation, and the test vectors
in `tests.c` for simple usage examples. You can also use the `demo` command
line program to encrypt and decrypt data.
## OpenSSL API Comparison
In December 2018, OpenSSL merged an AES-SIV implementation derived
from libaes_siv. As of February 2019 this implementation has not been
released yet; it will appear some time post-1.1.1. However, despite
the two implementations' common ancestry, they are not API-compatible.
The OpenSSL team had to make an ugly-but-necessary compromise in order
to shoehorn SIV mode into OpenSSL's EVP API, which is a streaming API
that was never designed to support SIV's two-pass operation. When used for
SIV operations, the EVP API is forced to return an error if you invoke
`EVP_(En|De)crypt_Update` more than once for the same message.
When designing libaes_siv, I rejected this behavior as an unacceptable
breakdown of the API contract and opted to dispense with the EVP
abstraction altogether rather than permit it to leak. libaes_siv's API
remains stylistically similar to EVP, but is nonetheless distinct and
avoids the above pitfall.
## Performance
On the author's Intel Core i7-6560U laptop, libaes_siv can process
approximately 796 MiB of plaintext or ciphertext or 963 MiB of
associated data per second using 256-bit keys
(i.e., AES-128). Encrypting a zero-byte message takes approximately
990ns. To obtain numbers for your own system, run `make bench &&
./bench`.
## Software assurance
libaes_siv's test suite includes all test vectors from RFC 5297 and
achieves 100% code coverage according to
[gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html). It produces
clean output from [Valgrind](https://valgrind.org) and from Clang's
[undefined behavior
sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html),
and is verified using [ctgrind](https://github.com/agl/ctgrind) to run
in constant time.
Nonetheless, libaes_siv should at present be considered beta-quality
code. It has not yet been tested on platforms other than x86-64 Linux
or benefited from any significant amount of user feedback, and
the codebase is in need of additional review by cryptographers and
expert C programmers.
## Bugs and pull requests
Use the GitHub issue tracker. For reporting sensitive security issues,
contact the author directly. (Note: I no longer use PGP. Please
request my Signal details if necessary).
## A note on version numbers
libaes_siv version numbers are of the form `<major>.<minor>.<patch>`
and follow a semantic versioning scheme. The major version number
will be incremented with any backward-incompatible ABI change. The
minor version number will be incremented if new functionality is
added without impacting ABI backward-compatibility. The patch
version number will be incremented for releases that make no
externally-visible changes.
As a result of this scheme, on ELF platforms, the .so version will
be the same as the release version.
Version numbers indicate nothing about code quality or maturity. No
code known or suspected to be less suitable for production use than
previous releases will ever be tagged with a version number.

View File

@ -1,2 +0,0 @@
Vendoring of git@github.com:dfoxfranke/libaes_siv.git.
Code from commit 509550e92a416172b9b8255e275f3a04d5fd4545

View File

@ -1,594 +0,0 @@
/* Copyright (c) 2017-2019 Akamai Technologies, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE 1
#include "config.h"
#include "aes_siv.h"
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#ifdef ENABLE_DEBUG_OUTPUT
#include <stdio.h>
#endif
#ifdef _MSC_VER
/* For _byteswap_uint64 */
#include <stdlib.h>
#endif
#include <string.h>
#include <openssl/cmac.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#ifdef ENABLE_CTGRIND
#include <ctgrind.h>
#endif
#if CHAR_BIT != 8
#error "libaes_siv requires an 8-bit char type"
#endif
#if -1 != ~0
#error "libaes_siv requires a two's-complement architecture"
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
#undef inline
#elif defined(__GNUC__) || defined(__clang__)
#define inline __inline__
#elif defined(_MSC_VER)
#define inline __inline
#else
#define inline
#endif
#if defined(__GNUC__) || defined(__clang__)
#define LIKELY(cond) __builtin_expect(cond, 1)
#define UNLIKELY(cond) __builtin_expect(cond, 0)
#else
#define LIKELY(cond) cond
#define UNLIKELY(cond) cond
#endif
#ifndef ENABLE_CTGRIND
static inline void ct_poison(const void *data, size_t len) {
(void)data;
(void)len;
}
static inline void ct_unpoison(const void *data, size_t len) {
(void)data;
(void)len;
}
#endif
static void debug(const char *label, const unsigned char *hex, size_t len) {
/* ENABLE_CTGRIND has to override ENABLE_DEBUG_OUTPUT since sensitive data
gets printed.
*/
#if defined(ENABLE_DEBUG_OUTPUT) && !defined(ENABLE_CTGRIND)
size_t i;
printf("%16s: ", label);
for (i = 0; i < len; i++) {
if (i > 0 && i % 16 == 0) {
printf("\n ");
}
printf("%.2x", (int)hex[i]);
if (i > 0 && i % 4 == 3) {
printf(" ");
}
}
printf("\n");
#else
(void)label;
(void)hex;
(void)len;
#endif
}
typedef union block_un {
uint64_t word[2];
unsigned char byte[16];
} block;
const union {
uint64_t word;
char byte[8];
} endian = {0x0102030405060708};
#define I_AM_BIG_ENDIAN (endian.byte[0] == 1 && \
endian.byte[1] == 2 && \
endian.byte[2] == 3 && \
endian.byte[3] == 4 && \
endian.byte[4] == 5 && \
endian.byte[5] == 6 && \
endian.byte[6] == 7 && \
endian.byte[7] == 8)
#define I_AM_LITTLE_ENDIAN (endian.byte[0] == 8 && \
endian.byte[1] == 7 && \
endian.byte[2] == 6 && \
endian.byte[3] == 5 && \
endian.byte[4] == 4 && \
endian.byte[5] == 3 && \
endian.byte[6] == 2 && \
endian.byte[7] == 1)
#if defined(__GNUC__) || defined(__clang__)
static inline uint64_t bswap64(uint64_t x) { return __builtin_bswap64(x); }
#elif defined(_MSC_VER)
static inline uint64_t bswap64(uint64_t x) { return _byteswap_uint64(x); }
#else
static inline uint32_t rotl(uint32_t x) { return (x << 8) | (x >> 24); }
static inline uint32_t rotr(uint32_t x) { return (x >> 8) | (x << 24); }
static inline uint64_t bswap64(uint64_t x) {
uint32_t high = (uint32_t)(x >> 32);
uint32_t low = (uint32_t)x;
high = (rotl(high) & 0x00ff00ff) | (rotr(high) & 0xff00ff00);
low = (rotl(low) & 0x00ff00ff) | (rotr(low) & 0xff00ff00);
return ((uint64_t)low) << 32 | (uint64_t)high;
}
#endif
static inline uint64_t getword(block const *block, size_t i) {
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
if (I_AM_BIG_ENDIAN) {
return block->word[i];
} else if (I_AM_LITTLE_ENDIAN) {
return bswap64(block->word[i]);
} else {
#endif
i <<= 3;
return ((uint64_t)block->byte[i + 7]) |
((uint64_t)block->byte[i + 6] << 8) |
((uint64_t)block->byte[i + 5] << 16) |
((uint64_t)block->byte[i + 4] << 24) |
((uint64_t)block->byte[i + 3] << 32) |
((uint64_t)block->byte[i + 2] << 40) |
((uint64_t)block->byte[i + 1] << 48) |
((uint64_t)block->byte[i] << 56);
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
}
#endif
}
static inline void putword(block *block, size_t i, uint64_t x) {
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
if (I_AM_BIG_ENDIAN) {
block->word[i] = x;
} else if (I_AM_LITTLE_ENDIAN) {
block->word[i] = bswap64(x);
} else {
#endif
i <<= 3;
block->byte[i] = (unsigned char)(x >> 56);
block->byte[i + 1] = (unsigned char)((x >> 48) & 0xff);
block->byte[i + 2] = (unsigned char)((x >> 40) & 0xff);
block->byte[i + 3] = (unsigned char)((x >> 32) & 0xff);
block->byte[i + 4] = (unsigned char)((x >> 24) & 0xff);
block->byte[i + 5] = (unsigned char)((x >> 16) & 0xff);
block->byte[i + 6] = (unsigned char)((x >> 8) & 0xff);
block->byte[i + 7] = (unsigned char)(x & 0xff);
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
}
#endif
}
static inline void xorblock(block *x, block const *y) {
x->word[0] ^= y->word[0];
x->word[1] ^= y->word[1];
}
/* Doubles `block`, which is 16 bytes representing an element
of GF(2**128) modulo the irreducible polynomial
x**128 + x**7 + x**2 + x + 1. */
static inline void dbl(block *block) {
uint64_t high = getword(block, 0);
uint64_t low = getword(block, 1);
uint64_t high_carry = high & (((uint64_t)1) << 63);
uint64_t low_carry = low & (((uint64_t)1) << 63);
/* Assumes two's-complement arithmetic */
int64_t low_mask = -((int64_t)(high_carry >> 63)) & 0x87;
uint64_t high_mask = low_carry >> 63;
high = (high << 1) | high_mask;
low = (low << 1) ^ (uint64_t)low_mask;
putword(block, 0, high);
putword(block, 1, low);
}
struct AES_SIV_CTX_st {
/* d stores intermediate results of S2V; it corresponds to D from the
pseudocode in section 2.4 of RFC 5297. */
block d;
EVP_CIPHER_CTX *cipher_ctx;
/* SIV_AES_Init() sets up cmac_ctx_init. cmac_ctx is a scratchpad used
by SIV_AES_AssociateData() and SIV_AES_(En|De)cryptFinal. */
CMAC_CTX *cmac_ctx_init, *cmac_ctx;
};
void AES_SIV_CTX_cleanup(AES_SIV_CTX *ctx) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_CIPHER_CTX_reset(ctx->cipher_ctx);
#else
EVP_CIPHER_CTX_cleanup(ctx->cipher_ctx);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER <= 0x10100060L
/* Workaround for an OpenSSL bug that causes a double free
if you call CMAC_CTX_cleanup() before CMAC_CTX_free().
https://github.com/openssl/openssl/pull/2798
*/
CMAC_CTX_free(ctx->cmac_ctx_init);
ctx->cmac_ctx_init = CMAC_CTX_new();
CMAC_CTX_free(ctx->cmac_ctx);
ctx->cmac_ctx = CMAC_CTX_new();
#else
CMAC_CTX_cleanup(ctx->cmac_ctx_init);
CMAC_CTX_cleanup(ctx->cmac_ctx);
#endif
OPENSSL_cleanse(&ctx->d, sizeof ctx->d);
}
void AES_SIV_CTX_free(AES_SIV_CTX *ctx) {
if (ctx) {
EVP_CIPHER_CTX_free(ctx->cipher_ctx);
/* Prior to OpenSSL 1.0.2b, CMAC_CTX_free() crashes on NULL */
if (LIKELY(ctx->cmac_ctx_init != NULL)) {
CMAC_CTX_free(ctx->cmac_ctx_init);
}
if (LIKELY(ctx->cmac_ctx != NULL)) {
CMAC_CTX_free(ctx->cmac_ctx);
}
OPENSSL_cleanse(&ctx->d, sizeof ctx->d);
OPENSSL_free(ctx);
}
}
AES_SIV_CTX *AES_SIV_CTX_new(void) {
AES_SIV_CTX *ctx = OPENSSL_malloc(sizeof(struct AES_SIV_CTX_st));
if (UNLIKELY(ctx == NULL)) {
return NULL;
}
ctx->cipher_ctx = EVP_CIPHER_CTX_new();
ctx->cmac_ctx_init = CMAC_CTX_new();
ctx->cmac_ctx = CMAC_CTX_new();
if (UNLIKELY(ctx->cipher_ctx == NULL ||
ctx->cmac_ctx_init == NULL ||
ctx->cmac_ctx == NULL)) {
AES_SIV_CTX_free(ctx);
return NULL;
}
return ctx;
}
int AES_SIV_CTX_copy(AES_SIV_CTX *dst, AES_SIV_CTX const *src) {
memcpy(&dst->d, &src->d, sizeof src->d);
if(UNLIKELY(EVP_CIPHER_CTX_copy(dst->cipher_ctx, src->cipher_ctx)
!= 1)) {
return 0;
}
if (UNLIKELY(CMAC_CTX_copy(dst->cmac_ctx_init, src->cmac_ctx_init)
!= 1)) {
return 0;
}
/* Not necessary to copy cmac_ctx since it's just temporary
* storage */
return 1;
}
int AES_SIV_Init(AES_SIV_CTX *ctx, unsigned char const *key, size_t key_len) {
static const unsigned char zero[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
size_t out_len;
int ret = 0;
ct_poison(key, key_len);
switch (key_len) {
case 32:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 16,
EVP_aes_128_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_128_ctr(),
NULL, key + 16, NULL) != 1)) {
goto done;
}
break;
case 48:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 24,
EVP_aes_192_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_192_ctr(),
NULL, key + 24, NULL) != 1)) {
goto done;
}
break;
case 64:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 32,
EVP_aes_256_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_256_ctr(),
NULL, key + 32, NULL) != 1)) {
goto done;
}
break;
default:
goto done;
}
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Update(ctx->cmac_ctx, zero, sizeof zero) != 1)) {
goto done;
}
out_len = sizeof ctx->d;
if (UNLIKELY(CMAC_Final(ctx->cmac_ctx, ctx->d.byte, &out_len) != 1)) {
goto done;
}
debug("CMAC(zero)", ctx->d.byte, out_len);
ret = 1;
done:
ct_unpoison(key, key_len);
return ret;
}
int AES_SIV_AssociateData(AES_SIV_CTX *ctx, unsigned char const *data,
size_t len) {
block cmac_out;
size_t out_len = sizeof cmac_out;
int ret = 0;
ct_poison(data, len);
dbl(&ctx->d);
debug("double()", ctx->d.byte, 16);
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Update(ctx->cmac_ctx, data, len) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Final(ctx->cmac_ctx, cmac_out.byte, &out_len) != 1)) {
goto done;
}
assert(out_len == 16);
debug("CMAC(ad)", cmac_out.byte, 16);
xorblock(&ctx->d, &cmac_out);
debug("xor", ctx->d.byte, 16);
ret = 1;
done:
ct_unpoison(data, len);
return ret;
}
static inline int do_s2v_p(AES_SIV_CTX *ctx, block *out,
unsigned char const* in, size_t len) {
block t;
size_t out_len = sizeof out->byte;
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
return 0;
}
if(len >= 16) {
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, in, len - 16) != 1)) {
return 0;
}
debug("xorend part 1", in, len - 16);
memcpy(&t, in + (len-16), 16);
xorblock(&t, &ctx->d);
debug("xorend part 2", t.byte, 16);
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, t.byte, 16) != 1)) {
return 0;
}
} else {
size_t i;
memcpy(&t, in, len);
t.byte[len] = 0x80;
for(i = len + 1; i < 16; i++) {
t.byte[i] = 0;
}
debug("pad", t.byte, 16);
dbl(&ctx->d);
xorblock(&t, &ctx->d);
debug("xor", t.byte, 16);
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, t.byte, 16) != 1)) {
return 0;
}
}
if(UNLIKELY(CMAC_Final(ctx->cmac_ctx, out->byte, &out_len) != 1)) {
return 0;
}
assert(out_len == 16);
debug("CMAC(final)", out->byte, 16);
return 1;
}
static inline int do_encrypt(EVP_CIPHER_CTX *ctx, unsigned char *out,
unsigned char const *in, size_t len, block *icv) {
#ifdef ENABLE_DEBUG_TINY_CHUNK_SIZE
const int chunk_size = 7;
#else
const int chunk_size = 1 << 30;
#endif
size_t len_remaining = len;
int out_len;
int ret;
if(UNLIKELY(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, icv->byte)
!= 1)) {
return 0;
}
while(UNLIKELY(len_remaining > (size_t)chunk_size)) {
out_len = chunk_size;
if(UNLIKELY(EVP_EncryptUpdate(ctx, out, &out_len, in, out_len)
!= 1)) {
return 0;
}
assert(out_len == chunk_size);
out += out_len;
in += out_len;
len_remaining -= (size_t)out_len;
}
out_len = (int)len_remaining;
ret = EVP_EncryptUpdate(ctx, out, &out_len, in, out_len);
assert(!ret || out_len == (int)len_remaining);
return ret;
}
int AES_SIV_EncryptFinal(AES_SIV_CTX *ctx, unsigned char *v_out,
unsigned char *c_out, unsigned char const *plaintext,
size_t len) {
block q;
int ret = 0;
ct_poison(plaintext, len);
if(UNLIKELY(do_s2v_p(ctx, &q, plaintext, len) != 1)) {
goto done;
}
ct_unpoison(&q, sizeof q);
memcpy(v_out, &q, 16);
q.byte[8] &= 0x7f;
q.byte[12] &= 0x7f;
if(UNLIKELY(do_encrypt(ctx->cipher_ctx, c_out, plaintext, len, &q)
!= 1)) {
goto done;
}
ret = 1;
debug("ciphertext", c_out, len);
done:
ct_unpoison(plaintext, len);
ct_unpoison(c_out, len);
ct_unpoison(v_out, 16);
return ret;
}
int AES_SIV_DecryptFinal(AES_SIV_CTX *ctx, unsigned char *out,
unsigned char const *v, unsigned char const *c,
size_t len) {
block t, q;
size_t i;
uint64_t result;
int ret = 0;
ct_poison(c, len);
memcpy(&q, v, 16);
q.byte[8] &= 0x7f;
q.byte[12] &= 0x7f;
if(UNLIKELY(do_encrypt(ctx->cipher_ctx, out, c, len, &q) != 1)) {
goto done;
}
debug("plaintext", out, len);
if(UNLIKELY(do_s2v_p(ctx, &t, out, len) != 1)) {
goto done;
}
for (i = 0; i < 16; i++) {
t.byte[i] ^= v[i];
}
result = t.word[0] | t.word[1];
ct_unpoison(&result, sizeof result);
ret = !result;
if(ret) {
ct_unpoison(out, len);
} else {
OPENSSL_cleanse(out, len);
}
done:
ct_unpoison(c, len);
return ret;
}
int AES_SIV_Encrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *plaintext, size_t plaintext_len,
unsigned char const *ad, size_t ad_len) {
if (UNLIKELY(*out_len < plaintext_len + 16)) {
return 0;
}
*out_len = plaintext_len + 16;
if (UNLIKELY(AES_SIV_Init(ctx, key, key_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_AssociateData(ctx, ad, ad_len) != 1)) {
return 0;
}
if (nonce != NULL &&
UNLIKELY(AES_SIV_AssociateData(ctx, nonce, nonce_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_EncryptFinal(ctx, out, out + 16, plaintext,
plaintext_len) != 1)) {
return 0;
}
debug("IV || C", out, *out_len);
return 1;
}
int AES_SIV_Decrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *ciphertext, size_t ciphertext_len,
unsigned char const *ad, size_t ad_len) {
if (UNLIKELY(ciphertext_len < 16)) {
return 0;
}
if (UNLIKELY(*out_len < ciphertext_len - 16)) {
return 0;
}
*out_len = ciphertext_len - 16;
if (UNLIKELY(AES_SIV_Init(ctx, key, key_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_AssociateData(ctx, ad, ad_len) != 1)) {
return 0;
}
if (nonce != NULL &&
UNLIKELY(AES_SIV_AssociateData(ctx, nonce, nonce_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_DecryptFinal(ctx, out, ciphertext, ciphertext + 16,
ciphertext_len - 16) != 1)) {
return 0;
}
debug("plaintext", out, *out_len);
return 1;
}

View File

@ -1,57 +0,0 @@
/* Copyright (c) 2017-2019 Akamai Technologies, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef AES_SIV_H_
#define AES_SIV_H_
#include <stddef.h>
#define LIBAES_SIV_VERSION_MAJOR 1
#define LIBAES_SIV_VERSION_MINOR 0
#define LIBAES_SIV_VERSION_PATCH 1
#define LIBAES_SIV_VERSION ((LIBAES_SIV_VERSION_MAJOR << 16) + \
(LIBAES_SIV_VERSION_MINOR << 8) + \
LIBAES_SIV_VERSION_PATCH)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AES_SIV_CTX_st AES_SIV_CTX;
AES_SIV_CTX *AES_SIV_CTX_new(void);
int AES_SIV_CTX_copy(AES_SIV_CTX *dst, AES_SIV_CTX const *src);
void AES_SIV_CTX_cleanup(AES_SIV_CTX *ctx);
void AES_SIV_CTX_free(AES_SIV_CTX *ctx);
int AES_SIV_Init(AES_SIV_CTX *ctx, unsigned char const *key, size_t key_len);
int AES_SIV_AssociateData(AES_SIV_CTX *ctx, unsigned char const *data,
size_t len);
int AES_SIV_EncryptFinal(AES_SIV_CTX *ctx, unsigned char *v_out,
unsigned char *c_out, unsigned char const *plaintext,
size_t len);
int AES_SIV_DecryptFinal(AES_SIV_CTX *ctx, unsigned char *out,
unsigned char const *v, unsigned char const *c,
size_t len);
int AES_SIV_Encrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *plaintext, size_t plaintext_len,
unsigned char const *ad, size_t ad_len);
int AES_SIV_Decrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *ciphertext, size_t ciphertext_len,
unsigned char const *ad, size_t ad_len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,19 +0,0 @@
#ifndef AES_SIV_CONFIG_H_
#define AES_SIV_CONFIG_H_
/* Enable ct_poison() and ct_unpoison() hooks for testing with
ctgrind. */
/* #undef ENABLE_CTGRIND */
/* Enable this to get test coverage for the portable versions of
putword() and getword() when you don't happen to have a PDP-11
in your test farm.
*/
/* #undef ENABLE_DEBUG_WEIRD_ENDIAN */
/* Enable this to get test coverage for the while loop in do_encrypt()
without having to have a multi-gigabyte test case that'll take
forever for Valgrind to crunch through
*/
/* #undef ENABLE_DEBUG_TINY_CHUNK_SIZE */
#endif

View File

@ -1,5 +1,5 @@
import { AppName, Path, Poke, uxToHex, PatpNoSig } from '../lib';
import { Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove, MetadataEditField, MetadataUpdateEdit } from './types';
import { Path, Poke, uxToHex, PatpNoSig } from '../lib';
import { MdAppName, Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove, MetadataEditField, MetadataUpdateEdit } from './types';
export const METADATA_UPDATE_VERSION = 2;
@ -11,7 +11,7 @@ export const metadataAction = <T extends MetadataUpdate>(data: T, version: numbe
export const add = (
ship: PatpNoSig,
appName: AppName,
appName: MdAppName,
resource: Path,
group: Path,
title: string,
@ -44,10 +44,10 @@ export const add = (
export { add as metadataAdd };
export const remove = (
appName: AppName,
appName: MdAppName,
resource: string,
group: string
): Poke<MetadataUpdateRemove> => metadataAction({
): Poke<MetadataUpdateRemove> => metadataAction<MetadataUpdateRemove>({
remove: {
group,
resource: {
@ -62,7 +62,7 @@ export { remove as metadataRemove };
export const edit = (
association: Association,
edit: MetadataEditField
): Poke<MetadataUpdateEdit> => metadataAction({
): Poke<MetadataUpdateEdit> => metadataAction<MetadataUpdateEdit>({
edit: {
group: association.group,
resource: {
@ -84,7 +84,7 @@ export const update = (
): Poke<MetadataUpdateAdd> => {
const metadata = { ...association.metadata, ...newMetadata };
metadata.color = uxToHex(metadata.color);
return metadataAction({
return metadataAction<MetadataUpdateAdd>({
add: {
group: association.group,
resource: {

View File

@ -1,4 +1,6 @@
import { AppName, Path, Patp } from '../lib';
import { Path, Patp } from '../lib';
export type MdAppName = 'groups' | 'graph';
export type MetadataUpdate =
MetadataUpdateInitial
@ -26,6 +28,7 @@ export type MetadataUpdateUpdate = {
export interface MetadataUpdateEdit {
edit: {
resource: MdResource;
group: string;
edit: MetadataEditField;
}
}
@ -41,7 +44,7 @@ export type MetadataUpdateRemove = {
export interface MdResource {
resource: string;
'app-name': AppName;
'app-name': MdAppName;
}
export interface MetadataUpdatePreview {

View File

@ -1,7 +1,7 @@
import { isBrowser, isNode } from 'browser-or-node';
import { fetchEventSource, EventSourceMessage, EventStreamContentType } from '@microsoft/fetch-event-source';
import { Action, Scry, Thread, AuthenticationInterface, SubscriptionInterface, CustomEventHandler, PokeInterface, SubscriptionRequestInterface, headers, SSEOptions, PokeHandlers, Message } from './types';
import { Action, Scry, Thread, AuthenticationInterface, SubscriptionInterface, CustomEventHandler, PokeInterface, SubscriptionRequestInterface, headers, SSEOptions, PokeHandlers, Message, FatalError } from './types';
import { uncamelize, hexString } from './utils';
/**
@ -198,8 +198,8 @@ export class Urbit {
resolve();
return; // everything's good
} else {
this.onError && this.onError(new Error('bad response'));
reject();
const err = new Error('failed to open eventsource');
reject(err);
}
},
onmessage: (event: EventSourceMessage) => {
@ -252,9 +252,8 @@ export class Urbit {
}
},
onerror: (error) => {
// Channel resume currently broken in eyre
if(false && this.errorCount++ < 5) {
console.log(this.errorCount);
console.warn(error);
if(!(error instanceof FatalError) && this.errorCount++ < 4) {
this.onRetry && this.onRetry();
return Math.pow(2, this.errorCount - 1) * 750;
}
@ -262,8 +261,8 @@ export class Urbit {
throw error;
},
onclose: () => {
throw Error('Ship unexpectedly closed the connection');
console.log('e');
throw new Error('Ship unexpectedly closed the connection');
},
});
})

View File

@ -192,3 +192,7 @@ export interface Message extends Record<string, any> {
action: Action;
id?: number;
}
export class ResumableError extends Error {}
export class FatalError extends Error {}

View File

@ -20,6 +20,7 @@ function fakeSSE(messages = [], timeout = 0) {
if (timeout > 0) {
setTimeout(() => {
controller.close();
clearInterval(interval);
interval;
}, timeout);
}
@ -82,21 +83,24 @@ describe('Initialisation', () => {
}, 500);
it('should handle failures', async () => {
fetchSpy = jest.spyOn(window, 'fetch');
airlock.onRetry = jest.fn();
airlock.onOpen = jest.fn();
fetchSpy
.mockImplementationOnce(() =>
Promise.resolve({ ok: true, body: fakeSSE() })
)
.mockImplementationOnce(() =>
Promise.resolve({ ok: false, body: fakeSSE() })
Promise.resolve({ ok: true, body: fakeSSE([], 100) })
)
airlock.onError = jest.fn();
try {
await airlock.eventSource();
airlock.eventSource();
await wait(200);
} catch (e) {
expect(airlock.onError).toHaveBeenCalled();
expect(airlock.onRetry).toHaveBeenCalled();
}
}, 200);
}, 300);
});
describe('subscription', () => {
@ -153,7 +157,14 @@ describe('subscription', () => {
fetchSpy = jest.spyOn(window, 'fetch');
airlock = new Urbit('', '+code');
airlock.onOpen = jest.fn();
fetchSpy.mockImplementation(fakeFetch(() => fakeSSE([ack(1, true)])));
fetchSpy
.mockImplementationOnce(() =>
Promise.resolve({ ok: true, body: fakeSSE() })
)
.mockImplementationOnce(() =>
Promise.resolve({ ok: false, body: fakeSSE([ack(1, true)]) })
)
const params = {
app: 'app',
mark: 'mark',
@ -165,7 +176,7 @@ describe('subscription', () => {
await airlock.poke(params);
await wait(300);
} catch (e) {
expect(params.onError).toHaveBeenCalled();
expect(true).toBe(true);
}
});
});

View File

@ -3,3 +3,4 @@
tests export-ignore
hashtable_tests export-ignore
shell.nix export-ignore
*.patch -text

View File

@ -1,3 +1,5 @@
# Configuration Result
/config.mk
/include/config.h
/include/ca-bundle.h
/include/ivory.h

View File

@ -1,4 +1,5 @@
include config.mk
include $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.mk))
jets = jets/tree.c $(wildcard jets/*/*.c)
noun = $(wildcard noun/*.c)
@ -9,7 +10,9 @@ worker = $(wildcard worker/*.c)
tests = $(wildcard tests/*.c)
bench = $(wildcard bench/*.c)
common = $(jets) $(noun) $(ur) $(vere)
compat := $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.c))
common = $(jets) $(noun) $(ur) $(vere) $(compat)
headers = $(shell find include -type f)
common_objs = $(shell echo $(common) | sed 's/\.c/.o/g')
@ -29,7 +32,7 @@ CFLAGS := $(CFLAGS)
################################################################################
.PHONY: all test clean mkproper
.PHONY: all test clean mrproper
################################################################################
@ -74,9 +77,11 @@ build/urbit-worker: $(common_objs) $(worker_objs)
@mkdir -p ./build
@$(CC) $^ $(LDFLAGS) -o $@
%.o: %.c $(headers)
# CCDEPS and CCEXTRA are empty except in MingW build,
# which uses them to inject a C source transform step
%.o: %.c $(headers) $(CCDEPS)
@echo CC $<
@$(CC) -I./include $(CFLAGS) -c $< -o $@
@$(CC) -I./include $(CFLAGS) $< $(CCEXTRA) -c -o $@
tags: $(all_srcs) $(headers)
ctags $^

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# support running off a tarball that doesn't contain binary pills
(( $($1 ../../bin/ivory.pill) > 512 )) || curl -L https://github.com/urbit/urbit/raw/urbit-v$URBIT_VERSION/bin/ivory.pill > ../../bin/ivory.pill
poor_mans_xxd () {
cch=0
echo "unsigned char $2[] = {"
while IFS='' read line
do
for i in $line
do
echo -n " 0x$i,"
cch=$((cch+1))
done
echo
done < <(od -An -v -tx1 $1)
echo "};"
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

View File

@ -0,0 +1,14 @@
# paths to brew packages
CFLAGS := $(CFLAGS) -I/opt/homebrew/include
LDFLAGS := $(LDFLAGS) -L/opt/homebrew/lib
# force linker to use static libraries
LDFLAGS := $(shell compat/m1brew/use-static-libs.sh $(LDFLAGS))
# add extra osx libraries
LDFLAGS := $(LDFLAGS) -framework SystemConfiguration
ifdef debug
CFLAGS := $(CFLAGS) -O0 -g
else
# clang hangs on noun/allocate.c if -g is specified with -O3
CFLAGS := $(CFLAGS) -O3
endif

View File

@ -0,0 +1,12 @@
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -15,7 +15,7 @@ do
log "Trying IMPL=$IMPL"
if IMPL=$impl make >/dev/null 2>/dev/null
- then sed -i 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile
+ then sed -i "" 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile
log "IMPL=$IMPL works"
exit 0
else log "IMPL=$IMPL failed"

View File

@ -0,0 +1,13 @@
diff --git a/makefile b/makefile
--- a/makefile
+++ b/makefile
@@ -12,5 +12,9 @@ shared: murmur3.c murmur3.h
$(CC) -fPIC -O3 -c murmur3.c
$(CC) -shared -Wl,--export-dynamic murmur3.o -o libmurmur3.so
+static: murmur3.c murmur3.h
+ $(CC) -fPIC -O3 -c murmur3.c
+ $(AR) rcs libmurmur3.a murmur3.o
+
clean:
rm -rf example *.o *.so

View File

@ -0,0 +1,85 @@
diff --git a/build/template-FAST_INT64/Makefile b/build/template-FAST_INT64/Makefile
--- a/build/template-FAST_INT64/Makefile
+++ b/build/template-FAST_INT64/Makefile
@@ -34,28 +34,27 @@
#
#=============================================================================
-# Edit lines marked with `==>'. See "SoftFloat-source.html".
+SOURCE_DIR ?= ../../source
+SPECIALIZE_TYPE ?= 8086-SSE
-==> SOURCE_DIR ?= ../../source
-==> SPECIALIZE_TYPE ?= 8086
+SOFTFLOAT_OPTS ?= \
+ -DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
+ -DSOFTFLOAT_FAST_DIV64TO32
-==> SOFTFLOAT_OPTS ?= \
-==> -DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
-==> -DSOFTFLOAT_FAST_DIV64TO32
+DELETE = rm -f
+C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
+COMPILE_C = \
+ cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
+MAKELIB = ar crs $@
+LIBNAME = libsoftfloat3
-==> DELETE = rm -f
-==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
-==> COMPILE_C = \
-==> cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
-==> MAKELIB = ar crs $@
+OBJ = .o
+LIB = .a
-==> OBJ = .o
-==> LIB = .a
-
-==> OTHER_HEADERS =
+OTHER_HEADERS =
.PHONY: all
-all: softfloat$(LIB)
+all: $(LIBNAME)$(LIB)
OBJS_PRIMITIVES = \
s_eq128$(OBJ) \
@@ -381,11 +380,11 @@ $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
-softfloat$(LIB): $(OBJS_ALL)
+$(LIBNAME)$(LIB): $(OBJS_ALL)
$(DELETE) $@
$(MAKELIB) $^
.PHONY: clean
clean:
- $(DELETE) $(OBJS_ALL) softfloat$(LIB)
+ $(DELETE) $(OBJS_ALL) $(LIBNAME)$(LIB)
diff --git a/build/template-FAST_INT64/platform.h b/build/template-FAST_INT64/platform.h
--- a/build/template-FAST_INT64/platform.h
+++ b/build/template-FAST_INT64/platform.h
@@ -34,17 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
-// Edit lines marked with `==>'. See "SoftFloat-source.html".
-
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define LITTLEENDIAN 1
+#define LITTLEENDIAN 1
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define INLINE inline
+#define INLINE inline
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define THREAD_LOCAL _Thread_local
+#define THREAD_LOCAL _Thread_local

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -euo pipefail
declare -a ldirs
for i in $@
do
case $i in
-L*) ldirs+=(${i:2});;
esac
done
for i in $@
do
case $i in
-l*)
lib=$(find ${ldirs[@]} -name lib${i:2}.a)
if [ "$lib" != "" ]
then
echo $lib
else
echo $i
fi;;
*) echo $i;;
esac
done

View File

@ -0,0 +1,355 @@
#include "c/portable.h"
#include <fcntl.h>
#include <sys/utime.h>
#include <windows.h>
// set default CRT file mode to binary
// note that mingw binmode.o does nothing
#undef _fmode
int _fmode = _O_BINARY;
// set standard I/O fds to binary too, because
// MSVCRT creates them before MingW sets _fmode
static void __attribute__ ((constructor)) _set_stdio_to_binary()
{
_setmode(0, _O_BINARY);
_setmode(1, _O_BINARY);
_setmode(2, _O_BINARY);
}
// from https://github.com/git/git/blob/master/compat/mingw.c
// -----------------------------------------------------------------------
int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
case ERROR_ACCESS_DENIED: error = EACCES; break;
case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
case ERROR_ALREADY_EXISTS: error = EEXIST; break;
case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
case ERROR_BAD_COMMAND: error = EIO; break;
case ERROR_BAD_DEVICE: error = ENODEV; break;
case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_LENGTH: error = EINVAL; break;
case ERROR_BAD_PATHNAME: error = ENOENT; break;
case ERROR_BAD_PIPE: error = EPIPE; break;
case ERROR_BAD_UNIT: error = ENODEV; break;
case ERROR_BAD_USERNAME: error = EINVAL; break;
case ERROR_BROKEN_PIPE: error = EPIPE; break;
case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
case ERROR_BUSY: error = EBUSY; break;
case ERROR_BUSY_DRIVE: error = EBUSY; break;
case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
case ERROR_CANNOT_MAKE: error = EACCES; break;
case ERROR_CANTOPEN: error = EIO; break;
case ERROR_CANTREAD: error = EIO; break;
case ERROR_CANTWRITE: error = EIO; break;
case ERROR_CRC: error = EIO; break;
case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
case ERROR_DEVICE_IN_USE: error = EBUSY; break;
case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
case ERROR_DIRECTORY: error = EINVAL; break;
case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
case ERROR_DISK_CHANGE: error = EIO; break;
case ERROR_DISK_FULL: error = ENOSPC; break;
case ERROR_DRIVE_LOCKED: error = EBUSY; break;
case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
case ERROR_FILE_EXISTS: error = EEXIST; break;
case ERROR_FILE_INVALID: error = ENODEV; break;
case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
case ERROR_GEN_FAILURE: error = EIO; break;
case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
case ERROR_INVALID_ACCESS: error = EACCES; break;
case ERROR_INVALID_ADDRESS: error = EFAULT; break;
case ERROR_INVALID_BLOCK: error = EFAULT; break;
case ERROR_INVALID_DATA: error = EINVAL; break;
case ERROR_INVALID_DRIVE: error = ENODEV; break;
case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
case ERROR_INVALID_FLAGS: error = EINVAL; break;
case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
case ERROR_INVALID_HANDLE: error = EBADF; break;
case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
case ERROR_INVALID_NAME: error = EINVAL; break;
case ERROR_INVALID_OWNER: error = EINVAL; break;
case ERROR_INVALID_PARAMETER: error = EINVAL; break;
case ERROR_INVALID_PASSWORD: error = EPERM; break;
case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
case ERROR_INVALID_WORKSTATION: error = EACCES; break;
case ERROR_IO_DEVICE: error = EIO; break;
case ERROR_IO_INCOMPLETE: error = EINTR; break;
case ERROR_LOCKED: error = EBUSY; break;
case ERROR_LOCK_VIOLATION: error = EACCES; break;
case ERROR_LOGON_FAILURE: error = EACCES; break;
case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
case ERROR_MORE_DATA: error = EPIPE; break;
case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
case ERROR_NOACCESS: error = EFAULT; break;
case ERROR_NONE_MAPPED: error = EINVAL; break;
case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
case ERROR_NOT_READY: error = EAGAIN; break;
case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
case ERROR_NO_DATA: error = EPIPE; break;
case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
case ERROR_OPEN_FAILED: error = EIO; break;
case ERROR_OPEN_FILES: error = EBUSY; break;
case ERROR_OPERATION_ABORTED: error = EINTR; break;
case ERROR_OUTOFMEMORY: error = ENOMEM; break;
case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
case ERROR_PATH_BUSY: error = EBUSY; break;
case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
case ERROR_PIPE_BUSY: error = EBUSY; break;
case ERROR_PIPE_CONNECTED: error = EPIPE; break;
case ERROR_PIPE_LISTENING: error = EPIPE; break;
case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
case ERROR_READ_FAULT: error = EIO; break;
case ERROR_SEEK: error = EIO; break;
case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
case ERROR_SHARING_VIOLATION: error = EACCES; break;
case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
case ERROR_SUCCESS: error = 0; break;
case ERROR_SWAPERROR: error = ENOENT; break;
case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
case ERROR_WRITE_FAULT: error = EIO; break;
case ERROR_WRITE_PROTECT: error = EROFS; break;
}
return error;
}
// from msys2 mingw-packages-dev patches
// -----------------------------------------------------------------------
static DWORD __map_mmap_prot_page(const int prot)
{
DWORD protect = 0;
if (prot == PROT_NONE)
return protect;
if ((prot & PROT_EXEC) != 0)
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
}
else
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_READWRITE : PAGE_READONLY;
}
return protect;
}
static DWORD __map_mmap_prot_file(const int prot)
{
DWORD desiredAccess = 0;
if (prot == PROT_NONE)
return desiredAccess;
if ((prot & PROT_READ) != 0)
desiredAccess |= FILE_MAP_READ;
if ((prot & PROT_WRITE) != 0)
desiredAccess |= FILE_MAP_WRITE;
if ((prot & PROT_EXEC) != 0)
desiredAccess |= FILE_MAP_EXECUTE;
return desiredAccess;
}
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
HANDLE fm, h;
void * map = MAP_FAILED;
const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
const DWORD protect = __map_mmap_prot_page(prot);
const DWORD desiredAccess = __map_mmap_prot_file(prot);
errno = 0;
if (len == 0
/* Usupported protection combinations */
|| prot == PROT_EXEC)
{
errno = EINVAL;
return MAP_FAILED;
}
if ((flags & MAP_ANON) == 0)
{
h = (HANDLE)_get_osfhandle(fildes);
if (h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return MAP_FAILED;
}
}
else h = INVALID_HANDLE_VALUE;
fm = CreateFileMapping(h, NULL, protect, 0, len, NULL);
if (fm == NULL)
{
errno = err_win_to_posix(GetLastError());
return MAP_FAILED;
}
map = MapViewOfFileEx(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len, addr);
errno = err_win_to_posix(GetLastError());
CloseHandle(fm);
if (map == NULL)
return MAP_FAILED;
if ((flags & MAP_FIXED) != 0 && map != addr)
{
UnmapViewOfFile(map);
errno = EEXIST;
return MAP_FAILED;
}
return map;
}
int munmap(void *addr, size_t len)
{
if (UnmapViewOfFile(addr))
return 0;
errno = err_win_to_posix(GetLastError());
return -1;
}
int msync(void *addr, size_t len, int flags)
{
if (FlushViewOfFile(addr, len))
return 0;
errno = err_win_to_posix(GetLastError());
return -1;
}
// -----------------------------------------------------------------------
// vere uses kill() only to kill lockfile owner with SIGTERM or SIGKILL
// Windows does not have signals, so I handle SIGKILL as TerminateProcess()
// and return an error in all other cases
int kill(pid_t pid, int sig)
{
if (pid > 0 && sig == SIGKILL) {
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (TerminateProcess(h, -1)) {
CloseHandle(h);
return 0;
}
errno = err_win_to_posix(GetLastError());
CloseHandle(h);
return -1;
}
errno = EINVAL;
return -1;
}
// libgcc built for mingw has included an implementation of mprotect
// via VirtualProtect since olden days, but it takes int rather than size_t
// and therefore fails or does unexpected things for >2GB blocks on 64-bit
// https://github.com/gcc-mirror/gcc/blob/master/libgcc/libgcc2.c
int mprotect (void *addr, size_t len, int prot)
{
DWORD np, op;
if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC))
np = PAGE_EXECUTE_READWRITE;
else if (prot == (PROT_READ | PROT_EXEC))
np = PAGE_EXECUTE_READ;
else if (prot == (PROT_EXEC))
np = PAGE_EXECUTE;
else if (prot == (PROT_READ | PROT_WRITE))
np = PAGE_READWRITE;
else if (prot == (PROT_READ))
np = PAGE_READONLY;
else if (prot == 0)
np = PAGE_NOACCESS;
else
{
errno = EINVAL;
return -1;
}
if (VirtualProtect (addr, len, np, &op))
return 0;
// NB: return code of ntdll!RtlGetLastNtStatus() is useful
// for diagnosing obscure VirtualProtect failures
errno = err_win_to_posix(GetLastError());
return -1;
}
int utimes(const char *path, const struct timeval times[2])
{
struct _utimbuf utb = {.actime = times[0].tv_sec, .modtime = times[1].tv_sec};
return _utime(path, &utb);
}
int fdatasync(int fildes)
{
HANDLE h = (HANDLE)_get_osfhandle(fildes);
if (h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return -1;
}
if (FlushFileBuffers(h))
{
errno = 0;
return 0;
}
else
{
errno = err_win_to_posix(GetLastError());
return -1;
}
}
intmax_t mdb_get_filesize(HANDLE han_u)
{
LARGE_INTEGER li;
GetFileSizeEx(han_u, &li);
return li.QuadPart;
}
char *realpath(const char *path, char *resolved_path)
{
// TODO
return strdup(path);
}

View File

@ -0,0 +1,18 @@
#ifndef _MINGW_IO_H
#define _MINGW_IO_H
#define mkdir(A, B) mkdir(A)
char *realpath(const char *path, char *resolved_path);
int fdatasync(int fd);
int utimes(const char *path, const struct timeval times[2]);
int kill(pid_t pid, int signum);
#define SIGUSR1 10
#define SIGALRM 14
#define SIGVTALRM 26
#define SIGSTK 31
#define SIG_COUNT 32
#endif//_MINGW_IO_H

View File

@ -0,0 +1,17 @@
# increase default thread stack size and link Windows implibs
LDFLAGS := $(LDFLAGS) -static -Wl,--stack,67108864 -lbcrypt -lntdll -lws2_32
# libcurl
CFLAGS := $(CFLAGS) -DCURL_STATICLIB
LDFLAGS := $(LDFLAGS) -lzstd -lcrypt32
# libh2o
CFLAGS := $(CFLAGS) -DH2O_NO_UNIX_SOCKETS
# libuv
LDFLAGS := $(LDFLAGS) -luserenv -liphlpapi -lpsapi
# secp256k1, due to _FORTIFY_SOURCE
LDFLAGS := $(LDFLAGS) -lssp
ifdef debug
CFLAGS := $(CFLAGS) -O0 -g
else
CFLAGS := $(CFLAGS) -O3 -g
endif

View File

@ -0,0 +1,7 @@
#include <signal.h>
// initialize msvcrt signals early, otherwise Ctrl-C does nothing
static void __attribute__ ((constructor)) _init_crt_signals()
{
signal(SIGINT, SIG_DFL);
}

View File

@ -0,0 +1,116 @@
#include "all.h"
#include "vere/vere.h"
/* _dup_std_handle(): creates an inheritable duplicate of a standard handle.
*/
static BOOL
_dup_std_handle(HANDLE* new_u, DWORD typ_u)
{
DWORD dum_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));
}
if ( !DuplicateHandle(GetCurrentProcess(), han_u, GetCurrentProcess(), new_u, 0, TRUE, DUPLICATE_SAME_ACCESS) ) {
fprintf(stderr, "vere: DuplicateHandle(%d): %d\r\n", typ_u, GetLastError());
exit(1);
}
return con_u;
}
/* _on_boot_completed_cb: invoked when the ship has finished booting.
*/
static void _on_boot_completed_cb() {
HANDLE hin_u = GetStdHandle(STD_INPUT_HANDLE);
SetEvent(hin_u);
CloseHandle(hin_u);
}
/* u3_daemon_init(): platform-specific daemon mode initialization.
*/
void
u3_daemon_init()
{
// detect if this process is the child daemon process
//
if ( ResetEvent(GetStdHandle(STD_INPUT_HANDLE)) ) {
u3_Host.bot_f = _on_boot_completed_cb;
return;
}
STARTUPINFOW psi_u;
ZeroMemory(&psi_u, sizeof(psi_u));
psi_u.cb = sizeof(psi_u);
psi_u.dwFlags = STARTF_USESTDHANDLES;
// duplicate standard output and error handles for the child process,
// replacing any raw console handles with handles to /dev/null
// print a warning if raw console output detected
//
// On Windows, console handles become invalid once the console is
// detached. This will cause urbit terminal output to fail. libuv
// provides no way of changing the handle of an open uv_pipe_handle,
// and Windows has no equivalent of dup2() for handles, so I cannot
// substitute a /dev/null handle once the terminal is initialized.
// It is possible to create an anonymous pipe and have the child
// process take over its drain end after it signals that the ship
// has booted, but -d is intended for background operation anyway
// and does not seem to warrant the added complexity.
//
if ( _dup_std_handle(&psi_u.hStdOutput, STD_OUTPUT_HANDLE) |
_dup_std_handle(&psi_u.hStdError, STD_ERROR_HANDLE) )
{
fprintf(stderr, "vere: -d used from a Windows console without redirection\r\n"
" no output from the daemon process will be visible\r\n");
fflush(stderr);
}
// create an event for the child process to signal
// the parent that the ship has finished booting
// pass the handle as "stdin" (otherwise unused with -d)
//
SECURITY_ATTRIBUTES sa_u = {sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
if ( !(psi_u.hStdInput = CreateEvent(&sa_u, TRUE, FALSE, NULL)) ) {
fprintf(stderr, "vere: CreateEvent: %d\r\n", GetLastError());
exit(1);
}
// create the child process with the same command line as parent
// it will start, re-parse the command line, and call u3_daemon_init
//
PROCESS_INFORMATION ppi_u;
if ( !CreateProcessW(NULL, _wcsdup(GetCommandLineW()), NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &psi_u, &ppi_u) ) {
fprintf(stderr, "vere: CreateProcess: %d\r\n", GetLastError());
exit(1);
}
CloseHandle(ppi_u.hThread);
// wait for the child process to exit or to signal the event
//
DWORD exi_u;
HANDLE han_u[2] = {ppi_u.hProcess, psi_u.hStdInput};
switch ( WaitForMultipleObjects(2, han_u, FALSE, INFINITE) ) {
case WAIT_OBJECT_0:
// the child process exited prematurely, propagate its exit code
//
if ( GetExitCodeProcess(ppi_u.hProcess, &exi_u) ) {
exit(exi_u);
}
fprintf(stderr, "vere: GetExitCodeProcess: %d\r\n", GetLastError());
exit(1);
case WAIT_OBJECT_0 + 1:
// the child process has finished booting, exit normally
//
exit(0);
default:
fprintf(stderr, "vere: WaitForMultipleObjects: %d\r\n", GetLastError());
exit(1);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
diff --git a/mdb.c b/mdb.c
--- a/mdb.c
+++ b/mdb.c
@@ -1707,28 +1707,27 @@ static char *const mdb_errstr[] = {
"MDB_PROBLEM: Unexpected problem - txn should abort",
};
-char *
-mdb_strerror(int err)
+void
+mdb_logerror(FILE* f, int err, const char* fmt, ...)
{
-#ifdef _WIN32
- /** HACK: pad 4KB on stack over the buf. Return system msgs in buf.
- * This works as long as no function between the call to mdb_strerror
- * and the actual use of the message uses more than 4K of stack.
- */
-#define MSGSIZE 1024
-#define PADSIZE 4096
- char buf[MSGSIZE+PADSIZE], *ptr = buf;
-#endif
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(f, fmt, ap);
+ va_end(ap);
+
int i;
if (!err)
- return ("Successful return: 0");
+ {
+ fprintf(stderr, ": %s\r\n", "Successful return: 0");
+ return;
+ }
if (err >= MDB_KEYEXIST && err <= MDB_LAST_ERRCODE) {
i = err - MDB_KEYEXIST;
- return mdb_errstr[i];
+ fprintf(stderr, ": %s\r\n", mdb_errstr[i]);
+ return;
}
-#ifdef _WIN32
/* These are the C-runtime error codes we use. The comment indicates
* their numeric value, and the Win32 error they would correspond to
* if the error actually came from a Win32 API. A major mess, we should
@@ -1742,18 +1741,20 @@ mdb_strerror(int err)
case EBUSY: /* 16, CURRENT_DIRECTORY */
case EINVAL: /* 22, BAD_COMMAND */
case ENOSPC: /* 28, OUT_OF_PAPER */
- return strerror(err);
+ fprintf(stderr, ": %s\r\n", strerror(err));
default:
;
}
- buf[0] = 0;
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ LPSTR ptr;
+ if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE);
- return ptr;
-#else
- return strerror(err);
-#endif
+ NULL, err, 0, (LPSTR)&ptr, sizeof (LPSTR), NULL))
+ {
+ fprintf(stderr, ": %s\r\n", ptr);
+ LocalFree(ptr);
+ } else
+ fprintf(stderr, ": <%d>\r\n", err);
}
/** assert(3) variant in cursor context */

View File

@ -0,0 +1,26 @@
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
int msync(void *addr, size_t length, int flags);
int mprotect(void *addr, size_t len, int prot);
#define PROT_NONE 0x00 /* No access. */
#define PROT_READ 0x01 /* Pages can be read. */
#define PROT_WRITE 0x02 /* Pages can be written. */
#define PROT_EXEC 0x04 /* Pages can be executed. */
#define MAP_FILE 0x0001 /* Mapped from a file or device. */
#define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */
#define MAP_TYPE 0x000f /* Mask for type field. */
#define MAP_SHARED 0x0010 /* Share changes. */
#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */
#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */
#define MAP_FAILED ((void *) -1)
#define MS_ASYNC 1 /* Sync memory asynchronously. */
#define MS_SYNC 0 /* Synchronous memory sync. */
#define MS_INVALIDATE 2 /* Invalidate the caches. */
#endif//_SYS_MMAN_H

View File

@ -0,0 +1,13 @@
diff --git a/makefile b/makefile
--- a/makefile
+++ b/makefile
@@ -12,5 +12,9 @@ shared: murmur3.c murmur3.h
$(CC) -fPIC -O3 -c murmur3.c
$(CC) -shared -Wl,--export-dynamic murmur3.o -o libmurmur3.so
+static: murmur3.c murmur3.h
+ $(CC) -fPIC -O3 -c murmur3.c
+ $(AR) rcs libmurmur3.a murmur3.o
+
clean:
rm -rf example *.o *.so

View File

@ -0,0 +1,152 @@
/* compat/mingw/ptty.c
**
*/
#include "all.h"
#include "vere/vere.h"
#include <winternl.h>
/* _ptty_get_type(): detects tty type.
*/
static DWORD
_ptty_get_type(int fd)
{
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE)
return FILE_TYPE_UNKNOWN;
DWORD t = GetFileType(h);
if (t != FILE_TYPE_PIPE)
return t ;
// https://github.com/fusesource/jansi-native/commit/461068c67a38647d2890e96250636fc0117074f5
ULONG result;
BYTE buffer[1024];
POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;
PWSTR name;
/* get pipe name */
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation, buffer, sizeof(buffer) - sizeof(WCHAR), &result)))
return FILE_TYPE_UNKNOWN;
name = nameinfo->Name.Buffer;
name[nameinfo->Name.Length] = 0;
// check for popular terminal emulators
// that use named pipes to communicate with subprocesses
if (wcsstr(name, L"\\ConEmu") ||
(wcsstr(name, L"msys-") || wcsstr(name, L"cygwin-")) && wcsstr(name, L"-pty"))
return FILE_TYPE_PIPE;
return FILE_TYPE_UNKNOWN;
}
/* _ttyf_nop(): stub function.
*/
static c3_o
_ttyf_nop(u3_utty* uty_u)
{
return c3y;
}
/* _ttyf_start_raw_input(): ends raw input on the tty.
*/
static c3_o
_ttyf_set_normal(u3_utty* uty_u)
{
c3_i e;
if ( 0 != (e = uv_tty_set_mode(&uty_u->pin_u.tty_u, UV_TTY_MODE_NORMAL)) ) {
fprintf(stderr, "uv_tty_set_mode(UV_TTY_MODE_NORMAL) -> %d\r\n", e);
return c3n;
}
return c3y;
}
/* _ttyf_start_raw_input(): sets the tty to raw input.
*/
static c3_o
_ttyf_set_raw(u3_utty* uty_u)
{
c3_i e;
if ( 0 != (e = uv_tty_set_mode(&uty_u->pin_u.tty_u, UV_TTY_MODE_RAW)) ) {
fprintf(stderr, "uv_tty_set_mode(UV_TTY_MODE_RAW) -> %d\r\n", e);
return c3n;
}
return c3y;
}
/* _ttyf_get_winsize(): gets the tty window size.
*/
static c3_o
_ttyf_get_winsize(u3_utty* uty_u, c3_l* col_l, c3_l* row_l)
{
c3_i col_i, row_i;
if ( 0 != uv_tty_get_winsize(&uty_u->pop_u.tty_u, &col_i, &row_i) ) {
return c3n;
}
*col_l = col_i;
*row_l = row_i;
return c3y;
}
/* _ttyf_get_winsize(): gets the tty window size.
*/
static c3_o
_ttyf_nop_winsize(u3_utty* uty_u, c3_l* col_l, c3_l* row_l)
{
return c3n;
}
/* u3_ptty_init(): initialize platform-specific tty.
*/
u3_utty*
u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c)
{
DWORD pip_l = _ptty_get_type(0);
DWORD pop_l = _ptty_get_type(1);
if ( pip_l == FILE_TYPE_UNKNOWN || pop_l == FILE_TYPE_UNKNOWN) {
*err_c = "not a tty";
return NULL;
}
if ( pip_l != pop_l ) {
*err_c = "partly redirected";
return NULL;
}
c3_i e;
u3_utty* uty_u = c3_calloc(sizeof(u3_utty));
if ( pip_l == FILE_TYPE_CHAR ) {
if ( 0 == (e = uv_tty_init(lup_u, &uty_u->pin_u.tty_u, 0, 0)) &&
0 == (e = uv_tty_init(lup_u, &uty_u->pop_u.tty_u, 1, 0)) )
{
SetConsoleOutputCP(CP_UTF8);
uty_u->sta_f = _ttyf_set_raw;
uty_u->sto_f = _ttyf_set_normal;
uty_u->wsz_f = _ttyf_get_winsize;
}
} else {
if ( 0 == (e = uv_pipe_init(lup_u, &uty_u->pin_u.pip_u, 0)) &&
0 == (e = uv_pipe_init(lup_u, &uty_u->pop_u.pip_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pin_u.pip_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pop_u.pip_u, 1)) )
{
fprintf(stderr, "vere: running interactive in a terminal emulator is experimental\r\n"
" use -t to disable interactivity or use native Windows console\r\n") ;
uty_u->sta_f = _ttyf_nop;
uty_u->sto_f = _ttyf_nop;
uty_u->wsz_f = _ttyf_nop_winsize;
}
}
if ( e ) {
*err_c = uv_strerror(e);
c3_free(uty_u);
return NULL;
}
uty_u->fid_i = 1;
uty_u->hij_f = _ttyf_nop;
uty_u->loj_f = _ttyf_nop;
return uty_u;
}

View File

@ -0,0 +1,167 @@
#include "all.h"
#include "rsignal.h"
#include <windows.h>
int err_win_to_posix(DWORD winerr);
// The current implementation of rsignal_ is single-threaded,
// but it can be extended to multi-threaded by replacing these
// static variables with a thread id-based hash map.
//
static __p_sig_fn_t _fns[SIG_COUNT];
static volatile DWORD _tid;
static HANDLE _hvt;
void rsignal_install_handler(int sig, __p_sig_fn_t fn)
{
if (sig < 0 || sig >= SIG_COUNT)
return;
DWORD newtid = GetCurrentThreadId();
DWORD oldtid = InterlockedExchange(&_tid, newtid);
if (oldtid != 0 && oldtid != newtid) {
fprintf(stderr, "\r\nrsignal_install_handler: %u -> %u\r\n", oldtid, newtid);
return;
}
__p_sig_fn_t oldfn = InterlockedExchangePointer((PVOID*)&_fns[sig], fn);
if (fn != 0 && oldfn != 0 && oldfn != fn) {
fprintf(stderr, "\r\nrsignal_install_handler: %p -> %p\r\n", oldfn, fn);
}
}
void rsignal_deinstall_handler(int sig)
{
rsignal_install_handler(sig, 0);
}
void rsignal_raise(int sig)
{
if (sig < 0 || sig >= SIG_COUNT)
return;
__p_sig_fn_t oldfn = InterlockedExchangePointer((PVOID*)&_fns[sig], 0);
if (oldfn == 0)
return;
if (_tid == GetCurrentThreadId()) {
oldfn(sig);
return;
}
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, _tid);
if (!hthread) {
fprintf(stderr, "\r\nrsignal_raise: OpenThread(%u): %d\r\n", _tid, GetLastError());
return;
}
if (SuspendThread(hthread) < 0) {
fprintf(stderr, "\r\nrsignal_raise: SuspendThread(%u): %d\r\n", _tid, GetLastError());
goto cleanup;
}
oldfn(sig);
if (!ResumeThread(hthread)) {
fprintf(stderr, "\r\nrsignal_raise: ResumeThread(%u): %d\r\n", _tid, GetLastError());
// abort because the main thread is stuck
abort();
}
cleanup:
CloseHandle(hthread);
}
static void _rsignal_vt_cb(PVOID param, BOOLEAN timedOut)
{
rsignal_raise(SIGVTALRM);
}
int rsignal_setitimer(int type, struct itimerval *in, struct itimerval *out)
{
if (in == 0) {
errno = EFAULT;
return -1;
}
if (type != ITIMER_VIRTUAL || out != 0) {
errno = ENOTSUP;
return -1;
}
if (_hvt != NULL) {
DeleteTimerQueueTimer(NULL, _hvt, NULL);
_hvt = NULL;
}
if (timerisset(&in->it_value) && !CreateTimerQueueTimer(&_hvt, NULL, _rsignal_vt_cb, NULL,
in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000,
in->it_interval.tv_sec * 1000 + in->it_interval.tv_usec / 1000, 0))
{
errno = err_win_to_posix(GetLastError());
return -1;
} else {
return 0;
}
}
// direct import from ntdll.dll
extern DWORD64 __imp_KiUserExceptionDispatcher;
static void _rsignal_longjmp(intptr_t* builtin_jb)
{
__builtin_longjmp(builtin_jb, 1);
}
void rsignal_post_longjmp(DWORD tid, intptr_t* builtin_jb)
{
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
if (!hthread) {
fprintf(stderr, "\r\nrsignal: OpenThread(%u): %d\r\n", tid, GetLastError());
return;
}
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext(hthread, &context)) {
fprintf(stderr, "\r\nrsignal: GetThreadContext(%u): %d\r\n", tid, GetLastError());
goto cleanup;
}
// see if the thread is currently handling a structured exception
// if so, let the handler (usually the libsigsegv handler) finish
// and set up the the signal to run at the exception resume point
// otherwise, passing a parameter to fn is completely unreliable
//
DWORD64 kibase;
PRUNTIME_FUNCTION ki = RtlLookupFunctionEntry(__imp_KiUserExceptionDispatcher, &kibase, NULL);
CONTEXT c = context;
while (1)
{
DWORD64 base, frame;
PRUNTIME_FUNCTION f = RtlLookupFunctionEntry(c.Rip, &base, NULL);
if (!f) break;
if (f == ki)
{
// KiUserExceptionDispatcher has a "bare" frame
// with $rsp pointing to the CONTEXT structure
//
((PCONTEXT)c.Rsp)->Rip = (DWORD64)_rsignal_longjmp;
((PCONTEXT)c.Rsp)->Rcx = (DWORD64)builtin_jb;
goto cleanup;
}
PVOID handler_data;
RtlVirtualUnwind(0, base, c.Rip, f, &c, &handler_data, &frame, NULL);
}
context.Rip = (DWORD64)_rsignal_longjmp;
context.Rcx = (DWORD64)builtin_jb;
if (!SetThreadContext(hthread, &context)) {
fprintf(stderr, "\r\nrsignal: SetThreadContext(%u): %d\r\n", tid, GetLastError());
goto cleanup;
}
cleanup:
CloseHandle(hthread);
}

View File

@ -0,0 +1,24 @@
#ifndef _RSIGNAL_H
#define _RSIGNAL_H
typedef struct {
jmp_buf jb;
unsigned long tid;
} rsignal_jmpbuf;
#define rsignal_setjmp(buf) (buf.tid = GetCurrentThreadId(), setjmp(buf.jb))
#define rsignal_longjmp(buf, val) if (buf.tid != GetCurrentThreadId()) {buf.jb.retval = (val); rsignal_post_longjmp(buf.tid, buf.jb.buffer);} else longjmp(buf.jb, val)
void rsignal_raise(int sig);
void rsignal_install_handler(int sig, __p_sig_fn_t fn);
void rsignal_deinstall_handler(int sig);
void rsignal_post_longjmp(unsigned long tid, intptr_t* builtin_jb);
#define ITIMER_VIRTUAL 1
struct itimerval {
struct timeval it_value, it_interval;
};
int rsignal_setitimer(int type, struct itimerval *in, struct itimerval *out);
#endif//_RSIGNAL_H

View File

@ -0,0 +1,25 @@
#include "all.h"
#include "rsignal.h"
#include "vere/vere.h"
/* _mingw_exception_filter: replaces libsigsegv on MingW
*/
EXCEPTION_DISPOSITION _mingw_exception_filter(
IN PEXCEPTION_RECORD ExceptionRecord,
IN ULONG64 EstablisherFrame,
IN OUT PCONTEXT ContextRecord,
IN OUT PDISPATCHER_CONTEXT DispatcherContext)
{
if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
ExceptionRecord->ExceptionInformation[0] == 1 &&
u3e_fault((void*)ExceptionRecord->ExceptionInformation[1], 1))
{
return ExceptionContinueExecution;
}
if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
rsignal_raise(SIGSTK);
}
return ExceptionContinueSearch;
}

View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <string.h>
enum { INIT, CPAR, DQ, DQS, SQ, SQS };
char line[1 << 16];
/* seh_handler_decorator: registers u3_exception_handler for all functions in given source file
*/
int main(int argc, const char* argv[])
{
if (argc != 2)
return 1;
int c, state = INIT, curly = 0, emit = 0;
while (fgets(line, sizeof(line), stdin))
{
if (line[0] == '#')
{
emit = !!strstr(line, argv[1]);
fputs(line, stdout);
}
else
for (int i = 0; line[i]; i++)
{
switch (state) {
case INIT:
case CPAR:
switch (line[i]) {
case ' ':
case '\t':
case '\n':
case '\r':
case '\f': break;
case '{': curly++; if (emit && curly == 1 && state == CPAR) goto emit_handler; goto reset;
case '}': curly--; goto reset;
case '"': state = DQ; break;
case '\'': state = SQ; break;
case ')': state = CPAR; break;
reset:
default: state = INIT; break;
} break;
case DQ:
switch (line[i]) {
case '\\': state = DQS; break;
case '"': state = INIT; break;
} break;
case DQS: state = DQ; break;
case SQ:
switch (line[i]) {
case '\\': state = SQS; break;
case '\'': state = INIT; break;
} break;
case SQS: state = SQ; break;
}
fputc(line[i], stdout);
continue;
emit_handler:
fputs("{__asm__(\".seh_handler _mingw_exception_filter,@except\\n\");", stdout);
state = INIT;
}
}
return 0;
}

View File

@ -0,0 +1,24 @@
# This include file injects a step that transforms vere C source to register
# a SEH exception handler for each function that is declared in a .c file.
# It inserts a .seh_handler directive into each function body with __asm__.
# This directive affects the x64 unwind tables (.pdata and .xdata sections)
# emitted by the compiler.
#
# See gas/config/obj-coff-seh.h in binutils source for .seh_handler, and
# https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
# for a description of how stack unwinding and SEH work in x64 Windows.
#
# When this file sets CCEXTRA, the first invocation of $(CC) in Makefile
# writes preprocessor output to stdout (-E -o -), which is piped to a simple
# parser that inserts __asm__ statements to each function in the .c file
# being compiled. The second invocation of $(CC) reads transformed source
# from stdin (-x cpp-output -). $< argument to $(sehdexe) tells the parser
# which .c file is being compiled.
sehdexe := build/seh_handler_decorator.exe
CCDEPS := $(CCDEPS) $(sehdexe)
CCEXTRA = -E -o -|$(sehdexe) $<|$(CC) $(CFLAGS) -x cpp-output -
$(sehdexe): compat/mingw/seh_handler_decorator.cc
@mkdir -p ./build
@$(CC) $< -o $@

View File

@ -0,0 +1,15 @@
#ifndef _MINGW_SETJMP_H
#define _MINGW_SETJMP_H
// msvcrt setjmp/longjmp are broken on 64-bit systems, use gcc builtins
typedef struct jmp_buf {
intptr_t buffer[5];
int retval;
} jmp_buf;
#define _setjmp setjmp
#define _longjmp longjmp
#define longjmp(buf, val) {buf.retval = (val); __builtin_longjmp(buf.buffer, 1);}
#define setjmp(buf) (__builtin_setjmp(buf.buffer) ? (buf.retval) : 0)
#endif//_MINGW_SETJMP_H

View File

@ -0,0 +1,36 @@
diff --git a/build/Win64-MinGW-w64/Makefile b/build/Win64-MinGW-w64/Makefile
--- a/build/Win64-MinGW-w64/Makefile
+++ b/build/Win64-MinGW-w64/Makefile
@@ -46,7 +46,8 @@ C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
COMPILE_C = \
x86_64-w64-mingw32-gcc -c -Werror-implicit-function-declaration \
-DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
-MAKELIB = x86_64-w64-mingw32-ar crs $@
+MAKELIB = x86_64-w64-mingw32-gcc-ar crs $@
+LIBNAME = libsoftfloat3
OBJ = .o
LIB = .a
@@ -54,7 +55,7 @@ LIB = .a
OTHER_HEADERS = $(SOURCE_DIR)/include/opts-GCC.h
.PHONY: all
-all: softfloat$(LIB)
+all: $(LIBNAME)$(LIB)
OBJS_PRIMITIVES = \
s_eq128$(OBJ) \
@@ -380,11 +381,11 @@ $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
-softfloat$(LIB): $(OBJS_ALL)
+$(LIBNAME)$(LIB): $(OBJS_ALL)
$(DELETE) $@
$(MAKELIB) $^
.PHONY: clean
clean:
- $(DELETE) $(OBJS_ALL) softfloat$(LIB)
+ $(DELETE) $(OBJS_ALL) $(LIBNAME)$(LIB)

View File

@ -0,0 +1,38 @@
diff --git a/src/win/pipe.c b/src/win/pipe.c
index 0f2bb869b..f81245ec6 100644
--- a/src/win/pipe.c
+++ b/src/win/pipe.c
@@ -270,6 +270,12 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
err = GetLastError();
+ if ((err == ERROR_INVALID_FUNCTION || err == ERROR_INVALID_PARAMETER) && (duplex_flags & UV_HANDLE_WRITABLE)) {
+ /*
+ * it's not a pipe, but simple writes should be fine
+ * let's trust callers to know what they're doing
+ */
+ } else
if (err == ERROR_ACCESS_DENIED) {
/*
* SetNamedPipeHandleState can fail if the handle doesn't have either
@@ -1054,7 +1054,6 @@ static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
assert(req != NULL);
assert(req->type == UV_WRITE);
assert(handle->type == UV_NAMED_PIPE);
- assert(req->write_buffer.base);
result = WriteFile(handle->handle,
req->write_buffer.base,
diff --git a/src/win/tty.c b/src/win/tty.c
index c359d5601..1b9d4f853 100644
--- a/src/win/tty.c
+++ b/src/win/tty.c
@@ -367,7 +367,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
break;
case UV_TTY_MODE_RAW:
- flags = ENABLE_WINDOW_INPUT;
+ flags = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT;
break;
case UV_TTY_MODE_IO:
return UV_ENOTSUP;

View File

@ -0,0 +1,152 @@
declare -a cdirs
declare -a ldirs
declare -a pdirs
declare -A hdeps
sources=(../../nix/sources.json ../../nix/sources-pmnsh.json)
patches=compat/$1
deriver=urbit-$1-build
markfil=.$1~
depdirs=
nixpath=${NIX_STORE-../build}
# LDFLAGS doesn't like absolute paths
if [ "${nixpath:0:1}" == "/" ]
then
mkdir -p $nixpath
nixpath=$(realpath --relative-to=. $nixpath)
fi
hex2nixbase32 () {
local digits='0123456789abcdfghijklmnpqrsvwxyz'
local bits=0
local left=0 # number of bits left in $bits
local i=0
while ((1))
do
while ((left>=5))
do
echo -n ${digits:$((bits&31)):1}
bits=$((bits>>5))
left=$((left-5))
done
if ((i == ${#1}))
then
break
fi
char=0x${1:i:2}
i=$((i+2))
bits=$((bits|(char<<(left))))
left=$((left+8))
done
echo -n ${digits:$bits:1}
}
buildnixdep () {
echo Building dependency $key...
local cache=https://app.cachix.org/api/v1/cache/${CACHIX_CACHE-}
local hash=
if [ -n "$url" ]
then
hash=${hdeps[$key]}
dir=$nixpath/$hash-$key
if [ -e $dir/$markfil ]
then
# dependency present, don't reupload
hash=
else
# dependency absent, check the binary cache if configured
if [ -n "${CACHIX_CACHE-}" ]
then
echo Checking binary cache for $hash-$key...
narinfo="$cache/${hash}.narinfo"
if curl -fLI "$narinfo"
then
url="$cache/$(curl -fL "$narinfo"|while IFS=: read k v; do if [ "$k" == "URL" ]; then echo $v; fi; done)"
echo Found $url
strip=0
hash=
fi
fi
mkdir -p $dir
pushd $dir
curl -fL "$url"|(tar --strip $strip -xzf - || true)
popd
fi
else
# local dependency
dir=../$key
fi
# patch and build the dependency if necessary
if [ ! -e $dir/$markfil ]
then
local patch=$patches/$key.patch
[ -e $patch ] && patch -d $dir -p 1 <$patch
pushd $dir
eval "$cmdprep"
eval make "$cmdmake"
touch $markfil
popd
fi
# if configured, upload freshly built dependency to binary cache
if [ -n "$hash" -a -n "${CACHIX_AUTH_TOKEN-}" ]
then
(
echo Uploading freshly built $hash-$key to binary cache...
tar -C $dir -czf $hash.tar .
local size=$(stat -c '%s' $hash.tar)
read filehash _ < <(sha256sum $hash.tar)
curl -fL -H "Content-Type: application/gzip" -H "Authorization: Bearer $CACHIX_AUTH_TOKEN" --data-binary @"$hash.tar" "$cache/nar"
curl -fL -H "Content-Type: application/json" -H "Authorization: Bearer $CACHIX_AUTH_TOKEN" --data-binary @- "$cache/${hash}.narinfo" <<EOF
{
"cStoreHash": "$hash",
"cStoreSuffix": "$key",
"cNarHash": "sha256:$(hex2nixbase32 $filehash)",
"cNarSize": $size,
"cFileHash": "$filehash",
"cFileSize": $size,
"cReferences": [],
"cDeriver": "$deriver"
}
EOF
echo Done. ) || true
rm $hash.tar || true
fi
}
# I have to go over the sources files several times
# because jq does not have a way to invoke external programs
jqprep='add|to_entries|.[]|.value.pmnsh as $p|select($p and $p.compat.'$1' != false)|(($p + $p.compat.'$1')|del(.compat)) as $o|'
# list external dependencies, create hash map and directory replacement regex
# use -j and \u0000 to work around https://github.com/stedolan/jq/issues/1870
while read -rd "" key json
do
# create 'store hash' from sources.json data and patch
patch=$patches/$key.patch
read hash _ < <((
echo -n $json
[ -e $patch ] && cat $patch)|sha256sum)
hash=$(hex2nixbase32 $hash)
hdeps[$key]=$hash
depdirs="$depdirs|gsub(\"\\\\.\\\\./$key\";\"\\(\$d)/$hash-$key\")"
done < <(jq --arg deriver "$deriver" -Sscrj "$jqprep"'select(.value.url)|.key," ",{($deriver):(.value|del(.pmnsh) + ({'$1':$o}))},"\u0000"' ${sources[@]})
# build dependencies, create include and library directory arrays
. <(jq --arg nixpath "$nixpath" -sr "$jqprep"'(if .value.url then ".." else $nixpath end) as $d|"
unset dir
key=\(.key|@sh) \\
url=\(.value.url//""|@sh) \\
strip=\($o.strip+1) \\
cmdprep=\($o.prepare//""'"$depdirs"'|@sh) \\
cmdmake=\($o.make//""'"$depdirs"'|@sh) \\
buildnixdep # sets dir
pdirs+=($dir) # XX support json override a la cdirs/pdirs
\($o.include//"."|if type == "array" then . else [.] end|map("cdirs+=(-I$dir/\(.))")|join("\n"))
\($o.lib//"."|if type == "array" then . else [.] end|map("ldirs+=(-L$dir/\(.))")|join("\n"))"' ${sources[@]})
CFLAGS="${CFLAGS-} ${cdirs[@]}"
LDFLAGS="${LDFLAGS-} ${ldirs[@]}"
PKG_CONFIG_PATH="$(IFS=:;echo "${pdirs[*]}"):${PKG_CONFIG_PATH-}"

Some files were not shown because too many files have changed in this diff Show More