Nixでハッシュ関係の処理をPythonで実装してみる

前回の記事でstore pathを手で計算する方法を見てきたが、output hashの計算については手で計算するのが無理だった。これをPythonスクリプトで実装するとどうなるかをやってみた。 ゴールとしてはoutput hashを計算するコードを実装することであるが、 Nix32表現の計算とtruncateオプションの計算はそれにあたって必要なので実装した おまけでderivation hashとsource hashの計算も実装した なお、今回のコードについて Nix 2.21.1を参考に作っている すべてのパターンは網羅できていない可能性が高い(特にoutput hashの計算方法) Nixのいくつかの処理をPythonで実装してみるのコードを一部使って実装する である。また、コードの実行例にあたって、前回の記事のderivationの準備にしたがってsampleのderivationが準備されているものとする。 Nix32表現の計算 Nix32の計算はlibutil/hash.ccで行われている。 以下の並びのビット列があるとする(見やすさのため8bitごとに縦棒で区切ってある)。 1 b07 b06 b05 b04 b03 b02 b01 b00 | b15 b14 b13 b12 b11 b10 b09 b08 | b23 b22 b21 b20 b19 b18 b17 b16 | ... Nix32表現では、以下のように5bitずつ取り出していく。 1 2 3 4 5 b04 b03 b02 b01 b00 b09 b08 | b07 b06 b05 b14 b13 b12 b11 b10 b19 b18 b17 b16 | b15 ....

2024-04-21 · (updated 2024-04-21) · 3 min · 622 words

Nixのstore path計算方法メモ

Nixでは、パッケージの再現性を担保するために、/nix/store/下にハッシュ値を含んだ名前であらゆるファイルを保管する。そのハッシュ値がどのような情報から計算されるものなのかを知っておくことは、なぜNixが再現性を確保できるのかを考える上で重要である。 そこで、この記事では、Nixのstore path、つまりその中に含まれるハッシュの計算方法について解説し、実際にステップバイステップで計算してみる。 参考記事 How Nix Isntantiation Works (Web Archive) Nix manual(unstable)Store Pathの仕様 Nix PillsのChapter 18 なお、本記事では nix derivation show コマンドの結果からいろいろと情報を取り出すために jq を用いる。 store pathの種類 ほとんどStore Pathの書き起こしみたいになってしまうが書いておく。 まずstore pathは、/nix/store/<digest>-<name>の形式を持っている。 <digest>というのは、fingerprint(後述)をSHA256でハッシュ化し、160bitに圧縮したうえでNix32表現にしたもの。ドキュメントには「SHA256の先頭160bitをBase32表現にしたもの」と記載があるが、 Base32という言葉はRelease Note 2.20でNix32という名前に改められた。理由としては通常の意味のBase32表現とは処理が異なり紛らわしいためのようだ 先頭160bitを単純に切り取ってNix32表現にするのではなく、実装では complressHash という関数で圧縮処理が行われている(該当ソース)。 fingerprintは、<type>:sha256:<inner-digest>:/nix/store:<name>の形式 <type>というのは以下のいずれか text:<input store path>:<input store path>:...:derivation。<input store path>には、(存在すれば)derivationが参照する他のファイルのパスを指定する source:<input store path>:<input store path>:...:外部から持ってきたファイルをNAR形式でアーカイブ化したもの sourceがinput store pathを持つケースってどんなときなの?と感じるが、確かにlibstore/store-api.ccにそれっぽいコードが見つかる。しかし実例がまだ良くわかっていない…。 output:<id>:derivationからビルドされたもの、もしくはビルド予定のものを表す。<id>には通常outが入るが、ビルド出力結果を複数分けているようなパッケージではbinやlib、devなどが指定されうる。 <inner-digest>は、inner-fingerprintをSHA256でハッシュ化し、Base16表現にしたもの inner-fingerprintの計算方法は、上述のtypeによって異なるが、これは後々実際に計算してみつつ解説する いろいろと書いてあるが、結局/nix/store下におかれるパスの種類は実質fingerprintの種類であり、すなわち3種類である。 text:derivationを表す source:ビルドに必要なファイル、ソースコードを表す output:ビルド生成物そのもの、ないしディレクトリを表す (前準備)derivationの準備 今回手で計算するもととなるderivationを簡単に書く。 Nix PillsのChapter 7の内容をもとに。汎用性とかは意識せず、x86_64-linux前提で書く ただNix Pillsをそのまま書き起こしになってしまうのもつまらないので、flakeを使って書いてみる。 まずいくつかのファイルを作成する flake.nix:flakeファイル default.nix で分けないで、ここに直接derivationを書く mubuilder....

2024-04-20 · (updated 2024-04-21) · 7 min · 1462 words