* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS @ 2021-12-16 16:17 pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard ` (4 more replies) 0 siblings, 5 replies; 65+ messages in thread From: pukkamustard @ 2021-12-16 16:17 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris Hello Guix, This is an initial patch and proposal towards decentralizing substitute distribution with ERIS. ERIS (Encoding for Robust Immutable Storage) [1] is an encoding of content into uniformly sized, encryped and content-addressed blocks. The original content can be reconstructed only with access to a read capability, which can be encoded as an URN. One key advantage of ERIS is that the encoding is protocol agnostic. Any protocol that can transfer small (32KiB) sized blocks referenced by the hash of their content will do. This can be done with things such as GNUNet, IPFS, OpenDHT, HTTP or a USB stick on a bicycle. The following patch allows substitutes to be published over IPFS using ERIS. This is inspired and very similar to previous work on distributing substitutes over IPFS [2]. The narinfos served by `guix publish` look like this: --8<---------------cut here---------------start------------->8--- StorePath: /gnu/store/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 URL: nar/gzip/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 Compression: gzip FileSize: 67363 ERIS: urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE URL: nar/zstd/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 Compression: zstd FileSize: 64917 ERIS: urn:erisx2:BIBO7KS7SAWHDNC43DVILOSQ3F3SRRHEV6YPLDCSZ7MMD6LZVCHQMEQ6FUBTJAPSNFF7XR5XPTP4OQ72OPABNEO7UYBUN42O46ARKHBTGM NarHash: sha256:1sagsz1mnlqkr8r8s6gwkzvvhq619rlzhpbxl3h0b111n5hn2w9w NarSize: 220704 References: 2fk1gz2s7ppdicynscra9b19byrrr866-glibc-2.33 81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 90lbavffg0csrf208nw0ayj1bz5knl47-gcc-10.3.0-lib Deriver: 260bk0ch4np4h2yz5yqhf8hjbsyhwpmr-hello-2.10.drv Signature: 1;strawberry;KHNpZ25hdHVyZSAKIChkYXRhIAogIChmbGFncyByZmM2OTc5KQogIChoYXNoIHNoYTI1NiAjNDk4ODkwODZDNTY4MzQyRENFQzk3QzA3NDE4NEQ1RkRCOTNCNDA2MUNCRDM4MUExRjVBQzVDODI0MTgwMTU3OSMpCiAgKQogKHNpZy12YWwgCiAgKGVjZHNhIAogICAociAjMEU2NDlFODE4QzRFNjNGNEY2OUQ5QTAwRjUwNjRDMzQ3QjY3RDM0RTM0NTg2MkI4NTc3RTg5MUY5Q0Q3NDhBQiMpCiAgIChzICMwMTZGRjA1MDdCQjZGMzA2NUEzMjYzRDA2MTAyRDc5MTBEOEZGODc5RTdENjREODRFODBENDBGMTJFMTBBOTQ1IykKICAgKQogICkKIChwdWJsaWMta2V5IAogIChlY2MgCiAgIChjdXJ2ZSBFZDI1NTE5KQogICAocSAjMDRDMkY4ODk1QTU0NDNGNTlCODk2NDEwMEI1MDY0NzU4RjQ1N0YzMENEREE1MTQyQzE0MDc0NjExNTA1NTc5MCMpCiAgICkKICApCiApCg== --8<---------------cut here---------------end--------------->8--- For every compressed nar the ERIS URN is computed and added. If the `--ipfs` is used for `guix publish` then the encoded blocks are also uploaded to the IPFS daemon. The nar could then be retrieved from anywhere like this: --8<---------------cut here---------------start------------->8--- (use-modules (eris) (eris blocks ipfs)) (eris-decode->bytevector "urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE" eris-blocks-ipfs-ref) --8<---------------cut here---------------end--------------->8--- These patches do not yet retrieve content from IPFS (TODO). But in principle, anybody connected to IPFS can get the nar with the ERIS URN. This could be used to reduce load on substitute server as they would only need to publish the ERIS URN directly - substitutes could be delivered much more peer-to-peer. Other transports that I have been looking in to and am pretty sure will work include: HTTP (with RFC 2169 [3]), GNUNet, OpenDHT. This is, imho, the advantage of ERIS over IPFS directly or GNUNet directly. The encoding and identifiers (URN) are abstracted away from specific transports (and also applications). ERIS is almost exactly the same encoding as used in GNUNet (ECRS). Blocks can be stored in any kind of databases (see for example the GDBM bindings [4]). A tricky things is figuring out how to multiplex all these different transports and storages... The ERIS specification is still considered "experimental". However we feel confident to stabilize it and intend to do so around February/March 2022 with a release 1.0.0 of the specification. This will ensure that the identifiers remain stable for the forseeable future (until the crypto breaks). Before that there is also a small external security audit of the specification planned (thanks to NGI0/NLnet!). This is just a little demo of the idea and some food for thought and discussion. Give it a try and let me know what you think! I've also pushed the patches to my personal Guix mirror if you want to check it out from there: https://inqlab.net/git/guix.git/log/?h=wip-eris Also CCing ~pukkamustard/eris@lists.sr.ht where there is some general ERIS related discussion. Thanks, -pukkamustard [1] http://purl.org/eris [2] https://issues.guix.gnu.org/33899 [3] https://www.ietf.org/rfc/rfc2169.txt [4] https://inqlab.net/git/guile-eris.git/tree/eris/blocks/gdbm.scm pukkamustard (3): publish: Add ERIS URN to narinfo WIP: gnu: guile-eris: Update to unreleased git version. publish: Add IPFS support. configure.ac | 5 ++ gnu/packages/guile-xyz.scm | 10 ++-- gnu/packages/package-management.scm | 1 + guix/narinfo.scm | 10 ++-- guix/scripts/publish.scm | 79 ++++++++++++++++++++++------- 5 files changed, 79 insertions(+), 26 deletions(-) -- 2.34.0 ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard @ 2021-12-16 16:20 ` pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 2/3] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 3/3] publish: Add IPFS support pukkamustard 2021-12-20 16:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès ` (3 subsequent siblings) 4 siblings, 2 replies; 65+ messages in thread From: pukkamustard @ 2021-12-16 16:20 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/scripts/publish.scm: (bake-narinfo+nar): Compute ERIS URN of compressed nars. (narinfo-string): Add #:eris-urns parameter and honor it. (store-item->recutils): Add #:eris-urn parameter and honor it. * guix/scripts/narinfo.scm: (<narinfo>)[eris-urns]: New field. (narinfo-maker): Handle ERIS URN. * configure.ac: (HAVE_GUILE_ERIS): New conditional. * gnu/packages/package-management.scm: (guix)[native-inputs]: Add guile-eris. --- configure.ac | 5 +++++ gnu/packages/package-management.scm | 1 + guix/narinfo.scm | 10 ++++++---- guix/scripts/publish.scm | 31 +++++++++++++++++++++-------- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 341cff8fbd..72396be8aa 100644 --- a/configure.ac +++ b/configure.ac @@ -170,6 +170,11 @@ GUILE_MODULE_AVAILABLE([have_guile_avahi], [(avahi)]) AM_CONDITIONAL([HAVE_GUILE_AVAHI], [test "x$have_guile_avahi" = "xyes"]) +dnl Check for Guile-eris. +GUILE_MODULE_AVAILABLE([have_guile_eris], [(eris)]) +AM_CONDITIONAL([HAVE_GUILE_ERIS], + [test "x$have_guile_eris" = "xyes"]) + dnl Guile-newt is used by the graphical installer. GUILE_MODULE_AVAILABLE([have_guile_newt], [(newt)]) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index 9496499850..5c49167782 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -394,6 +394,7 @@ (define code ("guile-zstd" ,guile-zstd) ("guile-ssh" ,guile-ssh) ("guile-git" ,guile-git) + ("guile-eris" ,guile-eris) ;; XXX: Keep the development inputs here even though ;; they're unnecessary, just so that 'guix environment diff --git a/guix/narinfo.scm b/guix/narinfo.scm index 4fc550aa6c..0972ede3c1 100644 --- a/guix/narinfo.scm +++ b/guix/narinfo.scm @@ -67,13 +67,14 @@ (define-module (guix narinfo) equivalent-narinfo?)) (define-record-type <narinfo> - (%make-narinfo path uri-base uris compressions file-sizes file-hashes - nar-hash nar-size references deriver system + (%make-narinfo path uri-base uris eris-urns compressions file-sizes + file-hashes nar-hash nar-size references deriver system signature contents) narinfo? (path narinfo-path) (uri-base narinfo-uri-base) ;URI of the cache it originates from (uris narinfo-uris) ;list of strings + (eris-urns narinfo-eris-urns) ;list of (strings | #f) (compressions narinfo-compressions) ;list of strings (file-sizes narinfo-file-sizes) ;list of (integers | #f) (file-hashes narinfo-file-hashes) @@ -134,7 +135,7 @@ (define (narinfo-signature->canonical-sexp str) (define (narinfo-maker str cache-url) "Return a narinfo constructor for narinfos originating from CACHE-URL. STR must contain the original contents of a narinfo file." - (lambda (path urls compressions file-hashes file-sizes + (lambda (path urls eris-urns compressions file-hashes file-sizes nar-hash nar-size references deriver system signature) "Return a new <narinfo> object." @@ -148,6 +149,7 @@ (define len (length urls)) (string-append cache-url url) (string-append cache-url "/" url))))) urls) + eris-urns compressions (match file-sizes (() (make-list len #f)) @@ -186,7 +188,7 @@ (define* (read-narinfo port #:optional url "FileHash" "FileSize" "NarHash" "NarSize" "References" "Deriver" "System" "Signature") - '("URL" "Compression" "FileSize" "FileHash")))) + '("URL" "ERIS" "Compression" "FileSize" "FileHash")))) (define (narinfo-sha256 narinfo) "Return the sha256 hash of NARINFO as a bytevector, or #f if NARINFO lacks a diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 6e2b4368da..8e4b90789b 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -58,6 +58,7 @@ (define-module (guix scripts publish) #:use-module (guix workers) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) + #:use-module (eris) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -308,7 +309,7 @@ (define* (store-item->recutils store-item #:key (nar-path "nar") (compression %no-compression) - file-size) + file-size eris-urn) "Return the 'Compression' and 'URL' fields of the narinfo for STORE-ITEM, with COMPRESSION, starting at NAR-PATH." (let ((url (encode-and-join-uri-path @@ -319,19 +320,22 @@ (define* (store-item->recutils store-item (($ <compression> type) (list (symbol->string type)))) ,(basename store-item))))) - (format #f "URL: ~a~%Compression: ~a~%~@[FileSize: ~a~%~]" - url (compression-type compression) file-size))) + (format #f "URL: ~a~%Compression: ~a~%~@[FileSize: ~a~%~]~@[ERIS: ~a~%~]" + url (compression-type compression) file-size eris-urn))) (define* (narinfo-string store store-path #:key (compressions (list %no-compression)) - (nar-path "nar") (file-sizes '())) + (nar-path "nar") (file-sizes '()) (eris-urns '())) "Generate a narinfo key/value string for STORE-PATH; an exception is raised if STORE-PATH is invalid. Produce a URL that corresponds to COMPRESSION. The narinfo is signed with KEY. NAR-PATH specifies the prefix for nar URLs. Optionally, FILE-SIZES is a list of compression/integer pairs, where the integer is size in bytes of the compressed NAR; it informs the client of how -much needs to be downloaded." +much needs to be downloaded. + +Optionally, ERIS-URNS is a list of compression/string pairs, where the +string is the ERIS URN of the compressed NAR." (let* ((path-info (query-path-info store store-path)) (compressions (actual-compressions store-path compressions)) (hash (bytevector->nix-base32-string @@ -352,9 +356,12 @@ (define* (narinfo-string store store-path store-path (map (lambda (compression) (let ((size (assoc-ref file-sizes - compression))) + compression)) + (eris-urn (assoc-ref eris-urns + compression))) (store-item->recutils store-path #:file-size size + #:eris-urn eris-urn #:nar-path nar-path #:compression compression))) @@ -632,6 +639,12 @@ (define (compressed-nar-size compression) (and stat (cons compression (stat:size stat))))) + (define (compressed-eris-urn compression) + (let* ((nar (nar-cache-file cache item #:compression compression)) + (stat (stat nar #f))) + (and stat + (cons compression (call-with-input-file nar eris-encode->urn))))) + (let ((compression (actual-compressions item compressions))) (for-each (cut compress-nar cache item <>) compressions) @@ -646,11 +659,13 @@ (define (compressed-nar-size compression) ;; thread's connection to the store since we would end up sending ;; stuff concurrently on the same channel. (with-store store - (let ((sizes (filter-map compressed-nar-size compression))) + (let ((sizes (filter-map compressed-nar-size compression)) + (eris-urns (filter-map compressed-eris-urn compression))) (display (narinfo-string store item #:nar-path nar-path #:compressions compressions - #:file-sizes sizes) + #:file-sizes sizes + #:eris-urns eris-urns) port))) ;; Make the cached narinfo world-readable, contrary to what -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 2/3] WIP: gnu: guile-eris: Update to unreleased git version. 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard @ 2021-12-16 16:20 ` pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 3/3] publish: Add IPFS support pukkamustard 1 sibling, 0 replies; 65+ messages in thread From: pukkamustard @ 2021-12-16 16:20 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * gnu/packages/guile-xyz.schm (guile-eris): Update to unreleased git version. [source]: Update source URI. [propagated-inputs]: Add guile-json-4 and guile-gdbm-ffi. --- gnu/packages/guile-xyz.scm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm index 8346d99996..5e6f31a6e2 100644 --- a/gnu/packages/guile-xyz.scm +++ b/gnu/packages/guile-xyz.scm @@ -4325,15 +4325,15 @@ (define-public guile-sodium (define-public guile-eris (package (name "guile-eris") - (version "0.2.0") + (version "f1e4dd87988f9a80b05a8051d7f5ba3daf79dcc1") (source (origin (method git-fetch) (uri (git-reference - (url "https://inqlab.net/git/eris.git") - (commit (string-append "v" version)))) + (url "https://inqlab.net/git/guile-eris.git") + (commit version))) (file-name (git-file-name name version)) - (sha256 (base32 "1ijglmwkdy1l87gj429qfjis0v8b1zlxhbyfhx5za8664h68nqka")))) + (sha256 (base32 "0kgm4b4qn2s74wjvxy273gdi1l1m81i2k4kkk1zc6vlcg3np7p06")))) (build-system gnu-build-system) (arguments '()) (native-inputs @@ -4345,7 +4345,7 @@ (define-public guile-eris guile-srfi-180)) (inputs (list guile-3.0)) (propagated-inputs - (list guile-sodium)) + (list guile-sodium guile-json-4 guile-gdbm-ffi)) (synopsis "Guile implementation of the Encoding for Robust Immutable Storage (ERIS)") (description "Guile-ERIS is the reference implementation of the Encoding for Robust -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 3/3] publish: Add IPFS support. 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 2/3] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard @ 2021-12-16 16:20 ` pukkamustard 1 sibling, 0 replies; 65+ messages in thread From: pukkamustard @ 2021-12-16 16:20 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/scripts/publish.scm: (show-help, %options): Add '--ipfs'. (render-narinfo/cached, bake-narinfo+nar, make-request-handler, run-publish-server): Add #:ipfs? and honor it. (guix-publish): Honor '--ipfs' and parameterize %ipfs-base-url. --- guix/scripts/publish.scm | 52 +++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 8e4b90789b..8e7fb47b9e 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -41,6 +41,8 @@ (define-module (guix scripts publish) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) + #:use-module (srfi srfi-171) #:use-module (web http) #:use-module (web request) #:use-module (web response) @@ -52,6 +54,7 @@ (define-module (guix scripts publish) #:use-module (guix base64) #:use-module (guix config) #:use-module (guix derivations) + #:use-module ((guix ipfs) #:prefix ipfs:) #:use-module (gcrypt hash) #:use-module (guix pki) #:use-module (gcrypt pk-crypto) @@ -59,6 +62,8 @@ (define-module (guix scripts publish) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) #:use-module (eris) + #:use-module (eris read-capability) + #:use-module (eris blocks ipfs) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -83,6 +88,7 @@ (define-module (guix scripts publish) run-publish-server guix-publish)) + (define (show-help) (format #t (G_ "Usage: guix publish [OPTION]... Publish ~a over HTTP.\n") %store-directory) @@ -102,6 +108,8 @@ (define (show-help) (display (G_ " --cache-bypass-threshold=SIZE serve store items below SIZE even when not cached")) + (display (G_ " + --ipfs[=GATEWAY] publish items over IPFS via GATEWAY")) (display (G_ " --workers=N use N workers to bake items")) (display (G_ " @@ -220,6 +228,10 @@ (define %options (lambda (opt name arg result) (alist-cons 'cache-bypass-threshold (size->number arg) result))) + (option '("ipfs") #f #t + (lambda (opt name arg result) + (alist-cons 'ipfs (or arg (ipfs:%ipfs-base-url)) + result))) (option '("workers") #t #f (lambda (opt name arg result) (alist-cons 'workers (string->number* arg) @@ -526,7 +538,7 @@ (define (bypass-cache? store item) (define* (render-narinfo/cached store request hash #:key ttl (compressions (list %no-compression)) (nar-path "nar") negative-ttl - cache pool) + cache pool ipfs?) "Respond to the narinfo request for REQUEST. If the narinfo is available in CACHE, then send it; otherwise, return 404 and \"bake\" that nar and narinfo requested using POOL." @@ -571,7 +583,8 @@ (define (delete-entry narinfo) (bake-narinfo+nar cache item #:ttl ttl #:compressions compressions - #:nar-path nar-path))) + #:nar-path nar-path + #:ipfs? ipfs?))) (when ttl (single-baker 'cache-cleanup @@ -631,7 +644,7 @@ (define (write-compressed-file call-with-compressed-output-port) (define* (bake-narinfo+nar cache item #:key ttl (compressions (list %no-compression)) - (nar-path "/nar")) + (nar-path "/nar") ipfs?) "Write the narinfo and nar for ITEM to CACHE." (define (compressed-nar-size compression) (let* ((nar (nar-cache-file cache item #:compression compression)) @@ -641,9 +654,19 @@ (define (compressed-nar-size compression) (define (compressed-eris-urn compression) (let* ((nar (nar-cache-file cache item #:compression compression)) - (stat (stat nar #f))) + (stat (stat nar #f)) + (block-reducer (if ipfs? + (eris-blocks-ipfs-reducer + #:ipfs-base-url (ipfs:%ipfs-base-url)) + rcount))) (and stat - (cons compression (call-with-input-file nar eris-encode->urn))))) + (cons compression + (call-with-input-file nar + (lambda (port) + (let ((read-cap _ + (eris-encode port #:block-reducer + block-reducer))) + (read-capability->string read-cap)))))))) (let ((compression (actual-compressions item compressions))) @@ -1115,7 +1138,8 @@ (define* (make-request-handler store cache pool narinfo-ttl narinfo-negative-ttl (nar-path "nar") - (compressions (list %no-compression))) + (compressions (list %no-compression)) + ipfs?) (define compression-type? string->compression-type) @@ -1147,7 +1171,8 @@ (define (handle request body) #:ttl narinfo-ttl #:negative-ttl narinfo-negative-ttl #:nar-path nar-path - #:compressions compressions) + #:compressions compressions + #:ipfs? ipfs?) (render-narinfo store request hash #:ttl narinfo-ttl #:negative-ttl narinfo-negative-ttl @@ -1218,7 +1243,7 @@ (define* (run-publish-server socket store advertise? port (compressions (list %no-compression)) (nar-path "nar") narinfo-ttl narinfo-negative-ttl - cache pool) + cache pool ipfs?) (when advertise? (let ((name (service-name))) ;; XXX: Use a callback from Guile-Avahi here, as Avahi can pick a @@ -1234,7 +1259,8 @@ (define* (run-publish-server socket store #:nar-path nar-path #:narinfo-ttl narinfo-ttl #:narinfo-negative-ttl narinfo-negative-ttl - #:compressions compressions) + #:compressions compressions + #:ipfs? ipfs?) concurrent-http-server `(#:socket ,socket))) @@ -1296,6 +1322,8 @@ (define-command (guix-publish . args) (repl-port (assoc-ref opts 'repl)) (cache (assoc-ref opts 'cache)) (workers (assoc-ref opts 'workers)) + (ipfs (assoc-ref opts 'ipfs)) + (ipfs? (if ipfs #t #f)) ;; Read the key right away so that (1) we fail early on if we can't ;; access them, and (2) we can then drop privileges. @@ -1315,7 +1343,8 @@ (define-command (guix-publish . args) (%private-key private-key) (cache-bypass-threshold (or (assoc-ref opts 'cache-bypass-threshold) - (cache-bypass-threshold)))) + (cache-bypass-threshold))) + (ipfs:%ipfs-base-url ipfs)) (info (G_ "publishing ~a on ~a, port ~d~%") %store-directory (inet-ntop (sockaddr:fam address) (sockaddr:addr address)) @@ -1344,7 +1373,8 @@ (define-command (guix-publish . args) #:nar-path nar-path #:compressions compressions #:narinfo-negative-ttl negative-ttl - #:narinfo-ttl ttl)))))) + #:narinfo-ttl ttl + #:ipfs? ipfs?)))))) ;;; Local Variables: ;;; eval: (put 'single-baker 'scheme-indent-function 1) -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard @ 2021-12-20 16:25 ` Ludovic Courtès 2021-12-23 11:42 ` pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (2 subsequent siblings) 4 siblings, 1 reply; 65+ messages in thread From: Ludovic Courtès @ 2021-12-20 16:25 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 Hi pukkamustard, pukkamustard <pukkamustard@posteo.net> skribis: > This is an initial patch and proposal towards decentralizing substitute > distribution with ERIS. Woohoo, sounds exciting! > ERIS (Encoding for Robust Immutable Storage) [1] is an encoding of content into > uniformly sized, encryped and content-addressed blocks. The original content > can be reconstructed only with access to a read capability, which can be > encoded as an URN. > > One key advantage of ERIS is that the encoding is protocol agnostic. Any > protocol that can transfer small (32KiB) sized blocks referenced by the hash of > their content will do. This can be done with things such as GNUNet, IPFS, > OpenDHT, HTTP or a USB stick on a bicycle. Yes, that’s nice. > The following patch allows substitutes to be published over IPFS using ERIS. > This is inspired and very similar to previous work on distributing substitutes > over IPFS [2]. > > The narinfos served by `guix publish` look like this: > > StorePath: /gnu/store/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 > URL: nar/gzip/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 > Compression: gzip > FileSize: 67363 > ERIS: urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE > URL: nar/zstd/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 > Compression: zstd > FileSize: 64917 > ERIS: urn:erisx2:BIBO7KS7SAWHDNC43DVILOSQ3F3SRRHEV6YPLDCSZ7MMD6LZVCHQMEQ6FUBTJAPSNFF7XR5XPTP4OQ72OPABNEO7UYBUN42O46ARKHBTGM Do we really need one URN per compression method? Couldn’t we leave compression (of individual chunks, possibly) as a “detail” handled by the encoding or the transport layer? > If the `--ipfs` is used for `guix publish` then the encoded blocks are also > uploaded to the IPFS daemon. The nar could then be retrieved from anywhere like > this: > > (use-modules (eris) > (eris blocks ipfs)) > > (eris-decode->bytevector > "urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE" > eris-blocks-ipfs-ref) > > These patches do not yet retrieve content from IPFS (TODO). But in principle, > anybody connected to IPFS can get the nar with the ERIS URN. This could be used > to reduce load on substitute server as they would only need to publish the ERIS > URN directly - substitutes could be delivered much more peer-to-peer. Nice. So adjusting ‘guix substitute’ should be relatively easy? > Other transports that I have been looking in to and am pretty sure will work > include: HTTP (with RFC 2169 [3]), GNUNet, OpenDHT. This is, imho, the > advantage of ERIS over IPFS directly or GNUNet directly. The encoding and > identifiers (URN) are abstracted away from specific transports (and also > applications). ERIS is almost exactly the same encoding as used in GNUNet > (ECRS). As a first step, ‘guix publish’ could implement RFC 2169, too. I gather implementing the HTTP and IPFS backends in ‘guix substitute’ should be relatively easy, right? > Blocks can be stored in any kind of databases (see for example the GDBM > bindings [4]). > > A tricky things is figuring out how to multiplex all these different > transports and storages... Yes. We don’t know yet what performance and data availability will be like on IPFS, for instance, so it’s important for users to be able to set priorities. It’s also important to gracefully fall back to direct HTTP downloads when fancier p2p methods fail, regardless of how they fail. > The ERIS specification is still considered "experimental". However we feel > confident to stabilize it and intend to do so around February/March 2022 with a > release 1.0.0 of the specification. This will ensure that the identifiers > remain stable for the forseeable future (until the crypto breaks). Before that > there is also a small external security audit of the specification planned > (thanks to NGI0/NLnet!). Neat. This is all very exciting. I look forward to playing around with it! Ludo’. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2021-12-20 16:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès @ 2021-12-23 11:42 ` pukkamustard 2021-12-24 14:48 ` Ludovic Courtès 0 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2021-12-23 11:42 UTC (permalink / raw) To: Ludovic Courtès; +Cc: ~pukkamustard/eris, 52555 Hi Ludo, Thanks for your comments! Ludovic Courtès <ludo@gnu.org> writes: >> StorePath: /gnu/store/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >> URL: nar/gzip/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >> Compression: gzip >> FileSize: 67363 >> ERIS: urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE >> URL: nar/zstd/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >> Compression: zstd >> FileSize: 64917 >> ERIS: urn:erisx2:BIBO7KS7SAWHDNC43DVILOSQ3F3SRRHEV6YPLDCSZ7MMD6LZVCHQMEQ6FUBTJAPSNFF7XR5XPTP4OQ72OPABNEO7UYBUN42O46ARKHBTGM > > Do we really need one URN per compression method? Couldn’t we leave > compression (of individual chunks, possibly) as a “detail” handled by > the encoding or the transport layer? > I agree that it would be nice to leave this to the encoding layer as that would allow certain optimizations (e.g. de-duplication). Unfortunately, we haven't figured out yet what the most suitable compression/format would be. Something like EROSFS seems good (as it aligns data to fixed block sizes) [1]. But this seems a bit "clunky" for just an archive format and there do not seem to be any libraries that we could use to neatly integrate. It seems possible to block-align a Tar archive, but that seems a bit hackey [2]. Other things to look into might be Tarlz [3] and ZPAQ [4]. To get started I suggest just using one of the compressions/formats already in Guix. zstd seems to be a reasonable choice (for the same reasons why it makes sense to use zstd with `--discover` [5]). Does that sound like a plan? [1] https://inqlab.net/git/guile-eris.git/tree/examples/dedup-fs/Readme.org [2] https://unix.stackexchange.com/questions/276908/make-tar-or-other-archive-with-data-block-aligned-like-in-original-files-for/279384#279384 [3] http://lzip.nongnu.org/tarlz.html [4] http://mattmahoney.net/dc/zpaq.html [5] https://guix.gnu.org/en/blog/2021/getting-bytes-to-disk-more-quickly/ >> If the `--ipfs` is used for `guix publish` then the encoded blocks are also >> uploaded to the IPFS daemon. The nar could then be retrieved from anywhere like >> this: >> >> (use-modules (eris) >> (eris blocks ipfs)) >> >> (eris-decode->bytevector >> "urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE" >> eris-blocks-ipfs-ref) >> >> These patches do not yet retrieve content from IPFS (TODO). But in principle, >> anybody connected to IPFS can get the nar with the ERIS URN. This could be used >> to reduce load on substitute server as they would only need to publish the ERIS >> URN directly - substitutes could be delivered much more peer-to-peer. > > Nice. So adjusting ‘guix substitute’ should be relatively easy? Yes, relatively! :) I meant to send in a V2 that does this before going on holidays, but I'm afraid I won't make it. V2 will come in early January! >> Other transports that I have been looking in to and am pretty sure will work >> include: HTTP (with RFC 2169 [3]), GNUNet, OpenDHT. This is, imho, the >> advantage of ERIS over IPFS directly or GNUNet directly. The encoding and >> identifiers (URN) are abstracted away from specific transports (and also >> applications). ERIS is almost exactly the same encoding as used in GNUNet >> (ECRS). > > As a first step, ‘guix publish’ could implement RFC 2169, too. > > I gather implementing the HTTP and IPFS backends in ‘guix substitute’ > should be relatively easy, right? Yes, those seem to be the two easiest backends to implement. >> A tricky things is figuring out how to multiplex all these different >> transports and storages... > > Yes. We don’t know yet what performance and data availability will be > like on IPFS, for instance, so it’s important for users to be able to > set priorities. It’s also important to gracefully fall back to direct > HTTP downloads when fancier p2p methods fail, regardless of how they > fail. Agree. Thanks, -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2021-12-23 11:42 ` pukkamustard @ 2021-12-24 14:48 ` Ludovic Courtès 0 siblings, 0 replies; 65+ messages in thread From: Ludovic Courtès @ 2021-12-24 14:48 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 Hi! pukkamustard <pukkamustard@posteo.net> skribis: > Ludovic Courtès <ludo@gnu.org> writes: > >>> StorePath: /gnu/store/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >>> URL: nar/gzip/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >>> Compression: gzip >>> FileSize: 67363 >>> ERIS: urn:erisx2:BIBC2LUTIQH43S2KRIAV7TBXNUUVPZTMV6KFA2M7AL5V6FNE77VNUDDVDAGJUEEAFATVO2QQT67SMOPTO3LGWCJFU7BZVCF5VXEQQW25BE >>> URL: nar/zstd/81bdcd5x4v50i28h98bfkvvkx9cky63w-hello-2.10 >>> Compression: zstd >>> FileSize: 64917 >>> ERIS: urn:erisx2:BIBO7KS7SAWHDNC43DVILOSQ3F3SRRHEV6YPLDCSZ7MMD6LZVCHQMEQ6FUBTJAPSNFF7XR5XPTP4OQ72OPABNEO7UYBUN42O46ARKHBTGM >> >> Do we really need one URN per compression method? Couldn’t we leave >> compression (of individual chunks, possibly) as a “detail” handled by >> the encoding or the transport layer? >> > > I agree that it would be nice to leave this to the encoding layer as > that would allow certain optimizations (e.g. de-duplication). > > Unfortunately, we haven't figured out yet what the most suitable > compression/format would be. Something like EROSFS seems good (as it > aligns data to fixed block sizes) [1]. But this seems a bit "clunky" for > just an archive format and there do not seem to be any libraries that we > could use to neatly integrate. It seems possible to block-align a Tar > archive, but that seems a bit hackey [2]. Other things to look into > might be Tarlz [3] and ZPAQ [4]. Yeah. Though it may be that deduplication at the block level doesn’t buy us much. That was the conclusion I reached a long time ago[a], and also seems to be supported by the recent guix-daemon deduplication improvements[b]. [a] https://hal.inria.fr/hal-00187069/en [b] https://issues.guix.gnu.org/24937#20-lineno0 > To get started I suggest just using one of the compressions/formats > already in Guix. zstd seems to be a reasonable choice (for the same > reasons why it makes sense to use zstd with `--discover` [5]). > > Does that sound like a plan? Sure! > I meant to send in a V2 that does this before going on holidays, but I'm > afraid I won't make it. V2 will come in early January! Alright, we’ll see! :-) Until then, enjoy your holidays! Ludo’. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard 2021-12-20 16:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès @ 2022-01-25 19:21 ` pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 1/5] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard ` (8 more replies) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard 4 siblings, 9 replies; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:21 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris Hello Guix, Here comes the V2 of a proposal towards decentralizing substitute distribution with ERIS. A quick summary (as this has become quite long): - This adds support for publishing and getting substitutes over IPFS. - By using the ERIS encoding we are not limited to using IPFS as transport. We can also use GNUNet, Named Data Networking (possibly) or just plain old HTTP. Support for these can be added in (guix eris). - These patches are still very rough and we need better logic for when to use IPFS et. al. and when to fallback to HTTP. - There might be performance issues when using IPFS via the IPFS daemon HTTP API. I found the setup for testing this a bit tricky. I will try and describe how I have been testing it. Please let me know how this can be improved! ** Authorize local substitutes We will be running a local substitute server so we need to add the local signing key to the list of authorized keys. In the system configurations: #+BEGIN_SRC scheme (modify-services %base-services (guix-service-type config => (guix-configuration (inherit config) (authorized-keys (cons* ;; allow substitutes from ourselves for testing purposes (local-file "/etc/signing-key.pub") %default-authorized-guix-keys))))) #+END_SRC ** Configure the local Guix checkout #+BEGIN_SRC shell ./bootstrap && ./configure --localstatedir=/var --sysconfdir=/etc #+END_SRC The ~--sysconfdir~ is required so that guix will use the ACL in ~/etc/guix/acl~. ** Start the IPFS daemon #+BEGIN_SRC shell guix shell go-ipfs -- ipfs daemon #+END_SRC Start a local substitute server: #+BEGIN_SRC shell sudo -E ./pre-inst-env guix publish --public-key=/etc/guix/signing-key.pub --private-key=/etc/guix/signing-key.sec --cache=/tmp/guix-publish-cache/ --port=8081 --compression=zstd:19 #+END_SRC We use port 8081 as IPFS is running on 8080. We use the temporary cache directory ~/tmp/guix-publish-cache~. ** Build some package locally First we build some package: #+BEGIN_SRC shell ./pre-inst-env guix build hello --no-substitutes --no-offload #+END_SRC #+RESULTS: : /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 ** Trigger the substitute server to "bake" a susbtitute #+BEGIN_SRC shell curl http://localhost:8081/khaaib6s836bk5kbik239hlk6n6ianc4.narinfo #+END_SRC --8<---------------cut here---------------start------------->8--- StorePath: /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 URL: nar/zstd/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 Compression: zstd NarHash: sha256:11pk3jsh4zk0gigyjk881ay1nnvjfgpd3xpb4rmbaljhbiis4jbm NarSize: 190480 References: 094bbaq6glba86h1d4cj16xhdi6fk2jl-gcc-10.3.0-lib 5h2w4qi9hk1qzzgi1w83220ydslinr4s-glibc-2.33 khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 Deriver: mc7i1cdi42gy89mxl48nhdhgrfa9lpq6-hello-2.11.drv Signature: 1;strawberry;KHNpZ25hdHVyZSAKIChkYXRhIAogIChmbGFncyByZmM2OTc5KQogIChoYXNoIHNoYTI1NiAjOTE0QTVGNTE4NUZGRUIzMzc4QTEwMzgzQzdFMEU1NDI1MEUyREZDRjk1RDUwOTNCMzU4QTFBNDE4OUFBRDVGNCMpCiAgKQogKHNpZy12YWwgCiAgKGVjZHNhIAogICAociAjMDkxMDA2NDlCMkMyMzhEQzE2ODhFQTgyQTdCOEJFMTc5MTVBMjVDQjc1NzcwQjlGRkNGOTFDRTg2MDgyNzAwQiMpCiAgIChzICMwMUFBQ0VERjY0N0VENTQyRTIwNENDMEM1M0VDMEY0QjQ4QzdEOTAyRkFEQTkxREI4NzRGQjE2MTQ4QTIzNUI2IykKICAgKQogICkKIChwdWJsaWMta2V5IAogIChlY2MgCiAgIChjdXJ2ZSBFZDI1NTE5KQogICAocSAjMDRDMkY4ODk1QTU0NDNGNTlCODk2NDEwMEI1MDY0NzU4RjQ1N0YzMENEREE1MTQyQzE0MDc0NjExNTA1NTc5MCMpCiAgICkKICApCiApCg== --8<---------------cut here---------------end--------------->8--- If you do this again after a few seconds you will get a different response that has the ERIS URN and the FileSizes. The reason for this is that Guix publish bakes the nars asyncrhonisly in the background: #+BEGIN_SRC shell curl http://localhost:8081/khaaib6s836bk5kbik239hlk6n6ianc4.narinfo #+END_SRC #+RESULTS: --8<---------------cut here---------------start------------->8--- StorePath: /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 URL: nar/zstd/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 Compression: zstd FileSize: 57691 NarHash: sha256:11pk3jsh4zk0gigyjk881ay1nnvjfgpd3xpb4rmbaljhbiis4jbm NarSize: 190480 ERISFormat: application/x-nix-archive+zstd-19 ERIS: urn:erisx2:B4AYPTXLTACB6WJYJ74RKBCVU3RBLHA4PY6HATUWRZNJ6THVSDUFM34K2ASUF3B6EOYEEBRZ5XEUR4PAAAIED7G7YSEZVZ5V7WWZ2PSC7Q References: 094bbaq6glba86h1d4cj16xhdi6fk2jl-gcc-10.3.0-lib 5h2w4qi9hk1qzzgi1w83220ydslinr4s-glibc-2.33 khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 Deriver: mc7i1cdi42gy89mxl48nhdhgrfa9lpq6-hello-2.11.drv Signature: 1;strawberry;KHNpZ25hdHVyZSAKIChkYXRhIAogIChmbGFncyByZmM2OTc5KQogIChoYXNoIHNoYTI1NiAjOTE0QTVGNTE4NUZGRUIzMzc4QTEwMzgzQzdFMEU1NDI1MEUyREZDRjk1RDUwOTNCMzU4QTFBNDE4OUFBRDVGNCMpCiAgKQogKHNpZy12YWwgCiAgKGVjZHNhIAogICAociAjMDkxMDA2NDlCMkMyMzhEQzE2ODhFQTgyQTdCOEJFMTc5MTVBMjVDQjc1NzcwQjlGRkNGOTFDRTg2MDgyNzAwQiMpCiAgIChzICMwMUFBQ0VERjY0N0VENTQyRTIwNENDMEM1M0VDMEY0QjQ4QzdEOTAyRkFEQTkxREI4NzRGQjE2MTQ4QTIzNUI2IykKICAgKQogICkKIChwdWJsaWMta2V5IAogIChlY2MgCiAgIChjdXJ2ZSBFZDI1NTE5KQogICAocSAjMDRDMkY4ODk1QTU0NDNGNTlCODk2NDEwMEI1MDY0NzU4RjQ1N0YzMENEREE1MTQyQzE0MDc0NjExNTA1NTc5MCMpCiAgICkKICApCiApCg== --8<---------------cut here---------------end--------------->8--- These patches have added the ERIS and ERISFormat fields. Eventually we would have figured out what the best format for use over ERIS is, for now we encode it in the ERISFormat field. ** Removing a package from the store This is necessary in order to make guix look for a substitute. #+BEGIN_SRC shell ./pre-inst-env guix gc -D /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 #+END_SRC ** Start the Guix daemon from the repository #+BEGIN_SRC shell sudo -E ./pre-inst-env guix-daemon --build-users-group=guixbuild --debug --substitute-urls=http://localhost:8081/ #+END_SRC Note this will probably stop your system Guix daemon. Run ~sudo herd restart guix-daemon~ to restart it. #+BEGIN_SRC shell ./pre-inst-env guix build hello #+END_SRC --8<---------------cut here---------------start------------->8--- substituting /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11... downloading from urn:erisx2:B4AYPTXLTACB6WJYJ74RKBCVU3RBLHA4PY6HATUWRZNJ6THVSDUFM34K2ASUF3B6EOYEEBRZ5XEUR4PAAAIED7G7YSEZVZ5V7WWZ2PSC7Q ... urn:erisx2:B4AYPTXLTACB6WJYJ74RKBCVU3RBLHA4PY6HATUWRZNJ6THVSDUFM34K2ASUF3B6EOYEEBRZ5XEUR4PAAAIED7G7YSEZVZ5V7WWZ2PSC7Q 502KiB/s 00:00 | 56KiB transferred /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11 --8<---------------cut here---------------end--------------->8--- We have just retreived the substitute for the hello package from IPFS. Hello decentralized substitutes! I have only tested this for fairly small packages (up to a few MB). One issue with IPFS might be that we have to create a new HTTP connection to the IPFS daemon for every single block (32KiB). The IPFS daemon does not seem to support HTTP connection re-use and neither does the Guile (web client). I fear this might become a performance issue. It seems possible to use IPFS more directly by exposing the Go code as a C library and then using that with the Guile FFI [1]. This is however a bit complicated and adds a lot of dependencies. In particular, this should not become a dependency of Guix itself. The performance of IPFS itself also needs to be evaluated, maybe the IPFS HTTP API will not be the bottle-neck. As mentioned in previous mail a simple HTTP transport for blocks would be a good fallback. This would allow users to get missing blocks (things that somehow got dropped from IPFS) directly from a substitute server. This is different then getting the entire NAR from a substitute server. A user might be missing a single 32KiB block and should be able to get only that. However, such a HTTP fallback would also suffer from the one-connection-per-block issue. As part of general ERIS research we are investigating CoAP as a better fallback transport. In any case, it would be necessary for the substitute server to store encoded blocks of the NAR. For this I think it makes sense to use a small database. We have bindings to use ERIS with GDBM [2]. It might also make sense to use SQLite, especially if there are other use-cases for such a database. I will be looking into the HTTP fallback and also using BitTorrent and GNUNet as transports. Thanks for making it so far and happy hacking! -pukkamustard [1] https://github.com/scala-network/libipfs/ [2] https://codeberg.org/eris/guile-eris/src/branch/main/eris/blocks/gdbm.scm pukkamustard (5): WIP: gnu: guile-eris: Update to unreleased git version. publish: Add ERIS URN to narinfo Add (guix eris). publish: Add support for storing ERIS encoded blocks to IPFS. substitute: Fetch substitutes using ERIS. Makefile.am | 1 + configure.ac | 5 +++ gnu/packages/guile-xyz.scm | 10 ++--- gnu/packages/package-management.scm | 1 + guix/eris.scm | 60 +++++++++++++++++++++++++++++ guix/narinfo.scm | 14 +++++-- guix/scripts/publish.scm | 32 +++++++++++++-- guix/scripts/substitute.scm | 21 +++++++--- 8 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 guix/eris.scm -- 2.34.0 ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 1/5] WIP: gnu: guile-eris: Update to unreleased git version. 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard @ 2022-01-25 19:21 ` pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo pukkamustard ` (7 subsequent siblings) 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:21 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * gnu/packages/guile-xyz.schm (guile-eris): Update to unreleased git version. [source]: Update source URI. [propagated-inputs]: Add guile-json-4 and guile-gdbm-ffi. --- gnu/packages/guile-xyz.scm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm index e2cf793acc..66ac486a74 100644 --- a/gnu/packages/guile-xyz.scm +++ b/gnu/packages/guile-xyz.scm @@ -4374,15 +4374,15 @@ (define-public guile-sodium (define-public guile-eris (package (name "guile-eris") - (version "0.2.0") + (version "bcbbcbc88f3ec1f2fafcd034ce5b620516bff105") (source (origin (method git-fetch) (uri (git-reference - (url "https://inqlab.net/git/eris.git") - (commit (string-append "v" version)))) + (url "https://codeberg.org/eris/guile-eris") + (commit version))) (file-name (git-file-name name version)) - (sha256 (base32 "1ijglmwkdy1l87gj429qfjis0v8b1zlxhbyfhx5za8664h68nqka")))) + (sha256 (base32 "17v3h2hqx080739rl57nfradp5vlmy24fgqdxry1zal5z9d3i8sr")))) (build-system gnu-build-system) (arguments '()) (native-inputs @@ -4394,7 +4394,7 @@ (define-public guile-eris guile-srfi-180)) (inputs (list guile-3.0)) (propagated-inputs - (list guile-sodium)) + (list guile-sodium guile-json-4 guile-gdbm-ffi)) (synopsis "Guile implementation of the Encoding for Robust Immutable Storage (ERIS)") (description "Guile-ERIS is the reference implementation of the Encoding for Robust -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 1/5] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard @ 2022-01-25 19:21 ` pukkamustard 2022-01-29 21:09 ` Maxime Devos 2022-01-29 21:15 ` Maxime Devos 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 3/5] Add (guix eris) pukkamustard ` (6 subsequent siblings) 8 siblings, 2 replies; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:21 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/scripts/publish.scm: (bake-narinfo+nar): Compute ERIS URN of compressed nars. (narinfo-string): Add #:eris-urn parameter and honor it. * guix/scripts/narinfo.scm: (<narinfo>)[eris-format,eris-urn]: New fields. (narinfo-maker): Handle ERIS URN and ERIS format. * configure.ac: (HAVE_GUILE_ERIS): New conditional. * gnu/packages/package-management.scm: (guix)[native-inputs]: Add guile-eris. --- configure.ac | 5 +++++ gnu/packages/package-management.scm | 1 + guix/narinfo.scm | 14 ++++++++++---- guix/scripts/publish.scm | 24 ++++++++++++++++++++---- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 341cff8fbd..72396be8aa 100644 --- a/configure.ac +++ b/configure.ac @@ -170,6 +170,11 @@ GUILE_MODULE_AVAILABLE([have_guile_avahi], [(avahi)]) AM_CONDITIONAL([HAVE_GUILE_AVAHI], [test "x$have_guile_avahi" = "xyes"]) +dnl Check for Guile-eris. +GUILE_MODULE_AVAILABLE([have_guile_eris], [(eris)]) +AM_CONDITIONAL([HAVE_GUILE_ERIS], + [test "x$have_guile_eris" = "xyes"]) + dnl Guile-newt is used by the graphical installer. GUILE_MODULE_AVAILABLE([have_guile_newt], [(newt)]) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index 05795824b5..a9094b8b7f 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -404,6 +404,7 @@ (define code ("guile-zstd" ,guile-zstd) ("guile-ssh" ,guile-ssh) ("guile-git" ,guile-git) + ("guile-eris" ,guile-eris) ;; XXX: Keep the development inputs here even though ;; they're unnecessary, just so that 'guix environment diff --git a/guix/narinfo.scm b/guix/narinfo.scm index 4fc550aa6c..a6a5d3b84b 100644 --- a/guix/narinfo.scm +++ b/guix/narinfo.scm @@ -45,6 +45,8 @@ (define-module (guix narinfo) narinfo-file-sizes narinfo-hash narinfo-size + narinfo-eris-format + narinfo-eris-urn narinfo-references narinfo-deriver narinfo-system @@ -68,8 +70,8 @@ (define-module (guix narinfo) (define-record-type <narinfo> (%make-narinfo path uri-base uris compressions file-sizes file-hashes - nar-hash nar-size references deriver system - signature contents) + nar-hash nar-size eris-format eris-urn references deriver + system signature contents) narinfo? (path narinfo-path) (uri-base narinfo-uri-base) ;URI of the cache it originates from @@ -79,6 +81,8 @@ (define-record-type <narinfo> (file-hashes narinfo-file-hashes) (nar-hash narinfo-hash) (nar-size narinfo-size) + (eris-format narinfo-eris-format) + (eris-urn narinfo-eris-urn) (references narinfo-references) (deriver narinfo-deriver) (system narinfo-system) @@ -135,7 +139,7 @@ (define (narinfo-maker str cache-url) "Return a narinfo constructor for narinfos originating from CACHE-URL. STR must contain the original contents of a narinfo file." (lambda (path urls compressions file-hashes file-sizes - nar-hash nar-size references deriver system + nar-hash nar-size eris-format eris-urn references deriver system signature) "Return a new <narinfo> object." (define len (length urls)) @@ -157,6 +161,8 @@ (define len (length urls)) ((lst ...) (map string->number lst))) nar-hash (and=> nar-size string->number) + eris-format + (if eris-urn (string->uri eris-urn) #f) (string-tokenize references) (match deriver ((or #f "") #f) @@ -184,7 +190,7 @@ (define* (read-narinfo port #:optional url (narinfo-maker str url) '("StorePath" "URL" "Compression" "FileHash" "FileSize" "NarHash" "NarSize" - "References" "Deriver" "System" + "ERISFormat" "ERIS" "References" "Deriver" "System" "Signature") '("URL" "Compression" "FileSize" "FileHash")))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 6e2b4368da..9c83f5183d 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -58,6 +58,7 @@ (define-module (guix scripts publish) #:use-module (guix workers) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) + #:use-module (eris) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -146,6 +147,9 @@ (define %default-gzip-compression ;; Since we compress on the fly, default to fast compression. (compression 'gzip 3)) +(define %eris-zstd-compression + (compression 'zstd 19)) + (define (default-compression type) (compression type 3)) @@ -324,7 +328,8 @@ (define* (store-item->recutils store-item (define* (narinfo-string store store-path #:key (compressions (list %no-compression)) - (nar-path "nar") (file-sizes '())) + (nar-path "nar") (file-sizes '()) + eris-urn) "Generate a narinfo key/value string for STORE-PATH; an exception is raised if STORE-PATH is invalid. Produce a URL that corresponds to COMPRESSION. The narinfo is signed with KEY. NAR-PATH specifies the prefix for nar URLs. @@ -347,7 +352,7 @@ (define* (narinfo-string store store-path StorePath: ~a ~{~a~}\ NarHash: sha256:~a -NarSize: ~d +NarSize: ~d~@[~%ERISFormat: application/x-nix-archive+zstd-19~%ERIS: ~a~] References: ~a~%" store-path (map (lambda (compression) @@ -359,7 +364,7 @@ (define* (narinfo-string store store-path #:compression compression))) compressions) - hash size references)) + hash size eris-urn references)) ;; Do not render a "Deriver" line if we are rendering info for a ;; derivation. Also do not render a "System" line that would be ;; expensive to compute and is currently unused. @@ -632,6 +637,16 @@ (define (compressed-nar-size compression) (and stat (cons compression (stat:size stat))))) + (define (eris-encode-nar compressions) + (and (member %eris-zstd-compression compressions) + (let* ((nar (nar-cache-file cache item + #:compression %eris-zstd-compression)) + (stat (stat nar #f))) + (and stat + (call-with-input-file nar + (cut eris-encode->string <> + #:block-size %eris-block-size-large)))))) + (let ((compression (actual-compressions item compressions))) (for-each (cut compress-nar cache item <>) compressions) @@ -650,7 +665,8 @@ (define (compressed-nar-size compression) (display (narinfo-string store item #:nar-path nar-path #:compressions compressions - #:file-sizes sizes) + #:file-sizes sizes + #:eris-urn (eris-encode-nar compression)) port))) ;; Make the cached narinfo world-readable, contrary to what -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo pukkamustard @ 2022-01-29 21:09 ` Maxime Devos 2022-01-29 21:15 ` Maxime Devos 1 sibling, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:09 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 302 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > +dnl Check for Guile-eris. > +GUILE_MODULE_AVAILABLE([have_guile_eris], [(eris)]) > +AM_CONDITIONAL([HAVE_GUILE_ERIS], > + [test "x$have_guile_eris" = "xyes"]) This could to be documented in (guix)Requirements. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo pukkamustard 2022-01-29 21:09 ` Maxime Devos @ 2022-01-29 21:15 ` Maxime Devos 2022-02-02 10:16 ` pukkamustard 1 sibling, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:15 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 1074 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > + (define (eris-encode-nar compressions) > + (and (member %eris-zstd-compression compressions) > + (let* ((nar (nar-cache-file cache item > + #:compression %eris-zstd-compression)) > + (stat (stat nar #f))) > + (and stat > + (call-with-input-file nar > + (cut eris-encode->string <> > + #:block-size %eris-block-size-large)))))) Why are exceptions turned into #f (in (stat nar #f))? Should this be done for all I/O errors, including, say, EOVERFLOW, ENOMEM or ENAMETOOLONG, or only for ENOENT? Is a race condition possible here? If so, maybe consider doing something like (catch 'system-error (lambda () (call-with-input-file ...)) (lambda exception (and it-is-a-ENOENT (apply throw exception)))) to avoid it? Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo 2022-01-29 21:15 ` Maxime Devos @ 2022-02-02 10:16 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:16 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: >> + (define (eris-encode-nar compressions) >> + (and (member %eris-zstd-compression compressions) >> + (let* ((nar (nar-cache-file cache item >> + #:compression %eris-zstd-compression)) >> + (stat (stat nar #f))) >> + (and stat >> + (call-with-input-file nar >> + (cut eris-encode->string <> >> + #:block-size %eris-block-size-large)))))) > > Why are exceptions turned into #f (in (stat nar #f))? > Should this be done for all I/O errors, including, say, EOVERFLOW, > ENOMEM or ENAMETOOLONG, or only for ENOENT? > > Is a race condition possible here? If so, maybe consider doing > something like > > (catch 'system-error > (lambda () (call-with-input-file ...)) > (lambda exception > (and it-is-a-ENOENT > (apply throw exception)))) > > to avoid it? A valid question. But (stat nar #f) is not something I introduced. It is already in guix/scripts/publish.scm like that. To me turning all exceptions to #f makes sense. Here we only want to know if the file is readable. As the NAR is baked in the background by another thread the case where the compressed NAR does exist yet will happen. In that case we don't worry, we just don't publish the `FileSize` and `ERIS` fields in the narinfo. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 3/5] Add (guix eris). 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 1/5] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo pukkamustard @ 2022-01-25 19:21 ` pukkamustard 2022-01-29 21:23 ` Maxime Devos 2022-01-29 21:24 ` Maxime Devos 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS pukkamustard ` (5 subsequent siblings) 8 siblings, 2 replies; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:21 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/ipfs.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 1 + guix/eris.scm | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 guix/eris.scm diff --git a/Makefile.am b/Makefile.am index a10aeb817b..7219386361 100644 --- a/Makefile.am +++ b/Makefile.am @@ -131,6 +131,7 @@ MODULES = \ guix/cve.scm \ guix/workers.scm \ guix/ipfs.scm \ + guix/eris.scm \ guix/build-system.scm \ guix/build-system/android-ndk.scm \ guix/build-system/ant.scm \ diff --git a/guix/eris.scm b/guix/eris.scm new file mode 100644 index 0000000000..163bbe05ac --- /dev/null +++ b/guix/eris.scm @@ -0,0 +1,55 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix eris) + #:use-module (eris) + #:use-module (eris blocks ipfs) + #:use-module (web client) + #:use-module (web response) + #:use-module (srfi srfi-71) + + #:export (guix-eris-block-reducer)) + +(define (ipfs-daemon-alive?) + "Attempt to connect to the IPFS daemon. Returns #t if the daemon is alive +and #f else." + (with-exception-handler + (const #f) + (lambda _ + (let ((response _ + (http-post (string-append (%ipfs-base-url) + "/api/v0/version")))) + (equal? 200 (response-code response)))) + #:unwind? #t)) + +(define guix-eris-block-reducer + (case-lambda + + ;; Check if IPFS Daemon is running. + (() (if (ipfs-daemon-alive?) + (eris-blocks-ipfs-reducer) + #f)) + + ;; Completion. Nothing to do. + ((_) #t) + + ((ipfs ref-block) + ;; If IPFS has been initialized store block there + (if ipfs + (eris-blocks-ipfs-reducer ipfs ref-block) + ipfs)))) -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 3/5] Add (guix eris). 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 3/5] Add (guix eris) pukkamustard @ 2022-01-29 21:23 ` Maxime Devos 2022-02-02 10:28 ` pukkamustard 2022-01-29 21:24 ` Maxime Devos 1 sibling, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:23 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 1702 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > +(define (ipfs-daemon-alive?) > + "Attempt to connect to the IPFS daemon. Returns #t if the daemon is alive > +and #f else." > + (with-exception-handler > + (const #f) > + (lambda _ > + (let ((response _ > + (http-post (string-append (%ipfs-base-url) > + "/api/v0/version")))) > + (equal? 200 (response-code response)))) > + #:unwind? #t)) This should preferably only be catching exceptions indicating that the daemon is down (exceptions indicating 404s, or system-errors indicating network errors, ...). > + > +(define guix-eris-block-reducer > + (case-lambda > + > + ;; Check if IPFS Daemon is running. > + (() (if (ipfs-daemon-alive?) > + (eris-blocks-ipfs-reducer) > + #f)) > + > + ;; Completion. Nothing to do. > + ((_) #t) > + > + ((ipfs ref-block) > + ;; If IPFS has been initialized store block there > + (if ipfs > + (eris-blocks-ipfs-reducer ipfs ref-block) > + ipfs)))) This (ipfs-daemon-alive?) seems racy, although it's probably not. Can we do (define guix-eris-block-reducer (case-lambda (() (guard (c (oops-it-fails-because-the-daemon-cannot-be- contacted? c) #false) (eris-block-ipfs-reducer)) [...])) instead? (I don't think this will work as-is, because from the name and thunkiness, it would appear that eris-block-ipfs-reducer returns a procedure ... Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 3/5] Add (guix eris). 2022-01-29 21:23 ` Maxime Devos @ 2022-02-02 10:28 ` pukkamustard 2022-02-02 15:36 ` Maxime Devos 0 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:28 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: >> +(define (ipfs-daemon-alive?) >> + "Attempt to connect to the IPFS daemon. Returns #t if the daemon is alive >> +and #f else." >> + (with-exception-handler >> + (const #f) >> + (lambda _ >> + (let ((response _ >> + (http-post (string-append (%ipfs-base-url) >> + "/api/v0/version")))) >> + (equal? 200 (response-code response)))) >> + #:unwind? #t)) > > This should preferably only be catching exceptions indicating that > the daemon is down (exceptions indicating 404s, or system-errors > indicating network errors, ...). Yes, I guess it could be checked a bit finer. But at the end if an exception happens then the IPFS daemon is probably not reachable, right? If we don't care about the reason why it is not reachable then why bother with catching finer grained exceptions? >> + >> +(define guix-eris-block-reducer >> + (case-lambda >> + >> + ;; Check if IPFS Daemon is running. >> + (() (if (ipfs-daemon-alive?) >> + (eris-blocks-ipfs-reducer) >> + #f)) >> + >> + ;; Completion. Nothing to do. >> + ((_) #t) >> + >> + ((ipfs ref-block) >> + ;; If IPFS has been initialized store block there >> + (if ipfs >> + (eris-blocks-ipfs-reducer ipfs ref-block) >> + ipfs)))) > > This (ipfs-daemon-alive?) seems racy, although it's probably not. > Can we do > > (define guix-eris-block-reducer > (case-lambda > (() (guard (c (oops-it-fails-because-the-daemon-cannot-be- > contacted? c) > #false) > (eris-block-ipfs-reducer)) > [...])) > > instead? (I don't think this will work as-is, because from the name and > thunkiness, it would appear that eris-block-ipfs-reducer returns a > procedure ... Yes, eris-block-ipfs-reducer returns and SRFI-171 reducer. This is a 3-arity procedure that is either initialized, called with a block to reduce and finalized. The #f that the initialization case returns (0-arity call) is the state of the reducer. In the block reducing case (2-ary call) the state (the ipfs variable) is checked if ipfs is alive. If not the blocks are just forgotten. So guix-eris-block-reducer always returns a SRF-171 reducer, regardless of if IPFS is alive or not. This is important as the ERIS URN can still be computed without the IPFS daemon running. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 3/5] Add (guix eris). 2022-02-02 10:28 ` pukkamustard @ 2022-02-02 15:36 ` Maxime Devos 0 siblings, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-02-02 15:36 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 1624 bytes --] pukkamustard schreef op wo 02-02-2022 om 10:28 [+0000]: > > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > > > +(define (ipfs-daemon-alive?) > > > + "Attempt to connect to the IPFS daemon. Returns #t if the > > > daemon is alive > > > +and #f else." > > > + (with-exception-handler > > > + (const #f) > > > + (lambda _ > > > + (let ((response _ > > > + (http-post (string-append (%ipfs-base-url) > > > + > > > "/api/v0/version")))) > > > + (equal? 200 (response-code response)))) > > > + #:unwind? #t)) > > > > This should preferably only be catching exceptions indicating that > > the daemon is down (exceptions indicating 404s, or system-errors > > indicating network errors, ...). > > Yes, I guess it could be checked a bit finer. But at the end if an > exception happens then the IPFS daemon is probably not reachable, > right? > If we don't care about the reason why it is not reachable then why > bother with catching finer grained exceptions? The exception could be caused by, say: * an unbound variable * wrong arity * type error * stack overflow * prompt tag does not exist in current environment * out of memory Except for the last one, these causes are all bugs and hence shouldn't be surpressed. Granted, this is a bit unlikely since this use of 'http-post' is very simple, but it's far from impossible for (web client) to have a bug. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 3/5] Add (guix eris). 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 3/5] Add (guix eris) pukkamustard 2022-01-29 21:23 ` Maxime Devos @ 2022-01-29 21:24 ` Maxime Devos 1 sibling, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:24 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 289 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > + #:use-module (eris) > + #:use-module (eris blocks ipfs) guile-eris is an optional dependency, so this needs to be autoloaded. Or guix/eris.scm must only be compiled when guile-eris is available. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS. 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (2 preceding siblings ...) 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 3/5] Add (guix eris) pukkamustard @ 2022-01-25 19:22 ` pukkamustard 2022-01-29 21:28 ` Maxime Devos 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard ` (4 subsequent siblings) 8 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:22 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/scripts/publish.scm (bake-narinfo+nar): Use guix-eris-block-reducer from (guix eris). --- guix/scripts/publish.scm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 9c83f5183d..556107ab7d 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -41,6 +41,7 @@ (define-module (guix scripts publish) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) #:use-module (web http) #:use-module (web request) #:use-module (web response) @@ -58,6 +59,7 @@ (define-module (guix scripts publish) #:use-module (guix workers) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) + #:use-module (guix eris) #:use-module (eris) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port @@ -644,8 +646,14 @@ (define (eris-encode-nar compressions) (stat (stat nar #f))) (and stat (call-with-input-file nar - (cut eris-encode->string <> - #:block-size %eris-block-size-large)))))) + (lambda (port) + (let ((eris-urn _ + (eris-encode port + #:block-size + %eris-block-size-large + #:block-reducer + guix-eris-block-reducer))) + (uri->string eris-urn)))))))) (let ((compression (actual-compressions item compressions))) -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS. 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS pukkamustard @ 2022-01-29 21:28 ` Maxime Devos 2022-02-02 10:24 ` pukkamustard 0 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:28 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 1484 bytes --] pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > + (let ((eris-urn _ > + (eris-encode port > + #:block-size > + %eris-block-size-large > + #:block-reducer > + guix-eris-block-reducer))) > + (uri->string eris-urn)))))))) IIUC (and quite probably I don't, because I've only being reading things cursorly), eris-encode returns #false when the IPFS daemon is down (because then guix-eris-block-reducer returns #false). In that case, (uri->string eris-urn) = (uri->string #false) would throw an exception: scheme@(guile-user)> ((@ (web uri) uri->string) #false) ice-9/boot-9.scm:1669:16: In procedure raise-exception: In procedure struct-vtable: Wrong type argument in position 1 (expecting struct): #f Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [1]> ,bt In web/uri.scm: 336:17 1 (uri->string #f #:include-fragment? _) In ice-9/boot-9.scm: 1669:16 0 (raise-exception _ #:continuable? _) Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS. 2022-01-29 21:28 ` Maxime Devos @ 2022-02-02 10:24 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:24 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: >> + (let ((eris-urn _ >> + (eris-encode port >> + #:block-size >> + %eris-block-size-large >> + #:block-reducer >> + guix-eris-block-reducer))) >> + (uri->string eris-urn)))))))) > > IIUC (and quite probably I don't, because I've only being reading > things cursorly), eris-encode returns #false when the IPFS daemon is > down (because then guix-eris-block-reducer returns #false). No, eris-encode will still return the ERIS URN. The blocks will just not be stored in IPFS if the IPFS daemon is not running. See also my response to the questions on guix-eris-block-reducer in (guix eris). -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (3 preceding siblings ...) 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS pukkamustard @ 2022-01-25 19:22 ` pukkamustard 2022-01-29 21:29 ` Maxime Devos ` (3 more replies) 2022-01-29 21:00 ` [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS Maxime Devos ` (3 subsequent siblings) 8 siblings, 4 replies; 65+ messages in thread From: pukkamustard @ 2022-01-25 19:22 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ~pukkamustard/eris * guix/scripts/substitute.scm (process-substitution): Fetch substitutes using ERIS. * guix/eris.scm (guix-eris-block-ref): New procedure. --- guix/eris.scm | 7 ++++++- guix/scripts/substitute.scm | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index 163bbe05ac..0999564c1f 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -23,7 +23,8 @@ (define-module (guix eris) #:use-module (web response) #:use-module (srfi srfi-71) - #:export (guix-eris-block-reducer)) + #:export (guix-eris-block-reducer + guix-eris-block-ref)) (define (ipfs-daemon-alive?) "Attempt to connect to the IPFS daemon. Returns #t if the daemon is alive @@ -53,3 +54,7 @@ (define guix-eris-block-reducer (if ipfs (eris-blocks-ipfs-reducer ipfs ref-block) ipfs)))) + +(define (guix-eris-block-ref ref) + "Dereference a block for decoding ERIS content" + (eris-blocks-ipfs-ref ref)) diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 908a8334a8..852264976e 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm @@ -62,6 +62,8 @@ (define-module (guix scripts substitute) #:use-module (srfi srfi-35) #:use-module (web uri) #:use-module (guix http-client) + #:use-module (guix eris) + #:use-module (eris) #:export (%allow-unauthenticated-substitutes? %reply-file-descriptor @@ -486,18 +488,27 @@ (define (fetch uri) #:port port #:keep-alive? #t #:buffered? #f))))) + (else - (leave (G_ "unsupported substitute URI scheme: ~a~%") - (uri->string uri))))) + (if (and (eris-read-capability? uri)) + (values (eris-decode->port uri + #:block-ref + guix-eris-block-ref) #f) + (leave (G_ "unsupported substitute URI scheme: ~a~%") + (uri->string uri)))))) + + (define* (best-uri narinfo #:key (eris? #f)) + (if (and eris? (narinfo-eris-urn narinfo)) + (values (narinfo-eris-urn narinfo) "zstd" #f) + (narinfo-best-uri narinfo #:fast-decompression? + %prefer-fast-decompression?))) (unless narinfo (leave (G_ "no valid substitute for '~a'~%") store-item)) (let-values (((uri compression file-size) - (narinfo-best-uri narinfo - #:fast-decompression? - %prefer-fast-decompression?))) + (best-uri narinfo #:eris? #t))) (unless print-build-trace? (format (current-error-port) (G_ "Downloading ~a...~%") (uri->string uri))) -- 2.34.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard @ 2022-01-29 21:29 ` Maxime Devos 2022-02-02 10:11 ` pukkamustard 2022-01-29 21:33 ` Maxime Devos ` (2 subsequent siblings) 3 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:29 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 316 bytes --] pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > +(define (guix-eris-block-ref ref) > + "Dereference a block for decoding ERIS content" > + (eris-blocks-ipfs-ref ref)) 'guix-eris-block-ref' just calls 'eris-blocks-ipfs-ref', so I'm not seeing the point of this procedure. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-29 21:29 ` Maxime Devos @ 2022-02-02 10:11 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:11 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: >> +(define (guix-eris-block-ref ref) >> + "Dereference a block for decoding ERIS content" >> + (eris-blocks-ipfs-ref ref)) > > 'guix-eris-block-ref' just calls 'eris-blocks-ipfs-ref', > so I'm not seeing the point of this procedure. Yes, currently it is an unnecessary level of abstraction. The idea is that when there are multiple backends/transports they are multiplexed here. E.g. guix-eris-block-ref would attempt to use HTTP/IPFS or whatever to get the block. Whatever calls guix-eris-block-ref does not need to know from where the blocks come. I hope to make this more clear in a V3 that will add HTTP transport. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard 2022-01-29 21:29 ` Maxime Devos @ 2022-01-29 21:33 ` Maxime Devos 2022-01-29 21:38 ` Maxime Devos 2022-01-29 21:40 ` Maxime Devos 3 siblings, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:33 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 474 bytes --] pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > + Superfluous new empty line? > (else > - (leave (G_ "unsupported substitute URI scheme: ~a~%") > - (uri->string uri))))) > + (if (and (eris-read-capability? uri)) guile-eris (which has the eris-read-capability? procedure) is an optional dependency, so you have to check here is Guix was compiled with guile-eris. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard 2022-01-29 21:29 ` Maxime Devos 2022-01-29 21:33 ` Maxime Devos @ 2022-01-29 21:38 ` Maxime Devos 2022-01-29 21:40 ` Maxime Devos 2022-01-29 21:40 ` Maxime Devos 3 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:38 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 498 bytes --] pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > + (define* (best-uri narinfo #:key (eris? #f)) > + (if (and eris? (narinfo-eris-urn narinfo)) > + (values (narinfo-eris-urn narinfo) "zstd" #f) > + (narinfo-best-uri narinfo #:fast-decompression? > + %prefer-fast-decompression?))) When Guix is compiled without guile-eris support, '(and eris? (narinfo-eris-urn narinfo))' is the worst, not the best. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-29 21:38 ` Maxime Devos @ 2022-01-29 21:40 ` Maxime Devos 0 siblings, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:40 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris Maxime Devos schreef op za 29-01-2022 om 22:38 [+0100]: > pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > > + (define* (best-uri narinfo #:key (eris? #f)) > > + (if (and eris? (narinfo-eris-urn narinfo)) > > + (values (narinfo-eris-urn narinfo) "zstd" #f) > > + (narinfo-best-uri narinfo #:fast-decompression? > > + %prefer-fast-decompression?))) > > When Guix is compiled without guile-eris support, > '(and eris? (narinfo-eris-urn narinfo))' is the worst, not the best. Nevermind, that's what (eris? #f) is for, I presume? Greetings, Maxime. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard ` (2 preceding siblings ...) 2022-01-29 21:38 ` Maxime Devos @ 2022-01-29 21:40 ` Maxime Devos 2022-02-02 10:38 ` pukkamustard 3 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:40 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 579 bytes --] pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: > + (define* (best-uri narinfo #:key (eris? #f)) > + (if (and eris? (narinfo-eris-urn narinfo)) > + (values (narinfo-eris-urn narinfo) "zstd" #f) > + (narinfo-best-uri narinfo #:fast-decompression? > + %prefer-fast-decompression?))) Why is ERIS the best here? Fast download speeds, decentralisation, less network I/O, less heat production, more pronouncable than HTTPS? I would add a comment here. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS. 2022-01-29 21:40 ` Maxime Devos @ 2022-02-02 10:38 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:38 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > pukkamustard schreef op di 25-01-2022 om 19:22 [+0000]: >> + (define* (best-uri narinfo #:key (eris? #f)) >> + (if (and eris? (narinfo-eris-urn narinfo)) >> + (values (narinfo-eris-urn narinfo) "zstd" #f) >> + (narinfo-best-uri narinfo #:fast-decompression? >> + %prefer-fast-decompression?))) > > Why is ERIS the best here? Fast download speeds, decentralisation, > less network I/O, less heat production, more pronouncable than HTTPS? > I would add a comment here. Those are all possible reasons. I think we first need to do some experiments to see if any of those claims can be justified. In general, the logic for when to use ERIS transports needs more thought. For one, I think it should be user configurable. I can imagine that certain users do not want to use decentralized substitutes at all. Users should be able to deactivate the entire ERIS thing. For the default, I personally think it would be ok to try and use ERIS. The only thing we absolutely need is a clean fallback logic that transparently falls back to getting the entire NAR by HTTP. Currently such a fallback is not yet implemented. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (4 preceding siblings ...) 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard @ 2022-01-29 21:00 ` Maxime Devos 2022-02-02 9:50 ` pukkamustard 2022-01-29 21:08 ` Maxime Devos ` (2 subsequent siblings) 8 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:00 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 623 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > ** Authorize local substitutes > > We will be running a local substitute server so we need to add the > local > signing key to the list of authorized keys. In the system > configurations: > > #+BEGIN_SRC scheme > (modify-services %base-services > (guix-service-type config => [...])) > #+END_SRC > [...] > ** Start the IPFS daemon > > #+BEGIN_SRC shell > guix shell go-ipfs -- ipfs daemon > #+END_SRC There's an ipfs-service-type nowadays, so starting the daemon manually isn't required (if using Guix System). Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-29 21:00 ` [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS Maxime Devos @ 2022-02-02 9:50 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 9:50 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Hi Maxime, Maxime Devos <maximedevos@telenet.be> writes: > There's an ipfs-service-type nowadays, so starting the daemon manually > isn't required (if using Guix System). Good point. Starting the daemon manually is only necessary if you don't use the service. I don't use the IPFS service. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (5 preceding siblings ...) 2022-01-29 21:00 ` [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS Maxime Devos @ 2022-01-29 21:08 ` Maxime Devos 2022-02-02 9:56 ` pukkamustard 2022-01-29 21:52 ` Maxime Devos 2022-01-30 11:46 ` Maxime Devos 8 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:08 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 677 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > I will be looking into the HTTP fallback and also using BitTorrent and GNUNet > as transports. I have been writing a (Guile) Scheme port of GNUnet's client libraries (https://git.gnunet.org/gnunet-scheme.git/). Currently only NSE is supported, but I'm working on DHT. DHT search/put already works to a degree (see examples/web.scm), but there are plenty of sharp edges (see TODOs about disconnecting, reconnecting and stopping fibers, and see guix.scm for Guile bugs that are patched out and extra guile- fibers features). Tests are being written a edge cases will be addressed. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-29 21:08 ` Maxime Devos @ 2022-02-02 9:56 ` pukkamustard 2022-02-02 11:09 ` Maxime Devos 0 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-02-02 9:56 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: >> I will be looking into the HTTP fallback and also using BitTorrent and GNUNet >> as transports. > > I have been writing a (Guile) Scheme port of GNUnet's client libraries > (https://git.gnunet.org/gnunet-scheme.git/). Currently only NSE is > supported, but I'm working on DHT. DHT search/put already works to a > degree (see examples/web.scm), but there are plenty of sharp edges > (see TODOs about disconnecting, reconnecting and stopping fibers, > and see guix.scm for Guile bugs that are patched out and extra guile- > fibers features). Very interesting! I have been following your work on that a bit. From what I understand gnunet-scheme interacts with the GNUNet services and sends messages to the various GNUNet services. Is that correct? Have you considered implementing the GNUNet protocols themeselves in Guile? I.e. instead of connecting with the GNUNet services and sending messages, implement R5N completely in Guile. IMHO this would be very nice as one could use GNUNet protocols completely in Guile and not rely on the GNUNet C code. I believe this is somewhat the direction being taken with the GNUNet Go implementation (https://github.com/bfix/gnunet-go) and also in line with recent efforts to specify the individual GNUNet components and protocols more independantly of one another (e.g. R5N is specified to work over IP - https://lsd.gnunet.org/lsd0004/). -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 9:56 ` pukkamustard @ 2022-02-02 11:09 ` Maxime Devos 0 siblings, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-02-02 11:09 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 2511 bytes --] pukkamustard schreef op wo 02-02-2022 om 09:56 [+0000]: > Maxime Devos <maximedevos@telenet.be> writes: > > > [[PGP Signed Part:Undecided]] > > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > > > I will be looking into the HTTP fallback and also using BitTorrent and GNUNet > > > as transports. > > > > I have been writing a (Guile) Scheme port of GNUnet's client libraries > > (https://git.gnunet.org/gnunet-scheme.git/). Currently only NSE is > > supported, but I'm working on DHT. DHT search/put already works to a > > degree (see examples/web.scm), but there are plenty of sharp edges > > (see TODOs about disconnecting, reconnecting and stopping fibers, > > and see guix.scm for Guile bugs that are patched out and extra guile- > > fibers features). > > Very interesting! I have been following your work on that a bit. > > From what I understand gnunet-scheme interacts with the GNUNet services > and sends messages to the various GNUNet services. Is that correct? Yes, it works like the C GNUnet client libraries, except it's in Guile Scheme and a few different design decisions were made, e.g. w.r.t. concurrency. > Have you considered implementing the GNUNet protocols themeselves in > Guile? I.e. instead of connecting with the GNUNet services and sending > messages, implement R5N completely in Guile. I didn't, at least not _yet_. As-is, things are already complicated enough and the client code seems a lot simpler than the service code. Though perhaps in the future ... E.g., for testing the DHT service, the test code effectively creates a tiny, limited, in-memory DHT service (not communicating to any peers) that's buggy in some respects (not yet committed, but will be in tests/distributed-hash-table.scm). > IMHO this would be very nice as one could use GNUNet protocols completely > in Guile and not rely on the GNUNet C code. While it's not a priority, I'm not opposed to someday implementing the services in Guile and testing whether they can communicate with C peers. However, keep in mind that GNUnet is supposed to be able to eventually replace the TCP/IP stack, and running the DHT, NSE, NAT, FS, CADET, TRANSPORT ... services in every web browser, in every mail client, in all "guix substitute" and "guix perform-download" processes, etc. is rather wasteful (memory-wise and CPU-wise), so I'd prefer this not to be the _default_ option. (I'm not sure if you were referring to that.) Greetings, Maxme. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (6 preceding siblings ...) 2022-01-29 21:08 ` Maxime Devos @ 2022-01-29 21:52 ` Maxime Devos 2022-02-02 11:10 ` pukkamustard 2022-01-30 11:46 ` Maxime Devos 8 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-29 21:52 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 909 bytes --] Hi, Is it possible for the following situation to happen? If so, why not? 1. server A is authentic 2. server M is malicious, it tries to trick the client into installing an incorrect substitute 3. (key of) server A is authorised 4. (key of) server M is _not_ authorised 5. server A and M are both in substitute-urls 6. server A only serves ‘classical’ substitutes, server B also serves via ERIS+ipfs 7. Both A and M set the same FileHash, References, etc. in the narinfo 8. However, M set an ERIS URN pointing to a backdoored substitute. 9. The client trusts A, and A and B have the same FileHash etc., so the client considers the narinfo of B to be authentic because it has the same FileHash. 10. The client prefers ERIS above HTTP(S), so it downloads via M. 11. The client now installed a backdoored substitute! Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-29 21:52 ` Maxime Devos @ 2022-02-02 11:10 ` pukkamustard 2022-02-03 20:36 ` Maxime Devos 0 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-02-02 11:10 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > Hi, > > Is it possible for the following situation to happen? > If so, why not? > > 1. server A is authentic > 2. server M is malicious, it tries to trick the client into > installing an incorrect substitute > 3. (key of) server A is authorised > 4. (key of) server M is _not_ authorised > 5. server A and M are both in substitute-urls > 6. server A only serves ‘classical’ substitutes, server B also serves > via ERIS+ipfs > 7. Both A and M set the same FileHash, References, etc. in the > narinfo > 8. However, M set an ERIS URN pointing to a backdoored substitute. > 9. The client trusts A, and A and B have the same FileHash etc., > so the client considers the narinfo of B to be authentic > because it has the same FileHash. > 10. The client prefers ERIS above HTTP(S), so it downloads via M. > 11. The client now installed a backdoored substitute! > > Greetings, > Maxime. No this should not work. The ERIS URN is only used if the entire narinfo is signed with a authorized signature. The FileHash is not used when getting substitutes via ERIS (being able to decode ERIS content implies integrity). The interesting case that would be allowed with ERIS is following: 1. Server A is authentic and its key is authorized. 2. Servers M1 to MN are potentially malicious and their keys are not authorized. 3. Server A and servers M1 to MN are in the substitute-urls. 4. Client gets Narinfo from server A and uses the ERIS URN from there. 5. Client can get blocks simultaneously from Server A and servers M1 to MN. 6. Client decodes content with the ERIS URN and can be sure that they have the valid substitute. So client only needs to trust A but can use M1-MN (simultaneously) for fetching the content. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 11:10 ` pukkamustard @ 2022-02-03 20:36 ` Maxime Devos 2022-02-04 10:20 ` pukkamustard 0 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-02-03 20:36 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 1766 bytes --] pukkamustard schreef op wo 02-02-2022 om 11:10 [+0000]: > The ERIS URN is only used if the entire narinfo is signed with a > authorized signature. Perhaps I'm missing something here, but in that case, shouldn't "ERIS" be added to %mandatory-fields in (guix narinfo)? Anyway, I don't see what prevents an unauthorised narinfo with a ERIS URN to be used: the narinfo is chosen with (define narinfo (lookup-narinfo cache-urls store-item (if (%allow-unauthenticated-substitutes?) (const #t) (cut valid-narinfo? <> acl)))) where lookup-narinfo is a tiny wrapper around lookup-narinfos/diverse. lookup-narinfos/diverse considers both unauthorised and authorised narinfos, and can choose an unauthorised narinfo if it's ‘equivalent’ to an authorised narinfo (using equivalent-narinfo?) equivalent-narinfo? only looks at the hash, path, references and size, and ignores the ERIS. As such, an unauthorised narinfo with a malicious ERIS URN could be selected. However, it turns out that all this doesn't really matter: whether the port returned by 'fetch' in (guix scripts substitute) came from file://, http://, https:// or ERIS, the file hash is verified later anyway: ;; Compute the actual nar hash as we read it. ((algorithm expected) (narinfo-hash-algorithm+value narinfo)) ((hashed get-hash) (open-hash-input-port algorithm input))) [...] ;; Check whether we got the data announced in NARINFO. (let ((actual (get-hash))) (if (bytevector=? actual expected) [...] False alarm I guess! Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-03 20:36 ` Maxime Devos @ 2022-02-04 10:20 ` pukkamustard 0 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-02-04 10:20 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > pukkamustard schreef op wo 02-02-2022 om 11:10 [+0000]: >> The ERIS URN is only used if the entire narinfo is signed with a >> authorized signature. > > Perhaps I'm missing something here, but in that case, shouldn't "ERIS" > be added to %mandatory-fields in (guix narinfo)? > > Anyway, I don't see what prevents an unauthorised narinfo with a ERIS > URN to be used: the narinfo is chosen with > > (define narinfo > (lookup-narinfo cache-urls store-item > (if (%allow-unauthenticated-substitutes?) > (const #t) > (cut valid-narinfo? <> acl)))) > > where lookup-narinfo is a tiny wrapper around lookup-narinfos/diverse. > lookup-narinfos/diverse considers both unauthorised and authorised > narinfos, and can choose an unauthorised narinfo if it's ‘equivalent’ > to an authorised narinfo (using equivalent-narinfo?) > > equivalent-narinfo? only looks at the hash, path, references and size, > and ignores the ERIS. As such, an unauthorised narinfo with a > malicious ERIS URN could be selected. You're right. I was not aware that parts of unauthorized narinfos are used when they are deemed equavelent to authorized narinfos with equivalent-narinfo?. > > However, it turns out that all this doesn't really matter: whether the > port returned by 'fetch' in (guix scripts substitute) came from > file://, http://, https:// or ERIS, the file hash is verified later > anyway: > > ;; Compute the actual nar hash as we read it. > ((algorithm expected) > (narinfo-hash-algorithm+value narinfo)) > ((hashed get-hash) > (open-hash-input-port algorithm input))) > > [...] > > ;; Check whether we got the data announced in NARINFO. > (let ((actual (get-hash))) > (if (bytevector=? actual expected) > [...] > > False alarm I guess! Yeah, good that the hash is checked. Still, I think we should not even try downloading a ERIS URN that is not authorized. I think adding a check to equivalent-narinfo? that makes sure that the ERIS URNs are equivalent if present would fix this. wdyt? -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard ` (7 preceding siblings ...) 2022-01-29 21:52 ` Maxime Devos @ 2022-01-30 11:46 ` Maxime Devos 2022-02-02 10:51 ` pukkamustard 8 siblings, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-01-30 11:46 UTC (permalink / raw) To: pukkamustard, 52555; +Cc: ~pukkamustard/eris [-- Attachment #1: Type: text/plain, Size: 3121 bytes --] pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: > I have only tested this for fairly small packages (up to a few MB). > > One issue with IPFS might be that we have to create a new HTTP connection to > the IPFS daemon for every single block (32KiB). The IPFS daemon does not seem > to support HTTP connection re-use According to <https://github.com/ipfs/go-ipfs/issues/3767>, the IPFS daemon supports connection reuse according to some people and doesn't according to other people. > and neither does the Guile (web client). Guix supports connection reuse, see 'call-with-cached-connection' in (guix scripts substitute). > I fear this might become a performance issue. IIUC, the performance problem primarily lies in the round-tripping between the client and the server. If the client and the server are on the same machine, then this round trip time is presumably small compared to, say, localhost contacting ci.guix.gnu.org. Still, connection reuse would be nice. > It seems possible to use IPFS more directly by exposing the Go code as a > C library and then using that with the Guile FFI [1]. This is however a bit > complicated and adds a lot of dependencies. In particular, this should not become > a dependency of Guix itself. The performance of IPFS itself also needs to be > evaluated, maybe the IPFS HTTP API will not be the bottle-neck. Security-wise, libipfs doesn't seem great: libipfs starts the IPFS daemon inside the process and guix/scripts/substitute.scm is run as root. > As mentioned in previous mail a simple HTTP transport for blocks would be a > good fallback. This would allow users to get missing blocks (things that > somehow got dropped from IPFS) directly from a substitute server. [...] Seems a good idea to me -- DHTs can be unreliable. I presume this will be implemented with some kind of timeout: if no block is received within N seconds, fallback to HTTP? Also, don't forget to insert this missing block back into IPFS/GNUnet/BitTorrent/..., otherwise less and less blocks will be available until nothing is available anymore. > In any case, it would be necessary for the substitute server to store encoded > blocks of the NAR. For this I think it makes sense to use a small database. We > have bindings to use ERIS with GDBM [2]. It might also make sense to use > SQLite, especially if there are other use-cases for such a database. Wouldn't this be a huge database? IIRC, according to logs.guix.gnu.org the size of the nars of the substitute servers are somewhere in the 200G-2T range or something like that. To reduce the size of the database, perhaps you could let the database be a mapping from block ids to the name of the nar + the position in the nar, and encode the block on-demand? The database doesn't seem necessary, the substitute server could have some end-point /publish-this-nar-again-into-IPFS/name-of-the-nar which, when contacted, inserts the nar again into IPFS. Then when a block was unavailable, the client contacts this end-point and retries. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-01-30 11:46 ` Maxime Devos @ 2022-02-02 10:51 ` pukkamustard 2022-02-02 11:27 ` Maxime Devos 2022-02-04 16:16 ` Maxime Devos 0 siblings, 2 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 10:51 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: > [[PGP Signed Part:Undecided]] > pukkamustard schreef op di 25-01-2022 om 19:21 [+0000]: >> I have only tested this for fairly small packages (up to a few MB). >> >> One issue with IPFS might be that we have to create a new HTTP connection to >> the IPFS daemon for every single block (32KiB). The IPFS daemon does not seem >> to support HTTP connection re-use > > According to <https://github.com/ipfs/go-ipfs/issues/3767>, the IPFS > daemon supports connection reuse according to some people and doesn't > according to other people. Hm, from what I understand connection re-use is something introduced in HTTP/2 and go-ipfs does not do HTTP/2 (https://github.com/ipfs/go-ipfs/issues/5974). >> and neither does the Guile (web client). > > Guix supports connection reuse, see 'call-with-cached-connection' > in (guix scripts substitute). Ah ok. Cool! >> I fear this might become a performance issue. > > IIUC, the performance problem primarily lies in the round-tripping > between the client and the server. If the client and the server are on > the same machine, then this round trip time is presumably small > compared to, say, localhost contacting ci.guix.gnu.org. > > Still, connection reuse would be nice. Remains to be seen if this is a problem. It is considerably more pronounced than with regular usage of IPFS as we make a HTTP request to IPFS for every 32KiB block instead of for an entire file (what most people do when using the IPFS daemon). >> It seems possible to use IPFS more directly by exposing the Go code as a >> C library and then using that with the Guile FFI [1]. This is however a bit >> complicated and adds a lot of dependencies. In particular, this should not become >> a dependency of Guix itself. The performance of IPFS itself also needs to be >> evaluated, maybe the IPFS HTTP API will not be the bottle-neck. > > Security-wise, libipfs doesn't seem great: libipfs starts the IPFS > daemon inside the process and guix/scripts/substitute.scm is run > as root. I agree. >> As mentioned in previous mail a simple HTTP transport for blocks would be a >> good fallback. This would allow users to get missing blocks (things that >> somehow got dropped from IPFS) directly from a substitute server. [...] > > Seems a good idea to me -- DHTs can be unreliable. I presume this will > be implemented with some kind of timeout: if no block is received > within N seconds, fallback to HTTP? Yes, exactly. > Also, don't forget to insert this missing block back into > IPFS/GNUnet/BitTorrent/..., otherwise less and less blocks will be > available until nothing is available anymore. This might be a bit of a burden for users. As you mention the size of such a database might become considerable. >> In any case, it would be necessary for the substitute server to store encoded >> blocks of the NAR. For this I think it makes sense to use a small database. We >> have bindings to use ERIS with GDBM [2]. It might also make sense to use >> SQLite, especially if there are other use-cases for such a database. > > Wouldn't this be a huge database? IIRC, according to logs.guix.gnu.org > the size of the nars of the substitute servers are somewhere in the > 200G-2T range or something like that. > > To reduce the size of the database, perhaps you could let the database > be a mapping from block ids to the name of the nar + the position in > the nar, and encode the block on-demand? Yes! I've also been thinking of this - a "in-file" block store. I think this makes a lot of sense for Guix but also other things (e.g. sharing your music collection). Another problem with IPFS/GNUNet is that they have their own storage. So even if are clever about storing blocks in Guix, IPFS and GNUNet will have their own copy of the blocks on disk. I think it would be much nicer if DHTs/transport layers don't do block storage but are provided with a callback from where they can get stored blocks. I believe this is what OpenDHT does (https://github.com/savoirfairelinux/opendht/wiki/API-Overview). I think we should propose such a change to the GNUNet R5N specification (https://lsd.gnunet.org/lsd0004/). > The database doesn't seem necessary, the substitute server could have > some end-point > > /publish-this-nar-again-into-IPFS/name-of-the-nar > > which, when contacted, inserts the nar again into IPFS. Then when a > block was unavailable, the client contacts this end-point and retries. But for a HTTP block endpoint we would still need such a database/block storage. I think it is important that we do not rely on IPFS for block storage. The decentralized block distribution should work even if the IPFS daemon is not available. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 10:51 ` pukkamustard @ 2022-02-02 11:27 ` Maxime Devos 2022-02-02 12:42 ` pukkamustard 2022-02-04 16:16 ` Maxime Devos 1 sibling, 1 reply; 65+ messages in thread From: Maxime Devos @ 2022-02-02 11:27 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 1180 bytes --] pukkamustard schreef op wo 02-02-2022 om 10:51 [+0000]: > > The database doesn't seem necessary, the substitute server could > > have > > some end-point > > > > /publish-this-nar-again-into-IPFS/name-of-the-nar > > > > which, when contacted, inserts the nar again into IPFS. Then when > > a > > block was unavailable, the client contacts this end-point and > > retries. > > But for a HTTP block endpoint we would still need such a > database/block > storage. > > I think it is important that we do not rely on IPFS for block > storage. The decentralized block distribution should work even if the > IPFS daemon is not available. Do we need a database at all? E.g., if the client cannot download the data in the range [start, end] because the corresponding block has disappeared, can it not simply download that range from https://ci.guix.gnu.org/nar/[...] (not sure about the URI) using a HTTP range request? (Afterwards, the client should insert the block(s) back into IPFS/GNUnet/whatever, maybe using this proposed ‘in-file block store’ such that other clients (using the same DHT mechanism) can benefit.) Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 11:27 ` Maxime Devos @ 2022-02-02 12:42 ` pukkamustard 2022-02-02 15:07 ` Maxime Devos 2022-02-02 15:27 ` Maxime Devos 0 siblings, 2 replies; 65+ messages in thread From: pukkamustard @ 2022-02-02 12:42 UTC (permalink / raw) To: Maxime Devos; +Cc: ~pukkamustard/eris, 52555 Maxime Devos <maximedevos@telenet.be> writes: >> I think it is important that we do not rely on IPFS for block >> storage. The decentralized block distribution should work even if the >> IPFS daemon is not available. > > Do we need a database at all? > > E.g., if the client cannot download the data in the range [start, end] > because the corresponding block has disappeared, can it not simply > download that range from https://ci.guix.gnu.org/nar/[...] > (not sure about the URI) using a HTTP range request? This does not work as the mapping from block reference to location in NAR can not be known by the client who only holds the ERIS URN. Furthermore, some blocks will be intermediary nodes - they hold references to content blocks (or other intermediary nodes) but not content itself. > (Afterwards, the client should insert the block(s) back into > IPFS/GNUnet/whatever, maybe using this proposed ‘in-file block store’ > such that other clients (using the same DHT mechanism) can benefit.) It might make sense for some clients to make content available to other clients and to go trough the extra effort of putting blocks back into IPFS/GNUNet/whatever. But this should be optional. Maybe we can call such clients "caching peers"? IMO A client should by default only deal with things that are strictly necessary for getting substitutes. The substistute servers (and caching peers) should make sure substitutes are available to clients, whether over IPFS/GNUNet/whatever or plain old HTTP. -pukkamustard ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 12:42 ` pukkamustard @ 2022-02-02 15:07 ` Maxime Devos 2022-02-02 15:27 ` Maxime Devos 1 sibling, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-02-02 15:07 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 1551 bytes --] pukkamustard schreef op wo 02-02-2022 om 12:42 [+0000]: > > (Afterwards, the client should insert the block(s) back into > > IPFS/GNUnet/whatever, maybe using this proposed ‘in-file block > > store’ > > such that other clients (using the same DHT mechanism) can > > benefit.) > > It might make sense for some clients to make content available to > other > clients and to go trough the extra effort of putting blocks back into > IPFS/GNUNet/whatever. But this should be optional. Maybe we can call > such clients "caching peers"? > > IMO A client should by default only deal with things that are > strictly > necessary for getting substitutes. The substistute servers (and > caching > peers) should make sure substitutes are available to clients, whether > over IPFS/GNUNet/whatever or plain old HTTP. If re-inserting missing blocks back into the IPFS/GNUnet/whatever is made optional and is off by default, then almost nobody will enable the ‘caching peer’ option and we will have freeloaders, somewhat defeating the point of GNUnet/whatever. In a classic setting (‘plain old HTTP’), serving and downloading is a separate thing. But in a P2P setting, downloading cannot be separated from uploading -- strictly speaking, a peer might be able to download without uploading (depending on the P2P system), but that's anti- social, not something that should be done by default. However, if re-inserting missing blocks is _on_ by default, then there doesn't seem to be any trouble. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 12:42 ` pukkamustard 2022-02-02 15:07 ` Maxime Devos @ 2022-02-02 15:27 ` Maxime Devos 1 sibling, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-02-02 15:27 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 2345 bytes --] pukkamustard schreef op wo 02-02-2022 om 12:42 [+0000]: > > E.g., if the client cannot download the data in the range [start, > > end] > > because the corresponding block has disappeared, can it not simply > > download that range from https://ci.guix.gnu.org/nar/[...] > > (not sure about the URI) using a HTTP range request? > > This does not work as the mapping from block reference to location in > NAR can not be known by the client who only holds the ERIS > URN. The client not only knows the ERIS URN, it also knows the location of the nar (over classical HTTP) because it's in the narinfo. > Furthermore, some blocks will be intermediary nodes - they hold > references to content blocks (or other intermediary nodes) but not > content itself. If an intermediary node (responsible for, say, bytes 900--10000) is missing, then the bytes 900--10000 could be downloaded via HTTP. Whether the node is close to the top, or close to the bottom, in ERIS' variant of Merkle trees, doesn't matter much. Granted, if the nar is, say, 1 GiB, and the top-level block is missing, then we'll have to download 1 GiB over HTTP, even if most lower blocks exist on IPFS/GNUnet/whatever, which isn't really great. We could also do some combination of the GDBM database and HTTP Content-Range requests: most nodes are leaf nodes (*). Instead of representing all nodes in the database, we could include only (intermediate) nodes responsible for data of size, say, 4MiB. (*) At least, that's the case for binary trees, presumably something similar holds for ERIS. I don't know the specifics for ERIS, but for (balanced) binary trees, not storing the leaf nodes would save about 50% (**), which is a rather nice space saving. (**) This assumes the ‘block size’ is the size for storing two pointers to the children, but in practice the block size would be quite a bit larger, so there would be more space savings? Perhaps we are overthinking things and the GDBM (***) database isn't overly large, or perhaps missing blocks are sufficiently rare such that we could simply download the _entire_ nar from classical HTTP in case of missing blocks ... (***) Guix uses SQlite databases, so I would use SQLite instead of GDBM unless there's a compelling reason to use GDBM instead. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS 2022-02-02 10:51 ` pukkamustard 2022-02-02 11:27 ` Maxime Devos @ 2022-02-04 16:16 ` Maxime Devos 1 sibling, 0 replies; 65+ messages in thread From: Maxime Devos @ 2022-02-04 16:16 UTC (permalink / raw) To: pukkamustard; +Cc: ~pukkamustard/eris, 52555 [-- Attachment #1: Type: text/plain, Size: 653 bytes --] pukkamustard schreef op wo 02-02-2022 om 10:51 [+0000]: > > Also, don't forget to insert this missing block back into > > IPFS/GNUnet/BitTorrent/..., otherwise less and less blocks will be > > available until nothing is available anymore. > > This might be a bit of a burden for users. As you mention the size of > such a database might become considerable. At least in GNUnet, there are quota on the size of the datastore (and presumably, whatever the DHT service uses as database). When it's exceeded, old blocks are removed. So I don't see a burden here, assuming that the quota aren't overly large by default. Greetings, Maxime. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 0/8] Decentralized substitute distribution with ERIS 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard ` (2 preceding siblings ...) 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo pukkamustard ` (8 more replies) 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard 4 siblings, 9 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard Hello Guix, I'm very happy to present a V3 of a proposal towards decentralizing substitute distribution with ERIS. An initial version [1] and a V2 [2] are now almost a years old! The idea is to use ERIS (Encoding for Robust Immutable Storage) [3] to allow more decentralized substitute distribution. ERIS defines an encoding of content into uniformly sized, encrypted and content-addressed blocks (32KiB). The content can be decoded from the blocks given a short identifier called the read capability. It allows a network-optimized form of content-addressing. Blocks can be transported over many different transport protocols, such as HTTP, CoAP, GNUnet, IPFS or a SD card sent via pigeons. Only the read capability must be transmited securely. Given an authentic read capability, the content can be decoded correctly from blocks that might have been transported over unreliable (and untrusted) protocols. For Guix, substitutes (Nar files) are encoded using ERIS and the read capability is added to the signed Narinfos. The read capability published in the Narinfo can then be used to decode the Nar from blocks that are fetched from many peers over many different protocols. This version of the patches allows blocks to be fetched over HTTP and IPFS. A summary of this patch series: - Use the stable version of the ERIS encoding (version 1.0.0) - Add two fields to Narinfos (ERIS and ERISFormat) - Store blocks of published substitutes in a local block store (in `/var/guix/eris`) - Add an endpoint for resolving ERIS blocks over HTTP (a la RFC 2169) - Use ERIS when fetching substitutes - Use IPFS for de-referencing ERIS blocks Testing procedure is a bit tedious, but described in the V2: https://issues.guix.gnu.org/52555#8-lineno16 Please give it a try or a read. Two commits are marked as WIP and have some todos regarding configuration. Suggestions in how to go about Guix wide configuration are very welcome. Some further ideas include: - We've been researching CoAP (RFC 7252) as a transport protocol for blocks. It is lightweight, performant, well-specified and optimized for small implementations, meaning it can be reasonably implemented in pure Guile. This would allow more light-weight peer connections (over UDP) and also discovery of local peers via CoAP service discovery [4] - very similar to how Avahi is currently used. - Publish substitutes to IPFS. Currently substitutes are not published to IPFS. It might make sense to add a CLI command that does this. In a previous verion of the series this was done when a substitute is requested over HTTP. But it seems to make sense to publish on IPFS (or other protocols) independantly of the HTTP endpoints. - Use an optimized format for encoding Nars. Based on some investigation into SquashFS, EROFS and de-duplication of files in substitutes [5], we have an initial proposal of how to encode Nars (and in general file system trees) in ERIS so that common files are de-duplicated: https://codeberg.org/eris/eer/pulls/2. - More transport protocols. Thanks for making it so far! :) I'd be very happy for your thoughs and ideas. There might also be opportunity to discuss these ideas at Guix Days in February. Best regards and a happy new year, pukkamustard [1] https://issues.guix.gnu.org/52555#0 [2] https://issues.guix.gnu.org/52555#8 [3] http://purl.org/eris [4] https://www.rfc-editor.org/rfc/rfc7252#section-7 [5] https://lists.gnu.org/archive/html/guix-devel/2020-12/msg00328.html pukkamustard (8): publish: Add ERIS URN to narinfo. publish: Store ERIS encoded blocks to a local block store. publish: Add HTTP endpoint for resolving ERIS blocks. WIP: substitute: Fetch substitutes using ERIS. eris/http: Add HTTP block de-referencer. WIP: eris: Use HTTP to get ERIS blocks. eris: Use parameterized %eris-peers when getting blocks. eris: Use IPFS to get ERIS blocks. Makefile.am | 4 + configure.ac | 5 + gnu/packages/package-management.scm | 1 + guix/eris.scm | 95 ++++++++++++ guix/eris/fs-store.scm | 66 +++++++++ guix/eris/http.scm | 82 +++++++++++ guix/eris/ipfs.scm | 214 ++++++++++++++++++++++++++++ guix/narinfo.scm | 16 ++- guix/scripts/publish.scm | 55 ++++++- guix/scripts/substitute.scm | 44 ++++-- 10 files changed, 563 insertions(+), 19 deletions(-) create mode 100644 guix/eris.scm create mode 100644 guix/eris/fs-store.scm create mode 100644 guix/eris/http.scm create mode 100644 guix/eris/ipfs.scm base-commit: c37b6fba1af0d823bd18c753484459b40fc8c041 prerequisite-patch-id: 38bf058b6e298a205d7c9bc19f6358ee3cd5257b prerequisite-patch-id: b2bb0971706132f1f02d99a9a7504fb195d6a74a prerequisite-patch-id: 60537c1eb34acc412769470c7ee90043bde600f9 prerequisite-patch-id: 71cb6edb430a0b8371b4c06d171b51e781bfe348 prerequisite-patch-id: 38a019a8380ac8dfb77bfb6304159ce8ca6d32dd prerequisite-patch-id: a53a66ddac48c405f30debc74b267de5895394c9 prerequisite-patch-id: 165aa2669327788a9e51436b8000643da742b16e prerequisite-patch-id: 2812cebf583538f6bdd2acccd6e0825ceca7ba25 prerequisite-patch-id: 0d04d66369e86604a7bbd59c28cafe3ee3bd7730 prerequisite-patch-id: ccb6e14312ab11227f5547d17cd7c5df2341238a prerequisite-patch-id: 0b7662f5b8b11edd52fd902d8e70827a6661323c prerequisite-patch-id: 26ee9dc07a521052655c3bdaf849febaf0464e50 prerequisite-patch-id: 8b2b3209e7f0053d75b52c2475a76feed2114de2 prerequisite-patch-id: 2fdb157131a90a1542357acaf17cb34db4ca7f9b prerequisite-patch-id: 1ddca41aca5544ab9fa3fa868271976293db1518 prerequisite-patch-id: 04eb88d682cb51708eba1dcd5e20e7b468daf1ce prerequisite-patch-id: 531d5e5039f76948cdf3fc21ccd9dc61fd9682f0 prerequisite-patch-id: 17a795a4022a0c80b2df3f362fa965ad65f42191 prerequisite-patch-id: 4216fc57a30c8c1d3db94a48aae78b73d9a2c77e prerequisite-patch-id: 305b8cf69729cb3d6167bb60189e6a9e1d228fd8 prerequisite-patch-id: 60de21549abd45931b5ecad335acb88a5369696c prerequisite-patch-id: 27c2475ac075bd74804106bbfab927cc168333a4 prerequisite-patch-id: 5f8bd6b339c6fc14deba1929a5cd934e3a8bbb68 prerequisite-patch-id: 93ad6954d493f65bf032525c09996de41c51de1d prerequisite-patch-id: 6195fafe0e46bf1b6ae15f08a1d1fa3c98b89cab prerequisite-patch-id: ee11d213a4ee466dff6379eeaeea292b6ba93fb0 prerequisite-patch-id: 857e9a0f3d1bc9ad5584c44bc767683a53e44972 prerequisite-patch-id: b87a0615ac48fe8950281f797cd2d096a98f4a2c prerequisite-patch-id: c554e46d5d315cd349df21ba153ef6ed580f0b3c prerequisite-patch-id: 232075806f66963ae7aa260cb6fd3e537f30f1e4 prerequisite-patch-id: 4c5479903595202ac84dcd5978c7c58f542110a4 prerequisite-patch-id: 9e68c0bacd9228f62607d52285f587988a49a6c6 prerequisite-patch-id: b6bcee4d778d2cbf9bcd3d55bb39a65fa5659a61 prerequisite-patch-id: d6702e7370f001971201f5f751719f888b1b9354 prerequisite-patch-id: ead326db75ec4a111dd64f56c985853319a3d55c prerequisite-patch-id: 2633f1445ab40e07536b7c0d0c7df2ca8699bc57 prerequisite-patch-id: 05955431fa785aabe4c11545fdbce46aff5c3deb prerequisite-patch-id: 4b212323a81b84bebacdeab2bda9f3efff768542 prerequisite-patch-id: 38106d6e8e5c6bcabed45f2a469ba2609ef8a904 prerequisite-patch-id: 482714ab5f307400a641012270afe5e6a392245c prerequisite-patch-id: 70739c3de04e8d66181af4850973a778de614385 prerequisite-patch-id: 464301961e7060a9d80879881114b76df3314d5c prerequisite-patch-id: 9096c39f5006697843fc26c1e32735f5bbc65da8 prerequisite-patch-id: 240bac4d775f14296009b6e8f41dc7fee540724a prerequisite-patch-id: 797bca2dd99a05e6886436a3eadf09037c19f174 prerequisite-patch-id: 0f37a06624e40cc1ea41c9f9dcc4097e98f0bc38 prerequisite-patch-id: e238c0b3d0889467b98693cd01db27331d1dad1b prerequisite-patch-id: 8fdcafd9def3b02af3a8df411ea6b2372b8ac0fb prerequisite-patch-id: 470061e10a39b26c52d53cce5c65a2295feefbd2 prerequisite-patch-id: 6aa5474a3378080a6536d46a3616833df711e65c prerequisite-patch-id: c8247c4fb50de660e145ff4b1bdb586d23cc9c59 prerequisite-patch-id: 7fdbe491552bcc0b718f3d82418a49bc3b225f79 prerequisite-patch-id: 1f26481841f7d528c236a07c988c6410f4b1ec1e prerequisite-patch-id: 9a4c598e9efeedce6f577cba794a5f3f6762c0c0 prerequisite-patch-id: cc12fbcd08457f67b9f0a947088fe69d4b593e5c prerequisite-patch-id: 736edff89d49035031cbd647fa99ed57e6e4f71e prerequisite-patch-id: d6e0c13f594235607d36a8d7cdf7390e4530dfdf prerequisite-patch-id: edbcbb20b76e5c64eb0d9c3971101c7e67aed63f prerequisite-patch-id: 6381b67d4b369d5f6ab111446e5082f179c906c8 prerequisite-patch-id: 7744b2dd228f3963c73acbf4dad19884ca4ab819 prerequisite-patch-id: 77fd89d1fcc9cb2d08c72f13c76c1c1b5bf09f0d prerequisite-patch-id: 5721541afe5a74e0cab98717a0b684f24dfb0bd9 prerequisite-patch-id: 16c506e2b7929ed0f63484be8af3e46d83b7e9c1 prerequisite-patch-id: 8a2c2e203e13fdb52cd2249e9e966ad89834f468 prerequisite-patch-id: 134efcd91e8eddb574dd7ca84fbf97c7dc55dab3 prerequisite-patch-id: 0b80209b680bc0da99f29a088b63ad529390475f prerequisite-patch-id: c206070aeaea4969fb718a1eab2a672eb6887be3 prerequisite-patch-id: 06e9164d837f5fe0fed7f53a6520eb119ad9c07d prerequisite-patch-id: c5cd707027c858c8c1360fca569036fd0e98d7c8 prerequisite-patch-id: 561ffda841ebf652dd4f0d6e59dffcc5b26aed3f prerequisite-patch-id: f96dc76e70647bd2e4097b36fae74ecd2b4ef706 prerequisite-patch-id: a31940d97c85bb1126e4d5e613f73a0d4e6e3ce3 prerequisite-patch-id: 204940d7d89e985068e5ab6cbd0c9753d5e6cbb6 prerequisite-patch-id: b9a0811fa8aa30c6bb67b3e6d76e2e0d73e5e300 prerequisite-patch-id: 3b683f608d01c23bcde0c179cfdc8f83ba430f9d prerequisite-patch-id: 9c7ad92ccae90d137e22c6f5dd2df6ba5006b10a prerequisite-patch-id: 07256b1e50c1a9ffcad34724bd2a0e9c8fc2dec1 prerequisite-patch-id: e48b0932283f2e81e5226b1e9eaeff4d25200aa9 prerequisite-patch-id: bf53daf969eddd302c084b2f77c707005fd6226a prerequisite-patch-id: 3aaeaf0c560dd750c0000f9871b461c348060fb8 prerequisite-patch-id: fb09c518a1e1eab86bd0e3dc9337d01abfb3aede prerequisite-patch-id: a6d38e15437ed0e19ca8de6d7ea8bec9f403a347 prerequisite-patch-id: 0582bad0ad1f76d7f3bb32ff9e1b986708fe92ab prerequisite-patch-id: 8c93bd940ae761f1ee27b3514c751a6b67fe648c prerequisite-patch-id: 547a83c461648121d964e0d677271ffae513ded0 prerequisite-patch-id: 93f020e5ace6a0034683807ab1acbaacd14c6c49 prerequisite-patch-id: 8d871c380f84927be637e51dbd79298030a26211 prerequisite-patch-id: bf4084d999bb48633f9b313fd5c1611a7f6880e0 prerequisite-patch-id: 5e105f911cecdb68d91b3b0e698351366af8c0ea prerequisite-patch-id: 428685a07eca306ff9b7804835d92a414651182c prerequisite-patch-id: 0bc436f66c4256680592ec5e11c3bca9e6735430 prerequisite-patch-id: 129c52d7ee4eba0666bcd088c85292a2230e714f prerequisite-patch-id: f42112e78fb5483035525aff61cc06a7dfd16e92 prerequisite-patch-id: 5dee96fef77d3ad04e7b8fb96f7f75d6d02cd287 prerequisite-patch-id: d36b9670d2734ece43529aa7b502eb5d142cd6b9 prerequisite-patch-id: e6cc80f307552a886e39113007dc62b326f32adf prerequisite-patch-id: ef3fa2f68f986c7ec54e9eca0446e30ee72c847e prerequisite-patch-id: 4e9255e48ae5452b35e058f149e77745c04fc436 prerequisite-patch-id: 1054691ce867cd6085bde390306e8df1cdc61e48 prerequisite-patch-id: f544cb093aaa2aa36783b05ea1c09fae389bf6bf prerequisite-patch-id: a0002a2545cbc48285dbea6f636cca51c7886560 prerequisite-patch-id: dfe2ed731d951b076a5896df61e08c604d1d9efb prerequisite-patch-id: 177b76db09d5e96ff0191e54d62f969c62239d43 prerequisite-patch-id: 392ee4da803f87deb0175842281dc404d65a2ee4 prerequisite-patch-id: a1a7038d4d35ed6b6352d2300c9c4fe8cd7d4c3e prerequisite-patch-id: e63d8db9db9124fb8ad50c384f7468980ba25b47 prerequisite-patch-id: 878f0ef3ffaabbc15d2ee4ee0564347f82926a8d prerequisite-patch-id: e8f134c6370d435f1716cfe9647d965ae7a4b1a9 prerequisite-patch-id: 7470f65f04ba4451f50e6c5f18ec14b51a858d01 prerequisite-patch-id: 20a28e6b1d370ba73029f263f6fa9e9a8d1160c1 prerequisite-patch-id: 16ccc436c7c92fb9e41dd9634d211576e4190337 prerequisite-patch-id: be1b5a39649b32ab1361c95d1b4736cf0074179d prerequisite-patch-id: 6ebca863c5453ecd1b9023646a229215ebd13452 prerequisite-patch-id: c6a0cd51aa6890d7ba6abbc6f08519a946ecbb0e prerequisite-patch-id: 1cbcafd9adf73b1664bf416a983b64781ccb3de1 prerequisite-patch-id: 5beac63517a1c0b8361e48cdb76031353571f899 prerequisite-patch-id: a28e0e677e8e70bde296b9eaad861da05f3a7572 prerequisite-patch-id: dbb7feae5390a6aec98ab0618a477983d217882f prerequisite-patch-id: faba2d31c61942f6f3ded0d4f6ed20ff52ebe865 prerequisite-patch-id: e9c4b4b08a2f4e9bfa08fba2c96f5acb2ff1361c prerequisite-patch-id: f95e278262ce40c3c304c3b0b97cdac02ab6cdc1 prerequisite-patch-id: 015cece7899c9b8af24dd542ceca65dafa2e6d4b prerequisite-patch-id: d57c54b60fd3fd151e7c3318df13cf2901c042a8 prerequisite-patch-id: 9a48f08769b01f60fa369881c0e1c0f4f5a62601 prerequisite-patch-id: 45d3527827fb17fb8946943ebe29fe61285ff8fc prerequisite-patch-id: a78104964358350ebb7ba4071d51b857a563b389 prerequisite-patch-id: 4c1247c66fa368185d6c5f1b91136cace31d2996 prerequisite-patch-id: ee23d06d8d676221dedefd0beeace4b2249f6203 prerequisite-patch-id: 76f871743dd063789d1ba543131205072da2e514 prerequisite-patch-id: 9f83e1a4b61a58e28055e02a3ea5f0d936c4a272 prerequisite-patch-id: 26a603cc8e14ff53e47cd23b88f380129b84a687 prerequisite-patch-id: 6f2ad843478baf980135f9f0996d0dbdfb2fe260 prerequisite-patch-id: db2c8aae4743505ad5a36fd6586e651206406a58 prerequisite-patch-id: 217b648e20131c63182a317e8aa963c3440e9956 prerequisite-patch-id: 02a38f9e6b58d115e7b1310933e72a6a718c8002 prerequisite-patch-id: 8bbedde3db4944f76e546a085dfc53937e733b0a prerequisite-patch-id: 27cd4a8b3b7daa02fa2aa549ed2c584ac58b118d prerequisite-patch-id: 6796a96b4cc332e170c9893515351a133bf3cbd9 prerequisite-patch-id: 028b42964bbcdb390f77c3fec97db30f42b29478 prerequisite-patch-id: c5d78227865719237dcb0356811008a5fa8c8a04 prerequisite-patch-id: 12e290b368ffbf85afcdbc66b5eeba744d015814 prerequisite-patch-id: d2a58d75b6c38a03da5a74c67195f6ed17840d29 prerequisite-patch-id: 4814320bf2499370e3ea6fb3bb6899239c3ae6ee prerequisite-patch-id: 956a1c74c9772838f4b1a46baa99375bc594e51b prerequisite-patch-id: b667030ab4aef0d15c68aac6ca1de8b9fef4eb19 prerequisite-patch-id: 9f9f39201b649d16cbe75da5e073fd5a9d12f97e prerequisite-patch-id: f669c71c4852e5ee6d46a20c3f3386f19df5d07a prerequisite-patch-id: 8122fd0b90e20029a339833b1a055da7dedfa21a prerequisite-patch-id: 94584e23cc9f1e37bbc3c54ac950d1ea76f5e900 prerequisite-patch-id: 184fcb20369b70452f1b9dbb9973f8870b2595ce prerequisite-patch-id: 6499fe37c121b9843b6d1988cfb1f11ef1193939 prerequisite-patch-id: 83407b3f6fb4d24f9947cdbcef079744bab36da8 prerequisite-patch-id: ba131ace8fbc158e1ab7b5c1854eb80fafb8cefe prerequisite-patch-id: 9706095b8330b04e91cbc43064cc3e769807840e prerequisite-patch-id: 2e8d8005aca3e5d66768cf667d1261762609c61f prerequisite-patch-id: 95747be36e38ae854fd4fd65f23194c2ec60eb87 prerequisite-patch-id: d389d08e983165dfb1fef9e7cbe38481efd29ccf prerequisite-patch-id: 66a0804e05983681af77fb26a0ce409ce050b733 prerequisite-patch-id: 82caea0441d0954e3e159de8708e24ca83514c1e prerequisite-patch-id: a966347d564354f512f71a875be7bd9d610fb4e6 prerequisite-patch-id: bd318b9b11b1e4568986bba81063269db42fcd4e prerequisite-patch-id: ec228f3dfab23d4d166023d327f0efe271fa20f1 prerequisite-patch-id: 33d563137eaea059421d7c800a92296a8b670ee6 prerequisite-patch-id: 597038c4efb635d3afa6882f7b380816639926dc prerequisite-patch-id: e50ae62c7af2f3c014bbd424f9dc6a916abfbb8e prerequisite-patch-id: c229274d1cd5f8ed8b7429560ce4cd7ad788af65 prerequisite-patch-id: 263f50ff048ac6964c4af48104123f0a6f55cb95 prerequisite-patch-id: a514d6fa23dd6a2e4001d89715342155849e0dfc prerequisite-patch-id: 325a0dfe5940ee861ad1729a305ba3d13d61bb85 prerequisite-patch-id: 2b0f90f5f5ad85b7fab1ee2340b6fa88255800b3 prerequisite-patch-id: 23d1e2410c7f933f6b2f467378c11e7d66c7a653 prerequisite-patch-id: de4ea7504ff38ab882b4e5e3087116246d91465a prerequisite-patch-id: 42d09d8fca07831b7eb57909e11a5f47c1dcad9d prerequisite-patch-id: 839d672c34031518dc716a7d5b2f36c174c1a19d prerequisite-patch-id: ac6cb5491164b907cd0b4802a06568d2a8671017 prerequisite-patch-id: 9da135c032972d11f7682f3c5e3f695741ea8fbd prerequisite-patch-id: ef7989acb42b3da2c340634ee07895770d26b88e prerequisite-patch-id: 221b01cd4f38453080f721f4f07e0fb5e1108ab9 prerequisite-patch-id: 93c27c637a45114ee87fbe02beec8475da9e3592 prerequisite-patch-id: 16a07eb39ffcb7fecc9de389fbce66455bd8815e prerequisite-patch-id: b05d09d133e8131d600fe9c087703327633372aa prerequisite-patch-id: 649e822307b5adb031dad10dc38739155bf5ae27 prerequisite-patch-id: 0c87eb233edb1362d249f4828486d1526e33afa3 prerequisite-patch-id: 2b62e27c777741fcc8c28f61ea9cd48fb99e894f prerequisite-patch-id: 063f7ffd5ff936f8493205d5aefea1421d52a8ca prerequisite-patch-id: 622cbebc7a82fb9789506c31329d9c9f4fbabe95 prerequisite-patch-id: 7bef9850ce8d1cd904a32f18c2202a8c8319091b prerequisite-patch-id: 3b454a5ddafb74a01e56515d3c22da496d2a1626 prerequisite-patch-id: 6269a9d9e5e76fbc034aa68dafd8e159912bbb2b prerequisite-patch-id: 77e4d852c6ff934e64cfc67e9ae350e26a83008a prerequisite-patch-id: 0d682ba3d1fd449326b1fb78b8a2f26f4cc695e1 prerequisite-patch-id: 4a02b8ff27880d5e182b5b0a62949f1861f7b396 prerequisite-patch-id: 2a0cc98bcf98efae96bc66f6d008ffdb85242952 prerequisite-patch-id: 5a62132a7f9889af3c45030163cf0ca5e96e24e9 prerequisite-patch-id: f63e64247a3106ce799c326608dc92e7a625bc84 prerequisite-patch-id: 320967154285a6b2bee8fe8a5687a84712f2cff9 prerequisite-patch-id: dee3e1bb39bb08e09bfa27f86cbe042e23f10d04 prerequisite-patch-id: 340e81de5468a8af063674aeae405b184315e886 prerequisite-patch-id: 8cf7228cca56823149287eb677441f2b831d7127 prerequisite-patch-id: ff8fa83584b7025c9d55880e81be8e612e5190ed prerequisite-patch-id: 3338fcba95ed51c00ffbf601093428915f89ecb4 prerequisite-patch-id: b735a0ba361b3dc3dbe366649535887901518f85 prerequisite-patch-id: 46d3971d3bfbc67438ffce11be263981ae9b4621 prerequisite-patch-id: cba3717d29ab9acfef78f7e70269d8deffc2b91b prerequisite-patch-id: 238d14ef175c0368e0c16f1d2ef9a5ec2d24efca prerequisite-patch-id: 1d51aa1c1e3a82251d203de985be62a0b9402752 prerequisite-patch-id: d9dc5987e2ce1d8d3d45227ba89cc1bb688fd312 prerequisite-patch-id: be97255da5e7c9f3bc824785fcd7d58863ed821b prerequisite-patch-id: 9d47fce0cc920022068265c72b9d72f02c8f75c3 prerequisite-patch-id: 0159d32f88bfd90eb4ff1eec43640c2c5482a4f9 prerequisite-patch-id: 2500f00e09cde491099d34567ca7e356d96a0b64 prerequisite-patch-id: 167fba505b6a0791ba4eea4de37ab8509c5f53b3 prerequisite-patch-id: 3e9769087da4ee6b1557eb5e1cbc3e8527520701 prerequisite-patch-id: aedc29d90774552741df4ff3c77a234397246f2c prerequisite-patch-id: 40f53217c453e002092469a32b43d317d77848d6 prerequisite-patch-id: a7c13980dbc2933e77706296a18a607e02aaf39b prerequisite-patch-id: 652ffa323a151f3d116b02b5b342cba239cd88ac prerequisite-patch-id: db6a4954d8ca87b0f7437e4c35c20be142f49bd7 prerequisite-patch-id: 5e4d4bf7ffcbc391bd8e473e347d2ad4ce70dec9 prerequisite-patch-id: be894f7c7db836724d92ff46d1cf7772899f99a0 prerequisite-patch-id: 7f8f6c49ef0e526c4920744a61132f798dcabc41 prerequisite-patch-id: db4b76df1c799482628afca46efef0fa687c546a prerequisite-patch-id: 9a2d794ab564ad0cd7aad5c8551fc2ffae9e5db4 prerequisite-patch-id: 017c8c510a7e683119f8f720c9c13a111b9de9a5 prerequisite-patch-id: b5dd7d30ca7d567e6877e0f6ae6b942abcafbf4b prerequisite-patch-id: a9a37c8beaebab4207cab2447b30e2b559d76e49 prerequisite-patch-id: 7a11e631dd100776319d05bc31d5dca4c90b686d prerequisite-patch-id: 4c84745aee8ba2835a8b425ca090e3ec1ad7205c prerequisite-patch-id: eace61f02ecbb0b5802b342f34ca5a331421edfe prerequisite-patch-id: 955131799e4b4b8fc5e06de951875c61c8e06883 prerequisite-patch-id: c0255702fd789d06f0f0096c949dca551956df16 prerequisite-patch-id: 03d030fdb65c756f6870a639a2f19d9b2bd7884b prerequisite-patch-id: 44686e39403fd7624d1b023f80170123c6cc6aa5 prerequisite-patch-id: b6c23623df08ac834bc1b5f172eede03543822a2 prerequisite-patch-id: c4a56f193a7df3b4da4057fc3376411363403f24 prerequisite-patch-id: 26a2355cd6f9d9fcb120c97b07fce4c7b41f4658 prerequisite-patch-id: f2c32e18e50c3dc1c41cb17173b8633d049f66da prerequisite-patch-id: 7c0686a24cd8dcc8431dd5922d76dad9bcb2788a prerequisite-patch-id: d134f3f1cf36457db602408790e279b102362dc4 prerequisite-patch-id: 26c9dece660b70ba3e94777ae7d19fed45b92598 prerequisite-patch-id: 280d663967cec1636f23762b571c3074ec4794cd prerequisite-patch-id: 3cddb89b1377cc136ef31818cba906f6f2059151 prerequisite-patch-id: 9f8baac223117475cff67cc5c94e3fc5a298c54e prerequisite-patch-id: 65f356957cedcb6ff5cd4c1fbe664b9eaeaf63bd prerequisite-patch-id: 72b256c50e1dd0f4309f0dfa382d2766516e9037 prerequisite-patch-id: a4aaf55e2a07d5facb5de78b4f9a934432f52751 prerequisite-patch-id: 0f875e80b2ff5ac51ef30d6f320fea01f3a0342f prerequisite-patch-id: c9577738146f388d7078cf3fd2e07d614a31e352 prerequisite-patch-id: f8122a0615164fe98481936d4b56914ca8381168 prerequisite-patch-id: cf2ad82da6f03a7f44d2af4872682e3921ebc001 prerequisite-patch-id: 081051e8d64c0a14a6850b402c3f70cf8d373f1e prerequisite-patch-id: 29a190649a1d1c02a7540dd794ef2a67f5888ae1 prerequisite-patch-id: cb099924ad6d71149afd7c9ff930b6a1dc5227b9 prerequisite-patch-id: d16cc8168d7b218505bb1778c65665594bbc24a6 prerequisite-patch-id: ae8cd0c468a717ff64828f22f7871038d28a3a72 prerequisite-patch-id: 3dd0fb6656b31cfa9aafc90cbb4dca9ca38de2bf prerequisite-patch-id: cd4622749ac7c291b90f5b759caeaf040937c2e3 prerequisite-patch-id: 2e34b98c819db20cac1315281150f9fafba2c5bd prerequisite-patch-id: 1d6033ab877e6f9875862ce5691e2db46159c05e prerequisite-patch-id: ae4fea1269d2aa704cdedf5fc41203d6401ee6d8 prerequisite-patch-id: 5189a544246c0a7576e957eade7193f26c8abd21 prerequisite-patch-id: 1248daa91efeb84c4e8f9cb4502d1bd6c5d98638 prerequisite-patch-id: 76a061d0732521408b135589ece85f0af3930aa7 prerequisite-patch-id: 17df94eba75fb269796ce53f975f714aeb5ec0b2 prerequisite-patch-id: 149514b25d4bd5c658bd5f73796a6ff48f016ce1 prerequisite-patch-id: 1bd538ff9b2e0001713793e03514ff9b74938c91 prerequisite-patch-id: 7f5ff5a7ad82ce766c7bc78da2f162515e44a30a prerequisite-patch-id: fc5bfc31ea1f4a94749e7abdaafe0ac6f294f39b prerequisite-patch-id: 00392c4b58a6ba92c2f995956177d7942ae1826f prerequisite-patch-id: f6983cfffe419757fccc1d03cef7765cefbcf822 prerequisite-patch-id: 995a2283d537bcd39c5db16457466ac59a27e45f prerequisite-patch-id: 81e964ce6293751d35382d0a21cc0082b5bc2f01 prerequisite-patch-id: ce3693f3da2ade089b4c18af7ed678c6517add8a prerequisite-patch-id: 0eb3ad2b01fbeef797836b507268f9d088ca7fcc prerequisite-patch-id: a1604a852cb160bf56b7a0701e07a8daf50f84fc prerequisite-patch-id: 96a55663dcb22456934a9cbbb764c3c3e8294dbb prerequisite-patch-id: 3e8348e14cd45fc8138b1319a56681413207ef4a prerequisite-patch-id: cd659ddc184b6d1ff17c2248d107d35b1064ae3f prerequisite-patch-id: 6f2f7967c53263d2679e381ca8fabb685d31fe0a prerequisite-patch-id: 07b45046a3f640ceb1000d786898def3cc94fe55 prerequisite-patch-id: 566da96e52c2719d91177e8da4e4a555ee60bd51 prerequisite-patch-id: b9102da8df60fbcfec3317cfe06562d5bded6d66 prerequisite-patch-id: 992998f8db8b3085ef90e4f615c267098b93a013 prerequisite-patch-id: 89327f32f753dd03830491459c1b7f519e99612d prerequisite-patch-id: 09ddc20bafa1011961d69decbd77219e548e8fb4 prerequisite-patch-id: 59d17ab140353d49aa11ecb00bbf142964e25f66 prerequisite-patch-id: eacab97f6fc7b620f96109d0428685abf8ab7194 prerequisite-patch-id: 6e4355d9aca92ea4cdece1ac7fc1dbb1f460ddea prerequisite-patch-id: cf93770547767ef32c547bdbc933f61d6830e765 prerequisite-patch-id: 07cb8f6e969caf58f2ca50b0925f16fc4629b94b prerequisite-patch-id: 5a4a1ca2796ed47618333ceadb922edb66749c7f prerequisite-patch-id: cb175d8ac0908cbf0b49811c1b4234b23d5a1f26 prerequisite-patch-id: d71d07fc9a06712cfb213fe1f7109745584d3ef6 prerequisite-patch-id: 5ab1f8c0d402adde3636fc62aa733e8875a09b1d prerequisite-patch-id: 592df70227053ea9ff4ee444517e8475288d4cc0 prerequisite-patch-id: 2237783d2e7b4688d58e4504a19456f602403f78 prerequisite-patch-id: c28681beca24880498ecad6f7fc5d34f38695c15 prerequisite-patch-id: 6953e19b4fc263766928e331837786d3f2001f02 prerequisite-patch-id: 1293070127758fcc311a0afb8290073bf55a999b prerequisite-patch-id: 3bc0acb24d050ad7a55d385db5e5ca9c0d29a4e6 prerequisite-patch-id: 0571116f706ac123e9514e8d879679447f1091a7 prerequisite-patch-id: fcc337918b527feeb28fe6528da10ca7239f15c2 prerequisite-patch-id: 742e6a2e5c86127438f2d633609f9d71ba93c432 prerequisite-patch-id: 2ad910ffd48e30d3c68fd0efd52b07fcee342655 prerequisite-patch-id: 5cd583bfcf37140cc8a8604fd4eb3206ae38cc6e prerequisite-patch-id: 3e69b58d41855064b7e20e45c9726e3df4cbb615 prerequisite-patch-id: 2be8fea7e58cd27e585de88b13212831b1ff40e3 prerequisite-patch-id: 4ad3d07e93f2c8543562c4f3ded3857b437f59a7 prerequisite-patch-id: 25f997fc72d02f28f1c68211a8f8546414459610 prerequisite-patch-id: 315f6eddf4838269a44bcd65a0a78380a51082e5 prerequisite-patch-id: ce41b476f0d36eead751c847c4ca2d015278f5a3 prerequisite-patch-id: fb1c53305e6d118084eb78bba0d2b638fb47a269 prerequisite-patch-id: ecdd2f8fc4e8071ccbf2b0a5f1d25c51e77fe32f prerequisite-patch-id: 1175b26ecd6a68d04feccfd04821c61124204f05 prerequisite-patch-id: fc31de609b7baa6592e9736395bbf79f165b3274 prerequisite-patch-id: 0fda1a6ac6c5b374b1d277fbbaa5db6ded007456 prerequisite-patch-id: ba7ac56032aa706e217508fb8901f7fd5c78ddbd prerequisite-patch-id: 18161493758ae7a4e98afd73eb2bc9141f5399a2 prerequisite-patch-id: 357d54440df78a1cade4f341708d1e740a6c2a79 prerequisite-patch-id: 26c60974313193d3f117d7d5c418f5ce406a57d0 prerequisite-patch-id: ef4134d5ad2aba0707c3af49bdd9a0bb358fb7f5 prerequisite-patch-id: 4b89ddf443c6032bf25f0a1056dc48cec97ac2ad prerequisite-patch-id: 955da5e10c0af2f4eb76d40b0f360ac855fd454b prerequisite-patch-id: 412a040abc1deb54ceffe342b3aef8ca39c9279b prerequisite-patch-id: 2e2b6e68c4d658c196ee1fa91632ac9b7321cc55 prerequisite-patch-id: 7c3fc3af9e4aea6d9dea805cce57851e3afca3f5 prerequisite-patch-id: 1acaf55ad38b8e356423788dce0321c053ab93a7 prerequisite-patch-id: dbc5ad9060c126c2d226386b2b1bb226c8195053 prerequisite-patch-id: dc83f26f3c33e3c760d1539c0f5a266a770d0faa prerequisite-patch-id: f24a49d06e0186f47607b1f523deaef3802120c6 prerequisite-patch-id: 036c7d55362de5df9a25ac890f6aae21a7a60eb3 prerequisite-patch-id: 38ee47c07a58245669c5ed5d9b6dc3cb42cbaf15 prerequisite-patch-id: 4ba1a60d22011b727ba86dd644070b92ebabdb3c prerequisite-patch-id: 6da054750840adca0f42fb84e91d3765cecbf201 prerequisite-patch-id: ab6227a469e6621c2ffd059e3c685914f73e0ec3 prerequisite-patch-id: 8a9963e54e2e263f2654bcc6b818f288ac6a6c22 prerequisite-patch-id: 40f041fea033efe1ad8631c92f915ec3af38d81c prerequisite-patch-id: 65569e3533f8f7e6a2d1a06fd19a30c8d9c05a17 prerequisite-patch-id: b7c1797c4d63d249a7b5469b5205e3a7237aae2b prerequisite-patch-id: 18e622fafdcef1f15d3bdd8421fa1b622a44d885 prerequisite-patch-id: 26a742e6067b1301a2242ab648b9fccca53d7179 prerequisite-patch-id: 16794c5e7fef9b8622d7ff3626dcf41394c1706f prerequisite-patch-id: 022b0eedf92feea278473cafa7927ed15daf87b1 prerequisite-patch-id: 1ff15aaf3626b8d3fb42d1b00fac46d4915045c4 prerequisite-patch-id: 4db3e227d4a1810a60df343ae4e0e214ed81110a prerequisite-patch-id: 57c4d722f5efcafa4c19cdaa719bff04bc76bd9e prerequisite-patch-id: 15913e7f57d79bb4537daee3fe0610e7a75eb3b4 prerequisite-patch-id: fda93bcc1fdb00e8171168fa43665b70c7b9289c prerequisite-patch-id: ba07e166d62fb89cc0f8693278959df4ad7c4ec0 prerequisite-patch-id: 14224d59864bcc8164ebf8f02c3e7ce428e58cbd prerequisite-patch-id: 9fd9e9d0161ad040a5382c7b3776d2031050b83e prerequisite-patch-id: bf42460296d9fc22891ea1f8d1c4a60c4ca614b9 prerequisite-patch-id: e2fee85ea0c8459fa1788bd1eff70655e88c4801 prerequisite-patch-id: 0714fffd5041115174a8ccde7f26221086be0ee1 prerequisite-patch-id: 46b9b5c2733ec5874dd2438fa59af223632376e6 prerequisite-patch-id: 4dcd6c7c5cb9e3ad0d96a25881cbe70a77e97194 prerequisite-patch-id: 4cd6875619a6a32a5a9303e9a1f72d066dead695 prerequisite-patch-id: a84d736764360a832e3b238eb497161baa482f90 prerequisite-patch-id: 255e195fdf9a836bbccf5c4038c678da1ce47084 prerequisite-patch-id: c61c9bba2e17e431e21ab5025e8996e202f73c82 prerequisite-patch-id: f434d1e92f0e0dc06e5538bee1fca742f0d46017 prerequisite-patch-id: 52734c2db39502aa813826f03f6defe75c1351c4 prerequisite-patch-id: 8dcb29725bb6102a4b6709702dafe71cc7d431ad prerequisite-patch-id: 7c64a309a0f764aa536fe9651c6224085ac35189 prerequisite-patch-id: 2c3a97f4a537547f6fead06b5ae138cca421e814 prerequisite-patch-id: 04cc37beda6b34c9bd603d495ca81ea6d9078f6f prerequisite-patch-id: 4547f247c0fabcbfa89275e5e4e9adc03155bad7 prerequisite-patch-id: 883ed01b7e6036827bc06db8c526d661c5a75467 prerequisite-patch-id: b3ea2b650168a612edef599976ab5079d7e82f16 prerequisite-patch-id: ea8a29322b084a51b24e4563df60136d9db19c46 prerequisite-patch-id: a50229361a16f64b365a16a9fa0506c009ca7276 prerequisite-patch-id: 703ececc75644172124aa002b29a2300300308c3 prerequisite-patch-id: 9d53ab977a18183a26d61f4dd5ee1e33ca093393 prerequisite-patch-id: 1e539bb3f62818a4188fc55a8d11b83844ef1ea3 prerequisite-patch-id: 00e60ab73b22e95aa864079593e770670ad6b4a4 prerequisite-patch-id: 007df29801bd8735ee439bc0a2efd6c73b70c5a3 prerequisite-patch-id: b447b581676c78dc9218f1cdf68bdbe7d8be4d55 prerequisite-patch-id: 63eaca1698b061dfb57649389b85aaa9d7ff2d68 prerequisite-patch-id: b0c3b4bc1d73fe35816a0b314b468717471cde24 prerequisite-patch-id: 1637e3c6dc8b4133357fbaa0c958f5f958400f49 prerequisite-patch-id: 66fb0166d183a65bcb11e4b09209e6aaf7b4f77a prerequisite-patch-id: b714a2bffe012293cb8358885bb1f6c33f8db42b prerequisite-patch-id: d4df7823239cd8d2650c515b348a468c78f500ae prerequisite-patch-id: 5501ee39e436067df2998764ae3e850575e9731f prerequisite-patch-id: bd9e9b9a1b487a4ad99e1dac63eba9637cd4f34b prerequisite-patch-id: 562d15006bdec22e8ed7b9185c11bd44ed2e8a14 prerequisite-patch-id: 57c58b761966e5d7091bb320eda47904fd1e7bdc prerequisite-patch-id: b4ec2b2583355bae45571c82e14323365232582f prerequisite-patch-id: 5706c8a5d28d4e9cb85d0c49b03c673b619ba753 prerequisite-patch-id: 833be32abc76ce57b401562ac098f382436a496b prerequisite-patch-id: 173474487c39e21a38bf222348cdc687427e9b7d prerequisite-patch-id: a683d20357a6be3754c9fd45692c0d0fc12641cd prerequisite-patch-id: a33120f50d7917fa90d6ec4bd56a1a94fdf6fa58 prerequisite-patch-id: fb7b6faab8c5bf5c4879b1c6b80767aa5938194c prerequisite-patch-id: 512014af58136a416d6f0608b3f4d602ac1a5345 prerequisite-patch-id: 570d0efec9ff48038cd08de26f7ac26677f6194f prerequisite-patch-id: eff12b723b3cdcf135f001b33d16eb565749a695 prerequisite-patch-id: 043c8bfa795dccbbc985630a20400dc8b5e61762 prerequisite-patch-id: f39e28eed10a92887fb1eff4edb97351725b8832 prerequisite-patch-id: 7fcee5f8a86c1574080f7d9eabe51795d89da64e prerequisite-patch-id: a389ef54b9db4bd638984e977a2bcba2adf26c66 prerequisite-patch-id: 87ef33abf0d69ca01094c10d3d40e814a85891c4 prerequisite-patch-id: 3d2372197f131554a24982ff9984d18c59375551 prerequisite-patch-id: 5d86be3500c702285dcd0aa09388c44b7ec70de6 prerequisite-patch-id: 1b0072dfca3c1c53459b0e1a0045b4af7700f1eb prerequisite-patch-id: 66bec8e4e21aa03394e7ad67f20bbecb9822256c prerequisite-patch-id: 0bce419a12968cafdb671082de3fa8f4a81eb10c prerequisite-patch-id: f425ea06a2cd7d5a550204034f233198b2d57d06 prerequisite-patch-id: cb7b9cea5a6da2f860e06ff6b9ed47e1bf657da6 prerequisite-patch-id: 678f480a9b519e71b2171790ded2eea5d9622398 prerequisite-patch-id: 44eca5a199cdafd9ef20d5d515130597d1aa8f3a prerequisite-patch-id: 236a047a503304b2baa407804e0e03d566932134 prerequisite-patch-id: 4b647998bbeb78d204faaffafbf7f3d676b5035a prerequisite-patch-id: 6e3b0318c48da95946fb865825777e1e274d52f1 prerequisite-patch-id: b718aced6f175cbf6e5e59cb192259ce3f9073dc prerequisite-patch-id: 6b1bedcbe4718d4cb668feb66eb1d76aabb565a9 prerequisite-patch-id: 7a25e6d56d4e9d56208a6ae479d1a19025caaa28 prerequisite-patch-id: e41b6ad1f6b707a252602c07b182766e8b475744 prerequisite-patch-id: 5a383ab5983626a1eec67a6558798f00c5b63fda prerequisite-patch-id: 739a8bf897dea46876477950c224c1d708e88db0 prerequisite-patch-id: 708961f4d68e8d7c1964a0ad2375409e1ff01666 prerequisite-patch-id: a5f8d45e55111d6a44e40996f9ef0618c2db9709 prerequisite-patch-id: be0b9936b8abbf5e0d645bb66d98796d1dafbb18 prerequisite-patch-id: e05182baa950adca91d88d13f9d4707b458ff9e5 prerequisite-patch-id: 32a645c5d034c00f601ca582a65532f584456f81 prerequisite-patch-id: e3eed08ffc93d8a71aeb8bface836b31fa3ba7ac prerequisite-patch-id: 5bdbbc3f0ce501c6999a3290f39ff6b5215a1065 prerequisite-patch-id: 3f971e057e719319466ee0cab3d581a14e29a883 prerequisite-patch-id: d7a6217ac94193d1f35506c28ad9d8e6e62a1001 prerequisite-patch-id: 63772960dd7071c009604ada332b6d6433d7f029 prerequisite-patch-id: a18bb9677d92af8394ca2dd6bcd0c6c3c1b19e05 prerequisite-patch-id: 525db65bd5b27007e9b520e9438b84ca1ace613d prerequisite-patch-id: 767e24a2bae22f8159aebce7d70d8e04ec931ac5 prerequisite-patch-id: 44e8684f1a0a433a97a96e0abbd87bd0ec8d746f prerequisite-patch-id: eb83640e79fb72dac48e4851f519950a62c8c172 prerequisite-patch-id: a5cb234603e668df4ae159d8c145e95613d8db04 prerequisite-patch-id: 60b0e4f257cab243efea19e380943446d306fa04 prerequisite-patch-id: b7491fed65739ede5567035ab3b002ae819ec722 prerequisite-patch-id: abfb7fb5dc5981b25731be2f994e101ef2c21463 prerequisite-patch-id: 84f6e32b56e4ebce3decaf1e55e37106e5b65fb7 prerequisite-patch-id: d76a7dc9422dcff88c961e3b6028cc92104caed1 prerequisite-patch-id: be190cd18b385f4fad026ee0a9521ed4cbe6a99e prerequisite-patch-id: 33dc591d2b673bf2a042e90bbeac35f660e266ac prerequisite-patch-id: 315d5ca54471620751744539f283e0ce9d4ffce7 prerequisite-patch-id: b8068b9798ea493637b6169e7a5d1960e28fb855 prerequisite-patch-id: 75a42b09baafac2c28ef223024205b26c8689a23 prerequisite-patch-id: 2ffcfbadb35c8f9422d8bfe8e457dda60561eaac prerequisite-patch-id: 4e99175bdd8c8f6e275d669f8ccf482783980dbc prerequisite-patch-id: efbfa5ebbe83c7df45c778b41e8197fe7dcde9da prerequisite-patch-id: ce77d82de687c4b84f6e36ad6981d4848d2faee0 prerequisite-patch-id: ca7f729f3c5588b6144f80081859d27be4c1c1f3 prerequisite-patch-id: 2984b03deccbd01d681fc7117584953de88c4de5 prerequisite-patch-id: 6d9bc1022837dc11cb1c66a3037e40944a98b8a6 prerequisite-patch-id: 594dc12944ce0340bd41563458b8dbb21953df01 prerequisite-patch-id: 62f956614f3dc3fdf1e5db1b0c1741cd802acb88 prerequisite-patch-id: 9fe4b4d5d5ce01ed5f63dff6a19ec04b3d4c0ea1 prerequisite-patch-id: 22fc0e59f42154422bbf8273f732f344847c87c2 prerequisite-patch-id: 8ee4e5f5a0a9a431dcff708c562fa6be8e345fec prerequisite-patch-id: 512a77525e5077b9acf066fe3973a67586e10978 prerequisite-patch-id: 7d880143a4fd09af6600137ac8bb485d2172a558 prerequisite-patch-id: e95a81c9a238ea6005eccb01e7d3862cd3f9f1ae prerequisite-patch-id: 53090b8016c8472b090ea12b37836f43179f4ca0 prerequisite-patch-id: a4d983aa678212fc8bafd3a61c75acc7d16d7cc2 prerequisite-patch-id: 7fd69149c985e6674400a1603dd9e222fe70704d prerequisite-patch-id: 62c5aaba8d53b1370b0331081f2f2b5e471cf8c7 prerequisite-patch-id: 9ef4f6ce23a0561a78d8f6e052765e1e3304868e prerequisite-patch-id: 3f80210584f579510c699f47b33d9e41afc5c903 prerequisite-patch-id: 14cd3dace51d58e6845607f364a4d2e4fd334c97 prerequisite-patch-id: 641026cf7ad0d1fd11ded66a603f20dd52bcaf80 prerequisite-patch-id: 8846f55d4602745c89c8cfc76c19e472e324ef76 prerequisite-patch-id: 0100d8445dda493f0d079a9c416731c24abcb22d prerequisite-patch-id: 777cef5770ca622324d5396a61e2eaebf9fdd44b prerequisite-patch-id: 8da2586c5c3cef21c0740d2aa9ee0c9590b63325 prerequisite-patch-id: 265ccff487712a2b0427420182c2d255dce76706 prerequisite-patch-id: 926c7f6f138b8a92b4710e37fff0a8ff7df745a7 prerequisite-patch-id: 798857cc87ff166349bcd19ff96f91e8609af552 prerequisite-patch-id: 017dca40450632def1382a9960ad76370f987f66 prerequisite-patch-id: 7a2999f00ede845b26e173e39febac70d1f52fc9 prerequisite-patch-id: 53c08f59de14a07f44b76fbe52e443130444fe2a prerequisite-patch-id: 52367860e8594fac0ef29579d0fea948128ea77c prerequisite-patch-id: 7206721662cb46634fbe7cdaa68f51fc351533c1 prerequisite-patch-id: 4d53f7022a94a3dafcf3bfb33f89b64ee9760874 prerequisite-patch-id: c05c248f031f529678a9b9fc5a87e094aeee5863 prerequisite-patch-id: cdf85348b51b842b1d99e623fa2e60f2c76f39a6 prerequisite-patch-id: 38428a6d4dc7398f1bafe8b8a1986b3adf488916 prerequisite-patch-id: 2446268fb386044794c3ed905a7c468d49fd810d prerequisite-patch-id: a7df638909f8f24365180047818519ce5d1c4a86 prerequisite-patch-id: 50bf609621ab5e043524567e40f6c51c8301a44d prerequisite-patch-id: 345f1da6a39c5c1313eb9445f670c6830c59fe20 prerequisite-patch-id: 784a5b734430a25ef9a97c92593a2e94a5916176 prerequisite-patch-id: 81f852ba3db2dd324bca07f3500da49a930f4019 prerequisite-patch-id: 80eff8b2edac166ae0ae1b1e14339dc92cc92aaa prerequisite-patch-id: bc089aadf82606b92b2b209cd280a85e675ae40c prerequisite-patch-id: e747be1ec17c00b973cafd542c41050378de2994 prerequisite-patch-id: 978448273549b5a513632e7b3cc2d955f7787728 prerequisite-patch-id: 092d4c49c46b173a4e268e14f3917500896d53ab prerequisite-patch-id: 456fe39f96d822bc11e62e432ad726bd3242065c prerequisite-patch-id: 2ee48295e01fb6d089e15d9da05e8d8a677f6dbe prerequisite-patch-id: 0da2ba754f285fd782f783b8492f10df6955e675 prerequisite-patch-id: 5ebea382042cafea310e815cd6349a5adaedd111 prerequisite-patch-id: a305e9a127b2967295bf35809e9d9ab5b9d01458 prerequisite-patch-id: c4aa2b0adbd758f9c18b51fc167aada20aee08fd prerequisite-patch-id: 59c25d56ac9ab79c39e9eb9c038745418dff59b2 prerequisite-patch-id: 650faedb8960d5f45c2e57794c2751f69abb9ef3 prerequisite-patch-id: b21ece8afdc1eeeb30e25b6714f13a621aa0abb3 prerequisite-patch-id: cb61e641bd8424e4eb70491f73d8e749accdc2dd prerequisite-patch-id: 8d7e2758c2c1ee628236cb7101ba09134c8c57cd prerequisite-patch-id: 6a4374fe4d88ce5cd785195cbc3962896e58015b prerequisite-patch-id: fe0b3f72550143448f619ca2ddf98314c66f71e8 prerequisite-patch-id: 8865990e35f5229b470246b74f03d1cd7ee36344 prerequisite-patch-id: 283d4faa50f07719907c3808ee862322ed8d3ec8 prerequisite-patch-id: b043f02e4838181eff0798f1586446589ff82d56 prerequisite-patch-id: b0efaa48484d39e864a53be3d3794763d41f6731 prerequisite-patch-id: 733712f77a706699775a6460abfde7ae6218e82a prerequisite-patch-id: 06f8b02aaa1a0f61e51410f0569eb3ca45060f1a prerequisite-patch-id: 4bf596702b645256018d83ccaa6bfdcc29bc22a3 prerequisite-patch-id: 88763ac03b5527607c77aceaad9af39b0fce223c prerequisite-patch-id: 524cf3fb84d438f0596eb7893e960b29acaad38a prerequisite-patch-id: 27c3fd5282cc4e8c7dc8e8ba41195139825c8c3b prerequisite-patch-id: eeb6931ff3d9ccfca672f813398e5d0f10e5b7d0 prerequisite-patch-id: ec21ecc41d9a05ec3bd6e3df3c1cc9c6fb5ccf81 prerequisite-patch-id: 94063476beef4b38d20f756f6fcbac3767e53e5a prerequisite-patch-id: 814b88589d0583c73d76170fdc2616c8bdf92eed prerequisite-patch-id: 0a5a4a3249da385746653a8002050a15ae05c8b6 prerequisite-patch-id: b1f40e9e41c6250b7ffa8ce167dd3f52dc488e86 prerequisite-patch-id: 26c55fa419b8bc5707d25d3af97d322cb4fb235d prerequisite-patch-id: 7d5581e683d5f33bc9a68f85739d44f4f7b7eb04 prerequisite-patch-id: 93d766ddb5281550701271261d2b7cded21a3aad prerequisite-patch-id: 06c9dcc3d0c484c1ddadcb9bfdf31ce61c9d4e53 prerequisite-patch-id: 00e0a617ef0639a042dc33db409e2d915f143b4a prerequisite-patch-id: 8f8b099330f316b27dcf0f824f1c7f2e5c35af8d prerequisite-patch-id: 74c79242fd8b28b006b5a829d3f41ed777e3937d prerequisite-patch-id: 884b1c069ab2eda7ad6f3db39fdfb4ca958c9d91 prerequisite-patch-id: 7f490e0c1fba72c8aff26587464ab44291050b51 prerequisite-patch-id: 89c48f814322bd435f86296098bfdaff4e4ea132 prerequisite-patch-id: 67861a27b6f43ddb7c5bfb84acf81b2249a71e98 prerequisite-patch-id: b222022c5c9e4f597e1dacfbe13a164ca2d0ebcb prerequisite-patch-id: 129bd609ce709abcdf0de3152156b17a9abf5631 prerequisite-patch-id: bffab6c16e118cb1a1b304ae145bb4939748b37c prerequisite-patch-id: ab8ec99c182f54546ba63783266878bd450c33e6 prerequisite-patch-id: c471cf162ed4d793d4827dc06996a672c87e4dce prerequisite-patch-id: b12cb1a99b9e44d8d3efaa0ec912c7d7b9145b04 prerequisite-patch-id: a893962782b388d69a8294a06fd405d0701fb95d prerequisite-patch-id: 1956fac354dc400d192d8b19917c1caab066566d prerequisite-patch-id: 450ebe76ad4c3af28540d3498c67348882c4af80 prerequisite-patch-id: 04d261fe798e5b511a7e7ff0b12fc7f2bf93fe5e prerequisite-patch-id: 858bc379c4db030dd13859729432c400c3151f98 prerequisite-patch-id: 9eb3844313678930eda6814249a0af3dd5b57759 prerequisite-patch-id: 33b43e26c2a19775fb2ebe552bd1c0a1b8dec071 prerequisite-patch-id: e2066f8e8c972547eb0c19574b875822b4a48e20 prerequisite-patch-id: 3bd97e96daf3543a0ede83a66cae6f7f0e6e9f02 prerequisite-patch-id: 605a3cb55b86fb10bb46559354db6855c5ccaccb prerequisite-patch-id: f661d0a2dddba2a5571ed91c428af9a27797b092 prerequisite-patch-id: 94442b32fbb9564c2e9535884f1ac3911ea30fcd prerequisite-patch-id: 961118ed2fb2a34fe51598fb3bfb26c68c211f34 prerequisite-patch-id: 9ec37202063d631c8245319f4e15cafb99d3825a prerequisite-patch-id: d1a7e79954eec4902dd292d8c76feddad18b25a9 prerequisite-patch-id: d420577ef70a415366a889801ad41365495ab5d5 prerequisite-patch-id: f040d5a05a570ecb8bfaeb56bbb18c5dc9345b78 prerequisite-patch-id: f7b42ac471a92db7b35a099830de0da828cac34e prerequisite-patch-id: 373d96c34f6653c13d2e3e7c2b4df39721335586 prerequisite-patch-id: 812a8fbdb719d738687ffaf37e65f3e4e99b81d2 prerequisite-patch-id: c507d15944e92fe6c97a9946eeb3400ce15a2115 prerequisite-patch-id: f4d224f2cc2672f68d73f1021a076002f6a2a68c prerequisite-patch-id: fe5944dab202605da26cb490dd4fffd606e746e3 prerequisite-patch-id: 96eaa2d43a29c18a1edcc13f6dc4b0a0b67a5c1a prerequisite-patch-id: 952ad86512d51c1bc73abf4b3ec104d977575fb1 prerequisite-patch-id: ea95f5e183105f6b67e95d87fa95b3e512c21f9f prerequisite-patch-id: f4bc3372c0a920940293682b08a8fa14e59e6a14 prerequisite-patch-id: 21748ab35d96557f9452622e824eacf4929b9e81 prerequisite-patch-id: 909581870d0cffc6301afc13eafe9492f27a7ae9 prerequisite-patch-id: 875efff11a4707912b19872550c234350edeccd7 prerequisite-patch-id: 602bcecb84b1f430adacfabb4afecbc4a698d29f prerequisite-patch-id: b1653e6f4f7aa5e2d1c34492755394ddb5af03f0 prerequisite-patch-id: 23d4ab442d75617edba48f552aa33e9fa54b856d prerequisite-patch-id: 9e274bea14c4f9a50d5ad0244284e5303a9fb64a prerequisite-patch-id: a918cbd9443dfb5b5a2ed452039e0c8b10b81da6 prerequisite-patch-id: a386379e24ae3f6ae06028038a65b328fd06e63a prerequisite-patch-id: 873e7963b35c668e362b96a902aaea975c808a8b prerequisite-patch-id: b580153f1cd70168ad618573fc98ba7650031fd0 prerequisite-patch-id: 5e38afc1153b3a697091a5c528eece2ee861dbba prerequisite-patch-id: a83690a4689863b02c59a0753aecb68b957c2e57 prerequisite-patch-id: ba40e82d0efebf6a3152352bad8be8137e800814 prerequisite-patch-id: b1b3c0d9c3097829936a35575fb255713a0ff3eb prerequisite-patch-id: 149946d378999078cc517c0414066d264cd3af7f prerequisite-patch-id: 53458c10c5381f619a7dd6a36c20b4730afb4298 prerequisite-patch-id: 2565745ff1a2904ac7138e262cf38a45fa74f3f4 prerequisite-patch-id: 84974761820839a21b8d621b60111eed78602f18 prerequisite-patch-id: a9c8b05b6ad0e2ec24e77fb13849efc4f70fc162 prerequisite-patch-id: 0ddce048ab55f096b849702ac3b7c2c0ef1d4c37 prerequisite-patch-id: 83d9e434e0268c9c94274bfc472e4693033a5d9b prerequisite-patch-id: ea7139213c995cfd2dda267d517a06eecbf7107b prerequisite-patch-id: 15cac8a9aad7c93b7e19415758d212a07f69742e prerequisite-patch-id: e972d692bf586f97a8b4152cc9095cab317a397f prerequisite-patch-id: 31030dabd4ff554e8be625f0aebc0e07927cd1c9 prerequisite-patch-id: dd82858811ef1bb128e68aa8042eaecfdd2ab772 prerequisite-patch-id: 886f3e849fcb5d9f6a718564077c8b1f24745ee6 prerequisite-patch-id: eee96ea5e2c75e3d02076979ba87ef2c9e914a19 prerequisite-patch-id: 80e8224d16bf0e571887aba550f34235e16b5eed prerequisite-patch-id: b820b96049ff401ef215671beb57af172d058fed prerequisite-patch-id: 22593fa1f754a5d970b8241f1a0526bfec4b977d prerequisite-patch-id: 8f3cc922cb1601f86969c4ccc1a99c874b5c2ce2 prerequisite-patch-id: a52fb1b05404487590867de8a8d3a8fe1239b862 prerequisite-patch-id: 7b625b640877b4654cabe00cda564a5411849a7e prerequisite-patch-id: 650afa428d752ad126da069e1b1c263ab250ba9d prerequisite-patch-id: aa8942c352f883c3bcba3f30c58e23bd8fb0e0c1 prerequisite-patch-id: 9a859f915481fa2cdc06f07fb0e4603dd8d23fd2 prerequisite-patch-id: caa82bdc29e967fe0a50b55bb1a13827eb7c21ef prerequisite-patch-id: acf03b307df14ce36127cc8018e6b846935318ff prerequisite-patch-id: 17b30e1e9c3865b046cc00869e7280f3d2c2e611 prerequisite-patch-id: 4ef4b8d613bd52ccc9fb3609b2e429a183ac5969 prerequisite-patch-id: 3f0c6cfa6d338949c226ac2c8607f591bff68537 prerequisite-patch-id: d5fc69dbf4d67e43263e2fa47c999f18e168b570 prerequisite-patch-id: e6cd5f86ca5e6b2cbd34db797dd7902b973d8a54 prerequisite-patch-id: b0e7fccd617597d8549cf439029ace3c9afafc90 prerequisite-patch-id: b2619d6436c05665fd6961592498f3d1666094a9 prerequisite-patch-id: c12f214836a6a45cbed8cbced6746e41872cf35a prerequisite-patch-id: 5135ad2c05245532f4fdaa6fb8242c5bb3a78b87 prerequisite-patch-id: c9e4f0dd3537c8e36ca77791b328229a4693bfd0 prerequisite-patch-id: 6eaa656a0ceabdb9cc981a796c473dd43255b1c5 prerequisite-patch-id: 95eb57495789a8562915cf349bc09a9b2e474c46 prerequisite-patch-id: 52204eb267a570c620ef18705a43070b8808cbfd prerequisite-patch-id: f49de6dc5741528715c0ae39b50f0a7a2718417d prerequisite-patch-id: e8b7e58333e82b4aabe48aae8c29be5a68c5f7b9 prerequisite-patch-id: a97c47ce9918ead425e5d3ba69756a9abdf703bf prerequisite-patch-id: 9671130372657c6d20fa9f64c28f631a9f46e689 prerequisite-patch-id: 23b7e939357af014e5aa2640e56e10560ebf1aee prerequisite-patch-id: 6709b227a765965726cb59216be35bbf7d14ee4b prerequisite-patch-id: 3f6d6758f2fbe344c608e67440934fc9b4555161 prerequisite-patch-id: e83a8ca75c457f2763ecb9f79a65fffc62a0cc5b prerequisite-patch-id: e5cf7e1d9c3ced77260db9a96d3a9c6aae20684f prerequisite-patch-id: 6dac9c34435c65277ca5734f923275ecc59d001d prerequisite-patch-id: 606dd4732c7fde5a7ed4d03ccf27d92a299b27ad prerequisite-patch-id: e2a579d5a7ae90ff688dae82fe9ea56c2e063218 prerequisite-patch-id: 94d076e7ad5843d4b2fbe3d9e497dcc731d6dd55 prerequisite-patch-id: f24c67c4de0b7ce4212808a80efcdb027b3991b3 prerequisite-patch-id: bbf25d5cef502ac2eec946788d386d0e23c36461 prerequisite-patch-id: 5cbc51811824f9b0ca8b647f899afad862341609 prerequisite-patch-id: e059847c6907a54c9350445f81ce2608908f58b7 prerequisite-patch-id: 96524116919f2efb2f34baefeab80185a56c6bec prerequisite-patch-id: 48a05e62af0e31dc0791ddfa4aeebcb5e488eda2 prerequisite-patch-id: 12a17635848ca0a6937b1f90403633c24d1e7dc4 prerequisite-patch-id: 0eaf7802a398de01d9571185fad0e1e0050089fd prerequisite-patch-id: 740fe89b92da813d42e75819228225ea7a87f65d prerequisite-patch-id: bb8d6f8fbe00745325abb1ab8f150e11193d46c3 prerequisite-patch-id: 650c950ef0b1bdc17c6116440e27f5653b1500cb prerequisite-patch-id: a8052b8fdbd865c4b0f6f5a9e780307bb7299952 prerequisite-patch-id: b02649af7d6359f077038cbc60bcfc1ec0b2f8e8 prerequisite-patch-id: f72d4e4dcfef67e6593f19294a3c5edc671e351c prerequisite-patch-id: 9e676a2b682755aa132e69150dc5520f55e3f2c8 prerequisite-patch-id: 4f54c86f4fe72c963a6e13f8fed20f243a65cb37 prerequisite-patch-id: 0397a7cc6effad1379c32336996eafd858ed0ed7 prerequisite-patch-id: 5d1a82d6929dcb2bfbe3fe810430b42e6e3be130 prerequisite-patch-id: ff0bc5d4bc288f4d88605fa46e0485599e72734a prerequisite-patch-id: 3520933078f10cac7a822cac20a2d7c08870d7c3 prerequisite-patch-id: 753c9f1468c6233c7b4fa2efca11c0e18f03ecee prerequisite-patch-id: 3ee184a2b577f049df6c203415a7e99566191d49 prerequisite-patch-id: 11ee570e9a475cf70873235c7ba3f8c3629b32c3 prerequisite-patch-id: 90509945344c1d0e6314511b30aeb94f1ce909f4 prerequisite-patch-id: 964978dc3d84f9001554ff93ce72b8eebf94b0cc prerequisite-patch-id: 253b016272071ccf1ad6e2800421e2eb018629cd prerequisite-patch-id: 387f09a752aaeb32e8be82959a840fadcb43782b prerequisite-patch-id: 59da070c774e388864d1d8a6520989378bcfbfc1 prerequisite-patch-id: 1643db946909840b14931907904228a1c4831e29 prerequisite-patch-id: 81432baa3a5d7c3d09687f88854f2ed92d6b5346 prerequisite-patch-id: 79333921a2522eae428026d6fd2728adc6b2b039 prerequisite-patch-id: bce14fa84e9c8b0a8c47b827cdc238a3c882e4bb prerequisite-patch-id: 9a3106f6a23e312c40194d9a91fab50579ac64dd prerequisite-patch-id: 96732846a6e9af831df5f04eab96cf7614349ab8 prerequisite-patch-id: b40034215f4cb44767e4cff4fdabb219c16f38ac prerequisite-patch-id: 4ff22edce1439af3d6b7282b59d751cf261d7463 prerequisite-patch-id: 5fe53961bb42672a5c9b20d49f335c36b57d3698 prerequisite-patch-id: cec3f6f2595ef77eae7095e8b608eb00e44d1aab prerequisite-patch-id: fe6f0ae34455f23c923d38d923fe16f8708143a1 prerequisite-patch-id: bebe94a723ef25ff795004341d3522635b1c4b3e prerequisite-patch-id: 5e4ede659c5b9c5f36c9b2ca9c7b39000207eb39 prerequisite-patch-id: d8d7fe873ee3af54a5ec98eb927efefbcfa2dd33 prerequisite-patch-id: f444165db02ac0580e11ae282d701efb4781974f prerequisite-patch-id: a3b47e1d24579c9a8a9302684237eb1574aac56b prerequisite-patch-id: 9bd17bea969a3a66eeb702eb4f8f852ec63c0cda prerequisite-patch-id: 5b2883aa586333ff252deedba445a816bb1b4f90 prerequisite-patch-id: 4579defdc01e30a6bbfde006e7d9dd215417081a prerequisite-patch-id: b9dfc9cff450aef02fba5b7e12de7084f3a38bfb prerequisite-patch-id: f94b13769bdb79cdbbc75681936ebd903d3d9c54 prerequisite-patch-id: 831bf2a39db010d4d040b224f1316ccc81061c89 prerequisite-patch-id: e4479fcb5d9c04b7722cb1abbd0b57c0ab9cc7f3 prerequisite-patch-id: a5dbc9c733bbd0659be58527295ba044518bed66 prerequisite-patch-id: 356a6f9d01eb9055a01ad5b7bd55edd2b460ddc4 prerequisite-patch-id: 27ed19a8426dc6a83ae9e7f4a3d80b691cd8ac5a prerequisite-patch-id: 004e13b154b21fc7b989d153404d805970d5aa3f prerequisite-patch-id: 5d5fb2616b31a2e3577a4bc4094af2aad8057b1d prerequisite-patch-id: f27f698adc449658d0007437f72e99993879ceed prerequisite-patch-id: 7fbaabf3eda99a2971fca9cee1da6dbfcddd82b8 prerequisite-patch-id: 50fd1b13b9c8dba02778cf7ee419ad614e960137 prerequisite-patch-id: e07f0e5b65430e5286d340503961e69d3fa45bf5 prerequisite-patch-id: 9e61d061519194aa0c058cbd75bd1d4fae9033d7 prerequisite-patch-id: d4ba6ad69578f6ea4b4935ad890ee79886dd8cc8 prerequisite-patch-id: 98b1457e53ca86a9669920cbca590bdc61c83bb4 prerequisite-patch-id: d838682c41cac0e0b396dbc22dd54223dfc0c9e0 prerequisite-patch-id: 0862991dfd4c262c7feed1aca40e28ab3276d3da prerequisite-patch-id: e176ed652ab2fea613fdbdba4cd89fb3c665c498 prerequisite-patch-id: c4d3f9ee4505e671a039bf6a9c5e09e51e3327f1 prerequisite-patch-id: 63cd2156a2c80298679e649d501dfb3cc9277228 prerequisite-patch-id: 62d89274420efe783f6d03c2bee42f2622c8fa81 prerequisite-patch-id: 972b28ff11c756a5d503cbb703ae78238ecd2044 prerequisite-patch-id: 5de5c2aa9ba92f0f1eac6f60e19fd351d1029966 prerequisite-patch-id: 4d92001a10e7ac505f56c2e8bd25a861b2e89ebc prerequisite-patch-id: 58cf483dc6496fddb25996f7657a15a1f17c4d8f prerequisite-patch-id: 9e46aa10805f09080997860bc8bffcb4a609cb9e prerequisite-patch-id: 3c836b04148567373feb7ea74ec84ab338555689 prerequisite-patch-id: d23258c854242ae9a376df57c9be6388dd1c00e0 prerequisite-patch-id: 43bfb876d5e62dceaa13ab677e97f4b3daf126b1 prerequisite-patch-id: ffde0aa9f020bc89410ceeb835281df3787290fc prerequisite-patch-id: 2550a8f4de5ebc0dfd7e807172c1486ed71a4510 prerequisite-patch-id: 7fb17efb5e79f4e924ff34e2710b91e02044f896 prerequisite-patch-id: febbe9410ddd18adf27ba17482a77e2e1bca83de prerequisite-patch-id: 467f160af12e9d391d4d7604ced2391a2fcde460 prerequisite-patch-id: 92e2ca149843b470eb0d98439df089bd9031c62d prerequisite-patch-id: 9da052c8b63c341b192c2531740c38175978462f prerequisite-patch-id: 4113b1ed139ecdfd84da9cbcf7e643eec699e2e0 prerequisite-patch-id: 8155921886749158973c77c052f9f4993fa854ca prerequisite-patch-id: c95130b8ac235c602d24dd8802e4d68a73643042 prerequisite-patch-id: 7d7deaaed9c5c9c3683b7002a8385546adecf428 prerequisite-patch-id: c2df85accac5b7cb2893c628a451c89af5f8dc07 prerequisite-patch-id: 397cd40e170ea311ca78421007c7d5aa4e952511 prerequisite-patch-id: c19315820cf5403c928549d56616bd37f501a587 prerequisite-patch-id: 8236bbed0594cd6ff5a862484696f3a29304fa7b prerequisite-patch-id: acfe7438e2e086bb6dad336ef75c2d9896c6ecec prerequisite-patch-id: 23b8945f6af7abb0bb96f46115d59fef6e19e89b prerequisite-patch-id: 58622eb013b7fed1916cf164abe3b309dd0ce76d prerequisite-patch-id: bf72837647d036c68dfa3c2ff2b0c02f2a407369 prerequisite-patch-id: e6cfc8efd00274a48578cceadfc111a26bf15af9 prerequisite-patch-id: b853280a96ba1b3041688c0be5513840418b2e15 prerequisite-patch-id: 6c5486b30d59a0d8070baa41f7a88c75939ca745 prerequisite-patch-id: e778ebb0420ce080ee542ac099c96cb6048a951e prerequisite-patch-id: b71a583cf42f6f78e0d2d1481e81775de3bf5ddc prerequisite-patch-id: 937f120f2870ecf0ef7836779186f0c9f7736692 prerequisite-patch-id: 25de2490c37b01e3c13affc078fd4f66a5688222 prerequisite-patch-id: 54f229a7a175e8d32a651e332330a2766cffc8d4 prerequisite-patch-id: 6439ea63fdb30a0800674a5cf293460af1de7037 prerequisite-patch-id: b0ef91f6a39a417011bab2f1825c281364265a1f prerequisite-patch-id: a0d7960592f26c1a23f6e235194395e7aa7417af prerequisite-patch-id: f48bee677486fee97fbefc624a1a7b5eb8e5717c prerequisite-patch-id: ded500e20ece2430d591115fcc48475fcddbac46 prerequisite-patch-id: 08413dac0dc1a94ca0ba28139aa6a7ef25d93ac3 prerequisite-patch-id: 834e84fc7c6ec0385fa10eda637891e5d53188d1 prerequisite-patch-id: 063293e44bcd516942436026c8432479e06630fc prerequisite-patch-id: 1c2e465ecbcd2dc73446850eec711d5975261e78 prerequisite-patch-id: 9a09cb1d28394c1024a86a90b7ec85eef9f4146e prerequisite-patch-id: 37b3a04b0c8f81e0f1f5eb1bd954ba5f10ad5353 prerequisite-patch-id: 334fb4fd7d28dc0e663a9120ca4ed3e8189cbf3d prerequisite-patch-id: 9e37d3eb3f8747806ef0df6a4f79886e3b46a4d4 prerequisite-patch-id: 2132be424a8f89fb33286c2cc3c7514cfe30cf7f prerequisite-patch-id: 7b9dd002bcfff8bb64ad17bbe4ed8d57ea05f72d prerequisite-patch-id: 0e91802bfb6c7262e285ef2b338fe0bef89089a9 prerequisite-patch-id: 58b44df943a7772032a8d7c237c12ba0060040b4 prerequisite-patch-id: 5e79f7b3dccc5ebd8a6485a8765f49217fb36f01 prerequisite-patch-id: d9f210df249068e37e737447a1c33a50bc360640 prerequisite-patch-id: 0d6276dc8e3beded8c1513cf3cd0b7cc0cef6cb1 prerequisite-patch-id: f7aa5d77d6eb82d6ac1b1abbe49e8705b0fe8c64 prerequisite-patch-id: c1ff581bdda73051b45d5ee47b356927c63920bd prerequisite-patch-id: a8edc107ac77c38d1651baf191567a70fbdc32ce prerequisite-patch-id: 3ceb36a0bc216eab306811f40645d41daf3563e1 prerequisite-patch-id: 8e0cd83dc8dbf7d835a51d275194523413fe7a9e prerequisite-patch-id: 461065731d52ad521d83ff676267de16828716bf prerequisite-patch-id: 8150455ba98c5547707e95c95c2e47625131db3a prerequisite-patch-id: c2b4f5a818c2d5e7c90be0d2968a1b2f646b05de prerequisite-patch-id: f4a1eb8a545ec9903e9bc1d903ff591880c080a4 prerequisite-patch-id: b6c2d68e264e45dc5209bc4c7086c745be0b34f2 prerequisite-patch-id: de974cf8cde6cc19cc8882a5ca66f122d739a259 prerequisite-patch-id: bde1a70673eec0694a52f55c99396c67e2330046 prerequisite-patch-id: 360c6adfea2a54afd57aa9cde18903aaf8222c59 prerequisite-patch-id: 0eef4f33368a7827aa8fb66d38407344165eeb3b prerequisite-patch-id: 3bc76ae0581a93fd6e009a197642fa9849ec7416 prerequisite-patch-id: 0400d13ee9f5a5a9de7a37a70904374a7630e608 prerequisite-patch-id: c5892764a7176f3368b815ecd11bf25b9055f4a8 prerequisite-patch-id: e1c2e08c7076cdb6993a1219a0eda8642f90337d prerequisite-patch-id: 5c8742b8236a914c947176846956ea48ab593559 prerequisite-patch-id: 4e5fd6340b3a9be479dc8528c59da42617363d50 prerequisite-patch-id: d54b8cf4cac55414199a4cfa06d802229c6fd361 prerequisite-patch-id: f4b2d1faab1502d7c9be66628961600d7605aa6f prerequisite-patch-id: b3fc01e5bda073a45eefcf3151dedfff0e031543 prerequisite-patch-id: 19b568fbdff7db6c176dfdd25c3373f363692945 prerequisite-patch-id: 0d804387d08c473426f5774d22585358c702cc3e prerequisite-patch-id: b1c53669890c6bee3136abd9f173293ff9a9e275 prerequisite-patch-id: 8a5ee7f5bcefda1a59b84da796fcbeb09930b403 prerequisite-patch-id: 5428e83633fd6e8633b646ae63a5c4980f346aa0 prerequisite-patch-id: be965f93b9b7ed07630d79806313779d24926639 prerequisite-patch-id: 44a55ad6ba390c88ca89a9ae847371331e83e85e prerequisite-patch-id: 948c6f03b451d20121ba97f709db4b8c84987e44 prerequisite-patch-id: 0e9a0cefa01d52bf759595408985ab5da5f18caa prerequisite-patch-id: 71a974abbd0fd98543d2ddecb7d4ce7f91470063 prerequisite-patch-id: 1a75acd25bf476b0f3ecc22a69e4689c81fb799e prerequisite-patch-id: 1f262bdc9b53cdf828f416d41aff42a64a32b887 prerequisite-patch-id: a334353c37996960ee619fd5c9f67e3f4123cd95 prerequisite-patch-id: 77a8ca14a82ab4e39e036c6798e5dd4a295c9a42 prerequisite-patch-id: a276fb83a0ffdd13c93f62fe890d91536cb5d419 prerequisite-patch-id: e69c3c74c745e764af6637550fdb2026f394448f prerequisite-patch-id: c0cac9a6b6d2e9a3321371397fd519cee48d7cc2 prerequisite-patch-id: d11967353fd0027dbabf7c87c538504006c539a8 prerequisite-patch-id: 7d2b55e6368db71b978c954d9cfc2cdb538965aa prerequisite-patch-id: 525112049d37a658731dc9c8aa3626375219e512 prerequisite-patch-id: 7a5cfed32c2a40fc2448b0c573a77f056afd816f prerequisite-patch-id: cd70ca1b7eff6f682990c13cf2155236243cdf5b prerequisite-patch-id: 9e294031288dda1f3dbddbb415161785c119bf53 prerequisite-patch-id: 10c28cbccb49d4061bfcd05c4bd305ec2be48924 prerequisite-patch-id: 39cde9fd11a1ed41ea79264dbeeea70f341d91ca prerequisite-patch-id: e2864df360884a2a3ccea67e74ea6ca6b7742e1e prerequisite-patch-id: 77865a54465e7827e99f0a11a23ec5403cabb752 prerequisite-patch-id: 51669dcfed01f9d8b42a775ddb76c71f44204633 prerequisite-patch-id: 826a8112c0e16451ce9a09dee2b816ef21b00d56 prerequisite-patch-id: c541e61afd50cfa5bb7e4be83ea1d41ffa82e69e prerequisite-patch-id: cc110ec0b6437432fd6b16ed7139901b57cd0f45 prerequisite-patch-id: c9957e8d81b88363684e201120863750356389ff prerequisite-patch-id: ea978a318c37da546844673f11ce4b65714ec6e9 prerequisite-patch-id: faa6843fe527b9fcbf62d6c006490c285f8124b5 prerequisite-patch-id: 2fd8fac6c97731672dac16c2378cc4c58c4161f6 prerequisite-patch-id: e2b3922df96b72eadde00277e8c51349e0ad2f82 prerequisite-patch-id: 84f2151f3a949dcd6ab263e89d5eee2892cdddd5 prerequisite-patch-id: d161b7cf48092ea68440be8ad09fb4b342ec1c5d prerequisite-patch-id: f6ba3a4d623d63ec66746e1f3b1c487ced74787f prerequisite-patch-id: 9d2763d7c8ea872d2ee4c312d912c40cbd7287bb prerequisite-patch-id: b2a8338edb9aa469578e8a2cf584fb4c87cf77f3 prerequisite-patch-id: 7521f2a81f76f1614a4d695f476fca3d4e397c1d prerequisite-patch-id: 53b3957b66faba747476d0e82443612f6dd9aaa0 prerequisite-patch-id: a3432f1ac6393b2a3a2cfbf316009b11db69b81e prerequisite-patch-id: 42f159f1353a8051838a429cadc162e50d24858d prerequisite-patch-id: 602570bcc895ff8a7ea13e49e982a393394f96ec prerequisite-patch-id: 3fdfe65d09caa39dabd18b1057bbe7572279bbcb prerequisite-patch-id: a0bacda2487d4b02fc8efd2eac391549ab89e8bd prerequisite-patch-id: 3988884d0b4430f806eea737dfca4d9d4195d137 prerequisite-patch-id: 656abfb2784950bc3a8e1025b97448f1212d1960 prerequisite-patch-id: 4a83e56a3752b546e63f64c0d0f947947a09a9fd prerequisite-patch-id: 505822009f48a48cb7dc218a40d4287835784a91 prerequisite-patch-id: c7a845b0dfffc0c4acfc49dd0ce951d95d1ea4f4 prerequisite-patch-id: 0a2b28017b0f603aa2339252810123f654ce6ba0 prerequisite-patch-id: 90f8fe71ee14a20bd63031baf1cd96fbf8b26a08 prerequisite-patch-id: efd5c460d2a24e134e9496726d9316be52abf982 prerequisite-patch-id: 058c067ecebf92d174389298c87fd8f4de4d53c0 prerequisite-patch-id: 5d38188732379bf99b4a46cceafd044bb70a9114 prerequisite-patch-id: 264743c7527e3212e70c78825dfeb78b90da1b46 prerequisite-patch-id: ffe1ec0998fca6f09808abbbdd3e5f36d8b99aef prerequisite-patch-id: cccfbbb276df204f3a30f5076669e3c4e3465a1e prerequisite-patch-id: f997568b909a534556150aee7eac7e31bc253490 prerequisite-patch-id: 39b516b62db7df0ce370dd8124eeb7bbc1f45e42 prerequisite-patch-id: e09888ce6131958a85c4825dc73a954834850e9b prerequisite-patch-id: 6f04086c894d6e015df96de40f95f4ceb36d99a0 prerequisite-patch-id: f65ad1dfbcddd0e86cfaae6400a5849de31e8a84 prerequisite-patch-id: 1d60bbd2fb52819635eda97dca5842d05b9a1ce8 prerequisite-patch-id: 9af0e7f3210e1ed3fe1d7a51a6520bc47d48f2aa prerequisite-patch-id: f9802b80019a8d89cfae81f4cbbdcc329013fc61 prerequisite-patch-id: ab52102730b4823c5339e8e9967ee62bfa900ee3 prerequisite-patch-id: a25ca258cf441aaca9ee6f11a63789d78b73bdf8 prerequisite-patch-id: d08c2322164079f84ca7620d8903c59691074aaa prerequisite-patch-id: 396ea25f5a93546fb5b37b19e6631c8f8d9f404a prerequisite-patch-id: 673451f3abee96162497b0727128d09e7904d180 prerequisite-patch-id: a62862a51186455ea47150d171c2fe3fa9f023a8 prerequisite-patch-id: 71ddb50fd4bd5659a013616d13e273a6743f3a8a prerequisite-patch-id: fcc6fcb225a5fcc94be9ffd1f185c88992529ea3 prerequisite-patch-id: bd219bf706ce0ef272e72b1649b3ca4b949f3374 prerequisite-patch-id: 57e549b6596e21bd3ccc6a499cee56d32a0584d4 prerequisite-patch-id: 3b785c2fe948fda7904b7a716dd832594bc13171 prerequisite-patch-id: bdde999968b76d9eb349df4da3722225d6697862 prerequisite-patch-id: b72231886e1003e7b9330ac5aa7bd362d76c4877 prerequisite-patch-id: 8a4b9ae19564bb79125074b5ea416a4a696f7eb6 prerequisite-patch-id: f8e356e068e91a4d5d67dc7e3b2c981be85d427b prerequisite-patch-id: 694b77c2d40bde39f58967ff115c52197248a955 prerequisite-patch-id: 91771507dd145993c04b732a5e673bad9d1a8cd2 prerequisite-patch-id: b8a6564d2637e3ca90031521c48488fff578c1a4 prerequisite-patch-id: e6cab312a4d0d4a8b0c9e4e2ebd7c8516e1adbeb prerequisite-patch-id: 447b2a2e0c1531956e2387463cf1dc255f18fa40 prerequisite-patch-id: b8fc90f31e71837cd7844299a20d911cde7b80f2 prerequisite-patch-id: 2a3a6ac888e56de6d9329b755a0883d19d408373 prerequisite-patch-id: f456088d55cbe54efa99a92ce1d45a367c66890a prerequisite-patch-id: aca9324cd23174d71ac0e2eccf5be156ddcd7e7d prerequisite-patch-id: d7cf8702604a02cc93309ba8a713524c3d4614ae prerequisite-patch-id: 80cd78917cf21cf24029204e4f760b2a6ebd513d prerequisite-patch-id: c9a70206e5881639cf5807983083112387d6f3d2 prerequisite-patch-id: f0193d9a41dad05e3fc3a8779db98d2d740f0d10 prerequisite-patch-id: 9e3e83fdcd2fa437256806da0daab860de7f321c prerequisite-patch-id: 73771ed935ddca253e4f3dc99d9d85c1c32acf9c prerequisite-patch-id: 22ed24e96fcd07333ebea17cc99cc1b127bbe210 prerequisite-patch-id: 237ec17c105411409747abca0398ca7e0279201e prerequisite-patch-id: 0de3ba6a87f355da53e902def1355e61baad2c08 prerequisite-patch-id: fa5875bd8bba5b65790c60f576812ef0b22e7642 prerequisite-patch-id: 527ef5f9cad99339182d3a2f8ae1de5b29d2b5c3 prerequisite-patch-id: eecbc5483d67d002e344c5015a88f92f3362a8dc prerequisite-patch-id: 95e515d7a0939da823f1a4d17422514196f49c47 prerequisite-patch-id: 55fbc09c0732f6e767f13eda0c86e5a39316fa05 prerequisite-patch-id: 5dc1dac88f427012b9d221179ccc85513f0c4ffc prerequisite-patch-id: ae462986e9b9b2b9c4bdd4eda6abfff06bbfa58a prerequisite-patch-id: 25ef85b3ff1e39c2807c934af0a0f9d1e6b90c84 prerequisite-patch-id: 3c2a9454fc0700d056b6c70a3ff774be0c008833 prerequisite-patch-id: 2263442fd9af8dccb1344c4e95c79cdf71adfa33 prerequisite-patch-id: 5550dcd9d154a780071daf238e53894155f87462 prerequisite-patch-id: c8ee73c8006ca1ae5fb3f97dfb2a27a5b6092e93 prerequisite-patch-id: 9b16215d19f6f03a82cb79b1926771d07617f7ca prerequisite-patch-id: 3ef4522174f535b89d28984553255e3ce1cef37d prerequisite-patch-id: 7774e94a17cf7a5d53500fb16f53bb721a475d23 prerequisite-patch-id: 7ebfb306071f40e16580296ff86e474736199a97 prerequisite-patch-id: 1ec59b11b989250590f9b52b689223204cd65e5d prerequisite-patch-id: f238d4d7186e301d18c4b973498b9366f98c8452 prerequisite-patch-id: 0a3563727d4422f8080bd922ae4c9a54916ec61e prerequisite-patch-id: ba6b6473eacbeb9b00a02a09fb6d975d5911c52c prerequisite-patch-id: 09c6cb203dc5ab7748fe46325e41b8898e51efff prerequisite-patch-id: 3158282b6d65f506681e08051a0d6b0efadd9d55 prerequisite-patch-id: 1c19ccac47dc435c2c61cd73326baec8116facfe prerequisite-patch-id: a6f4a08af83962dae1efc31e2691c69cf9e007b1 prerequisite-patch-id: 8d758ff0772c437072436151a484a5e837612277 prerequisite-patch-id: f6e40277904afe3860f3b287c14c63f79d21c32e prerequisite-patch-id: f4c9dae1969b2e83f1ef95b4744466b7760abf6e prerequisite-patch-id: 6072f05a52b29f5b9433a5b2801c40e74e1a4d1c prerequisite-patch-id: 544322637f19ad2073d8f36a6344806e620cc19f prerequisite-patch-id: f82a7437f7fbac861bca072268bcedddf7c20b6f prerequisite-patch-id: f39ee52a8e84e618cd77fec55835d37778ff4871 prerequisite-patch-id: 5167423f5ae06a563c8552a79c270aca1f881bdb prerequisite-patch-id: 636d751c2a9e281e0c3327071c1f7e736db1f187 prerequisite-patch-id: 66a2f1f3f37eb04596d3b086ec581d707d2295db prerequisite-patch-id: f1d3e065289e8756a2a36179a6f55126ab838e20 prerequisite-patch-id: 9e40ca16005e444cc68f81f96ddf9f25263c5019 prerequisite-patch-id: b017ffbeb1d6c41b98c57504b758076c78f41fbf prerequisite-patch-id: da707549d8ecfaab807c4121a3f6bc0bb01f27a4 prerequisite-patch-id: 69062950823906ff86c85771c8f9fd08b539b6ba prerequisite-patch-id: 9906f38be644a9bd85239a53c55f8a084dc5f345 prerequisite-patch-id: 583a4fc34811b04d98e666e3d1b57f4a8defdccd prerequisite-patch-id: 93f628a6f75d70b00a8b1f3590c6a71e4ef5a3b6 prerequisite-patch-id: 6e3b544b362fe97a7323655a7853bd05101f69ed prerequisite-patch-id: 4ad49e30ce2c4931920a99f004e0233d2adb20bc prerequisite-patch-id: 72f980aa23149b7be999f38457c9bb3b91446103 prerequisite-patch-id: c78943254b3f0c4887a1bbba6baa6ddfd77c7ddc prerequisite-patch-id: 7aa0e7114a5dbbd669f374757c0cf143a342473b prerequisite-patch-id: c9f5fae7ea26cb5ac4aeb7ce45263fd713ae452a prerequisite-patch-id: d2e3d1f7be35fcf081afa3baa8a336960dbd6b05 prerequisite-patch-id: 29969c8dd8d41feefecaa040f348985b7aa3be63 prerequisite-patch-id: 3b367da0b0c8e61d569f1d4160bb52b062472671 prerequisite-patch-id: 5adae13a9f60c9930e195d489b93400df930385d prerequisite-patch-id: 0f5f65ffb64a43cff95c5178d1a2ad26c8f083db prerequisite-patch-id: 940598aa8672639d55428b93de052abaf02471a5 prerequisite-patch-id: c7b300d19f930b46ed8e0409bcc3085f06d7f06d prerequisite-patch-id: 6002ea5ff79f2731ac1d23a1c8462cf35f064ea1 prerequisite-patch-id: 4c220d090f66cdfaa22440ab6f42bd9406e77763 prerequisite-patch-id: 976392040c0e2b303147dad6343888739a90f750 prerequisite-patch-id: 15e7e8cbc547147af4d0a7993367d55b2cc05bc0 prerequisite-patch-id: 18e73aeb1310fe7e31d68988cadcb93ff2f6d667 prerequisite-patch-id: 85a78028e8942e85135b1432b48c9d4f8ec034ce prerequisite-patch-id: 7c17768dbd7a8602dbadfb55f11e1f4b6b5374a7 prerequisite-patch-id: 5887835458444c67a2df8f8d58c0e0da134ec1f9 prerequisite-patch-id: 2b400713c496e08d85cf279b9d0a83665818d761 prerequisite-patch-id: d8019526227890838ab3be8a37dc7a98d2dc6d8d prerequisite-patch-id: e7793b5bba70e7545e1828f9000e0f4ccf327d50 prerequisite-patch-id: d5deaa49a686192f92f3c64a333fadaff6e83329 prerequisite-patch-id: 35895bd13d6f0414c9a3244192e42ff33a3622a3 prerequisite-patch-id: 708ff9ff776510e9bcfce8f9d4574577c757fca8 prerequisite-patch-id: 3be775b6b4d789c7e2737ed287ab18a7a3049e8a prerequisite-patch-id: b630bae5761cb79f68936012d1db32e137957f7d prerequisite-patch-id: bbb07fe6c0d5d95a2e28fb6e4b8bc6b9c278cd86 prerequisite-patch-id: fe5ce4332f1ac2e0323586c006db5a58516536c8 prerequisite-patch-id: f174422d89b8b8a6665255758e6be7d818fbf399 prerequisite-patch-id: 6a6463c28782c68e085e167ddbc57e4847364320 prerequisite-patch-id: e88b3e9844c12a81138f599f30bbfd81c642a1fb prerequisite-patch-id: 27d818bc470a342898d9fb83d39d6de8a93a63b2 prerequisite-patch-id: c9aca263c9e4b3539793bd248044a684ce142c31 prerequisite-patch-id: ccc448e5bcddd34e9a36b86bf47ee1d6b9564e01 prerequisite-patch-id: ce9b54cbccacb26b502f75dbff4958c95c1d8046 prerequisite-patch-id: ee8ff6fdcb6d3892684c53287ea0466c2ef14fc3 prerequisite-patch-id: 8bafc8f189e0dc6a2a3f2ab83b2d69d90a7a5ab0 prerequisite-patch-id: 1a666ced5b478ab83e9c5a09bce39e049cfa6727 prerequisite-patch-id: 7dc8cdee66caf90f2267f95fa9f321804758f287 prerequisite-patch-id: 2d786fc40e90ef2e29fe592429e5764e6e4c4921 prerequisite-patch-id: 8f4ed2ab5153d42097bee629d80a14f71a1ba76f prerequisite-patch-id: 689b92845fb8e99319b947e64c07b1f77788be2d prerequisite-patch-id: 23d5a1624d914b0d15fe36986488683af6aa2bd0 prerequisite-patch-id: c6c60220c9604f9479607ff8568d501ba4dec94a prerequisite-patch-id: 9cf4cd40796ab76bb08f8bdea3196e6eca0a10c8 prerequisite-patch-id: fffa61f73ec7a37fce07c2f2aba8fe12c64e8f72 prerequisite-patch-id: 28d0c2ea76304dfda9fc0dfdb7458090b697dac3 prerequisite-patch-id: dd25aec72f8af0a29f79b752b46e5e30116e9b82 prerequisite-patch-id: 850b114088db4ecdc0f1265bec0b4a2dbcbea17e prerequisite-patch-id: 3dba2954ad73c22fc10390346355e0faa089476d prerequisite-patch-id: 5cdcb64f4704826858d8603679aecdfdeddba650 prerequisite-patch-id: bd0ee7ad44663c0a822ab25481260a1d4c0d2ed3 prerequisite-patch-id: b3b9b1b18c80ebcee2591654c42e6df2db2719f7 prerequisite-patch-id: b0f6386cf084e281c891ac0ddc598732d7a7a69d prerequisite-patch-id: 288870b81a0ab7f115b0284f5cb758fb9ddcf1d9 prerequisite-patch-id: d0b87c15bfc36b96a604e75cf9e7af3b79dff852 prerequisite-patch-id: 93cb5409fe97e1ae0d079b1766aa0807bdba16b3 prerequisite-patch-id: 04e67073bc08b8305c59973bbc948c84e491feb4 prerequisite-patch-id: 7181e5d0e5275ea2639498013a16585b4ab611da prerequisite-patch-id: dbe0e58abb2e99c9482d6d43e41be3a88f305c5a prerequisite-patch-id: eaea428d674debdaf9e481807fa98977280b5a16 prerequisite-patch-id: 698af4f60bb6baa680c2b76dd297700aa9e5866f prerequisite-patch-id: f7904ac77d70a0f426c6c2f7370906abf641854b prerequisite-patch-id: cde47814a150fe47c90ff62252f1460d884be7bb prerequisite-patch-id: 80366359bfabd97aac5b1d9750c6fb1f0242a399 prerequisite-patch-id: 92549a42e1ffa0846e3bc4045439cb77faeec3ab prerequisite-patch-id: 5073538b042d7662fbbc19aa4653a70be396594d prerequisite-patch-id: be089bda3a3a60a3c72c6877458680112a6afc7e prerequisite-patch-id: 5fe2c890797982bd068010fec8eaf901101919b9 prerequisite-patch-id: 4e67d88432f7b6d4476ecd52492bcb82fe4a2e59 prerequisite-patch-id: b8fb3f2182fc9f9ef7d2bce862009c702242554a prerequisite-patch-id: e6b32205a4c51008302e612bccd80409677f24bd prerequisite-patch-id: 9e3d70ef269de16999048c53e1de168caad89d37 prerequisite-patch-id: a3c25a448a9bce0649ea740c19b2fa83d3156c97 prerequisite-patch-id: 0654f74e299cf2d2a1ab81033e4a380c3fe90120 prerequisite-patch-id: eb12632fa1e7b2941daa302ad48d86a91b11efe8 prerequisite-patch-id: e06d3d443670592068873abb22f02926dee40b16 prerequisite-patch-id: 160c61c118c3710aed82694476d8f75e0208a284 prerequisite-patch-id: 1d1e37aa40f4aeb20070419842669bc6f4db4196 prerequisite-patch-id: ea09823b2611dce94593ffc762d6d9bd2f88d6c5 prerequisite-patch-id: 000aacbb61e3f72b4b24ecd96c345054a23d380b prerequisite-patch-id: 23dee26629bdd37bf56570fea4b5ee3e849ea6f7 prerequisite-patch-id: dcdf4b50c0ee546b0ef68a73413ca1c63acb8306 prerequisite-patch-id: 9d1ea7177f2fb6541fe4c67856451240126da572 prerequisite-patch-id: ca403eb650dc37513cd231800c85cb89e8f7d66e prerequisite-patch-id: e6f8b3b0191d06c75e1d663ffed3f6c89067a3e3 prerequisite-patch-id: 6809cbdd27f84767afa3852b515be3ebb1fd3526 prerequisite-patch-id: 118415dd83d50a85f620fce036a0968b6590f1c7 prerequisite-patch-id: 3cccabe7621cc0bd7c3bb8d5525cd0fe2edf49c2 prerequisite-patch-id: 8665b4cd1631492ef48a8b2d978f3a9cc7bc55d3 prerequisite-patch-id: fb480aa48dfbf0440cf2ca2d01ff059641ef65d8 prerequisite-patch-id: 3e55043e4a03270c2a10a72f8de95bab79e4a93c prerequisite-patch-id: 59a4bd9bbaa73a30b642e29ceb2a5158467fc617 prerequisite-patch-id: 5ececb4b98fc993ce59fdecb11e7dd2c9005ef59 prerequisite-patch-id: c331e0f4e824552aad5a38ddbde77bd6dcc53697 prerequisite-patch-id: d9ccf138af90e329ce1c121825518780dc6a3eba prerequisite-patch-id: 4fc23afaeae9299da19cb5fe7578eb2a1c276374 prerequisite-patch-id: f0ece3e3495686c877d381d4836f843d67a55dbf prerequisite-patch-id: dbde23d608cfae7d4cd96cef5e29414bfa54e3e1 prerequisite-patch-id: fdc85d520b4393f2a3873913039bb200a98d7566 prerequisite-patch-id: f677148d575eeaacbe3a4fcf5d1c71718a237ff8 prerequisite-patch-id: 08bdb6b0871dbf058ae433bafb9ac2c5e73c04b8 prerequisite-patch-id: 9146fbb045dc5ab2815182fb8ba4a7b891cc7461 prerequisite-patch-id: bda520d1aa96fa932b970cb42e27875182a51097 prerequisite-patch-id: 315de2216bc6c4196a316274c00047063e5bf9a4 prerequisite-patch-id: 3bf3fc73094300b93cb4933ff9022784ae95df47 prerequisite-patch-id: 58f1ffe880ad36d5570c2987e2ca8d7faecc7fa8 prerequisite-patch-id: 74aad0f6b446e41ccbd2293128331e719db1527a prerequisite-patch-id: 8a47ad6e9ea68f858c1426ebc8180fc86c3c708b prerequisite-patch-id: c1d25f323d74ebb151d0310468cfc18bcee3d0e1 prerequisite-patch-id: 8d1b1046383e3498377a6f22ffec173532b68343 prerequisite-patch-id: 80ff6c2a9ca7a9c8244c4761b7a62043df1bb24d prerequisite-patch-id: 0cefad6ffa9cae8c3e8a918d972d8aef17595524 prerequisite-patch-id: 1eb971bc1e94dddf4c790445a48a3fdbfbe6233c prerequisite-patch-id: 0334c932356c426bb0b1913b35243949566960b0 prerequisite-patch-id: 819b2807f56a1d5317bcb86c9f506c637f6abc38 prerequisite-patch-id: 2cea3b67b30f629dfdf2cd6988c67b4086dfa07c prerequisite-patch-id: e32374613dc08bc370bfcc8981c216a0a37da600 prerequisite-patch-id: efece4f64097efc231edd76f4afd3fcf0f1ca4b4 prerequisite-patch-id: a854da66a031a87d102dcf9c47b48432e1b166a8 prerequisite-patch-id: 17a9c19e70fe8a31453fdf112095a1750726b9eb prerequisite-patch-id: 05b3e888564dee17546b32c3e609822e2514673a prerequisite-patch-id: 09f6afb23aae7c5f63b580af6dd06af9f079329f prerequisite-patch-id: f0196c22f75607fb705e6674a2c74dcb72ee0ec7 prerequisite-patch-id: 8968ee96140dfaa0ec6c623d3eb0721f4a8f74e3 prerequisite-patch-id: c9ae65ff0bb41b63c0d5058a10e8f4e45a88f87a prerequisite-patch-id: 77b8c0855d2bd7f30b18ea76a1e82985423b72da prerequisite-patch-id: 3afa2543c1e65d2d383860f25eddee07b0c99ab8 prerequisite-patch-id: c58f6c69c91eec8764b81ff75c063df8e7020b1a prerequisite-patch-id: c640bf20ebb4557e3fbe0473e97130153392e0b2 prerequisite-patch-id: 7e0dab3f2b12c44f4e43c1e2daeca450087b77f3 prerequisite-patch-id: 042abadc05839eb7cee9bfe2725b3305684ce397 prerequisite-patch-id: 1199c1321a9d80fa2f9f03908fff46fddb481628 prerequisite-patch-id: dbfe8523a12d788bf1194ba120ac0ddf48019f31 prerequisite-patch-id: f24ce34076777494fa0e9d7369bde00317442fc1 prerequisite-patch-id: 57796717bf12375191534425ff3401fc827fe20b prerequisite-patch-id: e6f72703057b4abe1fe40c34a895d14ae5bc5d5b prerequisite-patch-id: a9a4c2706d68c951fe1a879005c754a4c9460240 prerequisite-patch-id: da89c60d2c292e4b3381ec71948d1932545fbaa4 prerequisite-patch-id: b14ac7cb60e20ef86e5da5d95b20e395d141c50d prerequisite-patch-id: c2e6d86aed66443c10ee32e2a129f6fc2ce44542 prerequisite-patch-id: 010fce6ab672d66c1c9c8346276c8b5957c78795 prerequisite-patch-id: f2c8aac94f3b13fdf7e94442f1f60ff721caf170 prerequisite-patch-id: 0215a13ab8aebbaf23ea65c9e766a49ed132f869 prerequisite-patch-id: 012ab4329bbcea19ae0e13e30b43544ea7986c3e prerequisite-patch-id: 1acb4fa8f9c063542f1a681a1b302fe881839478 prerequisite-patch-id: 7327e22567aa0ea07aac6db05b40347338ce03bb prerequisite-patch-id: 4aec66cd20bc766d2ad640f03fad5c56e3879c77 prerequisite-patch-id: e587a1882a0ba8ffb7d5b22b63d3debf2c2c828a prerequisite-patch-id: 8d5a26b2572284ac80f5d3e8b5a6979fefa9dcac prerequisite-patch-id: cc469219a6e721dd176cc92538e815996aa1e6dc prerequisite-patch-id: 5a968cdfac09402a559ceaf7713255f347bc1b2b prerequisite-patch-id: ab8b335e95eee5ab7800f03f04b079c390b8c318 prerequisite-patch-id: 9beeed69ab3041e987473c739d623dd3d4150e54 prerequisite-patch-id: ab5450681ed054a48e27d805e24d384a17cc5ea3 prerequisite-patch-id: 7b7b971cfab95845d823c25fe196ccb88340fe29 prerequisite-patch-id: 3270acc24e4eeb13168a01edc49f16bd35cee0d7 prerequisite-patch-id: 4a0a78ad2093a7a73db22827938a0be62c3a0a45 prerequisite-patch-id: 43d66275e06947b45109af4048bcd65cc819e491 prerequisite-patch-id: c36925a6df18cbfc67613ab71a37fc9d5397b053 prerequisite-patch-id: 5a714c465f5345febe33998301d8e929c9842f85 prerequisite-patch-id: 5f87f645a26f41683376305d2f3089948ac61783 prerequisite-patch-id: b42ffd1bcda39fb6538b090d74fbd352e6937f22 prerequisite-patch-id: c493d768a24901348df8e5aedd6b686d2142e179 prerequisite-patch-id: 2d9017993cbdd5574559243f511170183069c903 prerequisite-patch-id: 3293bf4a1c7e3e60a99c162f33ab2c54dd02e980 prerequisite-patch-id: 523defe78fe885e987475637d26224e956a26e0c prerequisite-patch-id: 04479a19952500b870bee725910a1715b8d0ab2c prerequisite-patch-id: ca2de9eb00a50d748ba1818d3b1bb463c602fe54 prerequisite-patch-id: 14ad40e99ee0808ae1051e772bc20a7969c79827 prerequisite-patch-id: 0afcc8813adfb9119fe2ba4aaaedda06da04de0e prerequisite-patch-id: bed686ad95922aae0d82f4483e2e69b26c172b6c prerequisite-patch-id: ef685cd6fd9d79553c6c27e248f0e2e98bafed56 prerequisite-patch-id: fa5b931e2a616b00a4e285312ed0ae438513adac prerequisite-patch-id: 6a0a600927b8f64272a327e3a29ed7bef37213e9 prerequisite-patch-id: 84ef0533ccca702acc35dfaa98b53b431a7d9fff prerequisite-patch-id: 64a7315f71e154f0b07408d5cb61a42e230465d3 prerequisite-patch-id: 9bc23f3b9a3e2f65d483c2eb5f424e505f30b9d0 prerequisite-patch-id: c219a13608716fb7184813e0e34e4f84de74ee2b prerequisite-patch-id: 24eb9ec1cc85876e77eac3f681e79f7234673d68 prerequisite-patch-id: 9d3f4f3d31af9b18603d4c116e50fb7cc76f33bb prerequisite-patch-id: fe7363c66ed56f18c61aaaf5acf9acefe018ab31 prerequisite-patch-id: a2e39bd0a47f3736b4967edde7805f80d3f6c334 prerequisite-patch-id: e6f693dd971f0d07b99fa37f9a6712d18f59959a prerequisite-patch-id: e81684f551f5b5349696a553ad4293649dd3da69 prerequisite-patch-id: 55bbc9d0d2e7e8fa8be628b7587e02a29f7d6d6c prerequisite-patch-id: f12b5d13c3cac212b08c5341c79c7990e0382817 prerequisite-patch-id: 3e60cc22fc5f51a935799ee9b42a4eb7f5eddeff prerequisite-patch-id: 58240dc0f11c0ba5cd778e92f2b1aeca3d211d3e prerequisite-patch-id: 0a153b6cb6abc5118255c25e544a50d6eab294c6 prerequisite-patch-id: 28283c19b0edb9f23791ac4b1a3e7708e4417c4b prerequisite-patch-id: b08d2edb9c772ee2cdcaf8d6c24e1c1678b42617 prerequisite-patch-id: 088643c1ca0befe3a096226a9afd4bb5fa76b86e prerequisite-patch-id: 87429b5612919bd1ac44534cdf87bdaf71346045 prerequisite-patch-id: fa5aeb74ab4cea67ddea96f69347dcdd04b63947 prerequisite-patch-id: 27a92194c2add29777ab6f2d47bb9fae5c42ba86 prerequisite-patch-id: eea73af02251febc3c3a936ac66f926ed4ba9e25 prerequisite-patch-id: 20cd0c780056835351a402d77a8381a5544def4b prerequisite-patch-id: a646bd8732f22075db6613d9edba28e557d65279 prerequisite-patch-id: b0286f2d6efb8019703bd81c6baa51214050c97b prerequisite-patch-id: e8e9cd72f3a8c4d840c44057a9506ee2079674dd prerequisite-patch-id: 5bb0ec623100c321ac1f1ef83448bf9ddcb6404f prerequisite-patch-id: 2ede9f88cc7cc26cebca0f023566d7d725d919a0 prerequisite-patch-id: ee11f94c46236326a237d810fb1e8171098a3adf prerequisite-patch-id: c6156a19cf2e033ab6bcdb3d5799c07f2792c59f prerequisite-patch-id: 7181695af068599909226db932836fd94f5047a4 prerequisite-patch-id: 0c9b90224ec1894989a8460440986677cdb2f9da prerequisite-patch-id: a5c4f46f4cbbf409c13b046dc3491af3bfcd360e prerequisite-patch-id: 9dd0b27fb677b640423db10d6b1e66a22734ade4 prerequisite-patch-id: b50f53a640fb978ee0ee6b935ddc3699858883d8 prerequisite-patch-id: 8e401834fa84ad4ce859d8d5d51b8639b18004d7 prerequisite-patch-id: 1089ec140887f86f2cac711013fde39ddfc5e28b prerequisite-patch-id: 7a1e7eca963e5702f60a5145802ccb3c8aadf5ac prerequisite-patch-id: 145d2c53b8991059f8bfd4c998a77600802b2241 prerequisite-patch-id: a0c3ba38ce1567c7ae993fe81e99317c137ca781 prerequisite-patch-id: 48edfb2b1de83bf8e7794656f6a2d5552b034ec9 prerequisite-patch-id: 37dc2fe16594088a0e7519d1ce5674bad86f8071 prerequisite-patch-id: 90f174eec7d734279634484b1b55c272b67d65a2 prerequisite-patch-id: b460d54cb3c0b4b07e7c9a5656684234da4f6fef prerequisite-patch-id: 4bb5abee82e6358497cc7988f440c2c038febe8c prerequisite-patch-id: 748721d1236b05f1b0931d1dc57d34d3c18748d5 prerequisite-patch-id: 75b14d2946d5dfeaba57eb445ff0cbed9e6f7d10 prerequisite-patch-id: 01837f60d040dbc05c7701a40828142e290e0557 prerequisite-patch-id: f3fc5cb4cdf849bdbd813dd9143d653843cb5a20 prerequisite-patch-id: 657131241517e41e7b0672c844686f71924454af prerequisite-patch-id: c57ff31556731fd8c93590383101a07424d1737a prerequisite-patch-id: dc57cd3dd81e978ee6d16c1268856dea3811bea3 prerequisite-patch-id: 02243a81f7a22620d821e75ece595ae4c0765dc8 prerequisite-patch-id: 2f7e1a9de6dfbd5ac4e202ab53cbd4f1791bc1c9 prerequisite-patch-id: 5924a01c50cbf37ef33fa824435c896ee5e4b141 prerequisite-patch-id: 0b0ea30192434c866233422546b1ff043d510f66 prerequisite-patch-id: 78b22261f8e22d2ea6e93914002b5814e41f89a2 prerequisite-patch-id: 2758fbd1aaa93ab01c61529e76762617b87a4d2d prerequisite-patch-id: 73a39a2ecc8849ff20ac56b40e320326ef51736c prerequisite-patch-id: 3ddc29545f78ee7a8b3ccaf78c68f2fe447ec4fa prerequisite-patch-id: 8386f30438653af8d7b97e913a153ac42db250fe prerequisite-patch-id: dc0c7464c55a5947537d37d2822b762148a72f3b prerequisite-patch-id: 33a52a01ae91de7ad90a4203754f5132a116a41d prerequisite-patch-id: 7b9a4b730566ec4d1de38fe89f79d5d938aa9f84 prerequisite-patch-id: d102909d4fdac353b42f2bfa612fdd8d69dfab02 prerequisite-patch-id: 14303baff7fbc215a7f8e4474049d08a815e0451 prerequisite-patch-id: e49889e7abb53913150b3f1ca2957e6eaa8dff30 prerequisite-patch-id: b65d4160f285178707fe0c14c0b7e448f61643e5 prerequisite-patch-id: 9e1d49e1f53bb2044348452f29154a58a6bb4422 prerequisite-patch-id: aba8a61723aa2aca6352b99d88660e852b3f8fde prerequisite-patch-id: 9623867b6178975f02af641fd4984c81cf829875 prerequisite-patch-id: e078f4378760ec94f71ea8f4d10fa9e4d7e1d801 prerequisite-patch-id: 8c9060fae0212a98ad9f4c446934ab5a2380a3a7 prerequisite-patch-id: f10880c042b2e46478e15e17c98bc81eb26eed06 prerequisite-patch-id: d60a776c56dda8ebc17d80ebfc8afb28b928231b prerequisite-patch-id: 32b48e01629ec068ff4e93984601aca127b34739 prerequisite-patch-id: c1ba9f962de0c9ead33fb59227d7c68d6bdd6eb8 prerequisite-patch-id: 2346f48eaa4e5a73e69f9e5d153861e1f6578896 prerequisite-patch-id: 51e4a7195c64845de89a171e31c5cc0f9a3f4d24 prerequisite-patch-id: 345247a730869af403a66e7e058a5dd97d46b49b prerequisite-patch-id: 7a452d59a9507d696b378b83eac1aac1a92575f8 prerequisite-patch-id: 4fc1bfe85c4f7a11b43b984fc7514fd6d750d958 prerequisite-patch-id: 0b7dbe08be5fc978875c3b3c1b52c057740e455e prerequisite-patch-id: ff9ae713c5fccc672106ea3fd07475ab5e0ad8b6 prerequisite-patch-id: 258ec8c2ea7e14f759ac006b7359e20a4c1b933d prerequisite-patch-id: 042b1e89175d3605a2eaaf6dcea91d1d3c2a71f5 prerequisite-patch-id: fd65fdc31437ce3700b6fc748e5cb738b8fd3f5f prerequisite-patch-id: 3a878bca4ac00363967399e49079a2d2dc6d1a91 prerequisite-patch-id: 992747cb3a5ab1db1d4721152331e2c8470cdcd5 prerequisite-patch-id: eaaf2a0efdf91bfc8ee572dbff107ac26b3c02ae prerequisite-patch-id: 2a0f924139c04178ee5edd9ff16efecfe1722e41 prerequisite-patch-id: d9c07a23a73c5a3b294480ae0a2193de96969ef2 prerequisite-patch-id: 24a0ef9937a458af7d8fdae1cd978b1368536baf prerequisite-patch-id: 056d850b90432a6aa2eabdd37ed3983b1cf301bf prerequisite-patch-id: 3aa2d11bc4e7c7870941e0dbac807af37c5bb6e7 prerequisite-patch-id: e73cd6747707c205dc4461be2e99b3709f76a8fe prerequisite-patch-id: 3949907cc2a90b92a04b1ff91e8582d837a90235 prerequisite-patch-id: 99d6a04715b4ec4ba27ba2236f067da1533e2d54 prerequisite-patch-id: b2c7c46581232b9e4b2a197868efbd796a986fa8 prerequisite-patch-id: 4a4279b9a475f3f9a307e223b4213b1ebaa6a79c prerequisite-patch-id: 737ded9601451c5ab8240167d2035199866d86e3 prerequisite-patch-id: ca5b26d41e7c4d9b3a23187328bb57a02328e995 prerequisite-patch-id: b9d710adfe9bd7aa3a7470c3838ff110fe57edca prerequisite-patch-id: ccd0b1786a382369fc166b3d66002eff9e41f790 prerequisite-patch-id: de8ed802d40009d1f42e0a359b5ee10df7585caf prerequisite-patch-id: efa652fb63dee4bde3009724648c2ac30ea493ab prerequisite-patch-id: dab1bb302680cf7be91dcd00692d0b94e07ec69a prerequisite-patch-id: 1aca2d1c9faeaf26ead596abcf36f620c0f98c4e prerequisite-patch-id: 12105b51e51c3d3df20e10882f3a321ea6c93eef prerequisite-patch-id: ab32b418abc8ce7eeea14cc4749971b7f9b382fd prerequisite-patch-id: 3e1a22d5fee49b066abdb69ac47c798cf5293a10 prerequisite-patch-id: 864db9beab1e0818a0a7069299118c479769d510 prerequisite-patch-id: 9b46db845e98acd8578eef9213f743938340ca89 prerequisite-patch-id: a7ee68cba2e47f2e27a298923ecd72cda73caa51 prerequisite-patch-id: 8cb700f962525967a794ed2d79402c761d7f718a prerequisite-patch-id: 106b213a76d3c5358af417a303c177030617916f prerequisite-patch-id: 952c74b2bc7ccff6338ae19f129b3ed8e4330862 prerequisite-patch-id: 561e8ec30eec1299c4d7c0fb423e0a608d63e66e prerequisite-patch-id: 88e4a9b56433aa0ff8239a1ef8a8e0788dc1f066 prerequisite-patch-id: 67a41440dea093b4f394190f3fd84e210ef80dbb prerequisite-patch-id: b74a0ac3a5ca11d43476ff14b2ebd0f65319f247 prerequisite-patch-id: eef626b76b9bca23c6986a55227cfe0f4ea891fc prerequisite-patch-id: 2934c1ea12b69d6348f7fbed3836da97cdb2fa24 prerequisite-patch-id: 7bd35a6cf631f825ff77444a05a7bdc363714d7e prerequisite-patch-id: 0bb12fe90d4901f8a3cb09d6b420a0e18a0da6e4 prerequisite-patch-id: 940f69a09158ad4e9bc8ffe52f707b99e22a9a9f prerequisite-patch-id: 7a5c9cc2175b240734efdceffd944940904647b7 prerequisite-patch-id: 088f240295445e52cc12f7c836ba90915df1aee2 prerequisite-patch-id: af55a23be9ebb5f874b8c2c2d2ee4c2deed838df prerequisite-patch-id: 5ed3b82203e9def93bf4767b5c2649b72553852f prerequisite-patch-id: 42b43cf5413400e86406812fcba21e1a679c3938 prerequisite-patch-id: 2614e8108af0b55f82e8f1bff9fe69086bcda95e prerequisite-patch-id: 9ddb7bd461e5b28071e77f4ed2b2040c681591bd prerequisite-patch-id: 948e559385e109b5a33992f986f0825500650761 prerequisite-patch-id: 8fa7cf9892548b6e8532971c84e39e982e37e9f3 prerequisite-patch-id: 2e60ba08c7ebcf622363910acd714a341b1a0e33 prerequisite-patch-id: d801e1b77d3a683934fbb86d2f82a536d26bfd40 prerequisite-patch-id: bc574258367ccdb38b420d40693ca068a4f1bba1 prerequisite-patch-id: aab6275ec5c361da4312edb146a911e6f526b1e7 prerequisite-patch-id: d64e4e60696a8080b46c89b233d177e47a61a9ff prerequisite-patch-id: 4c1ba6f6f4fe71255d19b258f83ec99adb734505 prerequisite-patch-id: e609f2dc69a507a44d09f491c3916db00dbc309f prerequisite-patch-id: f162dbed27a194aaff3575e8a3390ddf01373042 prerequisite-patch-id: e22714a37cb6211e9fa9388a0693e2242b16f217 prerequisite-patch-id: b64096b880e33ae1d770d66052645f85d447620d prerequisite-patch-id: db59ead45b3323da17deb9d8628e7a0a820e2fc3 prerequisite-patch-id: 544c658c2aabd2bbab2e29797bacc718a45c5ae8 prerequisite-patch-id: 7a047626fc4f65901bd44f6d9ad863b96db12d15 prerequisite-patch-id: 2d5c4898ce26bbadaa383c275985a3f9b66333c5 prerequisite-patch-id: c2b932835bd5f92891b653d3973c6ac36e849c5c prerequisite-patch-id: 576f6888eb1710a9ecbb24680add5f56d9e93f68 prerequisite-patch-id: 1950380a1a837cc1322f3a31d0b8246a98727a0b prerequisite-patch-id: abd3b91dbca0efa1931710f2357cdf3fc68f3498 prerequisite-patch-id: 9593a709028c3ab87fbe474baa2ec665a6c570ff prerequisite-patch-id: 78c247d148f26c3e4f635e63a7fd137daf269158 prerequisite-patch-id: dc2e1155f40f73dc00199f100c4f903dbee0986c prerequisite-patch-id: f6ac9da3187ee204184fe0b1ffdbfb3dab7563a2 prerequisite-patch-id: 4f7186bdc016dee60685e0e986c46dba47985f62 prerequisite-patch-id: 48d4b3248b9295db37f83c1bad662dcf8a9e82a6 prerequisite-patch-id: ac64c547bde1ed32f49f91610dd2e82e20a40ed7 prerequisite-patch-id: 6b23de06f320dee92959d80f8a74daff7784b670 prerequisite-patch-id: e8ee4f3d9d22acc83410b5bbc6cf061826c4aa91 prerequisite-patch-id: 722da4955c5ddbad987275b9e4324cea79ce1ab8 prerequisite-patch-id: adc0c96d72ba04a1cd798142e9a3f6d3470576b7 prerequisite-patch-id: f213995284ac171a9d3d57edf8e9d99e76e97d43 prerequisite-patch-id: 0242d3a753fdc47255be5fed972508b080993360 prerequisite-patch-id: c7d930cc310596ecea53878a2e14032c2b140547 prerequisite-patch-id: ea8661a07cdcff453466afa988b733daea79069f prerequisite-patch-id: 07e7ae59df46a05003a1f3211105bec2a6b8dfb1 prerequisite-patch-id: 48db46923f7161e3d6293559996e36fca9d73ec6 prerequisite-patch-id: 23d12ed22b972df82bc8a4298d1b4de0e693027f prerequisite-patch-id: 02e5cb8e0483ffcf952ab53fa947a1d59921cb67 prerequisite-patch-id: 3d685a95206fa411ecb3709d857527323cb78f01 prerequisite-patch-id: ad90ba2642c3747b7b5f0d946dabe291eb103458 prerequisite-patch-id: a4c318d2abf07fe1b5cc82cfa922d56bb1442b82 prerequisite-patch-id: 7f7e127090c8afb833a5fefb3c9dbd1ae0ccb8cc prerequisite-patch-id: 198179e9f47e324891cbdfdc9a1849f5088ae1a5 prerequisite-patch-id: d5c0fb4c21221f58f4778eda2844046524437d71 prerequisite-patch-id: f1266e10144a15eb2a694fa7d1226c3a3ba795ab prerequisite-patch-id: a88639f8858e0850bebe2487ebcedfa90e6fbaa9 prerequisite-patch-id: 430001ec7f19403de5fba96a4341822f8ac8ea19 prerequisite-patch-id: 80aee43bae5dc47fe9199b648674c327cb6e6d5f prerequisite-patch-id: e39672a47c6bef8fe7d98a4b09c2dfc3fdfc9c11 prerequisite-patch-id: a19e92d1f52da359d7eede6d6aeee314dfef4d4f prerequisite-patch-id: 4a85d066ddb0fab26a27ccbcac5a0ea9931e5543 prerequisite-patch-id: 54982fd9214f9ac9c0a1bdafcab965e3239e9fa8 prerequisite-patch-id: cde3ae464b2a4f065fdcf5d074149c95ff3b3105 prerequisite-patch-id: bc6fc49b8f6d031bd293fd437035522489cd6dbc prerequisite-patch-id: e25340ec0637a3883300e047fec5a68071ffd676 prerequisite-patch-id: 854bd64260935ba60248ed8f05228827c792f59f prerequisite-patch-id: da2aed25f98adbabda4d0d7c656fcab1d1858951 prerequisite-patch-id: 978e6278fa26df89e0fb69ff836823f9793a3180 prerequisite-patch-id: f4baccbc2d67e5c11ec064cfb4b661f2306ec177 prerequisite-patch-id: 62b0c2f12926c2cd1c96a426b8f2c4358dd1de4e prerequisite-patch-id: cdcf97f66c67900491151a6a6931940c74652cba prerequisite-patch-id: a6ffd81b211350c62743642aa6205bcf07bab706 prerequisite-patch-id: aa668dee2e37d06fdb99d1ffdad92382be0ec4d4 prerequisite-patch-id: 5a20c52ee40a715909aac619067b0fe1329a9381 prerequisite-patch-id: 99292665a316e52bdf93938fcf445193dce8bbc8 prerequisite-patch-id: f9f91fb526a1a12c3cf9b905b06d7bc22e63550e prerequisite-patch-id: 2ac628f715ff3bf8a824393cb07f88bbb2c79585 prerequisite-patch-id: 1936e7b8fa49a078e00546f7b3875d4d0a2b9701 prerequisite-patch-id: 8b6483ccc91527987ab77019b67ae6993a453bea prerequisite-patch-id: 269060257d8086db1674d4f601c375b3ce76bc76 prerequisite-patch-id: 1a38cc31b8ed110b2a6edab20663c25570262279 prerequisite-patch-id: dd421dd241eae9d24a07cb82d423c61bb3dddfea prerequisite-patch-id: bd09ef20e52dfba7350289452888aa63bbb0f3e4 prerequisite-patch-id: 39a0011cc0a08efc6c57ee766cf95445004f29dd prerequisite-patch-id: 453ea230415e0baa130bf4089841b9e33dec71f0 prerequisite-patch-id: 19b379c7470addabe3162a2f1a397cc09da81a40 prerequisite-patch-id: 413904e428df69f13663d92ef9b4c2ebe360e531 prerequisite-patch-id: 7a19ac99d05b845ddabb5a5b4a487dd9afe7e753 prerequisite-patch-id: f204ecbfae8da3e91e4f5e7f1ef6b0ee3e916e61 prerequisite-patch-id: 819544585575125fc6512f850af356b3f331c449 prerequisite-patch-id: 621125aa001bdfc8f9dde30bb139668909d3fc8e prerequisite-patch-id: 6d745385e11bf39537b5b0390d7f1d6fbda2d024 prerequisite-patch-id: 269060257d8086db1674d4f601c375b3ce76bc76 prerequisite-patch-id: 1a38cc31b8ed110b2a6edab20663c25570262279 prerequisite-patch-id: dd421dd241eae9d24a07cb82d423c61bb3dddfea prerequisite-patch-id: bd09ef20e52dfba7350289452888aa63bbb0f3e4 prerequisite-patch-id: 39a0011cc0a08efc6c57ee766cf95445004f29dd prerequisite-patch-id: 453ea230415e0baa130bf4089841b9e33dec71f0 prerequisite-patch-id: d4c41c68a9d62d1d7ca830b19d300a3facf0c3ba prerequisite-patch-id: cf6dab9859204012518546ef1cc65a3f2403bef6 prerequisite-patch-id: 2df0f634823a2a4437a67eb0ae24ffcb9dd87481 prerequisite-patch-id: da9971f079919bf1f5dec7a40e8b026f84411307 prerequisite-patch-id: 9673dfdf23b6df7ccb267934f6977e10b0c17df4 prerequisite-patch-id: f474c160b5f63da06fe5f3291914da9b17c34713 prerequisite-patch-id: c333872a1a2abb8361e13778375b14d73fde8263 prerequisite-patch-id: b9f44399b889d008a570b80006d3f28abff4b923 prerequisite-patch-id: 3009183faca47fde07b9bc37397bf45e3e2f90e4 prerequisite-patch-id: c72c397791a4e53cbe1615048855664b00b0bc6b prerequisite-patch-id: 8e5904b01e738f1a1cd6aa71b6e773ec58ffbb00 prerequisite-patch-id: c7e423901f365d8a22d63435f24e436d5d2a41f5 prerequisite-patch-id: b3e10092ac3ab86f4c178b63ad7e198c12643495 prerequisite-patch-id: 57b193a4a015a33e55fdc648f124a17e90f24cf5 prerequisite-patch-id: 7ef0c8b3f6f13929bea64fe818797c20a3fa1c0f prerequisite-patch-id: 4b1d4d6700fb92c0dabaa571fc48f229b3cd0bb4 prerequisite-patch-id: 2ad5937f5fb7d024258ac0e1736f45571cb42971 prerequisite-patch-id: 6ae363e72a59f84317b074f71eaa60158e5411da prerequisite-patch-id: d3f66895feb9bd74f61e4974c4db2f5b8da6f1fc prerequisite-patch-id: 78d232685b38bccb1bd7824c570f88f7af9da3f6 prerequisite-patch-id: eb100ca24e83b840ec682f9f95ee9f69e2d99276 prerequisite-patch-id: a00dc0a669b884c716816b6060fe5314b4be901b prerequisite-patch-id: 62ab02ecabcbca3ebd821c4500758ca4c9b7027e prerequisite-patch-id: 62e278d24166740219eb1d5b68a6520907bbc57a prerequisite-patch-id: 90834930dae884b2001d4cbe08a467a35c79c81c prerequisite-patch-id: e5acaa01a2646944a9c8166fa6de25626b3b9b15 prerequisite-patch-id: 14f351d538d6d2ea2e4276207bbdd566d5d41cf3 prerequisite-patch-id: 00c691c7b4f861c96ecc5dc20246b95d91f3af69 prerequisite-patch-id: f352c3e7256b99a5537ca654eb5179c4efdbc055 prerequisite-patch-id: 62296ab4f9425767af5eef82d7a116d7eac5544c prerequisite-patch-id: a56795495204b6b086a6e6cc1b3a6dc67f9e29a7 prerequisite-patch-id: 219a7152cad13ee5c6b2445990528187761f5d7f prerequisite-patch-id: 1195b606b2eb7b97e9baf24dfc804b62b9ed71c6 prerequisite-patch-id: 37f5682537c50f2dcd999f99ecfe2dbe2c290cd3 prerequisite-patch-id: f64c0f2ad5229bfb0b2222e845f7ba747dc86ab2 prerequisite-patch-id: 1221067ddd2563d8a2d6e0043f4ba6584b2e95e2 prerequisite-patch-id: 8e1c4367dccf6c109925be7a1fc83f35be22d5fa prerequisite-patch-id: f495a25b23b6e9098c8390fc973a285eb2f16dbf prerequisite-patch-id: d6e23eb698446e2bd6e042be7ce69c8ad1332fc1 prerequisite-patch-id: be0c877940c7c0d618133c0a5b0a4f9217f6bf17 prerequisite-patch-id: 9b87bc084f5e29327709d56bb26690554b245727 prerequisite-patch-id: 73a9f6818d19469dc2b34ca17df8cdd6f746432f prerequisite-patch-id: de653cdaf7cd1b6b48705b9c03f1e5bcdbf0416b prerequisite-patch-id: c5d838c7c851032e148382fead3efca0b601ffe6 prerequisite-patch-id: 614e56476640d521b855bcd8b1767dfec116de81 prerequisite-patch-id: 925ff8294d26ca3bea35a1fb46db709c61fd2c6a prerequisite-patch-id: 28087fdf013ed8ffdb5270292977ac76c6dcac0c prerequisite-patch-id: 09564bc8d94df8329ba83c5e13a4284a29051e43 prerequisite-patch-id: b32d7e35974a8f575c7af5c748a2d2030dfe9a4c prerequisite-patch-id: 134ca6555cfc5629ff4cef4650b31b724924cba2 prerequisite-patch-id: a311f950cbb3d6b6f236a391cf298df5d4ae5306 prerequisite-patch-id: 0bc1309d3e7f8ba9426e57c6d9c6367581b86b32 prerequisite-patch-id: d5658408fdd96fd97ca719f8074276704e6b1cda prerequisite-patch-id: 8351d80dd1b27990342ea9ca4cda31e87d241b8e prerequisite-patch-id: cd131c728f1b9597b7f0b07c8114f346b604993e prerequisite-patch-id: 128faa82b77bc1b37828ddd23fefef7e0950fbdd prerequisite-patch-id: 098d8bcb5a3cb914d6cfa4fc70321e97a216a2dd prerequisite-patch-id: 650a617ba4413efa384b90a3c3165702804ffdd3 prerequisite-patch-id: cb154bd2cd286242e78536eecb557a349c6a23e2 prerequisite-patch-id: dcd9d53b2266bb0d802c05e0ccd4344d3881dd47 prerequisite-patch-id: da862229047c252f41e3e241848cde351034065f prerequisite-patch-id: 7d431af7ab9d46043d304590a0ddd548f23ad214 prerequisite-patch-id: fbb1ed558951c23289f09fbac6c0150d8d21e12d prerequisite-patch-id: 97ecb0b487a2fce287ee5b1c3ac85fd878eca659 prerequisite-patch-id: 8effad9e140890fd95ba7f961f4b6b3a607da32e prerequisite-patch-id: 7b4083bfda3df16b267aafc8116454179f3bd415 prerequisite-patch-id: 37edab70a4944b7333a89dd4fabcabf8a3785942 prerequisite-patch-id: cdedcd9ac8a415982c52287886e83920e4198a07 prerequisite-patch-id: 1b4fd01a48468e50ccbd48e907f3fd95b63e4e69 prerequisite-patch-id: d72bdf17b893459d7460984922072b7706c44089 prerequisite-patch-id: 0f9de2369a9aee529b2219e797dddf58b0277d17 prerequisite-patch-id: c2ccc1d3b37f0bf978074c4e739a00f4aacd1b07 prerequisite-patch-id: 6999a16fc58749105eac7993203d56f527982e88 prerequisite-patch-id: 9f6627d2fec3dd4075192f2ef12dc636f9ed75c5 prerequisite-patch-id: 0ff40180717143bfb7c6d0bac6c1ec2b37625c6e prerequisite-patch-id: 456a764747dcc5056048abb24697737c6ebd40e3 prerequisite-patch-id: 2153d52aa5b0c24ce23b2794751362ea42e2230d prerequisite-patch-id: e2671c4401eb1f22be00171341c779b244f199b8 prerequisite-patch-id: e9f27ccada3449d69a9426557c66779af288b0c7 prerequisite-patch-id: b2987a6f5be5587983ce1980026e6d3489417f18 prerequisite-patch-id: 7c653b341e6d3675ab40add31e08bc12a2d4f18e prerequisite-patch-id: c91c1054816e328c790b76b17cff37f45d2a0d05 prerequisite-patch-id: 87188356a908125035e73fcb8de960535da9b298 prerequisite-patch-id: ed958ba68650522f2c2c8b1258fa3ee7f8d52546 prerequisite-patch-id: 3d236e83b04bf798c8681e35d6085c62b7f99257 prerequisite-patch-id: a14707e40c25c2df5d5b8bf536202e20be57f174 prerequisite-patch-id: 4d9ebaa2d7e3f6a213da706082679ba2520c7e58 prerequisite-patch-id: 9dee3d373bf4d14a9ceb72677f6c0d4b1805a561 prerequisite-patch-id: dc89cf8147b3166d5139eb375ec92bf2a9cd0e86 prerequisite-patch-id: e849c7fe2d7840194c6778ada0bd91be595e7751 prerequisite-patch-id: 2a4377f60394000709c0eecf47343c4de388be51 prerequisite-patch-id: 35a66b355335efe6dc255386c38b1bc2fd2d86da prerequisite-patch-id: e4546d2ebb01cea5e89b9051b353364c846ceeaa prerequisite-patch-id: e22698e9c8acee454ad0224f8c4439080e009243 prerequisite-patch-id: a1f7207ef961ba62b04bf61fae342536dce6beb9 prerequisite-patch-id: 1e7d08ea78c37678575768695e2a8250aa33c070 prerequisite-patch-id: 2528cdb43220719742e87677cab5b7f2edc34943 prerequisite-patch-id: 9c0d64e42ba2c945970ae3848fc2892ef9781ff6 prerequisite-patch-id: c9f9f6c7d09bd0f18674347d494e6f3f16fa71cc prerequisite-patch-id: 6d477b088dd525b730242fbee5abf0d543ca38a5 prerequisite-patch-id: 9b3ef42dd1c926e13fe4d9ba3cab24bff3217492 prerequisite-patch-id: d9a865feff6f5750d66eedb5f5ea5b2579b5c73b prerequisite-patch-id: d2fa1edb6a3196d162b2c1091f59409500fb7f91 prerequisite-patch-id: baab4612e670783b5b91a72358558d669accc5f8 prerequisite-patch-id: 6f91f829cad287425a56f574887bce022f137689 prerequisite-patch-id: dc14de4ad7dd939da9a0e234d0685a77d874166f prerequisite-patch-id: 9da98deb1e9dcd1df30d6853a1550cd8487a2dfe prerequisite-patch-id: c4b646cb50c1c8adf8ac764957b4ff5f4af2aa64 prerequisite-patch-id: 42dbd98ff52e82848134c6092f48c720d5385974 prerequisite-patch-id: e63b87bc6901f8dee0ca448a98e8494b19d0f432 prerequisite-patch-id: 62f6e5a075b52e8169150c81ec5493344ccabab2 prerequisite-patch-id: eb4328d63ba3f909d3998883a0f6104bcd8bb8b1 prerequisite-patch-id: f9d3e1b9ac66557350ae14a199b871a7ca3913cc prerequisite-patch-id: c750355c98fcb89cff0d130213ee947fd8c08554 prerequisite-patch-id: cf645de29d5dd11e10934ce53d2878052fe4b4cb prerequisite-patch-id: ebe9d34af42605608c1801408b868038deae3ce9 prerequisite-patch-id: b391bec3f476a19d7b1ffc0b01ac56946487a52b prerequisite-patch-id: 1c460f1c7752908eb0315e8fcc03f1e75de42eb4 prerequisite-patch-id: 08dcadf65be6dbcff4e80b27cdfa5874909b1573 prerequisite-patch-id: fc65c49ec452a3f2b6bc5166522f78f30ab4a7a5 prerequisite-patch-id: 58aac23e32748b038c04104e6bc13cc64e0230a1 prerequisite-patch-id: 74def7cb2967dd683de2463f985c15a890d41106 prerequisite-patch-id: 7f69c6ec051ad8d7c9335223893f441f4caa74b3 prerequisite-patch-id: a949d9aae6c2bbd5ef9a5f04d06f905df672edb5 prerequisite-patch-id: d153625b21ad7c6f5d40fe80a1deb2c2471319e3 prerequisite-patch-id: 52fa933bcd8577b1b65e13ac2d6d2875c6f4a0f6 prerequisite-patch-id: 3303fe7d708ea02cbc01e9b33d9adc8a9b1c045b prerequisite-patch-id: dc6b13086686477c88514d778d7e021be1b0439d prerequisite-patch-id: 9afddb6d1c545b33c3a16f600a28c273715d7ec2 prerequisite-patch-id: 7c591b9b2cd0fb17dfffd973c500e0cc8bed13e2 prerequisite-patch-id: 3a9579433efc826993f6fa181c1246381b942720 prerequisite-patch-id: 8740b8962108269b39beabfe181352c2018bd2ae prerequisite-patch-id: 9489c77fe45f1836e61dcf2dc0add9c14ae87835 prerequisite-patch-id: 5268285fa7f784f335fa6a2fd7dae80ffbc4faba prerequisite-patch-id: 922fa63fdf669335d6272314775c534d3a41b387 prerequisite-patch-id: 23cf0e99e8b6e865939d71f6132ef1e5511dbeb2 prerequisite-patch-id: 51374e205ada637fdd87d4e55295efac00c68147 prerequisite-patch-id: 7e0e6a94e09e25d4e2401c70203fcd80ceae8135 prerequisite-patch-id: 1b1d2edbc35ebf54734ab955c07434889cb6b14f prerequisite-patch-id: 2dc0189c53c564a1cf7e186796081107d8d998c9 prerequisite-patch-id: 19ff0e48f658998265b90ba548ea819aa2033edb prerequisite-patch-id: 6cceb99904b1ae24537a4bae213b5b947d0633bb prerequisite-patch-id: 9b6935ac6a62908cc7fc8fb5eebdd69a303848af prerequisite-patch-id: 46abaa77996099b9cc1348d1df00db37277d1477 prerequisite-patch-id: 8dcf987452b7ddf9f7fff0071f8911dfcad13df6 prerequisite-patch-id: 944bae44b757d60f8cfde4b51b122cb4414616f3 prerequisite-patch-id: e65cfea6e2866daf14a7a37dacb37102c4922c76 prerequisite-patch-id: d3af95a8aa5a082e7e89b2653aa2abb5da01d6b0 prerequisite-patch-id: ae8de7ed1daa93d3d61679b7582e47a7d8903cfc prerequisite-patch-id: 81a191b3333d6100f7f159c9afdfaec7d0237f6f prerequisite-patch-id: 4f8f93e2c86b1922d7b3c5f5e30f73769f1ca27f prerequisite-patch-id: ca724f4401c127330200e75d7886b28e7b31c85a prerequisite-patch-id: a6945d184da5edeb8108d900923b76f17a1cbdc4 prerequisite-patch-id: c18244d6a3307605baeb67b264e192b4c4785025 prerequisite-patch-id: 883f04f4b83309fb04356bdf60f290a75d8f41e2 prerequisite-patch-id: 65694713a9a669b798aba4dd394fbe0387029553 prerequisite-patch-id: 0f86a65ae664c567386e280c7d38f27856bbf2e6 prerequisite-patch-id: adcfca27fa170a77c9ae892e84b434d7c806933b prerequisite-patch-id: f7bf4f2f5186e1d084e4332f06b5834cd3575c98 prerequisite-patch-id: d496a61c049551397487f6083f9d41b1f236f3b2 prerequisite-patch-id: 521f951f7434c1676c225337de363f315460666e prerequisite-patch-id: 88d5e59e75185cafd94a4643eb4bcc28a1d99cde prerequisite-patch-id: 28491f473b86cdb3c5a1444eb1e552a692c95b88 prerequisite-patch-id: af11925f06fbf6410b34dcafe6ab3df3c44063bc prerequisite-patch-id: 225be2e6be689548a1ef6c9777a64d9d3c748f94 prerequisite-patch-id: dad17ffd28fb0292757a51726bd97f0decd610ae prerequisite-patch-id: a39d9cc12e3ffb9e82a2472864cd141efeffcc58 prerequisite-patch-id: d3ef2aea15c10fc636437281b6d7380d8269d576 prerequisite-patch-id: e2d79a5e6545fdedd9e8e2abaf4afd90a3bbfb8b prerequisite-patch-id: 9f8cbdf10149eced409f5a9fa99a05da3a5ca1d3 prerequisite-patch-id: 316958bafd10fc2f9305bb0657036cfc433a0b62 prerequisite-patch-id: f3eb822ab427ba8958838f1feb48eab4560d0876 prerequisite-patch-id: e59a304305a9f3296c683937f52944ed9f5350b9 prerequisite-patch-id: 39039d12b405868bf967f6e516a56dec1e8b176b prerequisite-patch-id: 97960e7a8b37c5d2a9c571d76d3e110837cded69 prerequisite-patch-id: d2d6733de2c3a34aabd4c978ee220e9cff232984 prerequisite-patch-id: ea15bbac1d59921b5772aac85f9dda79f632cddf prerequisite-patch-id: d7af91e94abb7d34477edb868e94092fa87cc603 prerequisite-patch-id: 2b43786227e51eca3d75898d177e103b77f0424b prerequisite-patch-id: 424d53139a06b4de0338620534ef9cc7277736bd prerequisite-patch-id: 8dc27bc085f906aa108b87567658c01760c3d103 prerequisite-patch-id: d853104e955282a75e6ff5dc6ba3773299bc3fd2 prerequisite-patch-id: 6f84e39f19119abd21ebc897fdcbdb071796b996 prerequisite-patch-id: 5530a7f3711a52c471eeb73191e2b7bbd817b683 prerequisite-patch-id: 34bc4fbe6cc555999a81d8c2d206c182bb0eee39 prerequisite-patch-id: 3792d1a25b319e6b89f01d771a28d0c6dac07c52 prerequisite-patch-id: 77c181289e2bdbcb17c6dd12b1fae7306a781472 prerequisite-patch-id: 6996dc776952ecaea3f165429ad020d475f83e2a prerequisite-patch-id: 1503e4cc2f6a826d9a4056f086358f16229bb809 prerequisite-patch-id: c8da8e184ea57f632ded01505218851281c692e9 prerequisite-patch-id: 67e9c707aabba68a8f48c84e62c0643f1db3bda6 prerequisite-patch-id: 7cc2421324a29242631f6cee9de72bf47411c3d3 prerequisite-patch-id: e9d5d7f43719797b8d3aa8a1cde5a8f4e346ce64 prerequisite-patch-id: dda8eaeca1a7973736b393dd8d45880e83b18666 prerequisite-patch-id: bc3ac1a2518e4ac26d8811c1fd1c2fd1bc5cd9a3 prerequisite-patch-id: 4b88153ed0caea8562e40272acd62e7c053982fe prerequisite-patch-id: 133b6b0a9d98e42f8a60569366fd06912cf565b4 prerequisite-patch-id: e0c58909847df30d73ba108187c01353fc5e90b1 prerequisite-patch-id: 2ada6f000dc1bb277d9f4fe7bcfa6d27d311eae7 prerequisite-patch-id: 945b6265a0832791c17eba0df392d2427f116241 prerequisite-patch-id: 9d6e47a153a7fea05fdbbfa763817ba53b58b258 prerequisite-patch-id: 1109db62ce858d789bcbce3855758c1b022085b3 prerequisite-patch-id: 1cfe9fd636a026b51f9fe76fc1a6254da34fa92b prerequisite-patch-id: cd7e79188ae3ecbc2cf707493d82c14aca2f7732 prerequisite-patch-id: 1a583c9e930fd07cdec8b6ea656e010537d3c9a3 prerequisite-patch-id: bf03ad2cfe40191806762922c1a9796719aabd23 prerequisite-patch-id: 3b31d0682800ee1b1fae1bd841bbd63f99974168 prerequisite-patch-id: e1708a7d63385be611cfa23f7b7b749499cc8dc0 prerequisite-patch-id: ce1ad728dbff18d9c7a61223905cc70d5eea9830 prerequisite-patch-id: e7680c3e3225d83573ee8b6e71c04137250154de prerequisite-patch-id: 87a6d68288907ea432f5472d09543e781a514119 prerequisite-patch-id: eff3211f02d78c1c987395259bcc9df14bd4633e prerequisite-patch-id: 7f04901784f55450f957bde64c870942dd04e632 prerequisite-patch-id: 68516c8bf8869f104d2fb8febe009f954d902b61 prerequisite-patch-id: e3424cd1f85cc71ff0e7a1298b97250c6f48d5f1 prerequisite-patch-id: d659bf18d0a4a6e17f351107c7116e1bedd89446 prerequisite-patch-id: dd6b60be202eaf92eb1b491aededa39beecd6b38 prerequisite-patch-id: 77af548188d90ce3d9a7af736bc0e54223017b09 prerequisite-patch-id: d63d1a31fa7069cb919682f781944f2d4b2c1d25 prerequisite-patch-id: dfaecc198f882e0cb9c07bcb35c252097ba126e0 prerequisite-patch-id: 5723953b3bebd2f6752d8045286631c0d7779550 prerequisite-patch-id: 0714909cd70b4f40b6c0c1c6e59811660e99fc7b prerequisite-patch-id: b3a96d9c0d41f7f4c8bf4ddd4d88fa53f183824f prerequisite-patch-id: 19cd49f82b36c7a7cdeae8e13e9788a8c05f366c prerequisite-patch-id: 4540426e44ea2fad1ca3761756b589e5a05ac3a6 prerequisite-patch-id: dd89b5d4b5b5dc31b31c24b46655ce208cdf21d0 prerequisite-patch-id: 3d2e146abfacf9899ef96597333867a22050991b prerequisite-patch-id: b2790d4be188bdf4ad3941e36eaf4d636645307b prerequisite-patch-id: 26323396e121aa81bdfac4ffa2d373c828a2fd12 prerequisite-patch-id: 7fdcbe6347ff156edc7d373553c54dc525d561bb prerequisite-patch-id: 15f6dc532ddf0b87d8a7e507c955b40e6bf73861 prerequisite-patch-id: 78e80c1cdff9a400798f939f6bbabe419cc079ec prerequisite-patch-id: 51236d284c10436c2b17269054e7414384ab3f2b prerequisite-patch-id: a4ea5464a083e9ae6351f94227c7ba81dc02ccb9 prerequisite-patch-id: 4979025ef7f1c6958444c2fc95d0fcf65e5d0f1c prerequisite-patch-id: 27096d642efd8b04e2a91cae6f7219293c9ad6b6 prerequisite-patch-id: 3dd12143cf4cf250d6a4aa795e81cacaeac73505 prerequisite-patch-id: 49951002e44bcff723a9db85d2c6a22ad74f88a3 prerequisite-patch-id: 62a44454df72d935cec6877ace78697b43a65145 prerequisite-patch-id: e77c85b505a369a52ff87b65a0e7c4819c1ead2c prerequisite-patch-id: 20fe16ed8859869d45e82fb8140397d7ca5648c8 prerequisite-patch-id: 70463dd5205ab58c1d0012062b64ff6acfa6ddfd prerequisite-patch-id: 5688a0e23f078dee209fa41141641d838851ad41 prerequisite-patch-id: 527506125030cc54def92afc03d16052d6a4d93b prerequisite-patch-id: e635606be37e645bfb03510babed92426726951d prerequisite-patch-id: 0e4db14911f3b131d4fe4986d546038c2afc75b8 prerequisite-patch-id: 47e7ed8736ec229f4113bfab93e872525359db45 prerequisite-patch-id: 020187525ee23ec30fbbde0b350f232345986b65 prerequisite-patch-id: 9672f58f53cc9d18f851ed9ba8e6999981dfa86c prerequisite-patch-id: e597ba9e9f3d370cf216107d4fce20d7ab14cee6 prerequisite-patch-id: 103e53a73edef7ec8c5f282de808ad3477f98987 prerequisite-patch-id: b6f9f51b605d26406c0d3db775c1c99307d468e3 prerequisite-patch-id: 1354b42f72dd45069a6651ca3326acacb46ed67c prerequisite-patch-id: 36ab714244cfb875f974a4bbc41b533d6a5199f7 prerequisite-patch-id: 3fa7d5b887ebdbc62e5606fd9c1fc36be1201a9a prerequisite-patch-id: c38fabeff5d18e42df42aeec5ad803fe73ec4f4c prerequisite-patch-id: 2a8be1024f6606f4b8615ad4c9c8ed8ef2444e3f prerequisite-patch-id: a7a43612dd7d5903e2c3db705c22800d2716d6f7 prerequisite-patch-id: bf9272e73ee17f19a67478d20024cbe868bf7fe3 prerequisite-patch-id: 32d63d21ee3673204c08835de6d815d470ece07e prerequisite-patch-id: ce5637f59e9f3f805d736e89fc931cd0790aaf7e prerequisite-patch-id: 84963a450ddb21f75e454621afd16b67e86bd797 prerequisite-patch-id: 9a4f0b9f89043d0f0ed34aa3aaddbc1712c269dc prerequisite-patch-id: 5f6ccfa5cf3c59ab88310c5acddc955e39f3f473 prerequisite-patch-id: a063dc60f3a419570787ce5c083e107ab836fe96 prerequisite-patch-id: eaf5b981c45b2895d3e3b924d92a52ddc603709c prerequisite-patch-id: 5ef580e13665be198582155dcfaa11b30fcab323 prerequisite-patch-id: e6bf41db14eae554c1d927258426182da27b1338 prerequisite-patch-id: 5e7226cf432f227fbaec14b54b55c62375de0137 prerequisite-patch-id: 82505d9095a530f5b4ad60ee2f25ffe291651dc4 prerequisite-patch-id: 528d5874773ed71f3a5bd647698908f029e0bd75 prerequisite-patch-id: cc230e576a90314163fee102c2c177cd48d357c7 prerequisite-patch-id: 6c1edffe5f57d5dbd731c3b6f41ae7be95afda79 prerequisite-patch-id: 528d5874773ed71f3a5bd647698908f029e0bd75 prerequisite-patch-id: f638c8dab84af960d2d86dc21f9400d2fae663d6 prerequisite-patch-id: 299153835306b29a64e75a63bb905604e62fc3bd prerequisite-patch-id: 05e83131fa69249f4b2e885e604675aa2562571d prerequisite-patch-id: 4e89faa3a076845839fd38d796d5124909a86dd1 prerequisite-patch-id: 77a95617750bf34ebf151f70aa7f942d85d8f0b6 prerequisite-patch-id: c184818a72cd0278bf755aab70b3ebcbab33c430 prerequisite-patch-id: b774f4ac7742f0eda4685c0f0203358a26d6bbb1 prerequisite-patch-id: 5719b7ad1197cbfe48d5db5f02dff8e1cb091d17 prerequisite-patch-id: f29b3a5c21012a6fa50b0a17d5266c88b7ab3c68 prerequisite-patch-id: c036e6f35734ff471c4addeab5c18dc55bfd7f12 prerequisite-patch-id: 342c519a278887905631113e22608d5291b06638 prerequisite-patch-id: 0164de39b7006879dac885fb727d3214aa72f7a9 prerequisite-patch-id: d5c2b8b6b8c278baa72d85242adf184f4405665a prerequisite-patch-id: 8803de24a3a0f8fc2fd0bc6500bb4f5bd014a3da prerequisite-patch-id: d2279a0d3bb555e0011de9f1471bc74f933a2d71 prerequisite-patch-id: 62a93c7d7a3c03c420a4db6242fda0ee218d6024 prerequisite-patch-id: 771c47acc58514a1dbab265894f6e8a5055587dd prerequisite-patch-id: 954f39dd2a19c14a047a1db0c6f088d257341d86 prerequisite-patch-id: 1afaa4d81bf13c93a38a271ebbd384bc811b694c prerequisite-patch-id: 9d4b99a012570dc29a692b182e7bf6362255dfaa prerequisite-patch-id: 65b0f4d7b9734b6c710c865b780df6bf1cb14739 prerequisite-patch-id: 75038e93278e4c3fd45fa8055b4d84eb60e1435b prerequisite-patch-id: c67d70737678ef078acd3119dd897a29d0c5a9e8 prerequisite-patch-id: b2fcb23cf6a2ef4ca92cb4c89f5284b4f4e9c1ee prerequisite-patch-id: cabf75c184d0ea8f064fcc456ff85b76bb64e404 prerequisite-patch-id: f1a5e441ab75cd4b7f40a7ccbbcc86bb518cf330 prerequisite-patch-id: ef1998d5d5ce34091e109be1bd8f6b762d505a4e prerequisite-patch-id: dceca5e237ce41d7754d32eec89d25c35c3d33d1 prerequisite-patch-id: e0cff519e62050ad0df968a99dd6c872993c1109 prerequisite-patch-id: 306eba0cc84d2ce6089813002afdfa37804ce960 prerequisite-patch-id: 36cee8f9130eb946aec4aa7aeac31bbbb02de901 prerequisite-patch-id: f6929679430856de227afad8c6c8ca0d808f4e8a prerequisite-patch-id: d9c19b99692a094585647683becfeedd7a63467e prerequisite-patch-id: 72692df05d204648a91ea983c5140306812ba577 prerequisite-patch-id: 521328aba92c5a0846c943a9d506091b21dc17e1 prerequisite-patch-id: a7f5edf9b2aff8e87e7e8e0d58634c2cb7b744bf prerequisite-patch-id: f62753573096bf56964aa3df84844a28fdf44ff5 prerequisite-patch-id: b82afdddd324bf8135c90050faf38585b3182f02 prerequisite-patch-id: d512cd4c6e46339af6d5956c8491da4b3f6bd00c prerequisite-patch-id: 0f5c738457ec396b132f6e2bd29333024c5d396a prerequisite-patch-id: 66677d7c145847ed2d769816c88f8a65625e7591 prerequisite-patch-id: df51592b280b2dc05e45b8c76b64e95d08ef2e3d prerequisite-patch-id: ac78be4611d02c597fd458ca585ed5356082ec8d prerequisite-patch-id: 3ab07830bcb133be7f12a93687ae6a1774bdc071 prerequisite-patch-id: e5bf699023c2b1637106d52ce4307a67d6a6f7e2 prerequisite-patch-id: 444f1b7ddd862d218b88041e309d2286b30116aa prerequisite-patch-id: c483140448ba91827e6a1c8ac94c3a6ef54d5500 prerequisite-patch-id: 9921afeb099aa87b21d5fc10db39806f1b3a04ab prerequisite-patch-id: 486d2db8ebc259e113891659e5b00364b34519eb prerequisite-patch-id: 71900b5a5feb513e108ca80d6fa5e7ff589ac175 prerequisite-patch-id: f58dd9e8036ebbe10ff7951cb492cb55f82934f3 prerequisite-patch-id: bc109209ca907dec5eef840c28bd7676a3a4a292 prerequisite-patch-id: 0a014c164262181b40e27cbe76fa1b022aa13f3d prerequisite-patch-id: 8c328add10ee98a8ca4953cf365e1e76f3833a41 prerequisite-patch-id: 316a5b9eef40555da935010fed4c6a53a9a76a13 prerequisite-patch-id: 37a33797c203d444511c9644bd884df00516942a prerequisite-patch-id: b983adf4101092d7f61c90ca699fbf8fc2a7132e prerequisite-patch-id: 40b4bd543bca2705bd0088783b832b6909c2460f prerequisite-patch-id: e66f429d56e01abba8e21d36d775f70a2776acd4 prerequisite-patch-id: 5d8f7ab9fba275f1173283f97f44e8321d00cfb5 prerequisite-patch-id: a72e09a2941d5c2d911c7085b2b3db685987fecf prerequisite-patch-id: 4b14d6db1e2b04c5030764c730f11b312467d508 prerequisite-patch-id: 62a6f69c8e28bf89900f0e0d50d37421051b2d87 prerequisite-patch-id: 83fa5e9e244ddbdfb594f1226763d2f7f892477b prerequisite-patch-id: 7c3191f77ebf32e34a7e9051bae742c7f84339bf prerequisite-patch-id: 660b74bc0e8a088d852fa307d1a2e0236e5c8c3b prerequisite-patch-id: 4f6d28c1f8eec6bed728f2cc4a591bf86d5aba85 prerequisite-patch-id: 5847a42e9e9d2c2460bb61a303e12f19cdbeb02b prerequisite-patch-id: 94b2a572d03e3f92d8ae04388d5bfbc4b66abead prerequisite-patch-id: b221ae1eb0897b3b7280dbcd5a6fc12b755e2e8b prerequisite-patch-id: 264aa1dc9f9f479b2a70791671de93a3f8e46c49 prerequisite-patch-id: 21227ef78b00186e6a4b87fd847ef7f78dc416a5 prerequisite-patch-id: 9ff346d78f42d80fb8313fdc1ca4a008fc6a66a1 prerequisite-patch-id: e83d91a6cecafd2f2334737ede0ca5e22952178a prerequisite-patch-id: 4c4594c5f069f0175dd4ce4ca05d426bae9d6a9e prerequisite-patch-id: 1a210d0c8703b1246a49b43af8c75501c6086e2f prerequisite-patch-id: 627a2c22998f92a6750f89f51be68d1773c58fc3 prerequisite-patch-id: dcd508d7afb7afdefa20ee140e7a7e5902098a28 prerequisite-patch-id: 5991f604a0b7d1f90c7d91ebf2488264e3eec9f6 prerequisite-patch-id: d34bfddca98fa534437c1f5a4453087018424997 prerequisite-patch-id: 8f6cf095369c5b97914e5667019f49cd7cb0470d prerequisite-patch-id: 2735081242989a493dfb952062a3f6b69a4df035 prerequisite-patch-id: fdf8ddf0ad9a3c2265113b2660db26e907219f3a prerequisite-patch-id: d1def1f9f9a72696f6011f248ac9c5507f4a3b5d prerequisite-patch-id: b66b62faa07406e256dce77ad079f81d061db7b0 prerequisite-patch-id: 4c5e23825c50b8f0e42743e35d84583720ec68ec prerequisite-patch-id: acbbe0190e10cd307fc760d942e382207b92fedf prerequisite-patch-id: 44bc7b3520927bb385377b6ee005a59e14318a11 prerequisite-patch-id: 7a7a95f8c972e13baf922e1df759b28be5939929 prerequisite-patch-id: 5a5d7f5476e63ba3b5ebd74b519778ae44e3c257 prerequisite-patch-id: b44766004eea193197e6b3ebb54462acec1b9e4a prerequisite-patch-id: a36bdf1be9ab03562a24e5e0c7315774cf45b8a1 prerequisite-patch-id: bce630f14aca74e134023f8bf7f89d3037269be7 prerequisite-patch-id: f2eb3bd12db550a0b3aca718e941bed8638a9798 prerequisite-patch-id: 8ec61c0c76996bb5878e5d81ce4c8dbe20186386 prerequisite-patch-id: 2270fb681027067330d3b257d33e614ee99bf3c8 prerequisite-patch-id: ec8918c5f235a56907651f06839d9d8a2c0083f9 prerequisite-patch-id: ea5627523c0cf035b43f27e1e1a5966bd05f5751 prerequisite-patch-id: 2eb1f1695bfc3779e644535d4c66196443b83828 prerequisite-patch-id: 7994508eb7064be4233a714531932ba3381f197e prerequisite-patch-id: 2df0f634823a2a4437a67eb0ae24ffcb9dd87481 prerequisite-patch-id: 0cfc74b1bdadfc0526569ad61edbb7c68981a8f1 prerequisite-patch-id: 201976a9c01eb41af505c08ec776060f22def4d8 prerequisite-patch-id: a232cc522eb3f01aabbc46e689d8a06d2a67510a prerequisite-patch-id: f95643d40a5960d48699e70aa6f71e354da5bae6 prerequisite-patch-id: c1ded88b358068a686fcb579ec63b55294b4a185 prerequisite-patch-id: 83fa5e9e244ddbdfb594f1226763d2f7f892477b prerequisite-patch-id: 3ec96c4f817afea0ae47c0528d07f7cf873ae657 prerequisite-patch-id: c243688596bda5ae0f1c4b4141a2b07fd19de213 prerequisite-patch-id: 4f6d28c1f8eec6bed728f2cc4a591bf86d5aba85 prerequisite-patch-id: acbbe0190e10cd307fc760d942e382207b92fedf prerequisite-patch-id: 4b14d114c2d00b975dff27cb1f80c35d5b2cda98 prerequisite-patch-id: f6b681acc52f61154f01a3e12e356d79342bfb66 prerequisite-patch-id: adcc572fb23022e834e82cda8bf902c118be6d0c prerequisite-patch-id: e32035892d949015f9148a36bb2aa1047e6c4928 prerequisite-patch-id: 7e1c9b2fdd11cdedf360c1a5880f3d85e25caea2 prerequisite-patch-id: 3c4fc5b524c99a892b281d51d77796711ec1dce4 prerequisite-patch-id: 48a4c064174322e13a178c01b10f99eba9f93708 prerequisite-patch-id: c456c6d43d90839c262c03e6585ecd32ec2dbb4e prerequisite-patch-id: a6a777bd6fccc0552824f4711db3089ca5df2d48 prerequisite-patch-id: 422e24ff0771b91badd11cdefd9795d12d3fc9c9 prerequisite-patch-id: 1447bd0ee476970ec525108f4791aae3bdaee9e0 prerequisite-patch-id: beea6d3fef28f8407c4efb58523c0a9686a14ee5 prerequisite-patch-id: 80ee2e3f6eea5efcd7740a9a21fd72cc0eb9966f prerequisite-patch-id: 344a884ae4e5e4a6912a812d363306e2880d8daa prerequisite-patch-id: b8c238932949f84c3bd75e0cbcce5b391f5fe1af prerequisite-patch-id: 461bde21babc948d2ce43a1c2425221bc6074420 prerequisite-patch-id: f97875bd4925073ad407fd192604ee64da1c6cea prerequisite-patch-id: cc543920b23a09dca18dd4357622c70be03f16a0 prerequisite-patch-id: 3f3c2f1408d0cb47edc17d7a6f80ca004e062ef9 prerequisite-patch-id: ea6973e3e546ebaf756a0c724482d20dc8449b6b prerequisite-patch-id: 215794765a0ec1a094eafadb3accefc38076098e prerequisite-patch-id: 7f14892ec64b97c8d3c7499f1a65ad5803493f58 prerequisite-patch-id: 48333b0d5c60d55517e58fa7cc7d16288ac9f534 prerequisite-patch-id: 3320769e4952a9b72decd22846782f5ea219527c prerequisite-patch-id: df14ef8706eca269a1f16a2530a401341c23ca73 prerequisite-patch-id: 59d687538b328b23992c6fa32ee9a1937cd4ce56 prerequisite-patch-id: 8b77fcb8844529bb31e178ed5e54dadbc6492ad4 prerequisite-patch-id: db0e115f250a64b7c31ab068cc940d683f1de4b4 prerequisite-patch-id: 96899fd96c4cdb4ef29759d6209b5567fa3b0c35 prerequisite-patch-id: 7640b1d985b997e13a27168ee88858a6bf3e048e prerequisite-patch-id: a2c3c33644c788d83855d9be010e9e74f61b9643 prerequisite-patch-id: 21c2487ea7cfe0644fd45958fdbf67553be97856 prerequisite-patch-id: 99b4bf3a13f4fe3fdf754144d06d633c28baa02d prerequisite-patch-id: 9524464d5007f3bb56f76664dca5002448b866bf prerequisite-patch-id: 246851424392b9af6b8ec69eb0156a8ce0305f1c prerequisite-patch-id: 61180e28a298d2143310b916a7e2b75e7f540a67 prerequisite-patch-id: 762b6ec83b23b45d11864a8884d696d7d57008bb prerequisite-patch-id: 315da9e1589195b912597170c9259df3afb1c4a3 prerequisite-patch-id: 1d62e43ce546aa158096f292059a7e8401119d48 prerequisite-patch-id: 139edf02000837c4667c21d7c60e01c81999a1e7 prerequisite-patch-id: 73adfb0b5887fe843aa7f0b8b3f5216cd1224b88 prerequisite-patch-id: 5b9a8d92f2d5a44070594763b9f103aa980c4d07 prerequisite-patch-id: cc1af71b1c000fd463467f164e98f152eea0928c prerequisite-patch-id: 7cd2708592ffd315c15f7cc1e700ffbff93fdc78 prerequisite-patch-id: 73737904cca600bc42450cb7aa785cacdc364988 prerequisite-patch-id: 600e1d9ac1229b6c4883c2be6bf3b75fd79f15ec prerequisite-patch-id: 8421d7961b40afa436b2980c665f7b47757d0171 prerequisite-patch-id: 0d39a79a0e1169c8a538c5cc102202eb3ac52e58 prerequisite-patch-id: 75af2b6bb5a7c10db0796665f4e0a1edc09ba2a2 prerequisite-patch-id: 886fb539f0bf5531194ceeae1798410ba2c7b6a0 prerequisite-patch-id: 763d601fdf8f8d4b52750002958b19d6040a5cb9 prerequisite-patch-id: 932b02fd0e4e88777cd8469ada2231d03c945221 prerequisite-patch-id: b06083bd476c7329a2e4eba571eedfca78afdacc prerequisite-patch-id: df9fa5715ea747018facc2ee34cd682ce5d970b9 prerequisite-patch-id: 40e7d0556fc1fef4b2df0a22478968197e78fb87 prerequisite-patch-id: f3980e6891c608862620be341b1adadc4d6ddedc prerequisite-patch-id: 4a4e624fa0257473dabf5ca8a0cc1ab7e4599622 prerequisite-patch-id: 5c8688ef9dcac402cdb71234abfee15ec6260843 prerequisite-patch-id: fa91a5f7bc7d86c07d5ee99c30734e0e42f4aaf3 prerequisite-patch-id: af9b875cd9554de4718aa9fd661e8ab8e61207d2 prerequisite-patch-id: 1cabb35e5c50b574524a9d74e9e0b759ee99368e prerequisite-patch-id: 0177464f62271c550c75c01ebb6c0837e16d3ceb prerequisite-patch-id: 7e82b14d54787e9cf5b3f8f8317c9e5254e28ac8 prerequisite-patch-id: 3382785956c76f896acb571ed6a852f45800d5f5 prerequisite-patch-id: aad57a302f2b1061dda3affbd3f7d624bd3da158 prerequisite-patch-id: 7919ec09599de3144c12180f75ce9b6f245a3632 prerequisite-patch-id: 9e41f12856b0ba82dce97520ec6af5fb2cf814f0 prerequisite-patch-id: 035b5f388b02d52e1704824f3cb6c791ea273ea3 prerequisite-patch-id: 7594d2f5cc15d44ea8d1b2dc066ef8a7360f9478 prerequisite-patch-id: c2cc09ad9feaf50e5bf868864ed7347b5707c807 prerequisite-patch-id: 24ab5716285cdcf68e1611eab04921348c51003f prerequisite-patch-id: 51470f4fd95440e39e30e6ebe28353e7cc763855 prerequisite-patch-id: 12c93a9c63914690c7a68dc030873b9a2e265bf6 prerequisite-patch-id: 6355da468462d56c375db88e9567dee836aae955 prerequisite-patch-id: 75059efce3eb140780b8b6800f209679ce51c340 prerequisite-patch-id: e30ca2acdc6d1e90e190e4dba2b395834c82a791 prerequisite-patch-id: e5e5e6aa20cfa23d302e6cfefc1800f631c718b3 prerequisite-patch-id: 9ac1a21e3a83a51c5a924d1fef6eac3236659d7a prerequisite-patch-id: abd7a9c50ac5dd448d7efa4dc7e20066de258ede prerequisite-patch-id: e96dd1a7a7fa14c3a3ae1cbedf2db47004304df9 prerequisite-patch-id: 200d98c6534038f805fe17a7f84b777cc9fe722c prerequisite-patch-id: 92ffa4ef0069cf8d36c44a4af0b3e97b590bf087 prerequisite-patch-id: fe4a2d9c4fe2b0fbdd496c8d7cb1752b354964fd prerequisite-patch-id: 60542e7dd3b4cdf6bdbab431aa4c7cbf4cea8b87 prerequisite-patch-id: 8600326ceee9660638540e72c85256dfd183bbb9 prerequisite-patch-id: 6a1e21c2e6ef8ed5439034b1ea83eac19cec8411 prerequisite-patch-id: 665d39cab94908fda6aaf7f568a8920ffe1a26f3 prerequisite-patch-id: 8276e04d48b8396763df8487cd0aa057f0a8d276 prerequisite-patch-id: ab2825f1a63fb5e5d5b81e49472f30796a232257 prerequisite-patch-id: a49133839440360aa197537ffaa3d711f3088b04 prerequisite-patch-id: 76fb270ac7726312662ec2d10a20445587c26b5c prerequisite-patch-id: 65e5fbc87d8c94a1f7ecf6986ad2d5c912976f25 prerequisite-patch-id: 2d8a93c899303ac5d899fe81d4860c41bb239f39 prerequisite-patch-id: cb3d78be4e90bd3e1fbbdf30eb68b1d8f5933d8f prerequisite-patch-id: 71865a445cf0229fbbed2bea3ee0ce16cb4e31ac prerequisite-patch-id: 7e735818990f075c3718e8d1447bf84ae77d7569 prerequisite-patch-id: e87363e60530970a297bb94bb7b10249e8a1cdfd prerequisite-patch-id: 050921285ecf602792aace7f98ce226eae313d34 prerequisite-patch-id: 668207b9218e1f82892681a39f49bdc54484161f prerequisite-patch-id: f94eaf176f05f66fee8f74a2742b8420194cdd00 prerequisite-patch-id: d868cdae63423b4a7ac3cbf5a781815eb3526688 prerequisite-patch-id: 241bdc11f9caa9d22f0032a5a11866417fc63335 prerequisite-patch-id: 569a30522adedce5011ba54e5e7340244c4d598b prerequisite-patch-id: e2fc6c460539c07b8269d99b347498f761ffeaab prerequisite-patch-id: fab05b8b5b002d5ca488c62eb82ab3a941a6d30e prerequisite-patch-id: a20d3b03461e9198ef0290a866dc0537dbcebe28 prerequisite-patch-id: 32b826773abe3c6ca03eaab57920698c86a76aa2 prerequisite-patch-id: d0c0841cd8fb6f75d4925b74b10fe92921d5ef22 prerequisite-patch-id: c15e960fb4bfad27c5a81e496241da0a55dcb0cc prerequisite-patch-id: e3702ffc411b7b8693fcde8fb3262808073f6318 prerequisite-patch-id: 2447b35425e045f4a6b025791315c5c128f8a392 prerequisite-patch-id: 9156639d5e4dc87d8f534a98a3f7bd402ca6dff0 prerequisite-patch-id: 3400b430e4dd479b80de0f197174eb98ed67481f prerequisite-patch-id: a10250ff2e0f191f7bb0ff2bd20fccc4c87bd49f prerequisite-patch-id: b46a214266ca656bb2cdeb736cef136f2f0f434b prerequisite-patch-id: 7fcf598e6f61059ca6bb72b82313bf74d85ed6a8 prerequisite-patch-id: f7208ff42c53124f3fe798fb41c2c6a26c4dba4f prerequisite-patch-id: 2a0e99f47338add1ec6c84933511eee6b455403c prerequisite-patch-id: a8364c7ddd7d7b895b3ee767e98ef90fe344fe06 prerequisite-patch-id: 8bd21e2aa8115e319212947ee933e40b975cb873 prerequisite-patch-id: c9a54bd9a1fc546ac9867640bc17ed1104b52dc3 prerequisite-patch-id: 2469514ea840bdef4c37cbc5bf4ac2348542b413 prerequisite-patch-id: bb6f6b94cd1ea3464f6611edc2d41b42af4aa852 prerequisite-patch-id: 1f27988fe5cbeb781929f0bb96b4ab87e379a184 prerequisite-patch-id: f7a2207e2055094834375a6466811ca161409d2e prerequisite-patch-id: 8e4b8239b1322ca8e5f59e0cb7527d50b0ab40c3 prerequisite-patch-id: 7b204c80a5665a36e1c06c2febaceef35f47c976 prerequisite-patch-id: 0ba4dbf550ad798ef5a683f55d068a2d50395689 prerequisite-patch-id: 564c9192e0a9980b4c29202acef0e72e932e8079 prerequisite-patch-id: 639214454e7153c40177fda26383c3968a0bc33b prerequisite-patch-id: 39f5f742aa6ced79d56805a61aaa5802bd161827 prerequisite-patch-id: 48d42de75662be6147d5dfb51088acdbd5ed1d8c prerequisite-patch-id: df8d85b42dfa0d723eba991797a30e3fd40e49ad prerequisite-patch-id: 99236b50848323242166e821b9b7d3ddafd1f131 prerequisite-patch-id: 5d3b04f583578151a0ad774a027cdaf2dea80be9 prerequisite-patch-id: 3d8845f304cc05fa5ed219385085135c2aab59c2 prerequisite-patch-id: 16b289ada55587ff5e49056e5f0b7e60ca0bce8f prerequisite-patch-id: 920f833b048bd438e49e2e3bfd6c3adb7752c3cb prerequisite-patch-id: 8e225f97e7885d4fa254ad32203189fd0e1ac1f6 prerequisite-patch-id: a4830de4489d374e7ca219f238ef63d5f0f354a0 prerequisite-patch-id: 946a87c89e436326f1dca2533d6eaf1e6bf5f2b3 prerequisite-patch-id: e417370c6cd464ff7f5c78764dad62fff064e7c2 prerequisite-patch-id: ff7e0826cc87239852621dc1c9b0dbe34b1bbb62 prerequisite-patch-id: 3aedcd153b75c303c01446d2df6fea4ccbd446bb prerequisite-patch-id: c8ca57be1b7c78b3051cf2854b38e73a8e96c8ce prerequisite-patch-id: 7143b3c91827975f9423849a33b3f93617c53728 prerequisite-patch-id: e9687912bdea07d7efe3f9d1bdf673f408112eae prerequisite-patch-id: 00abf3a86c4912c9ab8114cf534e9c8dc0f1a4e8 prerequisite-patch-id: ec1dd191976c18e27c28938e60782972159dba5e prerequisite-patch-id: 9ef75fe33fc864e4f05153de7e0f3b382fb28759 prerequisite-patch-id: 942299c71020f97432f07cf60370bdeb06d4ebfa prerequisite-patch-id: bd6ad19ae8da2bfbca048b70929e1a80aa3d89e2 prerequisite-patch-id: e7c0262e2675bab27dbaae0877629dc3bdf2644b prerequisite-patch-id: cc627b42159de4fb2a968a82da9817baf82eb80c prerequisite-patch-id: 28ee678d758944591eb90ba5debcb183d14bf1e4 prerequisite-patch-id: 51be13dc1407479cb2aa5c5c74f9035fda443751 prerequisite-patch-id: d4c744500bebe39c70bc8bb11221d999dfc91f9f prerequisite-patch-id: 7b1b4a020c180e0f504bd721cb6af818bad11816 prerequisite-patch-id: 633ba5f6363111450ee34a55b61b8b5c399fbfed prerequisite-patch-id: d3663657df1cdf5ffa0dc0c8049f43d858032ae5 prerequisite-patch-id: e687477dd8cd98554028ccfd6e5ea764ccea9a4f prerequisite-patch-id: 963dfb87777ede6fcc13ea3befc8e64a3c078242 prerequisite-patch-id: ad640d6b880064caa0046895252aa1fd2b3cecf2 prerequisite-patch-id: a948860d32742e4e368de2cd05f5eb90503cabdd prerequisite-patch-id: aeeb47ba73f2a22e0c23bb713bfa7af557ead2b7 prerequisite-patch-id: c1825faee128b4d54a8f3113201b3c5cff18ce9a prerequisite-patch-id: 8937348551a8e26e4d9a879b0e41c9cee800393d prerequisite-patch-id: 03d85445f0eea5a4a540d8bba7a25c74077ce868 prerequisite-patch-id: a8aab0d365505fcaffcbea9f94a20c42f0f81df1 prerequisite-patch-id: f9dc5f7f598579c9e3df9da79d2966d95e5ca74c prerequisite-patch-id: c4409b97228f6883417253b0dcc23db0f8c4e65b prerequisite-patch-id: 52718ac031e0ca56c5f416ea93f9b2ee70847a41 prerequisite-patch-id: 818f2a752d77fa9a2f6108b656a80bb0f932f85a prerequisite-patch-id: 181e1e17f6e89fe4bfb3e51e059aeb42191803b6 prerequisite-patch-id: f85b2bb60522a59b783946fd54c13b354586c8ea prerequisite-patch-id: ab65945caedb77ff7f5fcf83d22e5705aa5dd6db prerequisite-patch-id: acda7d73e1f7fbc4c3e3bd0e7f0f64cf737f7954 prerequisite-patch-id: 03e6acba41ce398748d342d7691f56aaf9513464 prerequisite-patch-id: 397cccefa1bccdbc56ba51225fe16878a188e8f2 prerequisite-patch-id: c27766f3687a2873dcae57930cee31680dc3b8f7 prerequisite-patch-id: 443a23a508a51822c749a43bae6be226f8568765 prerequisite-patch-id: d052f492a9526ef069d03b501ebdfae0433e77f1 prerequisite-patch-id: cb0e76205cf1fd487def7719ccbeacbed7d8c694 prerequisite-patch-id: 9afc5524fce6b2302db75458f358e889a5f0b31f prerequisite-patch-id: 2d95ae3ab50015ec1e6c22c7bb97568707d112be prerequisite-patch-id: a94096950e75f7d38be87dec21d85d78975350ce prerequisite-patch-id: 23f3505a0f1a16f542d09b85e5f512d31428ea01 prerequisite-patch-id: 77045f15cce7c116de8c803d3e4e4b2d885ad101 prerequisite-patch-id: 64593aafd8fb81afedfedd5a12adec969afbd076 prerequisite-patch-id: fa9c0e71416d3dd1abfe384eb0c8bb2f227dc8a7 prerequisite-patch-id: 150284d9c0488d0b468e09adb2f578a52710b5bc prerequisite-patch-id: df14ef8706eca269a1f16a2530a401341c23ca73 prerequisite-patch-id: e32035892d949015f9148a36bb2aa1047e6c4928 prerequisite-patch-id: f6b681acc52f61154f01a3e12e356d79342bfb66 prerequisite-patch-id: adcc572fb23022e834e82cda8bf902c118be6d0c prerequisite-patch-id: 7e1c9b2fdd11cdedf360c1a5880f3d85e25caea2 prerequisite-patch-id: 98e2ef5a7db6b2bd523c895bd917d7873caa65f6 prerequisite-patch-id: 0b0bb409aed1946331ecf7f795d5c8fe62fe266b prerequisite-patch-id: 9a9b54e443b4e06ab305d7a217f2f14c016daf85 prerequisite-patch-id: 6e4e84736e7e1c53da3228a881cdcb129723c16f prerequisite-patch-id: 590d292753247f7613c30509c17df5a74795b513 prerequisite-patch-id: 606515a5f66b7ce387f5dc934011eb22a2c5a637 prerequisite-patch-id: 4058152eb098c442f2bf4c3c343871f707649242 prerequisite-patch-id: 0164de39b7006879dac885fb727d3214aa72f7a9 prerequisite-patch-id: d5c2b8b6b8c278baa72d85242adf184f4405665a prerequisite-patch-id: 8803de24a3a0f8fc2fd0bc6500bb4f5bd014a3da prerequisite-patch-id: d2279a0d3bb555e0011de9f1471bc74f933a2d71 prerequisite-patch-id: 946a87c89e436326f1dca2533d6eaf1e6bf5f2b3 prerequisite-patch-id: 39f5f742aa6ced79d56805a61aaa5802bd161827 prerequisite-patch-id: 7623a2d414f7248a4d04c3304d890b98849c59e1 prerequisite-patch-id: 0880281ede305229a434d96af8b9a27272d14ca4 prerequisite-patch-id: 9c78301572442d90bb35d70a1d5d19c8bdd63c7d prerequisite-patch-id: c2e95f5c0c0f5045293ca67422863d01ee0d93b2 prerequisite-patch-id: d3663657df1cdf5ffa0dc0c8049f43d858032ae5 prerequisite-patch-id: c65d9888fa140698b37440fd1091773fb1044a20 prerequisite-patch-id: b534be1324dcc27967ccd90b8f6d81fbfbd240ca prerequisite-patch-id: 2b9b019b6e8f812c99ce648aedb83f2695305c97 prerequisite-patch-id: 211b9c3e9887b6c5b5fb1e333e12e0ee3bd7fae7 prerequisite-patch-id: c0df813e8e86a21584060a16b0959809059196b1 prerequisite-patch-id: b08fc0be2a7e3626ec1d12b4bce518364c9013aa prerequisite-patch-id: 47b389812332b1143c601a1dc0cbb3b0aea34f4d prerequisite-patch-id: ce529f5e6c44f7315d91764cfbd5c31d79fe9a27 prerequisite-patch-id: a13f2a8f60c186d4ef16724ff2838bbdcb57fe7d prerequisite-patch-id: d684cecc486fb51e90cf651f5fa2deedf1304d7f prerequisite-patch-id: d8537dd218c9684649d33f664fd03af8b43248bd prerequisite-patch-id: a53f6b70d7f187a917e1454a9e0cbfc93478699c prerequisite-patch-id: d6320e1c91def5fb718821c7a5375f544e911d79 prerequisite-patch-id: 2b0a45b49a979a304494981aa24c625573d7a9f2 prerequisite-patch-id: 63b4dee898ff7e95a35808309b6315c46ec1f8c9 prerequisite-patch-id: 649036931fcd6b04b2de17488f09532421f21946 prerequisite-patch-id: 1f686ebc6914b06821a4f6526b031b05fa9f5fac prerequisite-patch-id: 1f25cb3498bd7160fbca18ec9f0a33c6d47948e3 prerequisite-patch-id: ccadcf90b2b510f0ca6b08797a1958dc2cdf0907 prerequisite-patch-id: 156ba8752b6bfd82c3ddc1ef5552e658cc89fb63 prerequisite-patch-id: 9af607d43db8f4184c0368f1459a1e24c8759e67 prerequisite-patch-id: c3924631bfe9fa5753f2a5fe220ae357bb4ae652 prerequisite-patch-id: 840c5ddacc948ce17e780318d1e4d79eac72395a prerequisite-patch-id: 16659edfab3bed1083576429effcb1c4f231c19e prerequisite-patch-id: 9004cefbc87f8298d17bdeb17046024ad960cb78 prerequisite-patch-id: a245eb330fe84f13d79d67d45712a0934e7732c1 prerequisite-patch-id: e84abdfb76c15f5ecf4831a18abfb3ee41f1b911 prerequisite-patch-id: f9247f723598b29753755cc73c6f9bd91859b20e prerequisite-patch-id: 294cc77dd4e74d6558eaa2ef67ed03e52fd47b64 prerequisite-patch-id: fcdc06aae0f92100ebeeeab29126dfc1e0eb7437 prerequisite-patch-id: dfae112be3563fccd0cc7bcc10a8865156c3b8aa prerequisite-patch-id: 2f9fc568dbc4755fc22426990ab22623690e05ab prerequisite-patch-id: fb0fbe8ae50ca84d619ff4acb8e09ebe6013fec2 prerequisite-patch-id: 581c9b35b0a968e8f1143f2856a35ec36122a8ba prerequisite-patch-id: 425afdc375e5567ec68bf00a7c0a9c31bad5c603 prerequisite-patch-id: 3b9fae77df41705df4e3b6f7d35395f4a978bf89 prerequisite-patch-id: 9bb2f2a2e05982b6dfedb70e6376e291612bebee prerequisite-patch-id: 938e3216b0020be5b9891c05ec9f4c725f37d994 prerequisite-patch-id: 6359299f1e802e569a4c8597b3b4e099827aca83 prerequisite-patch-id: 254fe240b15e1fadb65418841ae787eef94d9bf8 prerequisite-patch-id: f18da612a7e88d0b99a8df182623c2134f4fc4a8 prerequisite-patch-id: 1c69e60a202ed085d80f32bb9f53eab95adcb492 prerequisite-patch-id: 2487e245f6a8cdae44c1b0f30dc05c099dc5db9a prerequisite-patch-id: 43abafc4250020834b71bddf2eeae784397c6d55 prerequisite-patch-id: fd82167e9abb936621b8a88cd999f6b201c6bc0b prerequisite-patch-id: 78f6b79cdd6e38c2f00f5a73e3ea60b4d4052ad9 prerequisite-patch-id: 691d25f0ac912fc4c6aa36dde3a9d942c8a01377 prerequisite-patch-id: a1e7b4ca7870f443c2ef7ce6fc214f8512a76fd7 prerequisite-patch-id: 1a933f0ce27cfc3c51de11911b09cfd80261d563 prerequisite-patch-id: 958c00e762477da3a141673acabc001cf1e66419 prerequisite-patch-id: c6e751a28c1564e14b557f037c1d315c1fc62e16 prerequisite-patch-id: 46445c9bd5b927f1a066e74c79484e28f53efe64 prerequisite-patch-id: a19386dd7896e3c24cc14908b67dec96b9b388ec prerequisite-patch-id: 4c9930f106576707c4310fa27068d224ca24ff22 prerequisite-patch-id: 81a8a05294c48540a860db7d172b4346fda502d8 prerequisite-patch-id: a37dc52162d3c52035092c259c961535a92d0a7d prerequisite-patch-id: b2cb3300cad5b7f4ab163a5d83053af12656013a prerequisite-patch-id: ed6cb93a6eabcb8fbcd268c087f2ce7506b3a567 prerequisite-patch-id: 7ac3fbf169559bc967ccfafbf1e60a538c21a1fa prerequisite-patch-id: b8e0eed2eaab169cca39c73303e64221dfb8e7f4 prerequisite-patch-id: 2148c3ab2a8bd3aa3b4ebe9ade107072675a5ca0 prerequisite-patch-id: 22d71d14f53b14f0c865f18cf43a15012a389d98 prerequisite-patch-id: d584a08cd8e20780211ccb8c70d9c5480ab46fe8 prerequisite-patch-id: fe937fadf30293aafdd2683063180d798a5af087 prerequisite-patch-id: 9367bc469b46ef1237d440a830aada13aa44048d prerequisite-patch-id: c9074a13de38078e9904c0c6838be3f4909953d9 prerequisite-patch-id: 5346fa3c256b582198e7d16211d47fa309032f21 prerequisite-patch-id: c98e204c5442257ed22a9fe4249982ac11b40341 prerequisite-patch-id: cb2aab6e97b676c01a219c88ba5a55fd04d0b912 prerequisite-patch-id: b60ff509402c0cc9ccee560507d32831b0c26be2 prerequisite-patch-id: e37fbf68bbeb0a108db86e25ef069f5910713f7e prerequisite-patch-id: 9c217fc1bd0c5018d8eee9d6547a767936838d4e prerequisite-patch-id: 7712321a514de4c9a8664a7e995c7ffa57d6ba66 prerequisite-patch-id: 5996f75760e203dc32a79a578bb065c9cbc24932 prerequisite-patch-id: f5282e5ab758fcd7b65385309d5d16730f70122f prerequisite-patch-id: 1f7a77975dc335f7c75ebf08f92d3daebadb365e prerequisite-patch-id: 6cc7a4f56d0c460e55191beaee0ff72828a2bdc2 prerequisite-patch-id: 638be2d8090838a94dcb66091e2d11f6832a3dfa prerequisite-patch-id: 438ae2bbda089a8186beb36db6753021d723d831 prerequisite-patch-id: bb91f7d690807bdbbad45d6803b37045c8a9a44f prerequisite-patch-id: c04dd9fc3dc7d40549b40ee93a97b2265b51ec98 prerequisite-patch-id: 46c656d933f3b6fd5454a3dd874eed787614d16e prerequisite-patch-id: 13f61a01915442bce0f46dbd85f28386c4af8e2f prerequisite-patch-id: 58492467ca774fcc1efd01acd71ac2cebce3dc18 prerequisite-patch-id: 8a11956f2c53800a233c3ae2a5e5d64e40fb656f prerequisite-patch-id: 2cf8b325a2a384a02dc88502b4d0a8dbd8dd3d09 prerequisite-patch-id: 0338c5ea8bf82e3ef742595960ca175b4e8b8a1f prerequisite-patch-id: 8b36287686eabad158d47ea2a1fb898b394ea94e prerequisite-patch-id: fd20e845a246dad913352db63a5bcd6f9963f6e8 prerequisite-patch-id: 0bb3fe3e9bfc8311560c38ea5bb2c26aa6e72df6 prerequisite-patch-id: 236e885b9c3547c5159741c3c3c91dd237d1926c prerequisite-patch-id: 984ffb2e26f764bcb96ed7511f22a89e34d42b58 prerequisite-patch-id: 45edf5b5e31678c1c96dd0fe94d77b90b4c7296b prerequisite-patch-id: cc0c41d73db13c4669ed42acbda592aa5545df0c prerequisite-patch-id: c75098d54266586c04c5c5e91e58e786a176e56a prerequisite-patch-id: f9575fba4604b38d0d9dedbe1df316a1e4aab394 prerequisite-patch-id: a16778554d914a4496568a8e090f86980504fd0f prerequisite-patch-id: acb7359ce65fd74fb9f6121fb408ab0bda3a4bf3 prerequisite-patch-id: 75219adbbd7d99d9addab90cac26c921f86582e7 prerequisite-patch-id: b439b71592aac7548e30e65392c738bb07ea3bfc prerequisite-patch-id: fa093d8da120517ec2446e4b24432f39e0e3006a prerequisite-patch-id: 53cf4b7e3333fdd471eba0c90ef37b7550763852 prerequisite-patch-id: e1b3f7b176102d75d06180ec0f4c39d2360743bf prerequisite-patch-id: 086b251b97e40e728e7773e359af5f0b68cf16a0 prerequisite-patch-id: 17bb376b4f18c63e759e18d0be3043310514cfd0 prerequisite-patch-id: 13d19cbe6c01583e4e66cd70d994253997d777ef prerequisite-patch-id: 57cc4f2b73c486b838a7e2cc91bec651ecb07b96 prerequisite-patch-id: 83f6e299157ac16ba63c48f43b444dba8adc7872 prerequisite-patch-id: a0c2d454fa8c26605ef51712049624cfa962a2cb prerequisite-patch-id: 1963cc1c54e8d53a956fc5842638e02214ca12f9 prerequisite-patch-id: 22f011788f82980fcf3aaf269fc459db891d9453 prerequisite-patch-id: f7de58f2aa3edcb360dd0d848e8ea1f4b62f751c prerequisite-patch-id: 103d0ff1ee263075cd73326a5de431709571d6fc prerequisite-patch-id: de2ce2b7b4f76e6f911ba6fd5760925674739485 prerequisite-patch-id: 0d61259290697c06ccbade768ec5d69c7f6ed621 prerequisite-patch-id: e7dd4d241c13f11502121b4dc3c98abcc525ff43 prerequisite-patch-id: cc3d66d7417d86731b078ca51dee2b6ee87a9649 prerequisite-patch-id: ac2999ca77ec169da7352afc3105fcf75cabf235 prerequisite-patch-id: 2b77c67fc4219c53d471508c3fd8948ba488e8e5 prerequisite-patch-id: c0971906d1b14af395e9b093ea40594e8af708fd prerequisite-patch-id: 149d7a91ed43929bef9cebfe7ed95f0d2a270bf0 prerequisite-patch-id: 574b79591f83cc9b123b1a5bda0b56aefa72e043 prerequisite-patch-id: 3a85df3bdb5793e5e442cda00846f24b4636db05 prerequisite-patch-id: 26cf4da1857919d902303f03812c722d355bafb1 prerequisite-patch-id: 7d47e412462412f7a2bf28ef96b13aa5f4de3545 prerequisite-patch-id: a51cde6f4d0b940e90be3b42f82be2eda92f8199 prerequisite-patch-id: 6dc8e65bb269bbc1332a32c2de6aba1c7817ae76 prerequisite-patch-id: 86a2f7a9492c393e93f6ed018604655ebc9c735b prerequisite-patch-id: f89de8712b9a9f6aee050cb5fabded287d089590 prerequisite-patch-id: a755263ceb339d4d8cb11611ed2253e4508d7da2 prerequisite-patch-id: 79d05b20d76453577668b0726f59792e20fe33a9 prerequisite-patch-id: fc9ba7995599fe5b1f4676a636b842eeaad38a52 prerequisite-patch-id: f49a2064408e5256085507c07ca5dcb6f1374bd8 prerequisite-patch-id: ce6cb98e1e63d5a47a9f40f917e269e76a731fa2 prerequisite-patch-id: d48a2178ec12f411ca1700c1b0179ba822983a90 prerequisite-patch-id: 3dda1855b1ee0cb80322dc6756c20c84f39baa5e prerequisite-patch-id: b7813658f10b737308182cf9409b209e960f5d7d prerequisite-patch-id: 291621040934eeafae1e62c7674efa1832eb0fa7 prerequisite-patch-id: 1049d474e1a4c0551b5b306e79b6de9c166f6194 prerequisite-patch-id: decc2c993d193ab22d8013d3e9d048d8264bc013 prerequisite-patch-id: d359e103ac5b7617b5a9585f9ea4476219211112 prerequisite-patch-id: 67187cc88111bef8164dac19bebd228a3fa566aa prerequisite-patch-id: 703df06165ae151692976a1811668812d57855a1 prerequisite-patch-id: c5c4a8553ae5a6e988c022c8b632026fcaa7cfa5 prerequisite-patch-id: 548c8292a2d71e3aa325472158e640d609988ae4 prerequisite-patch-id: 06fd15e473b4daf954fdc1f3d051a19bc6110c50 prerequisite-patch-id: b9fdef79aa413c3894fe05bd1295aea3d6e3f1be prerequisite-patch-id: ff115e993377be96ef2a37db128b710630afc8b0 prerequisite-patch-id: 2d209d39017065e0bfcdfe57a2e431cba92d2c82 prerequisite-patch-id: 1cd53952dfd35c5307c658ae73ecb19f3b30ae0d prerequisite-patch-id: b4a4f9ba3a018c2060b0b47d18d3eb314238f18d prerequisite-patch-id: 694b8637bf423ed279d0253ff69fb09a3aa79d29 prerequisite-patch-id: 786377fa5f2c851d7db8b27e027c8d5fec575493 prerequisite-patch-id: 02f831d529be0c1527e0b8ae2585a020f58490bc prerequisite-patch-id: f32a0e4b42c42e0980f5371db35e18a72c4744ec prerequisite-patch-id: 71c92d63085f6055fa8493e61efb6fe9e4dbd5bf prerequisite-patch-id: e5334b7e8f318ef4e9ba7985cc0d75380138af54 prerequisite-patch-id: 55c243c1a83ed393907609f9572ad0ac122938e0 prerequisite-patch-id: 96793b97a0d184785155718de4ec6ebd18a1e24f prerequisite-patch-id: 39f64d2ec4b1f77a8e879670042179ba58996469 prerequisite-patch-id: 318b8dd42dd4bc4e5daeb7b8c839b141fd637db3 prerequisite-patch-id: be79d45c269f5edf50221fdd5901f24ded2547c0 prerequisite-patch-id: 4eba011ddb39bc9f8876b4c41e68f737dfc4b70b prerequisite-patch-id: ad3614d6b98de5491bbef9711b6f645b3105460c prerequisite-patch-id: b77cb5be8182c753f8d79e177a99fd5ddc31839b prerequisite-patch-id: 08c3f59e2c3f9c313b1ce346b6218941805f35a9 prerequisite-patch-id: fcccb72f2af3c7104cdd12627232d52a7a0a1f89 prerequisite-patch-id: 6f275c6bb0caafe1ff7b323f85edd8b8bb22f559 prerequisite-patch-id: 8b04f91b76cdd809cdc5321eca33eba06c434316 prerequisite-patch-id: 00cbd2e33a7e3c92890a3d44669469f268c6eca9 prerequisite-patch-id: 98d9f0a09b1964387025ebbd759613a3fdb6c028 prerequisite-patch-id: 1d660587b789451840167395b89010645ad4d44d prerequisite-patch-id: 028f46486e127c2ebc777095b7a63e43521d5e4c prerequisite-patch-id: 785d30a7d77df0466ff2b089c2de78a24e513320 prerequisite-patch-id: ac3dbf7876e75bed9193981ceaa0c9efacfb25dc prerequisite-patch-id: cf7fc3d407e22d3899d06bfcbe790422a186bda8 prerequisite-patch-id: 23fd1307be1ba73a83709d19d62a46aaee741a4b prerequisite-patch-id: 57d254258cd49d0d06f3721a73b68a05b58f919e prerequisite-patch-id: f30f4784dea941b019cf928629aa1c419ed1f887 prerequisite-patch-id: 3cb04885b78eea5876f928188c7ea4d51e76da3d prerequisite-patch-id: 9d700b1a4c816a8c0ada7b484e7a75d6b521a310 prerequisite-patch-id: d607b743be822860015dd267306264b716e33e42 prerequisite-patch-id: 6f052d25dbde9c2c8184c51a545f899e9f8eb48c prerequisite-patch-id: 4b07208bb75ba16d99d8a86ab85587a602a2b534 prerequisite-patch-id: 210495efad29b970a11b0d47faa8593ba2fdc8c4 prerequisite-patch-id: 3dfe390ef9c17ecbf3819fffe139a4b4bd802ac9 prerequisite-patch-id: d613e1b422996d55e9961b100f17008d88e5a693 prerequisite-patch-id: 1211b77aa11a39c162a04a112714bd89daefaad2 prerequisite-patch-id: 69ce3fa3c82eba593c4b4b04967eac8e2eb85fdb prerequisite-patch-id: 25e9308b883f3435979161b7ddb381f57809ab38 prerequisite-patch-id: 2dbd7e22b9d30903c8fb2a3da94263dd5f83811d prerequisite-patch-id: 8bd45525d4570034e69815f87f66a2b71fec9e8f prerequisite-patch-id: 155af210bf9ba80535a9eb6282ed4aeed8ff298b prerequisite-patch-id: 0ce281e4e0f8ea09085f8f15a443e387876bb9ee prerequisite-patch-id: af8203343b3ad533444b7c42422ce7ffe08c73d2 prerequisite-patch-id: 3180289dd3337f2a3044edaf7a8fe09c83067f47 prerequisite-patch-id: 91966fc1201566ec13bd899035c8868cc8434c49 prerequisite-patch-id: a9597cf3b036a76c942a7fce8acdda02c21dd159 prerequisite-patch-id: d2ba50556d915d180a253a2f2935e44a8e5e4a67 prerequisite-patch-id: 46486776474d54ade2f3f308bfc4a4e620cf4ba8 prerequisite-patch-id: 67238c7acf2838daa32ee6b15dcc8640016a0c1c prerequisite-patch-id: 0f36665a5dccf22a102e61e27f901ca374c8591e prerequisite-patch-id: 552b0276948bc0d28b8ccf66e43171f2b4fd2d82 prerequisite-patch-id: 32bc29162405ec9ba39250d874ed516a6dddddaa prerequisite-patch-id: d0d3855ab53104abb9813b2ec75347b7f9516504 prerequisite-patch-id: e473e9daa4723f56aad8de5399e983974e571a86 prerequisite-patch-id: 3654e5f8e55a0896bd7e78647b218f3b55ec2ad7 prerequisite-patch-id: 7eb66366e1edc620e1b03a81035a8f3d50623dc0 prerequisite-patch-id: ab65b69e1de51c59a2347be3b136e71fe5f52fd7 prerequisite-patch-id: 89b8af5be67080c5ac81493b29bd00a1f0196ca4 prerequisite-patch-id: e866fdbd2f1f8992c6c94dab1ca6ef809267f28a prerequisite-patch-id: 453145c31d66953815888b78c220f2c2ef6b29a3 prerequisite-patch-id: 8e83ac0a6f5749c8989297108d3133a1c24aec62 prerequisite-patch-id: 83f01a36705b6d9fe6e8de9865db128c0a09f28b prerequisite-patch-id: 9b7d69a2483408c38eabee3ce51a66e4100407a5 prerequisite-patch-id: 382a3d1e3009149170eb2a0574e8d5688643f7c3 prerequisite-patch-id: 56f194611fe42bddde3621f3732d320ff9d988f0 prerequisite-patch-id: 517d9bfb549340ec8e3d2495ebf2623ade02cc03 prerequisite-patch-id: bc8fa98b65f510fc5483c1456cdcb518c2dc1af0 prerequisite-patch-id: 7586f6ff199b8544730d0d1812e053c057516a0b prerequisite-patch-id: e860322e3319815454e562afc0e8048da2714697 prerequisite-patch-id: e10b3a0ca0da9f69b4e1366eb56e8142c2fad585 prerequisite-patch-id: 7e50b6f9aca0a179dce52d4640d30b1ae3454a3c prerequisite-patch-id: 6f5141ec37619e3821d5cf8ac63b4a64e45968a3 prerequisite-patch-id: 17a97a1db51e8de76641d8821db89812597beb1b prerequisite-patch-id: be6ed26855b5e00d9f2f7a1d51937afdddd0ab3f prerequisite-patch-id: 03d916bf18bcc2a3fefba11e8a12aea21e151737 prerequisite-patch-id: 13b97f3e1f40bf8b77cb27dc0fb8a68f17d447a7 prerequisite-patch-id: 0c05387bcce645aba3344f656a9234cfa08d6249 prerequisite-patch-id: f707661b57f933a83c0eebdbedc596aeb0c01419 prerequisite-patch-id: 608fb24552193f3ac8d200958be0b688c41eaade prerequisite-patch-id: 1b3187527c2955fe1859b113bf3c2aafe5da9e17 prerequisite-patch-id: 7eadb4b4a2d9e22ca30e9d9b305bbd9e8c3719b3 prerequisite-patch-id: 335a15acc89f62fbddf82ea308c834eb7fcce298 prerequisite-patch-id: e5c359f65e5fd8a89b7097eec536b5ed6140c29b prerequisite-patch-id: cd7d2352cf03745f4dae01946646e5541297fce6 prerequisite-patch-id: ad1b01614c4ff24ffd12785336efec3d687699fb prerequisite-patch-id: 019177516cfd2b4270212dfcfc1bcd166325279e prerequisite-patch-id: 0268fa395a0264d72a8958c774f2cd562c92db29 prerequisite-patch-id: 615740f47b04b002d9c0dcbbd6a5233ebb1f877f prerequisite-patch-id: b073fedff7a250086ffc78daaf85e4b67b72c99f prerequisite-patch-id: 284fa526963197c34c7799f2f48721dd421351df prerequisite-patch-id: 671b97898c45ca6a886936e242411dadb8919b33 prerequisite-patch-id: be76a842b84af202f3214dffe55255328a9c3ab8 prerequisite-patch-id: e0a8354c567e7e3ca6b477518b1a610ada111d06 prerequisite-patch-id: 4433da8f4586297084c43cb6b6ab21b4e1ccafd2 prerequisite-patch-id: aa56ad902ab7f2a41174d0b15f278155b08a63df prerequisite-patch-id: 3ac3019d7bb97a65b80a758985e4c134939d2b9f prerequisite-patch-id: 6e7ef566cda9567ea3831610db0c93b4ea434f8f prerequisite-patch-id: 7251621235b03b1c2347b6eec4fe3237c9e08d20 prerequisite-patch-id: 7f3e66a7c0e966ac392869392da2a36ce5899f8d prerequisite-patch-id: 93d1d4ddbaa16e6b784b61b091738340c388c618 prerequisite-patch-id: c337dd34337fd856d48b44de1435a2c18193cec6 prerequisite-patch-id: bacb6c8028dded5eb67087123e8ad51d9437ac96 prerequisite-patch-id: 872fe610735d409f7221b8b8bf54c15974ac087c prerequisite-patch-id: c8cc89ff25e5a1a1ebe0abe1f0718eb16a655bd1 prerequisite-patch-id: 1a4fcecfdafbc05dbee4e14a36a6297b2ace2423 prerequisite-patch-id: c075ea144c8ad92b1864849a7f3db1097d2e5938 prerequisite-patch-id: 0d4af7243eca84302998b7bdd0feac89b67111cd prerequisite-patch-id: 804dc4eab2768bda4fd2ea8fb69dccbb3b15c6b2 prerequisite-patch-id: ce163eb295851c258def9f2e26eef74e03914a34 prerequisite-patch-id: 62095be9eda1896962cd4801c67d2e192153dd0e prerequisite-patch-id: 86d14d3ccab6abfabe49f68073e8a67061850d64 prerequisite-patch-id: 3bfdfb1e7fd65e7f744560823c401afa930d0537 prerequisite-patch-id: ff2226f20fead2c6f0ecbc0875077482dd2b6c4c prerequisite-patch-id: 09b13e172d095499435a3d349754a6996508db99 prerequisite-patch-id: c4725cd32d4f21159506487b95cc3a9f1218448c prerequisite-patch-id: fd2a49f8569b87391f949f9dc604ffc85970984f prerequisite-patch-id: f04d19a6c18809e0ff0503fdd3f8c8cdbcbe5bf4 prerequisite-patch-id: 9e3287e8b8a357d4f7ab0891d6f8fb1bb9e17e18 prerequisite-patch-id: f3d09d206e9a583b55eefb0bfa88bda1e65ac009 prerequisite-patch-id: e91ecb85d6918fd47591031d80fd1c453af803a3 prerequisite-patch-id: a684a71c213a2c4330dc49ad33855dba145ed915 prerequisite-patch-id: 5bb837fe3d86790f1298a0b602292657442716c3 prerequisite-patch-id: 89a99bcec7320697b0a57b61114e1e188203768e prerequisite-patch-id: d3e1c3a966e06a12d4b93b57b0c62d69715a566b prerequisite-patch-id: 3489eb99ae9a481d6a0173ea4d45a5adf0dd099c prerequisite-patch-id: e6e0426fdc6f315775c3f63b92b3d0745cc9226e prerequisite-patch-id: 07577205385ba70b0f678c74f6a41c30329ba917 prerequisite-patch-id: 2b34652672e4a15cc21547c88b030baab7969fe8 prerequisite-patch-id: 82ea67991a427f40a5ad1522e655391a57753c3f prerequisite-patch-id: ceeb6d405baf5ed59dcf2d01a1b709d03e1ac8a8 prerequisite-patch-id: d9e83b5a7023b5059e883cb440f3b8abac1cec57 prerequisite-patch-id: 6c194fe1b24bf4f9ab7512fe9ff4ef1392b65072 prerequisite-patch-id: 5d4179aee905e877d7a2e20dab405e543370e286 prerequisite-patch-id: 32623b2ba93e3da324f93331fcb6df5038dc9d67 prerequisite-patch-id: 3fae429d8aa73294151e6639177bef7ac3deeb94 prerequisite-patch-id: 635337e406e6660cb55565fc0038ca99ba062104 prerequisite-patch-id: f4d8d23e2f725e7e68348e15de53e878d41a76e9 prerequisite-patch-id: d03a503d2fa20df8d131e217cc0ab4279a032feb prerequisite-patch-id: 9d8dfd425ab6fc04d28a739f9c435459cfa6c615 prerequisite-patch-id: d7b27c3b4d23bc848999c1e568793cf2cd866a61 prerequisite-patch-id: b385774ef95025917da3b990d31a62a997e54660 prerequisite-patch-id: 8239a7e12ae0af6d68e89a515f81775e0dabc91f prerequisite-patch-id: ec56b7b28f1e32f529a8653b127a82de1135da7a prerequisite-patch-id: 3e033159952d9689575ad6216d428cd4f1dfdaa7 prerequisite-patch-id: fe577cacee49f1142a669ad3061bc6c452b7ff91 prerequisite-patch-id: 1841bebce629dc2f6a0811f3602c537ea81be73e prerequisite-patch-id: a379309285b06f07948bbe1be457552278ee94f3 prerequisite-patch-id: 7a61d6715b1f6cc464df88f61936ac71c84eb534 prerequisite-patch-id: b0573b9efaf5095859d6ab5bf0464e34e63e69ca prerequisite-patch-id: fb536537bf696a8217cbc2b74bf0e8ed7b81dff0 prerequisite-patch-id: 7a38331414c87f19e6d213e2730bdb3b27c5e181 prerequisite-patch-id: 33c8076419db2f93612f7d69cb5bdcef8b9b7de2 prerequisite-patch-id: c7e0b36996b8c30eb71fb590c966a02a5e084dd6 prerequisite-patch-id: 0060133fcedabce83b662cc82493790460f909f1 prerequisite-patch-id: d2a062e7a8cbaaacdf1a39ee78db13bb819e3dc5 prerequisite-patch-id: b7dfbce3db6c9a29cdcad9adaf161403c4412630 prerequisite-patch-id: 893f59897f67de20496f49c1d78561ce5755a218 prerequisite-patch-id: e81089fc58f8c6303f3908cd3ba981a1466eedd8 prerequisite-patch-id: 1cb1136c3e0fe50a9a31cfb30395fda0595fc9d0 prerequisite-patch-id: 828b63933eeb7bd781d48e95275a693d5dacbb52 prerequisite-patch-id: f1e6c4d05e723ccc51ec9756da7441fa36e2a66d prerequisite-patch-id: fb1cbb0edfb60be44380822952b63939891cab6d prerequisite-patch-id: 32aabff822b095d13bb378e8b387f4cb1efd24fe prerequisite-patch-id: 0339ca3426798514133a786188884fa4758b012d prerequisite-patch-id: d0a5c943eb79da66f7fd4fc4a37f33e9b7505edb prerequisite-patch-id: 031f5b240f1c496bea5c1cd58b2255a2108c9dbd prerequisite-patch-id: 571a2d0fb2806e821bbdbb4e6016adf4c66c9ba5 prerequisite-patch-id: 4fa81587a061a50b599ce10da4675ae072f7dd18 prerequisite-patch-id: 694b8637bf423ed279d0253ff69fb09a3aa79d29 prerequisite-patch-id: ccc8a7e6579197f864c956270f09b410948f45c1 prerequisite-patch-id: ed6418914108be07d4e041ebbf837e614ddc8d17 prerequisite-patch-id: 6fe65ffb6c9fbf3fa58b2b504de70e4be4b1a9b6 prerequisite-patch-id: 2353364954a7a9c9ea2713bbd70d20865c9948c8 prerequisite-patch-id: a354f0dbe0faf0caa8beb5de60f9dcbd42ee1a66 prerequisite-patch-id: f4c9b0b625fcbf6208a69806d93b5a990d97e6d6 prerequisite-patch-id: 3b28dd2dd16ffb88d07072b835e8d978794c278a prerequisite-patch-id: 91db39245f776c04e052237f52974363ff502e59 prerequisite-patch-id: 3473496f7eb903686b08ce0f85f921e63a4c4850 prerequisite-patch-id: b470a64c2da16ae681ea30d95f3073b869e83dfe prerequisite-patch-id: c377fbae96e05ceb7d22e70cda413f822cdd41bf prerequisite-patch-id: 17e7cc26cb5c545ae345656ea099187f52136ad7 prerequisite-patch-id: 7f87ee23468012ff45c38d6f5a05f6ad09049be3 prerequisite-patch-id: a10ca6d0b631704d94347c51b11e007ae4effddd prerequisite-patch-id: 99c836e233b07267ec4fb837f79409cfffe84452 prerequisite-patch-id: 1fee429b5612f5bfad8209f4e61d081e20eab450 prerequisite-patch-id: 7320f2d71a6f988cd5e7076d685cfccb3d66c904 prerequisite-patch-id: 7c52df1ab7a72810ddbe2a90c057786a88b47e13 prerequisite-patch-id: c814d10c7213bf1576afa2102916627963becd77 prerequisite-patch-id: abfcdd3a369902a8ea93b1a53ab7d780c9ee8cd4 prerequisite-patch-id: 26d30a7b682a8d62efea87e14dad49f9b378a062 prerequisite-patch-id: b82f9708820cf15144d75b38421166baa2aeaa86 prerequisite-patch-id: cd8cb349283da2f2f88656151765f086bcd3fabc prerequisite-patch-id: e8cf8f6184bec1122007ac0f2a8193bcf60afd8d prerequisite-patch-id: 842b7e0c51aa0396b76a63100f515241d744cf4f prerequisite-patch-id: b81a60420798737f2ce0a18ed3444daf7bd73477 prerequisite-patch-id: 5e9d60d54b3d3d29a0a418d89cb5af549b837d55 prerequisite-patch-id: e7f0e0f642c594588e0abbfefc7cc2ef6014b46a prerequisite-patch-id: 2bab30691f968de1c0bf2f05039069aeabb56438 prerequisite-patch-id: 71f38eefcac9c0486b4528186114316497669335 prerequisite-patch-id: 86cd27e95284ae8653414e2c7df7ec44e221be02 prerequisite-patch-id: e4d5f26f9a7899bebad3585fd801fd118fe79412 prerequisite-patch-id: a35a09f948f7a786b35881b62f0c013bb9abde62 prerequisite-patch-id: d9cd0790cd97fd1a56cdb6b592c1b7a76aa61c91 prerequisite-patch-id: f32df6676b3752c6d8d2bb77b99b40d52fe262ef prerequisite-patch-id: 06652d7fc58938dea5a8d8dfe302930f9ce8422a prerequisite-patch-id: 4424817c0ff766a1a404fefce5dd44f3492be70a prerequisite-patch-id: 89313dc1e00dde4799d5e5e742b614fa373b541d prerequisite-patch-id: 6ad12d9d00d13129faca27fe1880beb43b68d240 prerequisite-patch-id: 933ea000f4a100a7b11992f0f109c7233584ad7f prerequisite-patch-id: ab6de399988e963c04d9bf028154c27f8a392cb9 prerequisite-patch-id: 8a2f776f3cf024dd03f2538af89b4f44c16c5ea0 prerequisite-patch-id: d67ced7c725b6dae96a9e225e89f87506c13b4f0 prerequisite-patch-id: 7df0238dbfe3dcb278a2a117bcaaf0177b95c342 prerequisite-patch-id: 19d1008142d28a9e6bd0cd085b11970c619199e8 prerequisite-patch-id: 5c786c61bc86ff87f14a5f918ec76bafb041c2f4 prerequisite-patch-id: e4cf12c06f5c6024d14426513aa60fa5cdad4554 prerequisite-patch-id: 7e22d329f8d84008c9de49fcaa313fdab9c2b218 prerequisite-patch-id: 1086cff7a77b0084ae29c4bd764ff407328a7a7c prerequisite-patch-id: 4ed6ccefb88a62dffdc2ac1ac68f3ccb531b691c prerequisite-patch-id: 32ed86b38a461e8cd296a1e8af1b6a4ed1d1c7c1 prerequisite-patch-id: 002effbbe18770439243331975d5dd720241c524 prerequisite-patch-id: 8f689faea352b84753a920000ace3692968bdccc prerequisite-patch-id: 46b191e5f25f9e003a03b8227ba82d7c32c4d560 prerequisite-patch-id: aeecf79d79fb9beaadc7c11e4488b48436506b64 prerequisite-patch-id: dc5f25f6dd679137bd23fa6f6bb01a53030e8818 prerequisite-patch-id: f8897be22adf3609e80fc06fa4bff24a60d4ba74 prerequisite-patch-id: 8798668554fa55164b7016e8863b120e70ab2742 prerequisite-patch-id: 10606047556b4638b6b4786a9165c9a080b1d212 prerequisite-patch-id: a7db90ec4e814586cc7b355c404da59c05797af4 prerequisite-patch-id: a32f2ee49db9679971a70eef6be04aa8b1b869ef prerequisite-patch-id: 5e9551ecb73113a3a939e6a1ae7d4b9522b0178a prerequisite-patch-id: 536ee71e17330a1df67615f46c15d61c0b5ac60f prerequisite-patch-id: 3f5421a6d829f3364465aa0ed5843a0182e15895 prerequisite-patch-id: 42638530d6dbdd08f0838a4749dc24043e9a9901 prerequisite-patch-id: 039a8911b1fc02cf18da3e288ce71a110b62ff1d prerequisite-patch-id: 163ebd8eba172f3a68c758f5a6af5458789db3ed prerequisite-patch-id: 4ac2a1d653855fc545d3c3179cfcbde675548dc9 prerequisite-patch-id: 29c7828462e242d9055baf1e8ac11bfd0782a7b2 prerequisite-patch-id: 520404ab46e856d1267f1684e5e83eebef7f6d69 prerequisite-patch-id: 242febea67ea44982b593c7c7d01eea7b38f68a8 prerequisite-patch-id: 54fdf473f9e6ceb6cea7fb395436e933ec7cf034 prerequisite-patch-id: a08c754df561443c8d0250972061d8d109aeb426 prerequisite-patch-id: e5f0a86fb80301399316c7c23a5a3e25fbc382be prerequisite-patch-id: 473e16727b694560cbfea5a2d14328c9318e7c43 prerequisite-patch-id: 0c149e9651a69f43fd365a0e35b28dc7de37bc18 prerequisite-patch-id: 8211fb4878327adadb0a1d1332ae1317ea2ddba3 prerequisite-patch-id: f0dff46e71443df2147d198027bc1d4511166080 prerequisite-patch-id: a2986b6d118c6efe482b483d95927182c68b605b prerequisite-patch-id: c5d3e8459d1a488fe37ce55290d998e985e0dc44 prerequisite-patch-id: 48128f162d1fe9e0bffbe4ff97c9ca4f5355a298 prerequisite-patch-id: b7326ce2a475c1390541402888ac71913925ff66 prerequisite-patch-id: 1b7aff73eded79a6e5feb42ab436c8d66e78aa14 prerequisite-patch-id: bf1eb6cbc983a178ec3072e3b63d03967934b462 prerequisite-patch-id: 2e559fce1d36685841750ea5362bbb08cbfdb9da prerequisite-patch-id: 5f53fa40afc29d7b4b30d726d3b1903fa411bf72 prerequisite-patch-id: a6e8d88f1c820b94eaa492b592b769d8b536db9b prerequisite-patch-id: 0aba1735ac67dc7b2dc61a07e511d775c65ebb61 prerequisite-patch-id: b3df482f5fa688bb034e0b034ae5ef75b4be710c prerequisite-patch-id: 8a1149e267206f9a5419833f8392927f2f79b3f9 prerequisite-patch-id: 0b1df73132159562cacd826c337c93a62a24cd6a prerequisite-patch-id: eb4e88b658e2ec78447896ce5d97fe66c5c59f8f prerequisite-patch-id: 1b474c461ae1aab986c935bea8be2ff0cbe40d7d prerequisite-patch-id: ed9f38a1e52cd0893b68b0455075b81cb6de1dfe prerequisite-patch-id: 5a6ab6766362fae12a9e25caf02867456a77e8fe prerequisite-patch-id: 52b64cfcf4d58312179398bb120861b283a56c09 prerequisite-patch-id: 41f0e08a69b473f5cf85b03762a70e9661ef079e prerequisite-patch-id: 445019439c80e5c26ddc16afd5141a9070373b89 prerequisite-patch-id: 25c42086e479f360bc6c55386c6163b3efd44aa8 prerequisite-patch-id: fedebca1a8a7050a139bc47d448a9d95ecc05f5c prerequisite-patch-id: d7c2fd82ad2fc9043e34047117e7b79a19672833 prerequisite-patch-id: 89bac58775ed583f72fb81ef3fc74e45f5a0aaba prerequisite-patch-id: 26163c1c146c13b72c8fe9df41a1459d29aef123 prerequisite-patch-id: 50840c17680a9c15821551b1f344070cafe81bd2 prerequisite-patch-id: bfc4767e94a4b95c599aa4e865ac7f6cdc163c23 prerequisite-patch-id: 81123804b0c05dd0d3d23b150c8e844ff5d7a606 prerequisite-patch-id: 6026e40b816afc83a7182af6afcd27e963132a9d prerequisite-patch-id: 23289a452742bfa25ef62e459cbdc03d82fcaaad prerequisite-patch-id: e089060d33604e719fdcacf8e5ef8d4e9500169e prerequisite-patch-id: e843b03562218a6041072038650ae66abd0d97a3 prerequisite-patch-id: 5f1f2671d722ba9e46ba2e830b70fa8c963ea9dd prerequisite-patch-id: 148fbf7518fedcd94fc560460e8acb52ce166fb6 prerequisite-patch-id: ee53e45b43c046fd00bfb4ae4447daa2d26c8483 prerequisite-patch-id: efdb02a76e70facde9bb5f6e971f7b5f15d5ca81 prerequisite-patch-id: e4595ec7600509cafc78da2d80d0bf107e5fa32e prerequisite-patch-id: 179516c217cf79a9532c20011376ebe584444d52 prerequisite-patch-id: c582db414dc8c2c2cf0f2fe330e9fc52e3f8b199 prerequisite-patch-id: 902be7e81b77d2566a71c13fb9042987b69855f9 prerequisite-patch-id: e9972636cb777757cf0a3dd9fd89d32ce2bc77bc prerequisite-patch-id: 895fb7f3612fdbc31e1b41a17a3922f5ef975af3 prerequisite-patch-id: 74e24da5b7c6e76fe694c1f655fb60309005e557 prerequisite-patch-id: 79e544350e89c528ac8319e5d500e51f1c657127 prerequisite-patch-id: 32c6f3b0c07b60638dafe54ccd271ce63c7476c5 prerequisite-patch-id: e61f8ad8f39f39e38781a4526927aec7508b2508 prerequisite-patch-id: b625f0239846b80ae273254a08defc91e99667b1 prerequisite-patch-id: 5b94920a7117d6181224dc6d21057c898a1ffe97 prerequisite-patch-id: 41514ba9f823311a0e384596973d7e3e26a3d040 prerequisite-patch-id: ddeef556bd5775ab9ea9cfa83c26454dc38665f1 prerequisite-patch-id: 76dc3b52dbe4bbd1b581dc152ac5b8ba09f0abf1 prerequisite-patch-id: b3b2e0aa7d20a58bf08b8507f986f81a9a424465 prerequisite-patch-id: 247a6b1661a0032c95f05c5875d337c4ff713042 prerequisite-patch-id: db3f6eb6306f6d94d71e803b595d92c3e2e36931 prerequisite-patch-id: 531172b5be47293f91366a0a13888ff5b21a830c prerequisite-patch-id: 1f8364e5fd0385a0710da6c342c50b954a597ccb prerequisite-patch-id: 74c039cbbd95e9e8be1c7510faf7c5d52a74a460 prerequisite-patch-id: 460998322154b073c81eabe0d941d543dea46cab prerequisite-patch-id: 709150aaa4ecb46ea63ea9704d2c9ff740ea90e7 prerequisite-patch-id: 2884ee96538388ff208cc80e3955bce4143d5c93 prerequisite-patch-id: 971173392a9c8f385ab43278ff67771f7624185e prerequisite-patch-id: b5286893370ce46b73823c57c068374f1bde2253 prerequisite-patch-id: 8efc8aad2646f2e2ff7a78acaa4f56ff42cb087f prerequisite-patch-id: 3988e74ff38c9fc0c9008cab181002afdb9772f2 prerequisite-patch-id: 8ef1348647221afb637ad4d3077935ce3161e0c7 prerequisite-patch-id: 5e7a0186fbf2bc1980439524a4681d0b1c89d997 prerequisite-patch-id: 5c69272bf2a5459d999222527b04560ae3b11fa0 prerequisite-patch-id: e30e1e17001b4a17fec9d866d8e22714a4396f03 prerequisite-patch-id: 5ce53aca07b39b5d5021f0edd1f7081fc2452dea prerequisite-patch-id: 08c9b0a7440600a673b00e8e25d067c3be6f8cbe prerequisite-patch-id: da339fc4d626d871b1a1e3d1473522c8b702474d prerequisite-patch-id: af74c30ffbfc6ff9d0cbd8be32c54a56d2a74d86 prerequisite-patch-id: accd9cca7d3be6b211525fc42b2edf8134be6af1 prerequisite-patch-id: 9ccec28b7a3396f45298e65250c59f04094c0213 prerequisite-patch-id: d15461ff772c74bc68420dcb2f2cec5639afc338 prerequisite-patch-id: da03a39443820ef41071997c6afb8021c81a2b5c prerequisite-patch-id: 25b79099c23610954df6095a1f7f9d4519c7dffe prerequisite-patch-id: 43b8bbd96dff3d81494d72cde18aad80c93195fd prerequisite-patch-id: 3cd40e4771968e6ec7239d14929648f59da46f0c prerequisite-patch-id: 77a053a8bdc0ca34a9a4b47536d499beec5cf79b prerequisite-patch-id: 5d67418278a545642bf673174d7c1a5c208edc52 prerequisite-patch-id: d9ec859c6f7921a1a4c74b071895122f79bca0fb prerequisite-patch-id: 1f1da7e47939f693ae8fde324dcf9203ed247ca0 prerequisite-patch-id: f9cbc0bea1a9302266fbee283fa0b8914267d02f prerequisite-patch-id: c96621c8ad2fc3e04e68970f0d355d20c743249b prerequisite-patch-id: cff996c7639f7a9cdc116a09c05411036c93c755 prerequisite-patch-id: ef11089062b21ff4a2b7e1594794fa6b0fe1caa2 prerequisite-patch-id: b82ec99113491389a4f508cde94d1133e9840a2e prerequisite-patch-id: 60446e3ce98125d538ea1bd5ecc8317e1502ff83 prerequisite-patch-id: 1c17b9e31ed47420665db95abcd7c3960264c860 prerequisite-patch-id: b732c0460ea2125639063e0f00bd5ddcc34c343e prerequisite-patch-id: 9439e304c9bfa18d290fc2654b489b2ccd9b0107 prerequisite-patch-id: 6b361426f0f8d04df3b838adba8445d554105d81 prerequisite-patch-id: 4b579ca0dc8c192c24919507c1ea2b0aabe1ff3e prerequisite-patch-id: 0ff608f39fcfb1e322a18b499e5022bc6f29df7d prerequisite-patch-id: afb051290443ff2038545a9c1464272e3a957b68 prerequisite-patch-id: 2e1484d3bf804ae340916904bec7a50b1467ad41 prerequisite-patch-id: 848e6b53c7072432c6f078f381bfa27729d072cd prerequisite-patch-id: 82a399c5e05aecca6c6174e89f73b7c31cb6810c prerequisite-patch-id: 1ac5f094cb37631eebdc1138345d6c9f6c5f28ec prerequisite-patch-id: 0ef7ba6fdcfddb37631a012ea3bf52d3c730dd83 prerequisite-patch-id: ffc9311419e503f5a4157992e48376656f2f9072 prerequisite-patch-id: af93fdb5e079cfb7d7e350a87c6c6dc1bc306a5d prerequisite-patch-id: 1231dcad0fb1ddb043f4168d07ee5b89141a3eae prerequisite-patch-id: a8bf38bc9bf8c7a0861a402c2c4b26058664dd25 prerequisite-patch-id: 38363c92407fca6027d79845af61620640f74e9b prerequisite-patch-id: 43d90e3f5fc53e641ae277a816b0d04222329fa8 prerequisite-patch-id: d6ebb5c38b9c14f338269efc0dfaff85a20bf543 prerequisite-patch-id: 9b786f6621b1a23908971c6d5a53c7ad56b4ba7d prerequisite-patch-id: 5aee54034eccda4cfa5cc62cf220e637fe2facbe prerequisite-patch-id: 0246c3e52f773e86111d2ee5548848b667848614 prerequisite-patch-id: c5b39b02abd827bbbfe73e3d7668d27251adf498 prerequisite-patch-id: 4987c3039ee9da690a8cfed47c24410a554b0a7f prerequisite-patch-id: 1f8304ec9e126776b17b5970f053ef1c1f78dace prerequisite-patch-id: 8b555b6c12bb7bf9d4fcb9cfb4db1d36836f5c1a prerequisite-patch-id: 7d2c064f8481309a5771e41fbee28eec42155ed9 prerequisite-patch-id: 0fb751f20e6a77e3b440457557361d3290c187d8 prerequisite-patch-id: 6b390361ae6ca4f1947159e5497f633746a8bf58 prerequisite-patch-id: 732bacc09ee665e389dc5494c78bcb3b260910fa prerequisite-patch-id: 3a784b85af1a2efbe9ff263116945ae00d7f9b32 prerequisite-patch-id: 513cc5b1be80f58424ac6af9815c144a2e0effe4 prerequisite-patch-id: 5f571f36cbf3f7ae07fff270a09d98c187757a97 prerequisite-patch-id: 93fdb7d719875d733f756aed6ff258d2f2bd1c2b prerequisite-patch-id: 8e33a86743b2d696fc8a34f4e9d377488cd36d68 prerequisite-patch-id: b7c88b1555fbd773ceb1b570e032a84563df6e78 prerequisite-patch-id: 6d9ea46cb82908ed3b455b77117e1d51f1c47cd3 prerequisite-patch-id: bc7df8f6e921353a94e999c3a54ebea50f50e989 prerequisite-patch-id: e11429702173ef78ca3d35cdbd4099cf5f2e2782 prerequisite-patch-id: b7af15954795a4c0834696d120cd93cbcdb86a34 prerequisite-patch-id: dc0c39535c17a6e3e9ae39624db2b2f1b6bbe533 prerequisite-patch-id: bdf10025ee6f9a99f10ae688dfea09042d45034c prerequisite-patch-id: e4592b3fd20fcc7448ad2bd354921523144ef073 prerequisite-patch-id: 0c9025ed0495fe73d372874f156d2bf170298f46 prerequisite-patch-id: 97551deb46171097c91c89db9eb8ac4beedfec64 prerequisite-patch-id: 8ec6fba4051f0d74ed59615c52364cd555e9001c prerequisite-patch-id: 7b07b298da79a2dad513b71ac8df75aba2bd325c prerequisite-patch-id: a7e6c4323bd7335c228614a0f50c5def94a68d17 prerequisite-patch-id: 8468ba1de4f4c0cc1091dd641756c31afe9be7c2 prerequisite-patch-id: bbe955fa0015cb74570b649db4f7e376bcb98892 prerequisite-patch-id: a7196a880e75082a8f0008ee707be41fc4f8d627 prerequisite-patch-id: fc0bf169d577be068043d63076a6ac742bb7e30c prerequisite-patch-id: df6fd267dc6fc6efd20552f140d4248aca54578b prerequisite-patch-id: 4aa69a13e2df189ac75fc978537dafaa3853fbbe prerequisite-patch-id: 26194502978932bf6f81e012aacf5c66ae8ccf3b prerequisite-patch-id: ab6c1266149de1bad606f473e3b06dffb61b4f42 prerequisite-patch-id: aa8cd17b3a4436b5d070a2fad32c3ed5d7ff71cd prerequisite-patch-id: 5b94920a7117d6181224dc6d21057c898a1ffe97 prerequisite-patch-id: 0b3d3d087e9cacd996d19ef9641e2f23188ad58b prerequisite-patch-id: 513f8f35f264d6d797b4aa39cde84246d6c50408 prerequisite-patch-id: fe3a7a92ec8b3fda9b53ddc3e8b0808cad6b15cb prerequisite-patch-id: 4b9cb8fd725b8092ef6cfeeee9fe17ee0604818d prerequisite-patch-id: 76bf39ffd26e49bf7135eaafc11e1f17ecbb35e8 prerequisite-patch-id: 9b2a3fac162edf25d51b2dc7496d4929b09a62b6 prerequisite-patch-id: 83bc0e018f3c995d44a96db61cb88a0e16c8d612 prerequisite-patch-id: 656362f3c8e209284eba6abdd8fe45efe3893fce prerequisite-patch-id: 560a2b38a69972b5b3e04bfde0f7d1c6b03d500b prerequisite-patch-id: f324a2b904b374b819579d282a3562d7470591b1 prerequisite-patch-id: a0ac304f269206e71fe2be3587f173a139a7907f prerequisite-patch-id: 5ce16db109df4bfabe1ff74103fd8fac8ab47211 prerequisite-patch-id: 0f882ff1c372df30ed1bcb1fcf2309542ffc22a2 prerequisite-patch-id: bc4b45e927f0aea704910be65c9edac6261a15d0 prerequisite-patch-id: e4a7fed2b8b2f9bcc7c9dd74bc81fb1dacb4cda0 prerequisite-patch-id: a8fca49a4e7431671578b76e4ee3f5d0372019b2 prerequisite-patch-id: ef44ace6e7142d647dd3dab7b4e7b8ca235efa7c prerequisite-patch-id: d9d7d6e4d097ab0e5984da317e6f0453116b9b59 prerequisite-patch-id: 650fbf51657dd8fb2606e5c3aa9b8c7d79721684 prerequisite-patch-id: fb39876fffb4d0e7531c1ae64da4fd433d8a0fdf prerequisite-patch-id: 2ca90436250a1c29c46c5fa954fa3a237ac51f85 prerequisite-patch-id: 5c2c56c58106a60420196984d0e332007faa7600 prerequisite-patch-id: 97f779e910db1d089cf1d334019a2329f1baa25d prerequisite-patch-id: 821dd9eee988882db21309ec52b86736d2f3f469 prerequisite-patch-id: 23b2abf31d94847b5b17157c9a08ab88493be9c8 prerequisite-patch-id: 9f3764ae2a7a398ea7680bf86225b8887655b98f prerequisite-patch-id: 786f60dc161b5751f06a0843397a1501e8ccc396 prerequisite-patch-id: 572dd3299a007953d9c2f406d36ea2087d93d458 prerequisite-patch-id: 063db33120ce170b158452bd3bb6d47f843cd47c prerequisite-patch-id: 94b74df900f95ec509fad7d6a25a426561550ca1 prerequisite-patch-id: c4670cb4a7edade0d046f9d8fa37edbf2145200e prerequisite-patch-id: 1c9d47c3bf171f1f4fbd21d75b87d29b1c1ddc80 prerequisite-patch-id: b0f3b4aaa31e8b2b5872d60826a9923b909d5625 prerequisite-patch-id: 19408e7bf368f0fa7d4f6e6ae118e4e626e033cf prerequisite-patch-id: d8bd786368f0685a89d405eb5af359610082fa0f prerequisite-patch-id: 50cfb54c67090fbbc7e052297f77bfc3679fc64d prerequisite-patch-id: 87733d8a31abfe2f4df951f479f23fa650f8f0e4 prerequisite-patch-id: dd2173f08bc970f589168c138c27acad97649af7 prerequisite-patch-id: 9fbafe382102ea6ca4489f94c1e614376d26b7bf prerequisite-patch-id: 7789f71c7d74d4bd3f24c2d5d284dab756772f3a prerequisite-patch-id: 2340b60ce5b8b12923d1bb20add51fbaab651dfc prerequisite-patch-id: c0cba2004244c0c25dacd8bc0a03b5fa491ec67b prerequisite-patch-id: 3e771faf0ad60ed46e1ca0f1dd356d87dfe9b45e prerequisite-patch-id: 875630b25c44437e44565f260109b9fa3447687b prerequisite-patch-id: d327f47ed98255b3e9fa7d868c9b3354281e217a prerequisite-patch-id: 94275f10887705d539e4629fd85992afaa085c27 prerequisite-patch-id: be9a7e912549e097a9ed1889cbf2a74490ed613d prerequisite-patch-id: 82d037abd79874acbac432a47c1e72d0316254fd prerequisite-patch-id: 33cbfefd2539434eed9c5e71b87f99c290dede0e prerequisite-patch-id: a0b478f71a23ac93028080e318c5aec2cf1f62df prerequisite-patch-id: bb8bcbda82ef86404471a28fd9e1b99485f3612c prerequisite-patch-id: 073dbad043ac38fc2acf152519fd9bffceb275f1 prerequisite-patch-id: 87d701dd0fdb54c276d5f5152b6170625be9d6ca prerequisite-patch-id: 9957f3fb4a84e310d8cc5bba7ba57a27d88c5239 prerequisite-patch-id: 3d9e502603d6e677187af1e92cc74329c2fb4a35 prerequisite-patch-id: 58e6676c47307a2094ffe67b99fcae711168db2a prerequisite-patch-id: c237533fb9955e51ae9ee5d2703f39e78b59c1e8 prerequisite-patch-id: 59a0b12a15ecbceed48487034bee28b4490426ab prerequisite-patch-id: c0270e3ba35e3946052c7ac8de612022f08bb8db prerequisite-patch-id: 75fb859660f930b3d8963022ade03d6d72ad1a76 prerequisite-patch-id: ecb8fe8e79464beef3c85f158bfba2ceb1c81f50 prerequisite-patch-id: dc00bdaa420a1d9f76a30876c30adab1d5bb961f prerequisite-patch-id: 819c40643a16dd134c0291c0190619d7b1558ba7 prerequisite-patch-id: 478fba0161802975ad6e9e3d93d5823f185d3376 prerequisite-patch-id: a0b131b1eed17e2c830707562cf278af31ccdf38 prerequisite-patch-id: 0e39edfb842b6282a841cb261a61a1ef649bff02 prerequisite-patch-id: 7e9d040827a142f4831ec255418d4fdad6f7fe98 prerequisite-patch-id: c6d8067ec19e1f573a96ac0bce93618a12c9c72f prerequisite-patch-id: cb222ae54969ca8b96ba79493ee20a753263bc73 prerequisite-patch-id: e8248cc99891718277072bd75bddc68bc6b6bbf0 prerequisite-patch-id: f1e384d73c88f50cdd8deb2fe581bde5773620d8 prerequisite-patch-id: bc5559d38b3dd7a4cb125cc1c28ef10c0f573b07 prerequisite-patch-id: 0d43943321332f10c8984602b5978af1f347c98d prerequisite-patch-id: a5eda7748ff8421393d5cb01571b37576275af1a prerequisite-patch-id: e51c22f9d8899a97664ef6326351bc32b9803ffa prerequisite-patch-id: bc54aea85b476b4a44b4fc292f9ec2c5c37b77bc prerequisite-patch-id: 5f9b1e5506d75eb54ed9897977193e13c1783edb prerequisite-patch-id: 424e3fef43732d7542e18d0e6112c47753d34545 prerequisite-patch-id: 9c3a1a200e7e5348ac24913f08b6acaf416d5b1f prerequisite-patch-id: 9010394b3ee66fbb21949b87ad7855eafe374ecd prerequisite-patch-id: 8e229df8ecc4a960d1011bccca5dfba9f3a8bfd7 prerequisite-patch-id: 347393dc2a5fac23dcf9c9004aa89d39e06c473d prerequisite-patch-id: f89aa282e608a2bba1affb0b02213c0f60f3bcac prerequisite-patch-id: 9590dffb039bedd5758c48c339eff4ec47f80f04 prerequisite-patch-id: f4bd82d98af39029d792325850ecbb724091f95c prerequisite-patch-id: e40ea8932c546e6454a74d657e26dad612707f45 prerequisite-patch-id: 54f2f71b7449c38b54bd37d1415b9a25cf4d4b94 prerequisite-patch-id: 3f55640f5c4f2c66e8a918888da51df3e06bf6b5 prerequisite-patch-id: 4855f93a0b1ecc98bd04f16e543ef432d3f25845 prerequisite-patch-id: c12cd1c36e07244d8071f4df6b184d2eab4f228a prerequisite-patch-id: dad6a7f94126567b02ee812b7c6f6809960671a4 prerequisite-patch-id: a39d1ecc10b3140746a98105b5d3a9a53b38a05f prerequisite-patch-id: 224d18e7838aef45462040f88dea958f4551ed2d prerequisite-patch-id: de509e6e7f74efb12f8b35588837536b77b5406d prerequisite-patch-id: bb9d55129ad66e1f94e7c5ef9536e60a0bbb746c prerequisite-patch-id: f4f1c86735af61d363fdda58e60d27056cf1cade prerequisite-patch-id: db4604fe406d7c7156f35a66487b6b056936ec72 prerequisite-patch-id: 53259affbee4f399697852279ab941a234237659 prerequisite-patch-id: ebb00b702861f1e3a770903f4d89641c00c80996 prerequisite-patch-id: dd1c96cf0b2e6fd31e5444f98482862cfcb19d26 prerequisite-patch-id: 1f9c5145de878da7b70a073924ff69333847739c prerequisite-patch-id: 6f94b45cbe4d63e5a095221d0d64825a95d02afc prerequisite-patch-id: 9448f929d1e208d453152c9c0d40048873f2303c prerequisite-patch-id: e0818156453d24499d950b654bbad3a9e9f1005c prerequisite-patch-id: 7f9617c3a6bf1a44a82b76a2caaea352dad8f209 prerequisite-patch-id: 92ae5f9a9a58084b3fe6729669756c0bc55c19e3 prerequisite-patch-id: ed6288af8cf6771dcd4d2fc86db5616688c611b2 prerequisite-patch-id: d28b06360ab382fad114e1950fdb225b8792b786 prerequisite-patch-id: 3bbf7f4187cb111c66e545977e02462756760a25 prerequisite-patch-id: 4a76164d419dd490b0079d2e4feb479e7a00b3f8 prerequisite-patch-id: eaaa56cc0fcb8739cbc1322bbf38ec7877449dda prerequisite-patch-id: 2453fd435c6c5f50a911f3972dfcf3319fafc83d prerequisite-patch-id: 1d9208cbfae33b2bc038baa4a35d5b18fad8a255 prerequisite-patch-id: afb42891295d64778dd1ba49608fb39882ce6121 prerequisite-patch-id: 0c5338a021c7cd7e54e9aa0a2b20f46d718c6735 prerequisite-patch-id: d9e6e0f8844f3665fee9919807eb33e552f51be4 prerequisite-patch-id: 919e0cca1e3f4b8dbeb3c9c7ed52a88014d791da prerequisite-patch-id: d171c2726aa70ac4947ff1abd7341c180292c630 prerequisite-patch-id: b4b32bde7298af1ea89098400f1f3506e3515d11 prerequisite-patch-id: e5731be4a8db0538aac40749635d9ad11f6a1902 prerequisite-patch-id: 75eef4b403b223222bd5fd61d894467410266d07 prerequisite-patch-id: 70f02ff2e7b7a99fe3b5e616b5ae5ce2822f0be6 prerequisite-patch-id: 71161f5863d64cd3ca2b7bf4d17060bf07e97c55 prerequisite-patch-id: 9ef05447217cf9e29f4e2f39876a0ed3d0f14c60 prerequisite-patch-id: 733b0a57c4a8cb3ba22c3a63a51ad5d6f38025ea prerequisite-patch-id: a619e4f3db75a650e62a9b15293f182ff56cfe8c prerequisite-patch-id: fd42d13d18fd784d6b37da33d937e884eed2a0f9 prerequisite-patch-id: e6f758992f0748352b75ca6b278f3a5dabb68fb8 prerequisite-patch-id: 5d0c0815f0f61dd4f12b8d8abe8864249d8146b5 prerequisite-patch-id: 786051a77cd96f1f5be972b0dadd5cebbd6922df prerequisite-patch-id: de947968b840b4d4110433d166668a661f1196b8 prerequisite-patch-id: 2e9c54d4128a68292a8addab6d45913e686969b2 prerequisite-patch-id: 634049755878fb623249d01ebf29a6e2a1fac46d prerequisite-patch-id: 6247f74664df18a6754f0ef71c713c61fbcc0e55 prerequisite-patch-id: 5fc3c2104da3d19683bc6a8bca36fd21c1725976 prerequisite-patch-id: 414cae210bcb0e46ad3d4a711331d994b1a16cf5 prerequisite-patch-id: 80867b1b426454b82c660ea2b0df11fa1de7705b prerequisite-patch-id: 807903d3cc41eb9b101c52ceedd5c98d33d96b51 prerequisite-patch-id: 73d0e064cc28f7bcf827f9b896f66831f34c2d9d prerequisite-patch-id: a56d33d348662fb5ba2fb65cb79c851230d5f450 prerequisite-patch-id: 21d6549fc3ea9df380a5cf8b80ec89acd4486a80 prerequisite-patch-id: d9870d97e2243a070dc215aaf1b31e90f8177e73 prerequisite-patch-id: 4b07902b02eb5943622ba74d88372e1f24b6749a prerequisite-patch-id: 4a07456102c9ae11379e4f51015f933fe1ceed56 prerequisite-patch-id: 3164cc418b44e6d67ccdd7418bde9eca1525d7a8 prerequisite-patch-id: b18c18f89c88f85e9b25ff9c6b0450f607fec159 prerequisite-patch-id: df9aead93931a227ec1330abb0175e6696212755 prerequisite-patch-id: f8ed8f7a060f1587336154a70b6e802bd4913a91 prerequisite-patch-id: 11c525e56bfa7e6ba654aa3b09d21f36c67c8587 prerequisite-patch-id: 9d3d5da457477552c9044f4f02f5f18a59c8b0d7 prerequisite-patch-id: 4e58cf3e034068fd8912892cb57700b54f308f46 prerequisite-patch-id: 9935e619e9d768dee374659243cec1ee9d30010e prerequisite-patch-id: 95d2677cb2d5ba6589702728057d57136f8d2b9e prerequisite-patch-id: 023d40ee05b49c592263db6d49154eac0315c914 prerequisite-patch-id: 55624a110e35dc1bb1c849974c1a2074f6c5b757 prerequisite-patch-id: 6236d2f7d90b1ad69a158048762420659712aa92 prerequisite-patch-id: 693a25e4282fda1900fadbaefad9dfb3211d0a89 prerequisite-patch-id: 3ced9cfad9059414f175aa28cab39b446a9d163f prerequisite-patch-id: 73cfb3e7c2634dfe5312805cdf25e3dd050d04b1 prerequisite-patch-id: 118c173997b2db9d344308f786ea6dc222f04abf prerequisite-patch-id: 8bbd0364c2adedd4755d19004f8e7feed670d7ec prerequisite-patch-id: 3c4a475b92d57f0e6978866b5899a29430d69ad5 prerequisite-patch-id: 24385123c2ac1a10ea3890ab1be27f09492fd6b7 prerequisite-patch-id: 6d2872227da5db987d4df2d6c7dd3d352b93be7e prerequisite-patch-id: cdbc980dc7bfbc2a30cc1b187547e10f1219f871 prerequisite-patch-id: fd275a77b79b5959347533485881e51312069f5d prerequisite-patch-id: 62b21219f24b533f8ab87afa0337c2222cc91bc9 prerequisite-patch-id: f67e2427725af42142c4c025cde31a010e959f7a prerequisite-patch-id: 77c34f7eb5ade96154d8338a75216d438f245dc2 prerequisite-patch-id: d7d22219f415a3d037de5e58d5b4bf877d3ccb8b prerequisite-patch-id: 6176eba1ab736fa414355ea6f88e51968f0e3e1a prerequisite-patch-id: ff166c03109dff4347a5117d3202aded7713cc2e prerequisite-patch-id: a51793ce814dc83b414670441a7950a16a1e61c0 prerequisite-patch-id: da0888543d6988eaaf0252fd7e2944988d4ee17b prerequisite-patch-id: ec93f08a98566beabab1156cb4618f8f169acac4 prerequisite-patch-id: baed7ff99ebfa04511710cbf010e0bd32ca80e4a prerequisite-patch-id: 6ba86fab0cb014278a04c2bd634bd8594bbb5f5f prerequisite-patch-id: 233b308744033b4c2e10bbb5d3e52e9122522a2b prerequisite-patch-id: b1d8525e12f0fce455c8db731033eab27b0d961c prerequisite-patch-id: 292a3794bff10444eb222f57c359ae1a38c29ba8 prerequisite-patch-id: f50989710af25b47f43826dad054acd4b0ed519e prerequisite-patch-id: cb559aa7405da7ab5580ed564ac378b903c857b5 prerequisite-patch-id: 6320353f7cc86e5c5f1263aaeab64a6ffc2381d5 prerequisite-patch-id: 2b0b1dfea67b987eb16337102a9d50fcef02a449 prerequisite-patch-id: 86328395bccceb90299c7bab783a8f1e8b603d65 prerequisite-patch-id: f19f6dd38d5e199eb13b6c137ea28412a990198c prerequisite-patch-id: c03f10d045c6d963000bb144cc9a8cb6a21b2585 prerequisite-patch-id: bd132ed6435958018588209401cb23728d0216c3 prerequisite-patch-id: 6674216bbdb105bf07671e7ae3ccad2c10458193 prerequisite-patch-id: 204b86403376c87aeaf4352fd7e81dc734a7c204 prerequisite-patch-id: f0dd75fec3f9f20059469c47fee6ad394d43709a prerequisite-patch-id: 4fdc43d186c174d5908e6f91cabe9a47b2ad130f prerequisite-patch-id: 9f68130b178f025c4a1743e7d9f126fc78c11ae6 prerequisite-patch-id: f5fbd17ecc1181c5e659323a26e9056a2072a69e prerequisite-patch-id: 8bca576e133a3fa2a4e1de76f0254412ce1e49ab prerequisite-patch-id: 083cb90851e88122fd49ebff280a7d33c6817ca5 prerequisite-patch-id: f5d8edeed6dd63d975f453959e354aa1bcfa83c0 prerequisite-patch-id: 88f85b7b562645deab6c087ea43b73ae88be6f8f prerequisite-patch-id: 393ace3bfdae18e684ceafd68b86454b3cb7b95f prerequisite-patch-id: aaeb5abd0a644684c3998be4fec4f6c978825618 prerequisite-patch-id: fd6ff3b13e5e17ca32d89dbd0aee4fcb6afce2ce prerequisite-patch-id: f1732befe30033f28556a3dde8cc203831f0e141 prerequisite-patch-id: d12ccdfd4a3dc5e45dcdfd53965cb68904322630 prerequisite-patch-id: 44c786305b4a48e4d77aee1c7cdf23d4531acb82 prerequisite-patch-id: 33c82c6e4be8f7c76565470be82e8571e74b9e9a prerequisite-patch-id: 85058e1455284ef5ed671d9a0f2f6aafc5b31b97 prerequisite-patch-id: 82ed7288b769f74f7149644613aca4982a9050eb prerequisite-patch-id: 107100f72e9b639addb3c6f8a056b84aba2d6e45 prerequisite-patch-id: 4167b64b16a44907b95bb49dfef2acf653c08b7f prerequisite-patch-id: 2518d21cc3bd23a0a640e224dfeecd3aab66d0ee prerequisite-patch-id: db2896280c755fede5c748ebd466581ae6772927 prerequisite-patch-id: 7e270a630e3a9e97417e9d65d71d21b8b6409e53 prerequisite-patch-id: 215fdc1bc8fa950173344ae5b93f5d14df9b4e03 prerequisite-patch-id: c1bd615baa3bb6653ad7c7b2dcaa2d6c1a934ba3 prerequisite-patch-id: 1e3883ed9e639268335c6084828f0fe62fc53320 prerequisite-patch-id: 9317ee51ffc35176bb43ea224ecdbd3e13942bde prerequisite-patch-id: 0f3adf689a57b31d39c369ff95685c02dac77bdb prerequisite-patch-id: 3d920ae29fe61814a8aee74985c9b14caa238fbb prerequisite-patch-id: 02210d0f8a8f7d85395c9a34ed2fc7129c5af0b2 prerequisite-patch-id: d61149f3b6bc8244b30211f34bb63c886e42e7f3 prerequisite-patch-id: 2be4bda83b262b36ca457a4a092f4cd62538756f prerequisite-patch-id: 3ddbc3208b477eea46761853a5a4aa8d264d5515 prerequisite-patch-id: 9f41490cf1ae46c9ed756ec8816b4e0bb0726d6f prerequisite-patch-id: a076e8b81622f31d4cbe3d965110dbf1c1bad520 prerequisite-patch-id: 84a8ea459009f889714d5b385477b2ef0c4e7868 prerequisite-patch-id: 0a233f16da271412d3ae7848c4b1810dae44b42d prerequisite-patch-id: 32f61498294a01465cf379f8b23370224088d20f prerequisite-patch-id: 72a49ae1e8ddff45d95296b8e7003e4a5a7b9c50 prerequisite-patch-id: 6cc57f295a22f87afd165f1ebec81438b8377dcb prerequisite-patch-id: d2e38edda8767446465b79ae166ba0c6a3253421 prerequisite-patch-id: 632b49a0d7775a4edfd26826cc62d6b0d9ffdd40 prerequisite-patch-id: 3e9a65f00303439dcda1ec54aeb423886f915907 prerequisite-patch-id: a271827200f68b3d97ff00e5a8d2c3c0063ce876 prerequisite-patch-id: 0f0b922bf4dcdf097e26acef44e8a19f38951868 prerequisite-patch-id: a3b1332c7c9a1178a64b1c157f6bd222c6c9e94c prerequisite-patch-id: f42659f53a09c38dbefa0dcae8805dcb116dac5a prerequisite-patch-id: 403d843faad9cd285532af17d268d32b1dcc296d prerequisite-patch-id: 4aa271a1f70f1f9c39361b1919afb9979206f9f5 prerequisite-patch-id: 65dcc366cd051cdbe99d623da18f950ef2eb1bda prerequisite-patch-id: 2e3923d53a1e9e3cf781980fffbb83ed1b5bd83f prerequisite-patch-id: 1afe3d7f859fad87b64500d0556f7bceb2a46f16 prerequisite-patch-id: 21e5eabbd9fd2bc0ceaf2e680307e5517102dd75 prerequisite-patch-id: e2e04876446779c0bc2fbf4325da5cd43835373f prerequisite-patch-id: 33784702e675a95919d8904effbcac47b0b1637d prerequisite-patch-id: 4c6e7a460e3f55461eb4de835e2ea0a19434d8ba prerequisite-patch-id: 518053e93a3b7c0526955209963d8aea588d16df prerequisite-patch-id: 807e92e7e7f1449d5514476acdd1b88a0d0e5590 -- 2.38.1 ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2023-01-14 18:34 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2022-12-29 18:13 ` [bug#52555] [PATCH v3 2/8] publish: Store ERIS encoded blocks to a local block store pukkamustard ` (7 subsequent siblings) 8 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/scripts/publish.scm: (bake-narinfo+nar): Compute ERIS URN of compressed nars. (narinfo-string): Add #:eris-urn parameter and honor it. * guix/scripts/narinfo.scm: (<narinfo>)[eris-format,eris-urn]: New fields. (narinfo-maker): Handle ERIS URN and ERIS format. * configure.ac: (HAVE_GUILE_ERIS): New conditional. * gnu/packages/package-management.scm: (guix)[native-inputs]: Add guile-eris. --- configure.ac | 5 +++++ gnu/packages/package-management.scm | 1 + guix/narinfo.scm | 16 +++++++++----- guix/scripts/publish.scm | 34 ++++++++++++++++++++++++----- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 92dede8014..52a37a6113 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,11 @@ GUILE_MODULE_AVAILABLE([have_guile_avahi], [(avahi)]) AM_CONDITIONAL([HAVE_GUILE_AVAHI], [test "x$have_guile_avahi" = "xyes"]) +dnl Check for Guile-eris. +GUILE_MODULE_AVAILABLE([have_guile_eris], [(eris)]) +AM_CONDITIONAL([HAVE_GUILE_ERIS], + [test "x$have_guile_eris" = "xyes"]) + dnl Guile-newt is used by the graphical installer. GUILE_MODULE_AVAILABLE([have_guile_newt], [(newt)]) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index 2ffaa12247..3585f6c073 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -419,6 +419,7 @@ (define code ("guile-zstd" ,guile-zstd) ("guile-ssh" ,guile-ssh) ("guile-git" ,guile-git) + ("guile-eris" ,guile-eris) ;; XXX: Keep the development inputs here even though ;; they're unnecessary, just so that 'guix environment diff --git a/guix/narinfo.scm b/guix/narinfo.scm index 741c7ad406..d7f8c88f8f 100644 --- a/guix/narinfo.scm +++ b/guix/narinfo.scm @@ -45,6 +45,8 @@ (define-module (guix narinfo) narinfo-file-sizes narinfo-hash narinfo-size + narinfo-eris-format + narinfo-eris-urn narinfo-references narinfo-deriver narinfo-system @@ -68,8 +70,8 @@ (define-module (guix narinfo) (define-record-type <narinfo> (%make-narinfo path uri-base uris compressions file-sizes file-hashes - nar-hash nar-size references deriver system - signature contents) + nar-hash nar-size eris-format eris-urn references deriver + system signature contents) narinfo? (path narinfo-path) (uri-base narinfo-uri-base) ;URI of the cache it originates from @@ -79,6 +81,8 @@ (define-record-type <narinfo> (file-hashes narinfo-file-hashes) (nar-hash narinfo-hash) (nar-size narinfo-size) + (eris-format narinfo-eris-format) + (eris-urn narinfo-eris-urn) (references narinfo-references) (deriver narinfo-deriver) (system narinfo-system) @@ -135,8 +139,8 @@ (define (narinfo-maker str cache-url) "Return a narinfo constructor for narinfos originating from CACHE-URL. STR must contain the original contents of a narinfo file." (lambda (path urls compressions file-hashes file-sizes - nar-hash nar-size references deriver system - signature) + nar-hash nar-size eris-format eris-urn references deriver + system signature) "Return a new <narinfo> object." (define len (length urls)) (%make-narinfo path cache-url @@ -157,6 +161,8 @@ (define len (length urls)) ((lst ...) (map string->number lst))) nar-hash (and=> nar-size string->number) + eris-format + (if eris-urn (string->uri eris-urn) #f) (string-tokenize references) (match deriver ((or #f "") #f) @@ -184,7 +190,7 @@ (define* (read-narinfo port #:optional url (narinfo-maker str url) '("StorePath" "URL" "Compression" "FileHash" "FileSize" "NarHash" "NarSize" - "References" "Deriver" "System" + "ERISFormat" "ERIS" "References" "Deriver" "System" "Signature") '("URL" "Compression" "FileSize" "FileHash")))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 3bf3bd9c7c..76b5a429f4 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -40,6 +40,7 @@ (define-module (guix scripts publish) #:use-module (srfi srfi-34) #:use-module (srfi srfi-37) #:use-module (srfi srfi-71) + #:use-module (srfi srfi-171) #:use-module (web http) #:use-module (web request) #:use-module (web response) @@ -57,6 +58,7 @@ (define-module (guix scripts publish) #:use-module (guix workers) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) + #:use-module (eris) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -145,6 +147,9 @@ (define %default-gzip-compression ;; Since we compress on the fly, default to fast compression. (compression 'gzip 3)) +(define %eris-zstd-compression + (compression 'zstd 19)) + (define (default-compression type) (compression type 3)) @@ -323,7 +328,8 @@ (define* (store-item->recutils store-item (define* (narinfo-string store store-path #:key (compressions (list %no-compression)) - (nar-path "nar") (file-sizes '())) + (nar-path "nar") (file-sizes '()) + eris-urn) "Generate a narinfo key/value string for STORE-PATH; an exception is raised if STORE-PATH is invalid. Produce a URL that corresponds to COMPRESSION. The narinfo is signed with KEY. NAR-PATH specifies the prefix for nar URLs. @@ -345,10 +351,10 @@ (define* (narinfo-string store store-path "\ StorePath: ~a NarHash: sha256:~a -NarSize: ~d +NarSize: ~d~@[~%ERISFormat: application/x-nix-archive+zstd-19~%ERIS: ~a~] References: ~a~%" store-path - hash size references)) + hash size eris-urn references)) ;; Do not render a "Deriver" line if we are rendering info for a ;; derivation. Also do not render a "System" line that would be ;; expensive to compute and is currently unused. @@ -633,6 +639,22 @@ (define (compressed-nar-size compression) (and stat (cons compression (stat:size stat))))) + (define (eris-encode-nar compressions) + (and (member %eris-zstd-compression compressions) + (let* ((nar (nar-cache-file cache item + #:compression %eris-zstd-compression)) + (stat (stat nar #f))) + (and stat + (call-with-input-file nar + (lambda (port) + (let ((eris-urn _ + (eris-encode port + #:block-size 'large + #:block-reducer rcount + #:convergence-secret + %null-convergence-secret))) + eris-urn))))))) + (let ((compression (actual-compressions item compressions))) (for-each (cut compress-nar cache item <>) compressions) @@ -640,7 +662,8 @@ (define (compressed-nar-size compression) (match compressions ((main others ...) (let ((narinfo (narinfo-cache-file cache item - #:compression main))) + #:compression main)) + (eris-urn (eris-encode-nar compressions))) (with-atomic-file-output narinfo (lambda (port) ;; Open a new connection to the store. We cannot reuse the main @@ -651,7 +674,8 @@ (define (compressed-nar-size compression) (display (narinfo-string store item #:nar-path nar-path #:compressions compressions - #:file-sizes sizes) + #:file-sizes sizes + #:eris-urn eris-urn) port))) ;; Make the cached narinfo world-readable, contrary to what -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2022-12-29 18:13 ` [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo pukkamustard @ 2023-01-14 18:34 ` Ludovic Courtès 0 siblings, 0 replies; 65+ messages in thread From: Ludovic Courtès @ 2023-01-14 18:34 UTC (permalink / raw) To: pukkamustard; +Cc: 52555 pukkamustard <pukkamustard@posteo.net> skribis: > * guix/scripts/publish.scm: (bake-narinfo+nar): Compute ERIS URN of compressed nars. > (narinfo-string): Add #:eris-urn parameter and honor it. > * guix/scripts/narinfo.scm: (<narinfo>)[eris-format,eris-urn]: New fields. > (narinfo-maker): Handle ERIS URN and ERIS format. > * configure.ac: (HAVE_GUILE_ERIS): New conditional. > * gnu/packages/package-management.scm: (guix)[native-inputs]: Add guile-eris. I’d suggest separating the (guix narinfo) part from the rest. > @@ -135,8 +139,8 @@ (define (narinfo-maker str cache-url) > "Return a narinfo constructor for narinfos originating from CACHE-URL. STR > must contain the original contents of a narinfo file." > (lambda (path urls compressions file-hashes file-sizes > - nar-hash nar-size references deriver system > - signature) > + nar-hash nar-size eris-format eris-urn references deriver > + system signature) Maybe make ‘eris-format’ and ‘eris-urn’ named parameters. > + (define (eris-encode-nar compressions) > + (and (member %eris-zstd-compression compressions) > + (let* ((nar (nar-cache-file cache item > + #:compression %eris-zstd-compression)) > + (stat (stat nar #f))) > + (and stat > + (call-with-input-file nar > + (lambda (port) > + (let ((eris-urn _ > + (eris-encode port > + #:block-size 'large > + #:block-reducer rcount > + #:convergence-secret > + %null-convergence-secret))) > + eris-urn))))))) I think you remove the ‘let’ and just call ‘eris-encode’ in tail position (Guile truncates multiple-value returns.) Where is ‘eris-encode’ storing the blocks? I don’t see any parameter here. I guess it should go to /var/cache/guix/publish/eris or similar. > (let ((compression (actual-compressions item compressions))) > > (for-each (cut compress-nar cache item <>) compressions) > @@ -640,7 +662,8 @@ (define (compressed-nar-size compression) > (match compressions > ((main others ...) > (let ((narinfo (narinfo-cache-file cache item > - #:compression main))) > + #:compression main)) > + (eris-urn (eris-encode-nar compressions))) > (with-atomic-file-output narinfo > (lambda (port) > ;; Open a new connection to the store. We cannot reuse the main > @@ -651,7 +674,8 @@ (define (compressed-nar-size compression) > (display (narinfo-string store item > #:nar-path nar-path > #:compressions compressions > - #:file-sizes sizes) > + #:file-sizes sizes > + #:eris-urn eris-urn) Would be nice to make ERIS encoding optional, with a command-line switch to turn it on. Ludo’. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 2/8] publish: Store ERIS encoded blocks to a local block store. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2023-01-14 18:42 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2022-12-29 18:13 ` [bug#52555] [PATCH v3 3/8] publish: Add HTTP endpoint for resolving ERIS blocks pukkamustard ` (6 subsequent siblings) 8 siblings, 1 reply; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/eris.scm: New file. * guix/eris/fs-store.scm: New file. * Makefile.am (MODULES): Add new files. * guix/scripts/publish.scm (bake-narinfo+nar): Use guix-eris-block-reducer. --- Makefile.am | 2 ++ guix/eris.scm | 36 +++++++++++++++++++++ guix/eris/fs-store.scm | 67 ++++++++++++++++++++++++++++++++++++++++ guix/scripts/publish.scm | 14 +++++---- 4 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 guix/eris.scm create mode 100644 guix/eris/fs-store.scm diff --git a/Makefile.am b/Makefile.am index b54288c0fc..c549fc8580 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,6 +132,8 @@ MODULES = \ guix/least-authority.scm \ guix/read-print.scm \ guix/ipfs.scm \ + guix/eris.scm \ + guix/eris/fs-store.scm \ guix/platform.scm \ guix/platforms/arm.scm \ guix/platforms/mips.scm \ diff --git a/guix/eris.scm b/guix/eris.scm new file mode 100644 index 0000000000..29d5e7b1db --- /dev/null +++ b/guix/eris.scm @@ -0,0 +1,36 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix eris) + #:use-module (eris) + + #:use-module (guix config) + #:use-module (guix eris fs-store) + + #:export (guix-eris-block-reducer + + %eris-block-store-directory)) + +(define %eris-block-store-directory + (make-parameter + (or (getenv "GUIX_ERIS_BLOCK_STORE_DIRECTORY") + (string-append %state-directory "/eris")))) + +(define (guix-eris-block-reducer) + "Returns a block reducer that stores blocks of ERIS encoded content." + (eris-fs-store-reducer (%eris-block-store-directory))) diff --git a/guix/eris/fs-store.scm b/guix/eris/fs-store.scm new file mode 100644 index 0000000000..2ef7607988 --- /dev/null +++ b/guix/eris/fs-store.scm @@ -0,0 +1,67 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix eris fs-store) + #:use-module (rnrs io ports) + #:use-module (guix build utils) ; for mkdir-p + #:use-module (eris utils base32) + + #:export (eris-fs-store-reducer + eris-fs-store-ref)) + +;;; Commentary: +;;; +;;; This module provides a file-system based store of ERIS encoded blocks. +;;; +;;; Code: + +(define (eris-fs-store-reducer store-directory) + (case-lambda + (() (mkdir-p store-directory)) + + ((result) result) + + ((_ ref-block) + (let* ((ref (car ref-block)) + (b32 (base32-encode ref)) + (pre (substring b32 0 2)) + (suf (substring b32 2)) + (pre-dir (string-append store-directory "/" pre)) + (path (string-append pre-dir "/" suf)) + (block (cdr ref-block))) + + (mkdir-p pre-dir) + + (unless (file-exists? path) + (call-with-output-file path + (lambda (port) (put-bytevector port block)) + #:binary #t)) + + #t)))) + +(define (eris-fs-store-ref store-directory) + (lambda (ref) + (let* ((b32 (base32-encode ref)) + (pre (substring b32 0 2)) + (suf (substring b32 2)) + (path (string-append store-directory "/" pre "/" suf))) + (if (file-exists? path) + (call-with-input-file path + (lambda (port) (get-bytevector-all port)) + #:binary #t) + #f)))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 76b5a429f4..7f14e4d4d4 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -52,6 +52,7 @@ (define-module (guix scripts publish) #:use-module (guix base64) #:use-module (guix config) #:use-module (guix derivations) + #:use-module (guix eris) #:use-module (gcrypt hash) #:use-module (guix pki) #:use-module (gcrypt pk-crypto) @@ -647,12 +648,13 @@ (define (eris-encode-nar compressions) (and stat (call-with-input-file nar (lambda (port) - (let ((eris-urn _ - (eris-encode port - #:block-size 'large - #:block-reducer rcount - #:convergence-secret - %null-convergence-secret))) + (let ((eris-urn + _ (eris-encode port + #:block-size 'large + #:block-reducer + (guix-eris-block-reducer) + #:convergence-secret + %null-convergence-secret))) eris-urn))))))) (let ((compression (actual-compressions item compressions))) -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2022-12-29 18:13 ` [bug#52555] [PATCH v3 2/8] publish: Store ERIS encoded blocks to a local block store pukkamustard @ 2023-01-14 18:42 ` Ludovic Courtès 0 siblings, 0 replies; 65+ messages in thread From: Ludovic Courtès @ 2023-01-14 18:42 UTC (permalink / raw) To: pukkamustard; +Cc: 52555 pukkamustard <pukkamustard@posteo.net> skribis: > * guix/eris.scm: New file. > * guix/eris/fs-store.scm: New file. > * Makefile.am (MODULES): Add new files. > * guix/scripts/publish.scm (bake-narinfo+nar): Use guix-eris-block-reducer. [...] > +(define %eris-block-store-directory > + (make-parameter > + (or (getenv "GUIX_ERIS_BLOCK_STORE_DIRECTORY") > + (string-append %state-directory "/eris")))) > + > +(define (guix-eris-block-reducer) > + "Returns a block reducer that stores blocks of ERIS encoded content." > + (eris-fs-store-reducer (%eris-block-store-directory))) Maybe this should be private to (guix scripts publish)? Also, the store directory should be /var/cache/guix/publish/eris by default IMO. > +(define (eris-fs-store-reducer store-directory) > + (case-lambda > + (() (mkdir-p store-directory)) > + > + ((result) result) > + > + ((_ ref-block) > + (let* ((ref (car ref-block)) > + (b32 (base32-encode ref)) > + (pre (substring b32 0 2)) > + (suf (substring b32 2)) > + (pre-dir (string-append store-directory "/" pre)) > + (path (string-append pre-dir "/" suf)) > + (block (cdr ref-block))) > + > + (mkdir-p pre-dir) > + > + (unless (file-exists? path) > + (call-with-output-file path > + (lambda (port) (put-bytevector port block)) > + #:binary #t)) > + > + #t)))) > + > +(define (eris-fs-store-ref store-directory) > + (lambda (ref) > + (let* ((b32 (base32-encode ref)) > + (pre (substring b32 0 2)) > + (suf (substring b32 2)) > + (path (string-append store-directory "/" pre "/" suf))) > + (if (file-exists? path) > + (call-with-input-file path > + (lambda (port) (get-bytevector-all port)) > + #:binary #t) > + #f)))) Could you add docstrings, remove tabs, and use (ice-9 match) instead of car/cdr? :-) Whole files (blocks, right?) get loaded in memory. Is that OK or should it be avoided? There are time-of-check-to-time-of-use race conditions with those ‘file-exists?’ calls. In the case of ‘ref’, you can instead write: (catch 'system-error (lambda () (call-with-input-file …)) (lambda args (if (= ENOENT (system-error-errno args)) #f (apply throw args)))) In the case of ‘reducer’, perhaps it’d be safer to write the block atomically with ‘with-atomic-file-output’? (And remove the ‘file-exists?’ check too?) Write “file” rather than “path” (the latter is used to refer to “search paths”). :-) Ludo’. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 3/8] publish: Add HTTP endpoint for resolving ERIS blocks. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 2/8] publish: Store ERIS encoded blocks to a local block store pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 4/8] WIP: substitute: Fetch substitutes using ERIS pukkamustard ` (5 subsequent siblings) 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/eris/http.scm: New file. * Makefile.am (MODULES): Add it. * guix/scripts/publish.scm (make-request-handler): Add handler for RFC 2169 URN resolution endpoint. --- Makefile.am | 1 + guix/eris/http.scm | 40 ++++++++++++++++++++++++++++++++++++++++ guix/scripts/publish.scm | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 guix/eris/http.scm diff --git a/Makefile.am b/Makefile.am index c549fc8580..373f6b7c27 100644 --- a/Makefile.am +++ b/Makefile.am @@ -134,6 +134,7 @@ MODULES = \ guix/ipfs.scm \ guix/eris.scm \ guix/eris/fs-store.scm \ + guix/eris/http.scm \ guix/platform.scm \ guix/platforms/arm.scm \ guix/platforms/mips.scm \ diff --git a/guix/eris/http.scm b/guix/eris/http.scm new file mode 100644 index 0000000000..a8a9520197 --- /dev/null +++ b/guix/eris/http.scm @@ -0,0 +1,40 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix eris http) + #:use-module (eris utils base32) + #:use-module (web uri) + + #:use-module (srfi srfi-2) + + #:export (make-blake2b-urn-query-ref)) + +(define blake2b-uri-path-regexp + (make-regexp "^blake2b:" regexp/icase)) + +(define (make-blake2b-urn-query-ref block-ref) + (lambda (query) + (and-let* ((_ query) ; ensure query is not false + (urn (string->uri query)) + (_ (uri? urn)) + (_ (eqv? (uri-scheme urn) 'urn)) + (_ (regexp-exec blake2b-uri-path-regexp + (uri-path urn))) + (blake2b-ref (base32-decode + (string-drop (uri-path urn) 8)))) + (block-ref blake2b-ref)))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 7f14e4d4d4..15bdf02670 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -53,6 +53,8 @@ (define-module (guix scripts publish) #:use-module (guix config) #:use-module (guix derivations) #:use-module (guix eris) + #:use-module (guix eris fs-store) + #:use-module (guix eris http) #:use-module (gcrypt hash) #:use-module (guix pki) #:use-module (gcrypt pk-crypto) @@ -1083,6 +1085,14 @@ (define nar-path? (let ((expected (split-and-decode-uri-path nar-path))) (cut equal? expected <>))) + ;; Get ERIS blocks directly from the filesystem store. + (define eris-block-ref + (eris-fs-store-ref (%eris-block-store-directory))) + + ;; Create a handler for resolving blake2b URN queries. + (define blake2b-urn-query-ref + (make-blake2b-urn-query-ref eris-block-ref)) + (define (handle request body) (format #t "~a ~a~%" (request-method request) @@ -1125,6 +1135,16 @@ (define (handle request body) (("log" name) (render-log-file store request name)) + ;; /uri-res/N2R - RFC2169 URN resolution + (("uri-res" "N2R") + (let ((block (blake2b-urn-query-ref + (uri-query (request-uri request))))) + (if block + (values `((content-type . (application/octet-stream + (charset . "ISO-8859-1")))) + block) + (not-found request)))) + ;; Use different URLs depending on the compression type. This ;; guarantees that /nar URLs remain valid even when 'guix publish' ;; is restarted with different compression parameters. -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 4/8] WIP: substitute: Fetch substitutes using ERIS. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (2 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 3/8] publish: Add HTTP endpoint for resolving ERIS blocks pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 5/8] eris/http: Add HTTP block de-referencer pukkamustard ` (4 subsequent siblings) 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/scripts/substitute.scm (process-substitution): Fetch substitutes using ERIS. * guix/eris.scm (call-with-eris-block-ref): New procedure. TODO: - When to set prefer-eris? in scripts/substitute.scm? --- guix/eris.scm | 7 +++++++ guix/scripts/substitute.scm | 42 +++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index 29d5e7b1db..d9a0914b67 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -23,6 +23,7 @@ (define-module (guix eris) #:use-module (guix eris fs-store) #:export (guix-eris-block-reducer + call-with-eris-block-ref %eris-block-store-directory)) @@ -34,3 +35,9 @@ (define %eris-block-store-directory (define (guix-eris-block-reducer) "Returns a block reducer that stores blocks of ERIS encoded content." (eris-fs-store-reducer (%eris-block-store-directory))) + +(define (call-with-eris-block-ref f) + (let ((fs-store-block-ref + (eris-fs-store-ref + (%eris-block-store-directory)))) + (f fs-store-block-ref))) diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 0efa61b0d7..8cf011d7e6 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm @@ -55,12 +55,16 @@ (define-module (guix scripts substitute) #:use-module (ice-9 ftw) #:use-module (rnrs bytevectors) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-2) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:use-module (srfi srfi-71) #:use-module (web uri) + #:use-module (eris) + #:use-module (eris read-capability) + #:use-module (guix eris) #:use-module (guix http-client) #:export (%allow-unauthenticated-substitutes? %reply-file-descriptor @@ -439,11 +443,12 @@ (define-syntax-rule (with-cached-connection uri port exp ...) (define* (download-nar narinfo destination #:key status-port - deduplicate? print-build-trace?) + deduplicate? print-build-trace? + prefer-eris?) "Download the nar prescribed in NARINFO, which is assumed to be authentic and authorized, and write it to DESTINATION. When DEDUPLICATE? is true, and -if DESTINATION is in the store, deduplicate its files. Print a status line to -STATUS-PORT." +if DESTINATION is in the store, deduplicate its files. When PREFER-ERIS? is +true, attempt to ERIS to get the nar. Print a status line to STATUS-PORT." (define destination-in-store? (string-prefix? (string-append (%store-prefix) "/") destination)) @@ -474,14 +479,29 @@ (define (fetch uri) #:port port #:keep-alive? #t #:buffered? #f)))) + ((urn) + (let ((read-capability (->eris-read-capability uri))) + (if (eris-read-capability? read-capability) + (call-with-eris-block-ref + (lambda (block-ref) + (values (open-eris-input-port + read-capability + #:block-ref block-ref) + #f))) + (leave (G_ "unsupported substitute URI scheme: ~a~%") + (uri->string uri))))) (else (leave (G_ "unsupported substitute URI scheme: ~a~%") (uri->string uri))))) (let ((uri compression file-size - (narinfo-best-uri narinfo - #:fast-decompression? - %prefer-fast-decompression?))) + (if (and prefer-eris? (narinfo-eris-urn narinfo)) + (values (narinfo-eris-urn narinfo) "zstd" #f) + (narinfo-best-uri narinfo + #:fast-decompression? + %prefer-fast-decompression?)))) + + (unless print-build-trace? (format (current-error-port) (G_ "Downloading ~a...~%") (uri->string uri))) @@ -631,7 +651,8 @@ (define* (process-substitution/fallback port narinfo destination (define* (process-substitution port store-item destination #:key cache-urls acl - deduplicate? print-build-trace?) + deduplicate? print-build-trace? + prefer-eris?) "Substitute STORE-ITEM (a store file name) from CACHE-URLS, and write it to DESTINATION as a nar file. Verify the substitute against ACL, and verify its hash against what appears in the narinfo. When DEDUPLICATE? is true, and if @@ -660,7 +681,8 @@ (define narinfo (download-nar narinfo destination #:status-port port #:deduplicate? deduplicate? - #:print-build-trace? print-build-trace?))) + #:print-build-trace? print-build-trace? + #:prefer-eris? prefer-eris?))) \f ;;; @@ -858,7 +880,9 @@ (define reply-port #:acl (current-acl) #:deduplicate? deduplicate? #:print-build-trace? - print-build-trace?) + print-build-trace? + ;; TODO when to prefer ERIS? + #:prefer-eris? #t) (loop)))))) (opts (leave (G_ "~a: unrecognized options~%") opts)))))) -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 5/8] eris/http: Add HTTP block de-referencer. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (3 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 4/8] WIP: substitute: Fetch substitutes using ERIS pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 6/8] WIP: eris: Use HTTP to get ERIS blocks pukkamustard ` (3 subsequent siblings) 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/eris/http.scm (eris-http-block-ref): New procedure. --- guix/eris/http.scm | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/guix/eris/http.scm b/guix/eris/http.scm index a8a9520197..354d3be3be 100644 --- a/guix/eris/http.scm +++ b/guix/eris/http.scm @@ -18,11 +18,17 @@ (define-module (guix eris http) #:use-module (eris utils base32) + #:use-module (web uri) + #:use-module (web client) + #:use-module (web response) - #:use-module (srfi srfi-2) + #:use-module (rnrs base) + #:use-module (srfi srfi-2) ; and-let* + #:use-module (srfi srfi-71) ; extended let-syntax for multiple values - #:export (make-blake2b-urn-query-ref)) + #:export (make-blake2b-urn-query-ref + eris-http-block-ref)) (define blake2b-uri-path-regexp (make-regexp "^blake2b:" regexp/icase)) @@ -38,3 +44,39 @@ (define (make-blake2b-urn-query-ref block-ref) (blake2b-ref (base32-decode (string-drop (uri-path urn) 8)))) (block-ref blake2b-ref)))) + +(define (make-blake2b-urn ref) + (string-append "urn:blake2b:" (base32-encode ref))) + +(define (make-request-uri host ref) + (build-uri (uri-scheme host) + #:userinfo (uri-userinfo host) + #:host (uri-host host) + #:port (uri-port host) + #:path "/uri-res/N2R" + #:query (make-blake2b-urn ref))) + +(define* (eris-http-block-ref + ref + #:key host + (open-connection (lambda (host) (open-socket-for-uri host)))) + + (let* ((uri (make-request-uri host ref)) + (_ (format #t "URI: ~a\n" uri)) + (response body + (http-get uri + #:decode-body? #f + #:port (open-connection host) + #:keep-alive? #t))) + (if (eqv? (response-code response) 200) + body + #f))) + +;; (use-modules (eris) +;; (rnrs bytevectors)) + +;; (bytevector? +;; (eris-http-block-ref +;; (base32-decode +;; "4ACQM2Q5IB3DBHGKHM2WRTAXDBPMVZ7F6MG2TUXZ5QOJHW7P4N7Q") +;; #:host (string->uri "http://localhost:8081"))) -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 6/8] WIP: eris: Use HTTP to get ERIS blocks. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (4 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 5/8] eris/http: Add HTTP block de-referencer pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 7/8] eris: Use parameterized %eris-peers when getting blocks pukkamustard ` (2 subsequent siblings) 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard - guix/eris.scm (guix-eris-block-ref): Refactor from call-with-eris-block-ref and use eris-http-block-ref. - guix/eris/fs-store.scm (eris-fs-store-ref): Refactor to take keyword arguments. - guix/scripts/substitute.scm (download-nar): Use guix-eris-block-ref. - guix/scripts/publish.scm (make-request-handler): Use refactored eris-fs-store-ref. TODO: - default value for %eris-peers parameter in (eris) --- guix/eris.scm | 37 +++++++++++++++++++++++++++++++------ guix/eris/fs-store.scm | 21 ++++++++++----------- guix/scripts/publish.scm | 9 ++++----- guix/scripts/substitute.scm | 14 ++++++++------ 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index d9a0914b67..4af17c2807 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -21,9 +21,13 @@ (define-module (guix eris) #:use-module (guix config) #:use-module (guix eris fs-store) + #:use-module (guix eris http) + + #:use-module (web uri) + #:use-module (ice-9 match) #:export (guix-eris-block-reducer - call-with-eris-block-ref + guix-eris-block-ref %eris-block-store-directory)) @@ -36,8 +40,29 @@ (define (guix-eris-block-reducer) "Returns a block reducer that stores blocks of ERIS encoded content." (eris-fs-store-reducer (%eris-block-store-directory))) -(define (call-with-eris-block-ref f) - (let ((fs-store-block-ref - (eris-fs-store-ref - (%eris-block-store-directory)))) - (f fs-store-block-ref))) +(define %eris-peers + (make-parameter + ;; TODO + (list (string->uri "http://localhost:8081")))) + +(define* (try-in-order ref #:key block-refs) + (match block-refs + ((block-ref . rest) + (let ((block (block-ref ref))) + (if block + block + (try-in-order ref #:block-refs rest)))) + (() #f))) + +(define* (guix-eris-block-ref ref #:key open-connection) + (try-in-order + ref + #:block-refs + (list + (lambda (ref) + (eris-fs-store-ref ref + #:store-directory (%eris-block-store-directory))) + (lambda (ref) + (eris-http-block-ref ref + #:host (string->uri "http://localhost:8081") + #:open-connection open-connection))))) diff --git a/guix/eris/fs-store.scm b/guix/eris/fs-store.scm index 2ef7607988..38f5926280 100644 --- a/guix/eris/fs-store.scm +++ b/guix/eris/fs-store.scm @@ -54,14 +54,13 @@ (define (eris-fs-store-reducer store-directory) #t)))) -(define (eris-fs-store-ref store-directory) - (lambda (ref) - (let* ((b32 (base32-encode ref)) - (pre (substring b32 0 2)) - (suf (substring b32 2)) - (path (string-append store-directory "/" pre "/" suf))) - (if (file-exists? path) - (call-with-input-file path - (lambda (port) (get-bytevector-all port)) - #:binary #t) - #f)))) +(define* (eris-fs-store-ref ref #:key store-directory) + (let* ((b32 (base32-encode ref)) + (pre (substring b32 0 2)) + (suf (substring b32 2)) + (path (string-append store-directory "/" pre "/" suf))) + (if (file-exists? path) + (call-with-input-file path + (lambda (port) (get-bytevector-all port)) + #:binary #t) + #f))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 15bdf02670..0ce50b2942 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -1085,13 +1085,12 @@ (define nar-path? (let ((expected (split-and-decode-uri-path nar-path))) (cut equal? expected <>))) - ;; Get ERIS blocks directly from the filesystem store. - (define eris-block-ref - (eris-fs-store-ref (%eris-block-store-directory))) - ;; Create a handler for resolving blake2b URN queries. (define blake2b-urn-query-ref - (make-blake2b-urn-query-ref eris-block-ref)) + (make-blake2b-urn-query-ref + (lambda (ref) (eris-fs-store-ref + ref + #:store-directory (%eris-block-store-directory))))) (define (handle request body) (format #t "~a ~a~%" diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 8cf011d7e6..14a21f6c37 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm @@ -482,12 +482,14 @@ (define (fetch uri) ((urn) (let ((read-capability (->eris-read-capability uri))) (if (eris-read-capability? read-capability) - (call-with-eris-block-ref - (lambda (block-ref) - (values (open-eris-input-port - read-capability - #:block-ref block-ref) - #f))) + (values + (open-eris-input-port + read-capability + #:block-ref (lambda (ref) + (guix-eris-block-ref + ref + #:open-connection open-connection-for-uri/cached))) + #f) (leave (G_ "unsupported substitute URI scheme: ~a~%") (uri->string uri))))) (else -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 7/8] eris: Use parameterized %eris-peers when getting blocks. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (5 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 6/8] WIP: eris: Use HTTP to get ERIS blocks pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 8/8] eris: Use IPFS to get ERIS blocks pukkamustard 2023-01-14 18:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard --- guix/eris.scm | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index 4af17c2807..d56643bec4 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -54,15 +54,30 @@ (define* (try-in-order ref #:key block-refs) (try-in-order ref #:block-refs rest)))) (() #f))) +(define* (peer->block-ref peer #:key open-connection) + (case (uri-scheme peer) + + ((http https) + (lambda (ref) + (eris-http-block-ref ref + #:host peer + #:open-connection open-connection))) + + ;; unsupported ERIS peer URL + (else (lambda (_) #f)))) + (define* (guix-eris-block-ref ref #:key open-connection) (try-in-order ref #:block-refs - (list + (cons + + ;; first try and get block from local block store (lambda (ref) (eris-fs-store-ref ref #:store-directory (%eris-block-store-directory))) - (lambda (ref) - (eris-http-block-ref ref - #:host (string->uri "http://localhost:8081") - #:open-connection open-connection))))) + + ;; then try peers + (map (lambda (peer) + (peer->block-ref peer #:open-connection open-connection)) + (%eris-peers))))) -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v3 8/8] eris: Use IPFS to get ERIS blocks. 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (6 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 7/8] eris: Use parameterized %eris-peers when getting blocks pukkamustard @ 2022-12-29 18:13 ` pukkamustard 2023-01-14 18:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 8 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2022-12-29 18:13 UTC (permalink / raw) To: 52555; +Cc: pukkamustard * guix/eris/ipfs.scm: New files. * Makefile.am (MODULES): Add it. * guix/eris.scm (%eris-peers): Add IPFS. (peer->block-ref): Handle IPFS peer. --- Makefile.am | 1 + guix/eris.scm | 32 ++++--- guix/eris/ipfs.scm | 214 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 10 deletions(-) create mode 100644 guix/eris/ipfs.scm diff --git a/Makefile.am b/Makefile.am index 373f6b7c27..6f648a40a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,6 +135,7 @@ MODULES = \ guix/eris.scm \ guix/eris/fs-store.scm \ guix/eris/http.scm \ + guix/eris/ipfs.scm \ guix/platform.scm \ guix/platforms/arm.scm \ guix/platforms/mips.scm \ diff --git a/guix/eris.scm b/guix/eris.scm index d56643bec4..5b0c1ee36b 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -22,6 +22,7 @@ (define-module (guix eris) #:use-module (guix config) #:use-module (guix eris fs-store) #:use-module (guix eris http) + #:use-module (guix eris ipfs) #:use-module (web uri) #:use-module (ice-9 match) @@ -42,8 +43,10 @@ (define (guix-eris-block-reducer) (define %eris-peers (make-parameter - ;; TODO - (list (string->uri "http://localhost:8081")))) + ;; TODO: make ERIS peers configurable somewhere + (list + (string->uri "http://localhost:8081") + 'ipfs))) (define* (try-in-order ref #:key block-refs) (match block-refs @@ -55,18 +58,27 @@ (define* (try-in-order ref #:key block-refs) (() #f))) (define* (peer->block-ref peer #:key open-connection) - (case (uri-scheme peer) + (cond + ((uri? peer) (case (uri-scheme peer) - ((http https) - (lambda (ref) - (eris-http-block-ref ref - #:host peer - #:open-connection open-connection))) + ((http https) + (lambda (ref) + (eris-http-block-ref ref + #:host peer + #:open-connection open-connection))) - ;; unsupported ERIS peer URL - (else (lambda (_) #f)))) + ;; unsupported ERIS peer URL + (else (lambda (_) #f)))) + + ((eqv? 'ipfs peer) + (lambda (ref) + (eris-ipfs-ref ref #:open-connection open-connection))))) (define* (guix-eris-block-ref ref #:key open-connection) + "Attempts to dereference a block of some ERIS encoded content with reference +REF. First the local block store is checked, followed by remote peers as +configured in the parameter %eris-peers (in order). Returns #f if the block +could not be de-referenced." (try-in-order ref #:block-refs diff --git a/guix/eris/ipfs.scm b/guix/eris/ipfs.scm new file mode 100644 index 0000000000..9771414e7b --- /dev/null +++ b/guix/eris/ipfs.scm @@ -0,0 +1,214 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + + +;;; Commentary: +;;; +;;; This module provides an interface to the IPFS daemons HTTP API for storing +;;; and retrieving blocks. This can be used to store blocks of ERIS encoded +;;; content. +;;; +;;; See also the IPFS API documentation: +;;; https://docs.ipfs.io/reference/http/api/#api-v0-block-put + +(define-module (guix eris ipfs) + #:use-module (eris utils base32) + #:use-module (sodium generichash) + #:use-module (json) + #:use-module (web uri) + #:use-module (web client) + #:use-module (web response) + #:use-module (srfi srfi-71) + #:use-module (rnrs io ports) + #:use-module (rnrs bytevectors) + + #:use-module ((guix build download) + #:select ((open-connection-for-uri + . guix:open-connection-for-uri))) + #:export (%ipfs-base-url + + eris-ipfs-reducer + eris-ipfs-ref)) + + +;; CID encoding + +;; Multicodec codes +;; (https://github.com/multiformats/multicodec/blob/master/table.csv) +(define multicodec-raw-code #x55) +(define multicodec-blake2b-256-code #xb220) + +(define (blake2b-256->binary-cid hash) + "Encode a Blake2b-256 hash as binary CID" + (call-with-values + (lambda () (open-bytevector-output-port)) + (lambda (port get-bytevector) + ;; CID version + (put-u8 port 1) + ;; multicoded content-type + (put-u8 port multicodec-raw-code) + ;; set multihash to blake2b-256. This is the manually encoded varint of + ;; 0xb220 + (put-u8 port 160) (put-u8 port 228) (put-u8 port 2) + ;; set hash lenght + (put-u8 port 32) + ;; and finally the hash itself + (put-bytevector port hash) + + ;; finalize and get the bytevector + (get-bytevector)))) + +(define (binary-cid->cid bcid) + "Encode a binary CID as Base32 encoded CID" + ;; 'b' is the multibsae code for base32 + (string-append "b" + ;; the IPFS daemon uses lower-case, so to be consistent we + ;; also. + (string-downcase + ;; base32 encode the binary cid + (base32-encode bcid)))) + +(define blake2b-256->cid + (compose binary-cid->cid blake2b-256->binary-cid)) + + +;; IPFS API + +(define %ipfs-base-url + ;; URL of the IPFS gateway. + (make-parameter "http://localhost:5001")) + +(define* (call url decode + #:optional + (method http-post) + #:key port body (false-if-404? #t) (headers '()) + (keep-alive #t) + (open-connection guix:open-connection-for-uri) + (timeout 10)) + "Invoke the endpoint at URL using METHOD. Decode the resulting JSON body +using DECODE, a one-argument procedure that takes an input port; when DECODE +is false, return the input port. When FALSE-IF-404? is true, return #f upon +404 responses." + (let* ((url (if (string? url) (string->uri url) url)) + (port (or port (open-connection url #:timeout timeout))) + (response response-port + (if keep-alive + (method url #:streaming? #t + #:body body + #:port port + #:keep-alive? #t) + (method url #:streaming? #t + #:body body + #:port port + ;; IPFS daemon seems to responds with bad + ;; request if PUT requests are kept alive and + ;; do not have "Connection: close" header. + #:keep-alive? #f + #:headers `((connection close) + ,@headers))))) + (cond ((= 200 (response-code response)) + (if decode + (let ((result (decode response-port))) + (close-port response-port) + result) + response-port)) + ((and false-if-404? + (= 404 (response-code response))) + (close-port response-port) + #f) + (else + (close-port response-port) + (format #t "~a\n" response) + (throw 'ipfs-error url response))))) + +(define-syntax-rule (false-if-ipfs-error exp) + "Return $f if EXP triggers a network related or IPFS related exception." + (with-exception-handler + (lambda (exn) + (let ((kind (exception-kind exn)) + (errno (system-error-errno + (cons 'system-error (exception-args exn))))) + (cond + ((= errno ECONNREFUSED) #f) + (else (raise-exception exp))))) + (lambda () exp) + #:unwind? #t)) + +(define %multipart-boundary + ;; XXX: We might want to find a more reliable boundary. + (string-append (make-string 24 #\-) "2698127afd7425a6")) + +(define (bytevector->form-data bv port) + "Write to PORT a 'multipart/form-data' representation of BV." + (display (string-append "--" %multipart-boundary "\r\n" + "Content-Disposition: form-data\r\n" + "Content-Type: application/octet-stream\r\n\r\n") + port) + (put-bytevector port bv) + (display (string-append "\r\n--" %multipart-boundary "--\r\n") + port)) + +(define (ipfs-block-put bv) + "Store a block on IPFS and return the CID of the block" + (call (string-append (%ipfs-base-url) + "/api/v0/block/put" + "?format=raw&mhtype=blake2b-256") + (lambda (port) (assoc-ref (json->scm port) "Key")) + #:headers `((content-type + . (multipart/form-data + (boundary . ,%multipart-boundary)))) + #:body (call-with-bytevector-output-port + (lambda (port) (bytevector->form-data bv port))) + ;; IPFS daemon does not seem to accept connection re-use when putting + ;; blocks. + #:keep-alive #f)) + +(define* (ipfs-block-get cid #:key + (open-connection guix:open-connection-for-uri)) + "Get a block from IPFS via the HTTP API" + (false-if-ipfs-error + (call (string-append (%ipfs-base-url) + "/api/v0/block/get" + "?arg=" cid) + get-bytevector-all + #:timeout 5 + #:open-connection open-connection))) + +;; ERIS block reducer + +(define eris-ipfs-reducer + (case-lambda + ;; initialization. Nothing to do here. In an improved implementation we + ;; might create a single HTTP connection and reuse it for all blocks. + (() '()) + + ;; Completion. Again, nothing to do. + ((_) 'done) + + ;; store a block + ((_ ref-block) + ;; ref-block is a pair consisting of the reference to the block and the + ;; block itself. + (ipfs-block-put (cdr ref-block))))) + +(define* (eris-ipfs-ref ref #:key + (open-connection guix:open-connection-for-uri)) + "Dereference a block from IPFS" + (ipfs-block-get (blake2b-256->cid ref) + #:open-connection open-connection)) -- 2.38.1 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard ` (7 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 8/8] eris: Use IPFS to get ERIS blocks pukkamustard @ 2023-01-14 18:25 ` Ludovic Courtès 8 siblings, 0 replies; 65+ messages in thread From: Ludovic Courtès @ 2023-01-14 18:25 UTC (permalink / raw) To: pukkamustard; +Cc: 52555 Hello! pukkamustard <pukkamustard@posteo.net> skribis: > I'm very happy to present a V3 of a proposal towards decentralizing substitute > distribution with ERIS. An initial version [1] and a V2 [2] are now almost a > years old! Woohoo! 👍 > The idea is to use ERIS (Encoding for Robust Immutable Storage) [3] to allow > more decentralized substitute distribution. ERIS defines an encoding of > content into uniformly sized, encrypted and content-addressed blocks > (32KiB). The content can be decoded from the blocks given a short identifier > called the read capability. It allows a network-optimized form of > content-addressing. > > Blocks can be transported over many different transport protocols, such as > HTTP, CoAP, GNUnet, IPFS or a SD card sent via pigeons. Only the read > capability must be transmited securely. Given an authentic read capability, > the content can be decoded correctly from blocks that might have been > transported over unreliable (and untrusted) protocols. Neat! (Do we have an implementation yet for SD-cards-over-pigeons?) > For Guix, substitutes (Nar files) are encoded using ERIS and the read > capability is added to the signed Narinfos. The read capability published in > the Narinfo can then be used to decode the Nar from blocks that are fetched > from many peers over many different protocols. > > This version of the patches allows blocks to be fetched over HTTP and IPFS. Nice. > A summary of this patch series: > > - Use the stable version of the ERIS encoding (version 1.0.0) > - Add two fields to Narinfos (ERIS and ERISFormat) > - Store blocks of published substitutes in a local block store (in > `/var/guix/eris`) > - Add an endpoint for resolving ERIS blocks over HTTP (a la RFC 2169) > - Use ERIS when fetching substitutes > - Use IPFS for de-referencing ERIS blocks > > Testing procedure is a bit tedious, but described in the V2: > https://issues.guix.gnu.org/52555#8-lineno16 OK. There are still I guess a number of unknowns, including the cost of ERIS support for publishers (how much disk space ‘guix publish’ will use for blocks, how much CPU is needed to compute those blocks, bandwidth usage over IFPS/HTTP) and for consumers (performance of substitution over HTTP+ERIS or IPFS+ERIS CPU-wise and bandwidth-wise). To address that, we’ll need to make it easy to test, and to make it easy to disable it if things don’t work as expected. (Perhaps this is already the case, I’m thinking out loud.) > Thanks for making it so far! :) I'd be very happy for your thoughs and > ideas. There might also be opportunity to discuss these ideas at Guix Days in > February. Definitely! I think it would be great if you could present what you’re up to and maybe make a quick demo. Thanks for the great news to begin the year! Ludo’. ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 0/7] Decentralized substitute distribution with ERIS 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard ` (3 preceding siblings ...) 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 1/7] narinfo: Add ERIS field pukkamustard ` (6 more replies) 4 siblings, 7 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ludo, maximedevos Dear Guix, This is the V4 of a proposal towards decentralized subsitute distirbution using the ERIS encoding. The initial proposal was submitted in December 2021, V2 and V3 a year later in 2022. All is still very much work-in-progress, but I'm happy to submit it as is to keep up with good old traditions. Thank you also for all the valuable comments and feedback via mail and live at Guix Days last year. Sorry for being so slow to react. The general idea of the proposal is to use ERIS (http://purl.org/eris) for substitute distribution. This allows substitutes to be shared over various protocols such as IPFS, GNUnet, NNCP, HTTP, CoAP, a USB stick or some Spritely-esque fun. ERIS itself defines an encoding of content into uniformly sized, encrypted and content-addressed blocks. The original content can be decoded with a short read capability that can be encoded as an URN and access to the blocks that make up the content. Blocks can be shared over different protocols with low security requirements on the transport layer itself. Read capabilities need to be shared in a secure manner. This series does following: - Adds an `ERIS` field holding the ERIS read capability of a substitute to the Narinfo as published by `guix publish` - Allows the daemon/substitute script to decode content using the ERIS URN instead of fetching a substitute via HTTP. ## Changes to previous version ### Fibers When encoding and decoding it is important for performance to be able to fetch multiple blocks concurrently (from potentially multiple peers). For this we use Guile fibers. Fiberization is currently very crude as there seem to be weird interactions with the parallization strategies currently used by `guix publish` and `guix substitute`. Help here is extremely welcome. ### ERIS-FS In previous versions we encoded the Nar-file of the susbstitute. In this version we use a specialized encoding of file-system trees for ERIS: ERIS-FS (https://eris.codeberg.page/eer/eris-fs.xml). ERIS-FS allows de-duplication of files and much easier parlallized decoding of substitutes. The ideas are similar to the custom encoding defined for substitutes over IPFS (https://issues.guix.gnu.org/33899). One major consequence is that the SHA256 sum of the Nar file as published in the Narinfo is no longer used to verify integrity of downloaded susbtitute. Instead we must ensure that the `ERIS` field in the Narinfo is trusted, `equivalent-narinfo?` and such have been changed towards this. Thanks to Maxime for pointing out this subtlety! ### External Block Store Daemon Ludovic Courtès <ludo@gnu.org> writes: > Also, the store directory should be /var/cache/guix/publish/eris by > default IMO. This comment caused a lot of pondering and hacking! :) The problem seems to be that two processes need to be able to access the block store securely: `guix publish` when publishing substitutes and the Guix daemon when fetching substitutes (blocks need to be stored when fetching for de-duplication). `guix publish` is usually run as a non-privileged user, whereas the Guix daemon runs with much higher privileges. The block store needs to be secure in the sense that manipulating blocks should be prevented by less privileged processes. I'm afraid the only solution I came up with is that the block store is not a Unix directory or database, but a daemon that listens on a Unix Socket. Enter Kapla (https://codeberg.org/eris/kapla). Kapla is a Guile program that stores and transports blocks. The Guix daemon (via substitute scripts) and the `guix publish` server talk to Kapla over a Unix socket. Kapla stores blocks in a database (SQlite) and connects with multiple peers and/or services such as IPFS/GNUnet to get blocks. I was fighting such an architecture for a long time. I would have preferred if the Guix daemon and `guix publish` simply use a library for everything instead of relying on another external service. However, there seem to be some advantages: - Managing peers seem to be quite complex and stateful. Maybe better if this is externalized from Guix proper. - The block storage and transport mechanisms can be used to share any files (try `kapla encode my-file` and `kapla decode ...`). - We can experiment with more transports quicker in a service external to Guix and include dependencies that might not make sense to have in Guix proper. The protocol that is used to talk to the external block store is CoAP over Unix Sockets or TCP. Kapla is not the only software that speaks this protocol. There is also a Golang block store that can be used (https://codeberg.org/eris/eris-go). ### CoAP for block transport Currently the protocol over which blocks are transported over networks is the Constrained Application Protocol (CoAP) (https://eris.codeberg.page/eer/coap.xml). CoAP is well suited as it allows multiple asynchronous in-flight requests (unlike HTTP 1.1). This is important for parallizing block retrieval. It also allows bi-directional requests, making it attractive for more peer-to-peer systems where some peers might not have a public IP. As it is designed for constrained environment it is quite simple and the implementation we use is in pure Guile. More block transports can be added by implementing them in Kapla (e.g. IPFS or GNUnet) or using something completely different than Kapla that speaks CoAP over Unix Sockets (such as eris-go that also can use NNCP for block transport). ### Comments to V3 I hope to have addressed all comments to the V3 (Thanks Ludo!). This included things like organizing commits differently, using (ice-9 match) and how to handle multiple return values. ## Testing Testing is a bit complicated. We need to find a better and more systematic way of doing so. Suggestions are very welcome! Manually this is how to do it: 1. Authorize local substitutes We will be running a local substitute server so we need to add the local signing key to the list of authorized keys. In the system configurations: ``` (modify-services %base-services (guix-service-type config => (guix-configuration (inherit config) (authorized-keys (cons* ;; allow substitutes from ourselves for testing purposes (local-file "/etc/signing-key.pub") %default-authorized-guix-keys))))) ``` 2. Configure the local Guix checkout #+BEGIN_SRC shell ./bootstrap && ./configure --localstatedir=/var --sysconfdir=/etc && make #+END_SRC The ~--sysconfdir~ is required so that guix will use the ACL in ~/etc/guix/acl~. 3. Start a Kapla daemon: ``` ./pre-inst-env guix build kapla -- kaplad -d ``` The `-d` option enables debug output. Kapla will listen for connection on a Unix socket. The path will be output, e.g.: ``` 2023-12-23 15:10:23 (INFO): Listening on Unix socket /run/user/1000/eris.sock ``` 3. Build some package that we will ``` $ ./pre-inst-env guix build libchop --no-grafts /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 ``` 4. Start a local publish server ``` sudo -E ./pre-inst-env guix publish --public-key=/etc/guix/signing-key.pub --private-key=/etc/guix/signing-key.sec --cache=/tmp/guix-publish-cache/ --eris=coap+unix:///run/user/1000/eris.sock ``` I need to run it with sudo in order to be able to use the proper signing keys. The `--eris=STORE_URL` option defines where to store blocks. `--eris` can also be provided without a URL which will cause the ERIS read capability to be computed but blocks won't be stored anywhere. See "Proposed Deployment" on when this might make sense. 5. Get the narinfo from the publish server ``` $ curl http://localhost:8080/60m6qih391rq95ck64am8ir64z0sv0zr.narinfo StorePath: /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 NarHash: sha256:1i2hhzw81qfsba0d1b09ax13694imgjrpay0122gqll85dx7k7ml NarSize: 1021984 ERIS: urn:eris:BIARSURIJ3WYLEINE6W5ZF7LKTIHL42AE367TQ355ORW5UZVSTQGT5H5T2OLKF7XICML3VHLTLMDWXLUCQVKHRKNVREV3GMVX3J5RMT4GU References: 1i0iz5rgixyva0zy4bmaasjil2683xrn-mit-krb5-1.20 2w976k6g70gkfih9wwhalqsni209vcqz-gdbm-1.23 4p1l5bdxxbyyqc3wh0d07jv9rp1pdcy7-guile-2.0.14 60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 620h3panf2lss42ns625rlay522g2hza-tdb-1.4.7 8y0pwifz8a3d7zbdfzsawa1amf4afx1s-libgcrypt-1.10.1 930nwsiysdvy2x5zv1sf6v7ym75z8ayk-gcc-11.3.0-lib gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35 m9wi9hcrf7f9dm4ri32vw1jrbh1csywi-libgpg-error-1.45 pl09vk5g3cl8fxfln2hjk996pyahqk8m-bzip2-1.0.8 r5saysi65chivbv3y65nzsisx8rypp76-libtirpc-1.3.1 rib9g2ig1xf3kclyl076w28parmncg4k-bash-minimal-5.1.16 slzq3zqwj75lbrg4ly51hfhbv2vhryv5-zlib-1.2.13 z4likj1rnshd81hr0vwvwhdxpfwa1rz7-lzo-2.10 Deriver: zcly5fm6rsqis9csk33i7zfqjidjzy1a-libchop-0.5.2.drv Signature: 1;strawberry;KHNpZ25hdHVyZSAKIChkYXRhIAogIChmbGFncyByZmM2OTc5KQogIChoYXNoIHNoYTI1NiAjRjFEQTI3RkJDQzA4RTI2MzZDQkY3NEE5NkMwNjQ5QzZBQ0U3QjEzNDRGNzJFNEM1OUMwMzIyRUIzMjFFMUY4RCMpCiAgKQogKHNpZy12YWwgCiAgKGVjZHNhIAogICAociAjMDQwQzYwNzBBOTlBQjI1NEFDNkMwOTdGREIxMUREMkZBNEExNTFGNzYyOTBBRUNENzdCQUMzQ0M0REVERkI0RCMpCiAgIChzICMwQzZGMEFGOTgzODg1NDE5NzAwNzI0NEE5NDU2RTYyMDAxNEE2NUI5NDgxODc4QTlFNjJDOTA2RDQ3NTVGM0YyIykKICAgKQogICkKIChwdWJsaWMta2V5IAogIChlY2MgCiAgIChjdXJ2ZSBFZDI1NTE5KQogICAocSAjMDRDMkY4ODk1QTU0NDNGNTlCODk2NDEwMEI1MDY0NzU4RjQ1N0YzMENEREE1MTQyQzE0MDc0NjExNTA1NTc5MCMpCiAgICkKICApCiApCg== URL: nar/gzip/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 Compression: gzip FileSize: 345576 ``` Note the new `ERIS` field. You might have to get the narinfo twice for all the fields to appear. The ERIS read capability URN (urn:eris:BIARSURIJ...) contains enough information to decode the substitute. If you look at the kaplad log output you will see that some blocks were stored. You could now run: ``` kapla decode urn:eris:BIARSURIJ3WYLEINE6W5ZF7LKTIHL42AE367TQ355ORW5UZVSTQGT5H5T2OLKF7XICML3VHLTLMDWXLUCQVKHRKNVREV3GMVX3J5RMT4GU out ``` to decode the substitute to the folder out. The Guix daemon can do the same when getting substitutes. 6. Remove the libchop store item: ``` guix gc -D /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 ``` 7. Start the guix daemon from the checkout: ``` sudo -E ./pre-inst-env guix-daemon --build-users-group=guixbuild --eris-store-url=coap+unix:///run/user/1001/eris.sock --substitute-urls=http://localhost:8080/ ``` Note that the `--eris-store-url` argument points to the same store as what we used for the publish server - the blocks come go to and come from the same place. We need to use the local publish server for getting the narinfo with the `ERIS` field. 8. Get the substitute: ``` ./pre-inst-env guix build libchop --no-grafts substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'.substitute: updating substitutes from 'http://localhost:8080/'... 100.0% 0.3 MB will be downloaded: /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 substituting /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2... Downloading urn:eris:BIARSURIJ3WYLEINE6W5ZF7LKTIHL42AE367TQ355ORW5UZVSTQGT5H5T2OLKF7XICML3VHLTLMDWXLUCQVKHRKNVREV3GMVX3J5RMT4GU... /gnu/store/60m6qih391rq95ck64am8ir64z0sv0zr-libchop-0.5.2 ``` Substitute was fetched using ERIS! The daemon automatically tries to use ERIS when the `--eris-store-url` is passed and the narinfo has a signed ERIS field. If not it will fetch substitutes using HTTP. On failures while using ERIS it will also revert back to getting substitutes via HTTP. 9. Restart your system guix daemon ``` sudo herd restart guix-daemon ``` 10. Figure out a better way to test this. ## Proposed Deployment As an initial deployment it would be nice if the official Guix substitute servers include the ERIS read capability in the Narinfo withouth making blocks available. This only requires a bit of CPU for computing the ERIS read capability. No additional disk space or bandwidth is required by the official substitute servers. Users can get the signed ERIS read capability from the official Guix susbtitute servers but can fetch blocks from anywhere while still being sure to get the right substitutes. This would allow community members to make blocks available independently and experiment with various transports while not changing the trust-model when fetching substitutes. ## TODOs - [ ] Better fiberization of `guix publish` and `guix/scripts/substitute.scm` - [ ] Debug issue where blocks of large substitutes are not properly stored (possibly related to hackey fiberization). - [ ] Add Guix tests - [ ] Add documentation. - [ ] Write a RFC along the proposed Request-For-Comment process (https://issues.guix.gnu.org/66844) - [ ] Allow encoding of blocks without running `guix publish` (maybe an `eris` format for `guix pack`). - [ ] Dependencies (guile-eris and guile-coap) contain some fixes that need to be properly released. - [ ] Implement CoAP peer connections and maybe IPFS transport in Kapla. - [ ] Release initial version of Kapla. - [ ] Update service definitions for `guix-publish`, `guix-daemon` with an option to enable decentralized substitute stuff and add service definition for `kapla`. ## Hic Sunt Dracones Everything is still quite fragile. The fiberization of `guix substitute` and `guix publish` is hackey. Kapla is still very limited and unreleased. But I hope to have been able to capture the current state of things and paint a picture of the plan. Thanks for making it so far and for your comments, questions and hackings. Greetings, pukkamustard pukkamustard (7): narinfo: Add ERIS field. gnu: Add guile-coap. gnu: guile-eris: Update to 1.2.0-dev. publish: Add ERIS URN to narinfo. eris: Connect with an ERIS Store over CoAP+Unix. substitute: Decode substitutes using ERIS. gnu: Add kapla. Makefile.am | 1 + configure.ac | 5 + gnu/packages/guile-xyz.scm | 144 ++++++++++++++++++++++------ gnu/packages/package-management.scm | 1 + guix/eris.scm | 137 ++++++++++++++++++++++++++ guix/narinfo.scm | 17 +++- guix/scripts/publish.scm | 58 ++++++++--- guix/scripts/substitute.scm | 76 +++++++++++---- nix/nix-daemon/guix-daemon.cc | 5 + 9 files changed, 380 insertions(+), 64 deletions(-) create mode 100644 guix/eris.scm base-commit: 4a1b3830a8ff6b05ad9a2b27c8a2cdbd00a45787 -- 2.41.0 ^ permalink raw reply [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 1/7] narinfo: Add ERIS field. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 2/7] gnu: Add guile-coap pukkamustard ` (5 subsequent siblings) 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555 Cc: pukkamustard, ludo, maximedevos, Christopher Baines, Josselin Poiret, Ludovic Courtès, Mathieu Othacehe, Ricardo Wurmus, Simon Tournier, Tobias Geerinckx-Rice * guix/narinfo.scm (<narinfo>)[eris-urn]: New field. (narinfo-maker): Handle new field. (read-narifno): Handle new field. (equivalent-narinfo?): Require ERIS field to be equal. --- guix/narinfo.scm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/guix/narinfo.scm b/guix/narinfo.scm index a149d9a901..5f5ed8be6f 100644 --- a/guix/narinfo.scm +++ b/guix/narinfo.scm @@ -45,6 +45,7 @@ (define-module (guix narinfo) narinfo-file-sizes narinfo-hash narinfo-size + narinfo-eris-urn narinfo-references narinfo-deriver narinfo-system @@ -69,7 +70,7 @@ (define-module (guix narinfo) (define-record-type <narinfo> (%make-narinfo path uri-base uris compressions file-sizes file-hashes - nar-hash nar-size references deriver system + nar-hash nar-size eris-urn references deriver system signature contents) narinfo? (path narinfo-path) @@ -80,6 +81,7 @@ (define-record-type <narinfo> (file-hashes narinfo-file-hashes) (nar-hash narinfo-hash) (nar-size narinfo-size) + (eris-urn narinfo-eris-urn) (references narinfo-references) (deriver narinfo-deriver) (system narinfo-system) @@ -136,7 +138,7 @@ (define (narinfo-maker str cache-url) "Return a narinfo constructor for narinfos originating from CACHE-URL. STR must contain the original contents of a narinfo file." (lambda (path urls compressions file-hashes file-sizes - nar-hash nar-size references deriver system + nar-hash nar-size eris-urn references deriver system signature) "Return a new <narinfo> object." (define len (length urls)) @@ -158,6 +160,7 @@ (define (narinfo-maker str cache-url) ((lst ...) (map string->number lst))) nar-hash (and=> nar-size string->number) + (if eris-urn (string->uri eris-urn) #f) (string-tokenize references) (match deriver ((or #f "") #f) @@ -185,7 +188,7 @@ (define* (read-narinfo port #:optional url (narinfo-maker str url) '("StorePath" "URL" "Compression" "FileHash" "FileSize" "NarHash" "NarSize" - "References" "Deriver" "System" + "ERIS" "References" "Deriver" "System" "Signature") '("URL" "Compression" "FileSize" "FileHash")))) @@ -271,7 +274,13 @@ (define (equivalent-narinfo? narinfo1 narinfo2) (narinfo-references narinfo2)) (= (narinfo-size narinfo1) - (narinfo-size narinfo2)))) + (narinfo-size narinfo2)) + + ;; When downloading substitutes with ERIS the hash is not checked. To + ;; avoid malicious substitutes we must ensure that the ERIS URN is equal. + ;; See also <https://issues.guix.gnu.org/52555#43>. + (equal? (narinfo-eris-urn narinfo1) + (narinfo-eris-urn narinfo2)))) (define %compression-methods ;; Known compression methods and a thunk to determine whether they're -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 2/7] gnu: Add guile-coap. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 1/7] narinfo: Add ERIS field pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 3/7] gnu: guile-eris: Update to 1.2.0-dev pukkamustard ` (4 subsequent siblings) 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ludo, maximedevos * gnu/packages/guile-xyz.scm (guile-coap): New variable. --- gnu/packages/guile-xyz.scm | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm index 7b44dc3167..2fc6d079a1 100644 --- a/gnu/packages/guile-xyz.scm +++ b/gnu/packages/guile-xyz.scm @@ -1457,6 +1457,38 @@ (define-public guile-aws the Guile compiler tower to generate the DSL from AWS JSON specifications.") (license license:gpl3+)))) +(define-public guile-coap + (let ((commit "1218d4f98210a14b52cf8185c9a7d39ed8b28643") + (revision "0")) + (package + (name "guile-coap") + (version (git-version "0.2.0-dev" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://codeberg.org/eris/guile-coap.git") + (commit commit))) + (file-name (git-file-name name version)) + (sha256 (base32 "0mk9s4vzsi5y3sk8rs4a0jdcn6qj54nh7nwicdrsj77b9nghqwb3")))) + (build-system gnu-build-system) + (native-inputs + (list autoconf + automake + pkg-config + texinfo)) + (inputs (list guile-3.0)) + (propagated-inputs (list guile-fibers)) + (synopsis "Guile implementation of the Constrained Application Protocol (CoAP)") + (description "Gulie-CoAP is a Guile implementation of the Constrained +Application Protocol (CoAP). CoAP is a network transport protocol specialized +for use with constrained nodes and constrained networks (e.g. low-power, +lousy). This library implements basic serialization of CoAP messages over UDP +(RFC 7252) and TCP (RFC 8323) as well as an asynchronous TCP client (using +@code{guile-fibers})." ) + (home-page "https://codeberg.org/eris/guile-coap") + (license license:gpl3+)))) + (define-public guile-simple-zmq (let ((commit "d25d1865e3378d93c44e2b4f5246a70b078a489d") (revision "11")) -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 3/7] gnu: guile-eris: Update to 1.2.0-dev. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 1/7] narinfo: Add ERIS field pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 2/7] gnu: Add guile-coap pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 4/7] publish: Add ERIS URN to narinfo pukkamustard ` (3 subsequent siblings) 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ludo, maximedevos * gnu/packages/guile-xyz.scm (guile-eris): Update to 1.2.0-dev. [propagated-inputs]: Add guile-coap, guile-fibers, guile-sqlite3, guile-zstd and guile-cbor. --- gnu/packages/guile-xyz.scm | 66 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm index 2fc6d079a1..a66a6d8ad5 100644 --- a/gnu/packages/guile-xyz.scm +++ b/gnu/packages/guile-xyz.scm @@ -5152,38 +5152,46 @@ (define-public guile-sodium (license license:gpl3+))) (define-public guile-eris - (package - (name "guile-eris") - (version "1.0.0") - (source - (origin - (method git-fetch) - (uri (git-reference - (url "https://codeberg.org/eris/guile-eris.git") - (commit (string-append "v" version)))) - (file-name (git-file-name name version)) - (sha256 (base32 "0d4wbjwwaxk0zn5gjhl86qhvk1aisgzp1vnvy4xbvrv5ydqpgyqm")))) - (build-system gnu-build-system) - (arguments '()) - (native-inputs - (list autoconf - automake - pkg-config - texinfo - ;; test dependency - guile-srfi-180 - guile-quickcheck)) - (inputs (list guile-3.0)) - (propagated-inputs - (list guile-sodium)) - (synopsis "Guile implementation of the Encoding for Robust Immutable Storage (ERIS)") - (description - "Guile-ERIS is a Guile implementation of the @url{http://purl.org/eris, + (let ((commit "98ec63cc04c7c59be8d09beed99a0ab1975829ce") + (revision "0")) + (package + (name "guile-eris") + (version (git-version "1.2.0-dev" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://codeberg.org/eris/guile-eris.git") + (commit commit))) + (file-name (git-file-name name version)) + (sha256 (base32 "0n4crjqhj0ndni02xyrhwpzd325668vjbj3c1asy8wh2j50rvcs7")))) + (build-system gnu-build-system) + (arguments '()) + (native-inputs + (list autoconf + automake + pkg-config + texinfo + ;; test dependency + guile-srfi-180 + guile-quickcheck)) + (inputs (list guile-3.0)) + (propagated-inputs + (list guile-sodium + guile-coap + guile-fibers + guile-sqlite3 + guile-zstd + guile-cbor)) + (synopsis "Guile implementation of the Encoding for Robust Immutable +Storage (ERIS)") + (description + "Guile-ERIS is a Guile implementation of the @url{http://purl.org/eris, Encoding for Robust Immutable Storage (ERIS)}. ERIS allows arbitrary content to be encoded into uniformly sized, encrypted blocks that can be reassembled using a short read-capability.") - (home-page "https://codeberg.org/eris/guile-eris") - (license license:gpl3+))) + (home-page "https://codeberg.org/eris/guile-eris") + (license license:gpl3+)))) (define-public guile-r6rs-protobuf (package -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 4/7] publish: Add ERIS URN to narinfo. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard ` (2 preceding siblings ...) 2023-12-28 9:40 ` [bug#52555] [PATCH v4 3/7] gnu: guile-eris: Update to 1.2.0-dev pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 5/7] eris: Connect with an ERIS Store over CoAP+Unix pukkamustard ` (2 subsequent siblings) 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555 Cc: pukkamustard, ludo, maximedevos, Christopher Baines, Josselin Poiret, Ludovic Courtès, Mathieu Othacehe, Ricardo Wurmus, Simon Tournier, Tobias Geerinckx-Rice * guix/scripts/publish.scm (bake-narinfo+nar): Encode store item using ERIS. (show-help, %options): Add '--eris'. (guix-publish): Honor '--eris'. * gnu/packages/package-management.scm (guix): Add guile-eris to native-inputs. * guix/eris.scm: New file. * Makefile.am (MODULES): Add new file. --- Makefile.am | 1 + configure.ac | 5 ++ gnu/packages/package-management.scm | 1 + guix/eris.scm | 73 +++++++++++++++++++++++++++++ guix/scripts/publish.scm | 51 ++++++++++++++------ 5 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 guix/eris.scm diff --git a/Makefile.am b/Makefile.am index b64dcaa77c..86da4560e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -136,6 +136,7 @@ MODULES = \ guix/least-authority.scm \ guix/read-print.scm \ guix/ipfs.scm \ + guix/eris.scm \ guix/platform.scm \ guix/platforms/arm.scm \ guix/platforms/avr.scm \ diff --git a/configure.ac b/configure.ac index ecbd596a34..7e25099c4c 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,11 @@ GUILE_MODULE_AVAILABLE([have_guile_avahi], [(avahi)]) AM_CONDITIONAL([HAVE_GUILE_AVAHI], [test "x$have_guile_avahi" = "xyes"]) +dnl Check for Guile-ERIS. +GUILE_MODULE_AVAILABLE([have_guile_eris], [(eris)]) +AM_CONDITIONAL([HAVE_GUILE_ERIS], + [test "x$have_guile_eris" = "xyes"]) + dnl Guile-newt is used by the graphical installer. GUILE_MODULE_AVAILABLE([have_guile_newt], [(newt)]) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index 97ea41df66..9c0afb70dd 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -478,6 +478,7 @@ (define-public guix ("guile-zstd" ,guile-zstd) ("guile-ssh" ,guile-ssh) ("guile-git" ,guile-git) + ("guile-eris" ,guile-eris) ;; XXX: Keep the development inputs here even though ;; they're unnecessary, just so that 'guix environment diff --git a/guix/eris.scm b/guix/eris.scm new file mode 100644 index 0000000000..d98a9a62bd --- /dev/null +++ b/guix/eris.scm @@ -0,0 +1,73 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 pukkamustard <pukkamustard@posteo.net> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix eris) + + #:use-module (eris) + #:use-module (eris fs) + #:use-module (eris sqlite) + #:use-module (eris read-capability) + + #:use-module (web uri) + #:use-module (ice-9 match) + #:use-module (srfi srfi-171) + + #:export (%eris-store-url + eris-encode-store-item)) + +(define %eris-store-url + (make-parameter + (getenv "ERIS_STORE_URL") + (lambda (val) + (cond + ((uri? val) val) + ((string? val) (string->uri val)) + (else #f))))) + +(define %guix-eris-convergence-secret + (make-parameter %null-convergence-secret)) + +(define (guix-eris-block-reducer) + "Returns an ERIS block reducer." + (if (uri? (%eris-store-url)) + (match (uri-scheme (%eris-store-url)) + + ;; Store blocks in an SQLite database (see + ;; https://eris.codeberg.page/eer/sqlite.xml) + ('sqlite + (eris-sqlite-block-reducer (uri-path (%eris-store-url)))) + + ;; TODO + ;; ('coap+unix #f) + ;; ('coap+tcp #f) + + (_ (error "Don't know how to handle ERIS store URL " + (uri->string (%eris-store-url))))) + + ;; If no ERIS store URL is provided we just compute the ERIS URN without + ;; storing the blocks anywhere. As dummy block-reducer we use `rcount` from + ;; SRFI-171 that counts the number of blocks. + rcount)) + +(define* (eris-encode-store-item item) + "Encodes the store item ITEM using ERIS and returns the read capability as +string." + (eris-read-capability->string + (eris-fs-encode item + #:convergence-secret (%guix-eris-convergence-secret) + #:block-reducer (guix-eris-block-reducer)))) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 4457be1fce..2e7138f3c7 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -53,6 +53,7 @@ (define-module (guix scripts publish) #:use-module (guix workers) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) + #:use-module (guix eris) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -96,6 +97,8 @@ (define (show-help) (display (G_ " --cache-bypass-threshold=SIZE serve store items below SIZE even when not cached")) + (display (G_ " + --eris[=STORE] encode items using ERIS and publish blocks to STORE")) (display (G_ " --workers=N use N workers to bake items")) (display (G_ " @@ -218,6 +221,9 @@ (define %options (lambda (opt name arg result) (alist-cons 'workers (string->number* arg) result))) + (option '("eris") #f #t + (lambda (opt name arg result) + (alist-cons 'eris (or arg #t) result))) (option '("ttl") #t #f (lambda (opt name arg result) (let ((duration (string->duration arg))) @@ -319,7 +325,8 @@ (define* (store-item->recutils store-item (define* (narinfo-string store store-path #:key (compressions (list %no-compression)) - (nar-path "nar") (file-sizes '())) + (nar-path "nar") (file-sizes '()) + eris-urn) "Generate a narinfo key/value string for STORE-PATH; an exception is raised if STORE-PATH is invalid. Produce a URL that corresponds to COMPRESSION. The narinfo is signed with KEY. NAR-PATH specifies the prefix for nar URLs. @@ -341,10 +348,10 @@ (define* (narinfo-string store store-path "\ StorePath: ~a NarHash: sha256:~a -NarSize: ~d +NarSize: ~d~@[~%ERIS: ~a~] References: ~a~%" store-path - hash size references)) + hash size eris-urn references)) ;; Do not render a "Deriver" line if we are rendering info for a ;; derivation. Also do not render a "System" line that would be ;; expensive to compute and is currently unused. @@ -530,7 +537,7 @@ (define (bypass-cache? store item) (define* (render-narinfo/cached store request hash #:key ttl (compressions (list %no-compression)) (nar-path "nar") negative-ttl - cache pool) + cache pool eris?) "Respond to the narinfo request for REQUEST. If the narinfo is available in CACHE, then send it; otherwise, return 404 and \"bake\" that nar and narinfo requested using POOL." @@ -575,7 +582,8 @@ (define* (render-narinfo/cached store request hash (bake-narinfo+nar cache item #:ttl ttl #:compressions compressions - #:nar-path nar-path))) + #:nar-path nar-path + #:eris? eris?))) (when ttl (single-baker 'cache-cleanup @@ -636,7 +644,8 @@ (define (compress-nar cache item compression) (define* (bake-narinfo+nar cache item #:key ttl (compressions (list %no-compression)) - (nar-path "/nar")) + (nar-path "/nar") + (eris? #f)) "Write the narinfo and nar for ITEM to CACHE." (define (compressed-nar-size compression) (let* ((nar (nar-cache-file cache item #:compression compression)) @@ -644,7 +653,10 @@ (define* (bake-narinfo+nar cache item (and stat (cons compression (stat:size stat))))) - (let ((compression (actual-compressions item compressions))) + (let ((compression (actual-compressions item compressions)) + (eris-urn (if eris? + (eris-encode-store-item item) + #f))) (for-each (cut compress-nar cache item <>) compressions) @@ -662,7 +674,8 @@ (define* (bake-narinfo+nar cache item (display (narinfo-string store item #:nar-path nar-path #:compressions compressions - #:file-sizes sizes) + #:file-sizes sizes + #:eris-urn eris-urn) port))) ;; Make the cached narinfo world-readable, contrary to what @@ -1060,7 +1073,8 @@ (define* (make-request-handler store cache pool narinfo-ttl narinfo-negative-ttl (nar-path "nar") - (compressions (list %no-compression))) + (compressions (list %no-compression)) + (eris? #f)) (define compression-type? string->compression-type) @@ -1092,7 +1106,8 @@ (define* (make-request-handler store #:ttl narinfo-ttl #:negative-ttl narinfo-negative-ttl #:nar-path nar-path - #:compressions compressions) + #:compressions compressions + #:eris? eris?) (render-narinfo store request hash #:ttl narinfo-ttl #:negative-ttl narinfo-negative-ttl @@ -1162,7 +1177,7 @@ (define* (run-publish-server socket store advertise? port (compressions (list %no-compression)) (nar-path "nar") narinfo-ttl narinfo-negative-ttl - cache pool) + cache pool eris?) (when advertise? (let ((name (service-name))) ;; XXX: Use a callback from Guile-Avahi here, as Avahi can pick a @@ -1178,7 +1193,8 @@ (define* (run-publish-server socket store #:nar-path nar-path #:narinfo-ttl narinfo-ttl #:narinfo-negative-ttl narinfo-negative-ttl - #:compressions compressions) + #:compressions compressions + #:eris? eris?) concurrent-http-server `(#:socket ,socket))) @@ -1262,6 +1278,7 @@ (define-command (guix-publish . args) (repl-port (assoc-ref opts 'repl)) (cache (assoc-ref opts 'cache)) (workers (assoc-ref opts 'workers)) + (eris? (assoc-ref opts 'eris)) ;; Read the key right away so that (1) we fail early on if we can't ;; access them, and (2) we can then drop privileges. @@ -1281,7 +1298,8 @@ (define-command (guix-publish . args) (%private-key private-key) (cache-bypass-threshold (or (assoc-ref opts 'cache-bypass-threshold) - (cache-bypass-threshold)))) + (cache-bypass-threshold))) + (%eris-store-url (assoc-ref opts 'eris))) (if (eq? style 'systemd) (info (G_ "publishing (started via socket activation)~%")) (info (G_ "publishing ~a on ~a, port ~d~%") @@ -1289,6 +1307,10 @@ (define-command (guix-publish . args) (inet-ntop (sockaddr:fam address) (sockaddr:addr address)) (sockaddr:port address))) + (when (string? (assoc-ref opts 'eris)) + (info (G_ "publishing ERIS blocks to ~a~%") + (assoc-ref opts 'eris))) + (for-each (lambda (compression) (info (G_ "using '~a' compression method, level ~a~%") (compression-type compression) @@ -1312,7 +1334,8 @@ (define-command (guix-publish . args) #:nar-path nar-path #:compressions compressions #:narinfo-negative-ttl negative-ttl - #:narinfo-ttl ttl)))))) + #:narinfo-ttl ttl + #:eris? eris?)))))) ;;; Local Variables: ;;; eval: (put 'single-baker 'scheme-indent-function 1) -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 5/7] eris: Connect with an ERIS Store over CoAP+Unix. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard ` (3 preceding siblings ...) 2023-12-28 9:40 ` [bug#52555] [PATCH v4 4/7] publish: Add ERIS URN to narinfo pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 6/7] substitute: Decode substitutes using ERIS pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 7/7] gnu: Add kapla pukkamustard 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555 Cc: pukkamustard, ludo, maximedevos, Christopher Baines, Josselin Poiret, Ludovic Courtès, Mathieu Othacehe, Ricardo Wurmus, Simon Tournier, Tobias Geerinckx-Rice * guix/eris.scm (open-coap-unix-socket): New procedure. (guix-eris-block-reducer): Handle coap+unix URIs. * guix/publish.scm (bake-narinfo+nar): Start a fibers scheduler when encoding item with ERIS. --- guix/eris.scm | 63 ++++++++++++++++++++++++++++++---------- guix/scripts/publish.scm | 9 +++++- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index d98a9a62bd..3fbedd0cb7 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -21,8 +21,11 @@ (define-module (guix eris) #:use-module (eris) #:use-module (eris fs) #:use-module (eris sqlite) + #:use-module (eris coap) #:use-module (eris read-capability) + #:use-module (coap tcp) + #:use-module (web uri) #:use-module (ice-9 match) #:use-module (srfi srfi-171) @@ -42,27 +45,57 @@ (define %eris-store-url (define %guix-eris-convergence-secret (make-parameter %null-convergence-secret)) +(define (open-coap-unix-socket path) + (let ((sock (socket PF_UNIX SOCK_STREAM 0))) + ;; Release FD on exec + (fcntl sock F_SETFD FD_CLOEXEC) + ;; Set to non-blocking + (fcntl sock F_SETFL (logior O_NONBLOCK (fcntl sock F_GETFL))) + ;; Connect + (connect sock AF_UNIX path) + + ;; Initialize the CoAP connection + (open-socket-for-uri #f + #:socket sock + ;; Allow up to 64 in-flight requests + #:nstart 64))) + (define (guix-eris-block-reducer) "Returns an ERIS block reducer." - (if (uri? (%eris-store-url)) - (match (uri-scheme (%eris-store-url)) + (let ((store-url (%eris-store-url))) + (if (uri? store-url) + (match (uri-scheme store-url) + + ;; Store blocks in an SQLite database (see + ;; https://eris.codeberg.page/eer/sqlite.xml) + ('sqlite + (eris-sqlite-block-reducer (uri-path store-url))) - ;; Store blocks in an SQLite database (see - ;; https://eris.codeberg.page/eer/sqlite.xml) - ('sqlite - (eris-sqlite-block-reducer (uri-path (%eris-store-url)))) + ;; Connect to a CoAP ERIS store over a Unix socket + ('coap+unix + ;; Wrap the eris-coap-block-reducer to close the provided connection. + (let ((ecbr (eris-coap-block-reducer + (build-uri 'coap #:path ".well-known/eris") + #:nstart 64 + #:connection (open-coap-unix-socket + (uri-path store-url))))) + (case-lambda + (() (ecbr)) + ((conn ref-block) (ecbr conn ref-block)) + ((conn) + (ecbr conn) + (close-port conn))))) - ;; TODO - ;; ('coap+unix #f) - ;; ('coap+tcp #f) + ;; TODO + ;; ('coap+tcp #f) - (_ (error "Don't know how to handle ERIS store URL " - (uri->string (%eris-store-url))))) + (_ (error "Don't know how to handle ERIS store URL " + (uri->string (%eris-store-url))))) - ;; If no ERIS store URL is provided we just compute the ERIS URN without - ;; storing the blocks anywhere. As dummy block-reducer we use `rcount` from - ;; SRFI-171 that counts the number of blocks. - rcount)) + ;; If no ERIS store URL is provided we just compute the ERIS URN without + ;; storing the blocks anywhere. As dummy block-reducer we use `rcount` from + ;; SRFI-171 that counts the number of blocks. + rcount))) (define* (eris-encode-store-item item) "Encodes the store item ITEM using ERIS and returns the read capability as diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 2e7138f3c7..0b61354327 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -54,6 +54,7 @@ (define-module (guix scripts publish) #:use-module (guix store) #:use-module ((guix serialization) #:select (write-file)) #:use-module (guix eris) + #:use-module (fibers) #:use-module (zlib) #:autoload (lzlib) (call-with-lzip-output-port make-lzip-output-port) @@ -655,7 +656,13 @@ (define* (bake-narinfo+nar cache item (let ((compression (actual-compressions item compressions)) (eris-urn (if eris? - (eris-encode-store-item item) + ;; Encode with fibers. + ;; XXX: There seems to be some buggy interactions when + ;; running a fibers scheduler and connecting to the + ;; store. + (run-fibers (lambda () + (eris-encode-store-item item)) + #:drain? #t) #f))) (for-each (cut compress-nar cache item <>) compressions) -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 6/7] substitute: Decode substitutes using ERIS. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard ` (4 preceding siblings ...) 2023-12-28 9:40 ` [bug#52555] [PATCH v4 5/7] eris: Connect with an ERIS Store over CoAP+Unix pukkamustard @ 2023-12-28 9:40 ` pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 7/7] gnu: Add kapla pukkamustard 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555 Cc: pukkamustard, ludo, maximedevos, Christopher Baines, Josselin Poiret, Ludovic Courtès, Mathieu Othacehe, Ricardo Wurmus, Simon Tournier, Tobias Geerinckx-Rice * guix/scripts/substitute.scm: Decode substitutes using ERIS. * guix/eris.scm (eris-decode-store-item): New function. * nix/nix-daemon/guix-daemon.cc (options): Add eris-store-url option. --- guix/eris.scm | 45 +++++++++++++++++---- guix/scripts/substitute.scm | 76 +++++++++++++++++++++++++++-------- nix/nix-daemon/guix-daemon.cc | 5 +++ 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/guix/eris.scm b/guix/eris.scm index 3fbedd0cb7..1aa52e69dd 100644 --- a/guix/eris.scm +++ b/guix/eris.scm @@ -21,6 +21,7 @@ (define-module (guix eris) #:use-module (eris) #:use-module (eris fs) #:use-module (eris sqlite) + #:use-module (sqlite3) #:use-module (eris coap) #:use-module (eris read-capability) @@ -31,7 +32,8 @@ (define-module (guix eris) #:use-module (srfi srfi-171) #:export (%eris-store-url - eris-encode-store-item)) + eris-encode-store-item + eris-decode-store-item)) (define %eris-store-url (make-parameter @@ -83,8 +85,7 @@ (define (guix-eris-block-reducer) (() (ecbr)) ((conn ref-block) (ecbr conn ref-block)) ((conn) - (ecbr conn) - (close-port conn))))) + (ecbr conn))))) ;; TODO ;; ('coap+tcp #f) @@ -97,10 +98,40 @@ (define (guix-eris-block-reducer) ;; SRFI-171 that counts the number of blocks. rcount))) +(define (call-with-guix-eris-block-ref proc) + (let ((store-url (%eris-store-url))) + (if (uri? store-url) + (match (uri-scheme store-url) + + ('sqlite + (let ((db (eris-sqlite-open (uri-path store-url)))) + (proc (lambda (ref) (eris-sqlite-ref db ref))) + (sqlite-close db))) + + ('coap+unix + (let ((conn (open-coap-unix-socket (uri-path store-url))) + (req-uri (build-uri 'coap #:path ".well-known/eris"))) + (proc + (lambda (ref) + (eris-coap-block-ref req-uri ref #:connection conn))) + (close-port conn))) + + (_ (error "Don't know how to handle ERIS store URL " + (uri->string (%eris-store-url))))) + + (error "No ERIS store to get blocks.")))) + (define* (eris-encode-store-item item) "Encodes the store item ITEM using ERIS and returns the read capability as string." - (eris-read-capability->string - (eris-fs-encode item - #:convergence-secret (%guix-eris-convergence-secret) - #:block-reducer (guix-eris-block-reducer)))) + (eris-fs-encode item + #:convergence-secret (%guix-eris-convergence-secret) + #:block-reducer (guix-eris-block-reducer))) + +(define* (eris-decode-store-item eris-urn destination) + "Decode a store item with read-capability ERIS-URN to DESTINATION." + (call-with-guix-eris-block-ref + (lambda (block-ref) + (eris-fs-decode eris-urn destination + #:block-ref block-ref) + #t))) diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 37cd08e289..3c060f1c89 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm @@ -45,6 +45,8 @@ (define-module (guix scripts substitute) . guix:open-connection-for-uri))) #:autoload (gnutls) (error/invalid-session error/again error/interrupted) #:use-module (guix progress) + #:use-module (guix eris) + #:use-module (fibers) #:use-module ((guix build syscalls) #:select (set-thread-name)) #:use-module (ice-9 rdelim) @@ -656,9 +658,11 @@ (define* (process-substitution/fallback port narinfo destination (() (loop rest))))))) + (define* (process-substitution port store-item destination #:key cache-urls acl - deduplicate? print-build-trace?) + deduplicate? print-build-trace? + (eris? #f)) "Substitute STORE-ITEM (a store file name) from CACHE-URLS, and write it to DESTINATION as a nar file. Verify the substitute against ACL, and verify its hash against what appears in the narinfo. When DEDUPLICATE? is true, and if @@ -674,20 +678,56 @@ (define* (process-substitution port store-item destination (leave (G_ "no valid substitute for '~a'~%") store-item)) - (guard (c ((network-error? c) - (format (current-error-port) - (G_ "retrying download of '~a' with other substitute URLs...~%") - store-item) - (process-substitution/fallback port narinfo destination - #:cache-urls cache-urls - #:acl acl - #:deduplicate? deduplicate? - #:print-build-trace? - print-build-trace?))) - (download-nar narinfo destination - #:status-port port - #:deduplicate? deduplicate? - #:print-build-trace? print-build-trace?))) + (if (and eris? + (%eris-store-url) + (narinfo-eris-urn narinfo)) + + (unless + + ;; Attempt to fetch substitute via ERIS + (let ((eris-urn (narinfo-eris-urn narinfo))) + (format (current-error-port) + (G_ "Downloading ~a...~%") (uri->string eris-urn)) + (run-fibers + (lambda () + (guard + (c (else + (format (current-error-port) + (G_ "failed to decode substitute from ERIS URN ~a: ~a" + (uri->string eris-urn) + c)) + #f)) + (eris-decode-store-item eris-urn destination) + ;; Tell the daemon that we're done. + (format port "success ~a ~a~%" + (narinfo-hash narinfo) (narinfo-size narinfo)))))) + + ;; Retry without ERIS on failure. + (process-substitution port store-item destination + #:cache-urls cache-urls + #:acl acl + #:deduplicate? deduplicate? + #:print-build-trace? print-build-trace? + #:eris? #f)) + + (guard (c ((network-error? c) + (format (current-error-port) + (G_ "retrying download of '~a' with other substitute URLs...~%") + store-item) + (process-substitution/fallback port narinfo destination + #:cache-urls cache-urls + #:acl acl + #:deduplicate? deduplicate? + #:print-build-trace? + print-build-trace?))) + (download-nar narinfo destination + #:status-port port + #:deduplicate? deduplicate? + #:print-build-trace? print-build-trace?)))) + + + + \f ;;; @@ -876,7 +916,8 @@ (define-command (guix-substitute . args) ;; Download STORE-PATH and store it as a Nar in file DESTINATION. ;; Specify the number of columns of the terminal so the progress ;; report displays nicely. - (parameterize ((current-terminal-columns (client-terminal-columns))) + (parameterize ((current-terminal-columns (client-terminal-columns)) + (%eris-store-url (find-daemon-option "eris-store-url"))) (let loop () (match (read-line) ((? eof-object?) @@ -887,7 +928,8 @@ (define-command (guix-substitute . args) #:acl (current-acl) #:deduplicate? deduplicate? #:print-build-trace? - print-build-trace?) + print-build-trace? + #:eris? #t) (loop)))))) (opts (leave (G_ "~a: unrecognized options~%") opts)))))) diff --git a/nix/nix-daemon/guix-daemon.cc b/nix/nix-daemon/guix-daemon.cc index d7ab9c5e64..d6b054bc6c 100644 --- a/nix/nix-daemon/guix-daemon.cc +++ b/nix/nix-daemon/guix-daemon.cc @@ -90,6 +90,7 @@ builds derivations on behalf of its clients."); #define GUIX_OPT_MAX_SILENT_TIME 19 #define GUIX_OPT_LOG_COMPRESSION 20 #define GUIX_OPT_DISCOVER 21 +#define GUIX_OPT_ERIS_STORE_URL 22 static const struct argp_option options[] = { @@ -132,6 +133,8 @@ static const struct argp_option options[] = n_("use the specified compression type for build logs") }, { "discover", GUIX_OPT_DISCOVER, "yes/no", OPTION_ARG_OPTIONAL, n_("use substitute servers discovered on the local network") }, + { "eris-store-url", GUIX_OPT_ERIS_STORE_URL, n_("URL"), 0, + n_("use URL to retrieve blocks of ERIS encoded substitutes") }, /* '--disable-deduplication' was known as '--disable-store-optimization' up to Guix 0.7 included, so keep the alias around. */ @@ -270,6 +273,8 @@ parse_opt (int key, char *arg, struct argp_state *state) useDiscover = string_to_bool (arg); settings.set ("discover", useDiscover ? "true" : "false"); break; + case GUIX_OPT_ERIS_STORE_URL: + settings.set ("eris-store-url", arg); case GUIX_OPT_DEBUG: verbosity = lvlDebug; break; -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
* [bug#52555] [PATCH v4 7/7] gnu: Add kapla. 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard ` (5 preceding siblings ...) 2023-12-28 9:40 ` [bug#52555] [PATCH v4 6/7] substitute: Decode substitutes using ERIS pukkamustard @ 2023-12-28 9:40 ` pukkamustard 6 siblings, 0 replies; 65+ messages in thread From: pukkamustard @ 2023-12-28 9:40 UTC (permalink / raw) To: 52555; +Cc: pukkamustard, ludo, maximedevos * gnu/packages/guile-xyz.scm (kapla): New variable. --- gnu/packages/guile-xyz.scm | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm index a66a6d8ad5..f3d97cca37 100644 --- a/gnu/packages/guile-xyz.scm +++ b/gnu/packages/guile-xyz.scm @@ -102,6 +102,7 @@ (define-module (gnu packages guile-xyz) #:use-module (gnu packages multiprecision) #:use-module (gnu packages ncurses) #:use-module (gnu packages networking) + #:use-module (gnu packages ninja) #:use-module (gnu packages noweb) #:use-module (gnu packages nss) #:use-module (gnu packages package-management) @@ -5193,6 +5194,51 @@ (define-public guile-eris (home-page "https://codeberg.org/eris/guile-eris") (license license:gpl3+)))) +(define-public kapla + (let ((commit "fa72bcb116ed6ea20f76206145766cb46fa4f30d") + (revision "0")) + (package + (name "kapla") + (version (git-version "0.1.0-dev" revision commit)) + (source + (origin + (method git-fetch) + (uri (git-reference + (url "https://codeberg.org/eris/kapla.git") + (commit commit))) + (file-name (git-file-name name version)) + (sha256 (base32 "15g9dg6i93n5wkkma983hvcl5mgvw13yxxrv8ka5n5mvslk9f0wa")))) + (build-system gnu-build-system) + (arguments + (list + #:phases + #~(modify-phases + %standard-phases + (delete 'patch-source-shebangs) + (replace 'configure + (lambda* (#:key outputs #:allow-other-keys) + (invoke "guile" + "--no-auto-compile" + "configure" + (string-append "--prefix=" #$output)))) + (replace 'build (lambda _ (invoke "ninja"))) + (delete 'check) + (delete 'install)))) + (native-inputs (list ninja)) + (inputs (list guile-3.0)) + (propagated-inputs + (list guile-coap + guile-sqlite3 + guile-eris + guile-lib + guile-fibers)) + (synopsis "Block storage and transport for ERIS encoded content") + (description "Kapla is a tool for encoding content with ERIS and +managing blocks of ERIS encoded content. It allows blocks to be stored in a +local database and be shared over the network.") + (home-page "https://codeberg.org/eris/kapla") + (license license:agpl3+)))) + (define-public guile-r6rs-protobuf (package (name "guile-r6rs-protobuf") -- 2.41.0 ^ permalink raw reply related [flat|nested] 65+ messages in thread
end of thread, other threads:[~2023-12-28 9:41 UTC | newest] Thread overview: 65+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-12-16 16:17 [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 1/3] publish: Add ERIS URN to narinfo pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 2/3] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard 2021-12-16 16:20 ` [bug#52555] [RFC PATCH 3/3] publish: Add IPFS support pukkamustard 2021-12-20 16:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2021-12-23 11:42 ` pukkamustard 2021-12-24 14:48 ` Ludovic Courtès 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 0/5] " pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 1/5] WIP: gnu: guile-eris: Update to unreleased git version pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 2/5] publish: Add ERIS URN to narinfo pukkamustard 2022-01-29 21:09 ` Maxime Devos 2022-01-29 21:15 ` Maxime Devos 2022-02-02 10:16 ` pukkamustard 2022-01-25 19:21 ` [bug#52555] [RFC PATCH v2 3/5] Add (guix eris) pukkamustard 2022-01-29 21:23 ` Maxime Devos 2022-02-02 10:28 ` pukkamustard 2022-02-02 15:36 ` Maxime Devos 2022-01-29 21:24 ` Maxime Devos 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 4/5] publish: Add support for storing ERIS encoded blocks to IPFS pukkamustard 2022-01-29 21:28 ` Maxime Devos 2022-02-02 10:24 ` pukkamustard 2022-01-25 19:22 ` [bug#52555] [RFC PATCH v2 5/5] substitute: Fetch substitutes using ERIS pukkamustard 2022-01-29 21:29 ` Maxime Devos 2022-02-02 10:11 ` pukkamustard 2022-01-29 21:33 ` Maxime Devos 2022-01-29 21:38 ` Maxime Devos 2022-01-29 21:40 ` Maxime Devos 2022-01-29 21:40 ` Maxime Devos 2022-02-02 10:38 ` pukkamustard 2022-01-29 21:00 ` [bug#52555] [RFC PATCH v2 0/5] Decentralized substitute distribution with ERIS Maxime Devos 2022-02-02 9:50 ` pukkamustard 2022-01-29 21:08 ` Maxime Devos 2022-02-02 9:56 ` pukkamustard 2022-02-02 11:09 ` Maxime Devos 2022-01-29 21:52 ` Maxime Devos 2022-02-02 11:10 ` pukkamustard 2022-02-03 20:36 ` Maxime Devos 2022-02-04 10:20 ` pukkamustard 2022-01-30 11:46 ` Maxime Devos 2022-02-02 10:51 ` pukkamustard 2022-02-02 11:27 ` Maxime Devos 2022-02-02 12:42 ` pukkamustard 2022-02-02 15:07 ` Maxime Devos 2022-02-02 15:27 ` Maxime Devos 2022-02-04 16:16 ` Maxime Devos 2022-12-29 18:13 ` [bug#52555] [PATCH v3 0/8] " pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 1/8] publish: Add ERIS URN to narinfo pukkamustard 2023-01-14 18:34 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2022-12-29 18:13 ` [bug#52555] [PATCH v3 2/8] publish: Store ERIS encoded blocks to a local block store pukkamustard 2023-01-14 18:42 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2022-12-29 18:13 ` [bug#52555] [PATCH v3 3/8] publish: Add HTTP endpoint for resolving ERIS blocks pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 4/8] WIP: substitute: Fetch substitutes using ERIS pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 5/8] eris/http: Add HTTP block de-referencer pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 6/8] WIP: eris: Use HTTP to get ERIS blocks pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 7/8] eris: Use parameterized %eris-peers when getting blocks pukkamustard 2022-12-29 18:13 ` [bug#52555] [PATCH v3 8/8] eris: Use IPFS to get ERIS blocks pukkamustard 2023-01-14 18:25 ` [bug#52555] [RFC PATCH 0/3] Decentralized substitute distribution with ERIS Ludovic Courtès 2023-12-28 9:40 ` [bug#52555] [PATCH v4 0/7] " pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 1/7] narinfo: Add ERIS field pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 2/7] gnu: Add guile-coap pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 3/7] gnu: guile-eris: Update to 1.2.0-dev pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 4/7] publish: Add ERIS URN to narinfo pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 5/7] eris: Connect with an ERIS Store over CoAP+Unix pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 6/7] substitute: Decode substitutes using ERIS pukkamustard 2023-12-28 9:40 ` [bug#52555] [PATCH v4 7/7] gnu: Add kapla pukkamustard
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/guix.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.