1
0
forked from cheng/wallet

notes on playing around with nixos

This commit is contained in:
reaction.la 2024-08-25 06:22:09 +00:00
parent a5a8701cc8
commit 87d61098e5
No known key found for this signature in database
8 changed files with 278 additions and 50 deletions

34
.gitattributes vendored
View File

@ -4,23 +4,23 @@
# Force the following filetypes to have unix eols and encoding, so that Windows does not break them. # Force the following filetypes to have unix eols and encoding, so that Windows does not break them.
# If a file is going to be used on linux and windows, we want it invariant, # If a file is going to be used on linux and windows, we want it invariant,
# rather than automatically translated, because automatic translation always screw things up. # rather than automatically translated, because automatic translation always screw things up.
* text=auto eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 * text=auto eol=lf encoding=utf-8, whitespace=trailing-space,space-before-tab,tabwidth=4
.gitignore text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 .gitignore text eol=lf encoding=utf-8, whitespace=trailing-space,space-before-tab,tabwidth=4
.gitattributes text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 .gitattributes text eol=lf encoding=utf-8, whitespace=trailing-space,space-before-tab,tabwidth=4
.gitmodules text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 .gitmodules text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
*.sh text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=bash *.sh text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=bash
*.c text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 *.c text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
*.cpp text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=cpp *.cpp text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=cpp
*.rs text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=rust *.rs text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=rust
*.py text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=python *.py text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=python
*.h text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 *.h text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
*.txt text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 *.txt text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
*.html text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=html *.html text eol=lf encoding=utf-8 whitespace=space-before-tab,tabwidth=4 diff=html
*.htm text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=html *.htm text eol=lf encoding=utf-8 whitespace=space-before-tab,tabwidth=4 diff=html
*.md text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=markdown *.md text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=markdown
*.pandoc text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 *.pandoc text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
*.css text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=css *.css text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 diff=css
*.manifest text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4 *.manifest text eol=lf encoding=utf-8 whitespace=trailing-space,space-before-tab,tabwidth=4
makefile text eol=lf encoding=utf-8 makefile text eol=lf encoding=utf-8

158
README.html Normal file
View File

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>README</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="docs/pandoc_templates/style.css" />
<link rel="shortcut icon" href="docs/rho.ico">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="logo-header">
<a href="docs/manifesto/motivation.html">
<img src="docs/pandoc_templates/logo.svg" id="logo-graphic" alt="logo">
<div style="height:18px;"></div>
<div id="Rhocoin"></div>
</a>
</div>
<div class="button-bar">
<a href="README.html">readme</a>
<a href="LICENSE.html">license</a>
<a href="NOTICE.html">notice</a>
<a href="RELEASE_NOTES.html">release notes</a>
</div>
<header id="title-block-header">
<h1 class="title">README</h1>
<p><a href="docs/index.htm">pre alpha documentation (mostly a wish list)</a></p>
<p><a href="./license.txt">copyright © and license</a></p>
<p>pre-requisite, Pandoc to build the html documentation from the markdown files.</p>
<p>Windows pre-requisites: Visual Studio and git-bash</p>
<p>To obtain the source code from which the project can be built,
including this README.html, from the bash command line (git-bash in windows).</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> clone <span class="at">--recurse-submodules</span> missing url</span></code></pre></div>
<p>To build the docs, you need pandoc on the path.</p>
<pre class="bash2"><code>cd wallet/docs
./mkdocs.sh</code></pre>
<p>To configure and build the required third party libraries in windows, then
build the program and run unit test for the first time, you need to have
Visual studio build tools at their default location)</p>
<pre class="bash2"><code>cd wallet
./winConfigure.bat</code></pre>
<p>Or, if you are in the command shell or power shell,</p>
<pre class="bat"><code>.\winConfigure.bat</code></pre>
<p>After a pull from remote in which the submodules have changed, the pull
fails to automatically update the submodules by default, and when you
switch or checkout branches, the switch fails to automatically switch
and checkout the brances.</p>
<p>After a pull that gives you a status of modified submodules.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> submodule update <span class="at">--init</span> <span class="at">--recursive</span> <span class="at">--remote</span></span></code></pre></div>
<p>After a checkout or branch switch that gives you a status of modified submodules.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> submodule update <span class="at">--recursive</span></span></code></pre></div>
<p>The documentation is in pandoc flavored markdown, which is
conveniently edited in vscode with the <code>markdown lint</code> and <code>Pandoc</code>
extensions included and, if you have launched <code>code</code> in the docs directory,
with <code>file/preferences/Extensions/Markdown/Styles</code> set to
<code>pandoc_templates\\style.css</code>, that being the style used by the <code>mkdocs.sh</code> documentation build script.</p>
<p>On Windows, if Git Bash and Pandoc has been installed, you should be
able to run this shell file in bash by double clicking on it.</p>
<p>if you add the recommended repository configuration defaults to your local repository configuration</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> config <span class="at">--local</span> include.path ../.gitconfig</span></code></pre></div>
<p>this will substantially mitigate the problem of submodules failing to
update in pushes, pulls, checkouts, and switches.</p>
<p>It will, however, also implement signed commits, and insist you have set up a key pair as
explained in the contributor code of conduct because <a href="./docs/setup/contributor_code_of_conduct.html#code-will-be-cryptographically-signed" target="_blank" title="Contributor Code of Conduct">cryptographic software is under attack</a> from NSA
entryists and shills, who seek to introduce backdoors.</p>
<p><code>.gitconfig</code> also adds several git aliases:</p>
<ol type="1">
<li><code>git lg</code> to display the git log with committer name from <code>.gitsigners</code> that corresponds to the public key</li>
<li><code>git graph</code> to graph the commit tree with the committer name from <code>.gitsigners</code> that corresponds to the public key</li>
<li><code>git alias</code> to display the git aliases.</li>
<li><code>git utcmt</code> to make a commit without revealing your time zone.</li>
</ol>
<p><a href="./RELEASE_NOTES.html">Pre alpha release</a>, which means it does not yet work even well
enough for it to be apparent what it would do if it did work.</p>
<p style="background-color: #ccffcc; font-size: 80%;"><a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/80x15.png" /></a>&nbsp;reaction.la gpg key 154588427F2709CD9D7146B01C99BB982002C39F<br />This work is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</p>
</body>
</html>

52
RELEASE_NOTES.html Normal file
View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Release Notes</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="docs/pandoc_templates/style.css" />
<link rel="shortcut icon" href="docs/rho.ico">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="logo-header">
<a href="docs/manifesto/motivation.html">
<img src="docs/pandoc_templates/logo.svg" id="logo-graphic" alt="logo">
<div style="height:18px;"></div>
<div id="Rhocoin"></div>
</a>
</div>
<div class="button-bar">
<a href="README.html">readme</a>
<a href="LICENSE.html">license</a>
<a href="NOTICE.html">notice</a>
<a href="RELEASE_NOTES.html">release notes</a>
</div>
<header id="title-block-header">
<h1 class="title">Release Notes</h1>
<p>To build and run <a href="./README.html">README</a></p>
<p><a href="docs/index.htm">pre alpha documentation (mostly a wish list)</a> (In order to read these on this local system, you must first execute the document build script <code>mkdocs.sh</code>, with <code>bash</code>, <code>sed</code> and <code>pandoc</code>)</p>
<p>This software is pre alpha and should not yet be released. It does
not work well enough to even show what it would do if it was
working</p>
<p style="background-color: #ccffcc; font-size: 80%;"><a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/80x15.png" /></a>&nbsp;reaction.la gpg key 154588427F2709CD9D7146B01C99BB982002C39F<br />This work is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</p>
</body>
</html>

View File

@ -26,7 +26,7 @@ $endfor$
<link rel="shortcut icon" href="$targetDocroot$rho.ico"> <link rel="shortcut icon" href="$targetDocroot$rho.ico">
$for(header-includes)$ $for(header-includes)$
$endfor$ $endfor$
$header-includes$ $header-includes$
$if(math)$ $if(math)$
$if(mathjax)$ $if(mathjax)$
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>

View File

@ -257,4 +257,43 @@ Setup is also decribed as ridiculously easy -- compare and contrast with much gr
And the huge disadvantage that it only exists for Nix 23.05, while the latest "stable" (not very stable at all) release is 24.05 And the huge disadvantage that it only exists for Nix 23.05, while the latest "stable" (not very stable at all) release is 24.05
It also has only a minimal nginx setup. Not at all sure what will happen when I combine it with a real nginx setup. It also has only a minimal nginx setup. Not at all sure what will happen when I combine it with a real nginx setup.
We have to pin to a particular release: The following code is an example of such pinning
```nix
{ config, pkgs, ... }: {
imports = [
# builtins.fetchTarbll pins Nixos to a particular release, prevents the lastest release (24.05)from being default installed.
(builtins.fetchTarball {
# Pick a release version you are interested in and set its hash, e.g.
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-23.05/nixos-mailserver-nixos-23.05.tar.gz";
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
# release="nixos-23.05"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
sha256 = "0000000000000000000000000000000000000000000000000000";
})
];
mailserver = {
enable = true;
fqdn = "mail.example.com";
domains = [ "example.com" ];
# A list of all login accounts. To create the password hashes, use
# nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
loginAccounts = {
"user1@example.com" = {
hashedPasswordFile = "/a/file/containing/a/hashed/password";
aliases = ["postmaster@example.com"];
};
"user2@example.com" = { ... };
};
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
# down nginx and opens port 80.
certificateScheme = "acme-nginx";
};
security.acme.acceptTerms = true;
security.acme.defaults.email = "security@example.com";
}
```

View File

@ -3073,13 +3073,21 @@ directory url (with no trailing backslash).
### Git Daemon ### Git Daemon
Now integrated into Git, needs no separate install.
When correctly set up, the url for repo foo.git is `git://host/foo`
git-daemon will listen on port 9418. By default, it will allow access to any directory that looks like a git directory and contains the magic file git-daemon-export-ok. git-daemon will listen on port 9418. By default, it will allow access to any directory that looks like a git directory and contains the magic file git-daemon-export-ok.
This is by far the simplest and most direct way of allowing the world to get at your git repository. This is by far the simplest and most direct way of allowing the world to get at your git repository.
[Git documentation for Git daemon](https://git-scm.com/docs/git-daemon)
[Git Book for Git daemon](https://git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon)
### Gitweb ### Gitweb
Does much the same thing has git-daemon, makes your repository public with a Does much the same thing as git-daemon, makes your repository public with a
prettier user interface, and somewhat less efficient protocol. prettier user interface, and somewhat less efficient protocol.
Gitweb provides a great deal of UI for viewing and interacting with your Gitweb provides a great deal of UI for viewing and interacting with your

View File

@ -1,29 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEX1SfJRYJKwYBBAHaRw8BAQdAcXlEHKWZNw9o2Fj5ssAjCmsbthDz0DVzYKxF
pnwiDjm0JENoZW5nIFNoZW5nIDxDaGVuZ1NoZW5nQGZha2VtYWlsLmNoPoiQBBMW
CAA4AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEECW6uFvuNYuddJDGZvESC
5JZzcRwFAmH4/lYACgkQvESC5JZzcRxRcAEA2uPehywNxbp9DON0CJ578vbmX7qt
OmDjsHovsQ5I1W8BAMbQyOcIRYQlPTijl3I/R4sWLZ9hEYIbP+FS3JtbDYAFiJAE
ExYIADgWIQQJbq4W+41i510kMZm8RILklnNxHAUCX1SfJQIbAwULCQgHAgYVCgkI
CwIEFgIDAQIeAQIXgAAKCRC8RILklnNxHPteAQDFs4dbz7I1a5VoKXMupmSW3MMP
uHChIilz9P2JYX6oOAEAx4+tmu7DIGwBgNQZKuxlVgWYavkuEGYkLYdGgIBpwQi4
OARfVJ8lEgorBgEEAZdVAQUBAQdATTzhgBNNONqRkUDfj/dtps9n+BvZMcS1t6cD
tjLejT0DAQgHiHgEGBYIACAWIQQJbq4W+41i510kMZm8RILklnNxHAUCX1SfJQIb
DAAKCRC8RILklnNxHPB4AP4kKI590T81yFAEkcfKA3fFRxcDJwUqus2L4GpckyMq
ngEAv9viVp3aHvlXZMpQ4prvzC/Gpzs3TrsDXWEhg5PzDA+4MwRhhoZwFgkrBgEE
AdpHDwEBB0CuAAgmkYQetnz3BJ0ALBuVKn1aeBjMq+1sPKeyUDnjWIjvBBgWCAAg
FiEECW6uFvuNYuddJDGZvESC5JZzcRwFAmGGhnACGyIAgQkQvESC5JZzcRx2IAQZ
FggAHRYhBCuf+rsp/waNpunfl1ccOpw7nm/KBQJhhoZwAAoJEFccOpw7nm/KjykA
/2TcUdtOXUCRJsM+SvoG3xWjk7iCOuSTWsUkap9ha6daAQD2hLRL9/Z6c2mREKXz
7nR416Cs1YUACs98wTD5pBuYAk76AP9vr+uVoKbjf/q230SBNen2Hjhk8g+JD4Cu
ZpFKuVwZhQEAopykWKujX5dGU/1352QrUcoCVYbTMiXGIxL9CPrUzw+4MwRh2A+7
FgkrBgEEAdpHDwEBB0A9rVFSCmvpkkeSCmB+PDYqnJsz7Fq0b9NkN87xQ854i4j1
BBgWCAAmFiEECW6uFvuNYuddJDGZvESC5JZzcRwFAmHYD7sCGyIFCQHhM4AAgQkQ
vESC5JZzcRx2IAQZFggAHRYhBIDfnjfH6rZKSICJDtUTAeF2sxgoBQJh2A+7AAoJ
ENUTAeF2sxgogxsBAMAV8d12lHhnL64qbG+llKJKEXI1ZTSHLEcdXN5dOo6zAP9j
Na3cNcEwxreUlgUZhOjagxrMnGpd5l/pHVG/7ijECa/8AQDpNtaC1G/6bIwpekky
KdbZtliClpajSD7zoj2Bxe24nAD/TSwGmXzqr9+VeOctO/m6q+QKwFa3mGyOUWpp
oTNQfA0=
=Kusp
-----END PGP PUBLIC KEY BLOCK-----

@ -1 +1 @@
Subproject commit aff2cd0190c1b87e98862209a6a5c1b3c918c028 Subproject commit 8037402f847136a279e80f3813113aad7fac506f