diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..a01250e --- /dev/null +++ b/404.html @@ -0,0 +1,842 @@ + + + + + + + + + + + + + + + + + + Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..bbae553 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +jamdocs.org diff --git a/FAQ/index.html b/FAQ/index.html new file mode 100644 index 0000000..7baaf26 --- /dev/null +++ b/FAQ/index.html @@ -0,0 +1,1195 @@ + + + + + + + + + + + + + + + + + + + + + + FAQ - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

FAQ

+

Have a question that is not listed here? Let us know!

+

Contributing

+

Frequently Asked Questions

+

This FAQ compiles questions that relate to Jam in particular. For things related +to JoinMarket in general, please refer to the JoinMarket documentation.

+

How much can I earn?

+

Earning sats entails providing liquidity to other market participants. +Consequently, how much you can earn depends on multiple factors, market +conditions and liquidity size being two of them. In general, the more liquidity +you provide, the more you can earn. That being said, you are competing in an +open market, and because competition is global and only constraint by market +forces, the margin is usually thin.

+

If your offers are not taken by market participants, your offer might be too +expensive. Check the order book and compare your offer to the +market price. If your offer is competitive and is still ignored, make sure to +create a Fidelity Bond, which signals that you are a serious market +participant and not a malicious entity.

+

See also "a few words about incentives" from the JoinMarket +documentation.

+

How high are the fees that I do have to pay?

+

The amount of fees you have to pay depends on market and blockspace +conditions. They are dictated by supply and demand, both for collaborative +transactions and single user transactions.

+

Market makers provide liquidity and set the fee they want to earn, +either in absolute or percentage terms. Market takers have to agree +to take these offers voluntarily. Check the orderbook to get an +up-to-date overview of the current fee market.

+

In addition to these fees, you will have to pay mining fees for you and the makers. Mining fees depend +on how many transactions are currently in the mempool. Inspect your +mempool or use a public site like mempool.space to do a fee estimation.

+
+

Hint

+

We recommended that you run your own mempool.space +instance on your full node.

+
+

See also "a note on fees" from the JoinMarket documentation.

+

I'm getting an error when trying to open the wallet

+

The following error can pop up in case JoinMarket didnt't shut down cleanly:

+
wallet.jmdat cannot be created/opened, it is locked.
+
+
+

Warning

+

Make sure that you have written down your wallet seed before executing +any command

+
+

You can resolve this by manually deleting the wallet .lock file as explained +in issue #173.

+

Why is my collaborative transaction taking so long?

+

This can have multiple reasons. Tor or general network connection issues, +participants not responding in a timely manner, missing requirements to +source commitments (see the docs), period of slow +block production, unexpected increase of transaction fees, etc.

+

For a better assessment, the following can be taken as a guideline:

+
    +
  • single collaborative transactions generally take only a few minutes (<15min)
  • +
  • a scheduled sweep can take hours, even days (<3days)
  • +
+

If an operation takes longer than that, then there might be a different issue. +See "Something else is/seems stuck" for more info.

+

Something else is/seems stuck; what can I do?

+

If a single collaborative transaction takes hours, or if your +scheduled sweep already takes over three days, there might be a different +underlying problem.

+

A general rule of thumb is: Any operation either succeeds or fails. +If an operation is aborted prematurely, there is no danger of loss of funds.

+

All operations can be aborted by locking your wallet.

+

Since Jam does not yet have a way to provide fine grained error information to users, +it is always a good idea to inspect the log files for warning and error messages.

+

How do I view the log file?

+

If you are running Jam with one of the supported integrations (RaspiBlitz, +Citadel, Umbrel, etc.) chances are you can view the logs inside the app +(See Settings > Show logs).

+

If the option is not displayed, or if you run the standalone docker image +yourself, you can find all log files inside the container in directory +/var/log/jam/. See jmwalletd_stdout.log or jmwalletd_stderr.log for +problems with Jam.

+

e.g. tail -n 200 -f /var/log/jam/jmwalletd_stdout.log

+

If you run JoinMarket natively, you can find the logs files inside the logs +folder of JoinMarket's working directory (e.g. /home/<user>/.joinmarket/logs)

+

e.g. tail -n 200 -f /home/user/.joinmarket/logs/jmwalletd_logs.log

+

How to resolve "No connection to gateway"?

+

This can have several reasons and basically means that the UI cannot reach the backend service. +Depending on your installation (native setup, docker images, +local/remote hosts, etc.), there are a number of things you should verify.

+

Please make sure that:

+
    +
  • Your Bitcoin Core instance is up and running, fully synced and is accepting RPC requests.
  • +
+
bitcoin-cli getblockchaininfo
+
+
    +
  • The backend service is running and is reachable on the specified ports. + Verify that you get a response from the server, by executing a request + on the host that is running your JoinMarket instance (if you run an Umbrel node, + this requests needs to be executed inside the Jam docker container):
  • +
+
curl --insecure https://127.0.0.1:28183/api/v1/session
+
+
    +
  • +

    Check the logs for any errors or warnings.

    +
  • +
  • +

    If all the above fails, try restarting every service or do a complete node reboot.

    +
  • +
  • +

    As a last resort, seek help in the support channel.

    +
  • +
+

Can I import an existing wallet?

+

Yes, it is possible to import an existing wallet. +However, not yet via the web interface, but with a few manual steps via the command line.

+
    +
  • Log into the host machine, e.g. with ssh (see an example for Umbrel below)
  • +
  • Navigate to JoinMarket's root directory
  • +
  • Invoke the recover mechansim of the wallet-tool.py script
  • +
+
. jmvenv/bin/activate # if virtual environment is enabled
+python3 scripts/wallet-tool.py recover --gap-limit=200 --recoversync
+
+
    +
  • Answer questions (provide seed phrase, etc.). Make sure that you put ".jmdat" +at the end of the name for the wallet, otherwise it won't be displayed in Jam. +Answer the question for support of fidelity bonds with "y" (yes).
  • +
+
root@821939a90a7c:/src# python3 scripts/wallet-tool.py recover --gap-limit=200 --recoversync
+User data location: /root/.joinmarket/
+Input mnemonic recovery phrase: zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong
+Input mnemonic extension, leave blank if there isnt one: 
+Enter new passphrase to encrypt wallet: 
+Reenter new passphrase to encrypt wallet: 
+Input wallet file name (default: wallet.jmdat): recover.jmdat
+Would you like this wallet to support fidelity bonds? write 'n' if you don't know what this is (y/n): y
+Write down this wallet recovery mnemonic
+
+zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong
+
+Recovered wallet OK
+
+
    +
  • All done.
  • +
+

Here is an example of how you'd get into the Jam container on Umbrel:

+
    +
  • Log into your umbrel with ssh umbrel@umbrel.local
  • +
  • Move into the jam container with docker exec -it jam_web_1 bash
  • +
  • Navigate to JoinMarket's root directory with cd /src
  • +
  • Now follow the import procedure as explained above
  • +
  • Leave the command line with exit (multiple times)
  • +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/about/index.html b/about/index.html new file mode 100644 index 0000000..9cac0b4 --- /dev/null +++ b/about/index.html @@ -0,0 +1,999 @@ + + + + + + + + + + + + + + + + + + + + + + About - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

About

+

Jam is a graphical user interface for JoinMarket, and while obviously related, +is a separate project developed by a separate set of people.

+

About Jam

+

Jam is a free and open-source project that aims to improve the +financial privacy of yourself and others, without relying on a trusted third +party. It was started in 2021 by various volunteers and is still +developed and maintained on a volunteer basis. As mentioned above, Jam is a +front-end for JoinMarket, a privacy-focused bitcoin software that uses a +peer-to-peer marketplace to facilitate collaborative transactions.

+

The goal of Jam is to provide an interface that makes JoinMarket easier to use, +and thus more easily accessible for more people.

+

About JoinMarket

+

JoinMarket is a special kind of software that is aimed at improving the privacy +and fungibility of bitcoin transactions. The main way to improve privacy and +fungibility on-chain is via collaborative transactions.

+

A collaborative transaction requires the coordination of multiple parties. The +right resources (UTXOs) have to be available in the right quantity +at the right time.

+

Consequently, the problem that needs to be solved is not a technological +problem, but an economic problem. JoinMarket solves this problem not by central +coordination, but by creating a market that allows participants to allocate +these resources in the best way, according to their individual needs.

+

About the Name

+

The name "Jam" is a backronym, stands for JoinMarket's Awesome, Man, +and shouldn't be taken too seriously. However, it works on multiple levels +(Let's jam the signal!) and "cooking jam" is also a fun metaphor for mixing +something in a tasty way (and putting it in jars).

+

+ +

+

About the Philosophy

+

We believe that, in the long run, open protocols will survive. Platforms, on the +other hand, are run by companies and all companies eventually go bankrupt.

+

The motivation behind Jam (and JoinMarket—and Bitcoin, for that matter) is to +build something that doesn't go away.

+

Motivation

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/change.png b/assets/change.png new file mode 100644 index 0000000..e150abe Binary files /dev/null and b/assets/change.png differ diff --git a/assets/citadel.png b/assets/citadel.png new file mode 100644 index 0000000..9fa4b1e Binary files /dev/null and b/assets/citadel.png differ diff --git a/assets/collaborative-tx.png b/assets/collaborative-tx.png new file mode 100644 index 0000000..31d1e32 Binary files /dev/null and b/assets/collaborative-tx.png differ diff --git a/assets/genesis-dark.png b/assets/genesis-dark.png new file mode 100644 index 0000000..2a51b52 Binary files /dev/null and b/assets/genesis-dark.png differ diff --git a/assets/genesis-light.png b/assets/genesis-light.png new file mode 100644 index 0000000..7c4c40c Binary files /dev/null and b/assets/genesis-light.png differ diff --git a/assets/github-checkmark.png b/assets/github-checkmark.png new file mode 100644 index 0000000..86b103a Binary files /dev/null and b/assets/github-checkmark.png differ diff --git a/assets/github-checkmark.svg b/assets/github-checkmark.svg new file mode 100644 index 0000000..2857dc0 --- /dev/null +++ b/assets/github-checkmark.svg @@ -0,0 +1,42 @@ + + diff --git a/assets/github-verified.png b/assets/github-verified.png new file mode 100644 index 0000000..889e2a8 Binary files /dev/null and b/assets/github-verified.png differ diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/interface/cheatsheet-light.png b/assets/interface/cheatsheet-light.png new file mode 100644 index 0000000..ad69e27 Binary files /dev/null and b/assets/interface/cheatsheet-light.png differ diff --git a/assets/interface/cheatsheet.png b/assets/interface/cheatsheet.png new file mode 100644 index 0000000..fda320c Binary files /dev/null and b/assets/interface/cheatsheet.png differ diff --git a/assets/interface/earn-light.png b/assets/interface/earn-light.png new file mode 100644 index 0000000..62b4e6e Binary files /dev/null and b/assets/interface/earn-light.png differ diff --git a/assets/interface/earn.png b/assets/interface/earn.png new file mode 100644 index 0000000..2dd9e3c Binary files /dev/null and b/assets/interface/earn.png differ diff --git a/assets/interface/fb01-time-light.png b/assets/interface/fb01-time-light.png new file mode 100644 index 0000000..a7a9dd7 Binary files /dev/null and b/assets/interface/fb01-time-light.png differ diff --git a/assets/interface/fb01-time.png b/assets/interface/fb01-time.png new file mode 100644 index 0000000..3e2ff5b Binary files /dev/null and b/assets/interface/fb01-time.png differ diff --git a/assets/interface/fb02-jar-light.png b/assets/interface/fb02-jar-light.png new file mode 100644 index 0000000..c8bfef1 Binary files /dev/null and b/assets/interface/fb02-jar-light.png differ diff --git a/assets/interface/fb02-jar.png b/assets/interface/fb02-jar.png new file mode 100644 index 0000000..c702fe5 Binary files /dev/null and b/assets/interface/fb02-jar.png differ diff --git a/assets/interface/fb03-utxos-light.png b/assets/interface/fb03-utxos-light.png new file mode 100644 index 0000000..99603e7 Binary files /dev/null and b/assets/interface/fb03-utxos-light.png differ diff --git a/assets/interface/fb03-utxos.png b/assets/interface/fb03-utxos.png new file mode 100644 index 0000000..9e065e2 Binary files /dev/null and b/assets/interface/fb03-utxos.png differ diff --git a/assets/interface/fb04-frozen-light.png b/assets/interface/fb04-frozen-light.png new file mode 100644 index 0000000..38c3067 Binary files /dev/null and b/assets/interface/fb04-frozen-light.png differ diff --git a/assets/interface/fb04-frozen.png b/assets/interface/fb04-frozen.png new file mode 100644 index 0000000..213d38c Binary files /dev/null and b/assets/interface/fb04-frozen.png differ diff --git a/assets/interface/fb05-overview-light.png b/assets/interface/fb05-overview-light.png new file mode 100644 index 0000000..7e07e05 Binary files /dev/null and b/assets/interface/fb05-overview-light.png differ diff --git a/assets/interface/fb05-overview.png b/assets/interface/fb05-overview.png new file mode 100644 index 0000000..8f985c5 Binary files /dev/null and b/assets/interface/fb05-overview.png differ diff --git a/assets/interface/jam-light.png b/assets/interface/jam-light.png new file mode 100644 index 0000000..9eec39f Binary files /dev/null and b/assets/interface/jam-light.png differ diff --git a/assets/interface/jam-running-light.png b/assets/interface/jam-running-light.png new file mode 100644 index 0000000..ec33fcd Binary files /dev/null and b/assets/interface/jam-running-light.png differ diff --git a/assets/interface/jam-running.png b/assets/interface/jam-running.png new file mode 100644 index 0000000..7fb472c Binary files /dev/null and b/assets/interface/jam-running.png differ diff --git a/assets/interface/jam.png b/assets/interface/jam.png new file mode 100644 index 0000000..3e78ccf Binary files /dev/null and b/assets/interface/jam.png differ diff --git a/assets/interface/receive-light.png b/assets/interface/receive-light.png new file mode 100644 index 0000000..e1fd3e8 Binary files /dev/null and b/assets/interface/receive-light.png differ diff --git a/assets/interface/receive.png b/assets/interface/receive.png new file mode 100644 index 0000000..698218d Binary files /dev/null and b/assets/interface/receive.png differ diff --git a/assets/interface/send-light.png b/assets/interface/send-light.png new file mode 100644 index 0000000..27bcf87 Binary files /dev/null and b/assets/interface/send-light.png differ diff --git a/assets/interface/send.png b/assets/interface/send.png new file mode 100644 index 0000000..6f5c3d4 Binary files /dev/null and b/assets/interface/send.png differ diff --git a/assets/interface/settings-light.png b/assets/interface/settings-light.png new file mode 100644 index 0000000..de226c2 Binary files /dev/null and b/assets/interface/settings-light.png differ diff --git a/assets/interface/settings.png b/assets/interface/settings.png new file mode 100644 index 0000000..796a711 Binary files /dev/null and b/assets/interface/settings.png differ diff --git a/assets/interface/wallet-jars-light.png b/assets/interface/wallet-jars-light.png new file mode 100644 index 0000000..48486ad Binary files /dev/null and b/assets/interface/wallet-jars-light.png differ diff --git a/assets/interface/wallet-jars.png b/assets/interface/wallet-jars.png new file mode 100644 index 0000000..5ca7d15 Binary files /dev/null and b/assets/interface/wallet-jars.png differ diff --git a/assets/interface/wallet-light.png b/assets/interface/wallet-light.png new file mode 100644 index 0000000..b95e4ce Binary files /dev/null and b/assets/interface/wallet-light.png differ diff --git a/assets/interface/wallet.png b/assets/interface/wallet.png new file mode 100644 index 0000000..4dcf7e9 Binary files /dev/null and b/assets/interface/wallet.png differ diff --git a/assets/jam-flow.png b/assets/jam-flow.png new file mode 100644 index 0000000..a8e2f8f Binary files /dev/null and b/assets/jam-flow.png differ diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 0000000..b20ec68 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Contributing

+

There are many ways you can contribute: testing, sharing ideas, writing +documentation, creating tutorials, and—of course—writing code.

+

Say Hello

+

It doesn't hurt to say hi and connect with the people that are already working +on Jam, or have worked on it in the past.

+

Matrix Room

+

Telegram Chat

+

Study the Basics

+

Identity and privacy are complex topics in general, and Bitcoin privacy is +particularly tricky. Make sure to familiarise yourself with the basics before +you get involved.

+

Privacy Fundamentals

+

Bitcoin Wiki: Privacy

+

Understand the Philosophy

+

Before you really get going you should understand the philosophy behind Jam and +the foundations it is built upon.

+

Motivation

+

A Cypherpunk's Manifesto

+

What to Work On

+

While a very rough roadmap and some milestones exist, it's usually +best to "scratch your own itch." Found a bug? Fix it! Have a proposal to make +something better? Create an issue! Found a typo? Fix it! Is Jam not available in +your language? Translate it!

+

It can be daunting to get started, but Jam, like every software project, is just +code & design & text.

+

Code

+

Review a pull request or work on some open issues. +Small tasks that are relatively easy to do will have the +"good first issue" label.

+

Design

+

Have a look at the Figma files, comment on them, or propose +a change.

+

Text

+

If you're good with words and copy editing, or if you want to help to +translate Jam into multiple languages, join the translation team.

+

Just Get Started!

+

Since all development happens out in the open and there are no gatekeepers, +getting involved is as easy as showing up.

+

This is a free and open-source software project and we love +receiving pull-requests, bug reports, ideas, and feedback from everyone. See the +CONTRIBUTING.md file on GitHub for more details on how to get started +participating in this project.

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/css/blockquote-cite.css b/css/blockquote-cite.css new file mode 100644 index 0000000..18451ab --- /dev/null +++ b/css/blockquote-cite.css @@ -0,0 +1,3 @@ +blockquote cite:before { + content: ' —'; +} diff --git a/css/external-links.css b/css/external-links.css new file mode 100644 index 0000000..09d47f8 --- /dev/null +++ b/css/external-links.css @@ -0,0 +1,4 @@ +a[target='_blank']:after { + content: ' \f08e'; + font-family: 'FontAwesome'; +} diff --git a/glossary/index.html b/glossary/index.html new file mode 100644 index 0000000..697d706 --- /dev/null +++ b/glossary/index.html @@ -0,0 +1,2224 @@ + + + + + + + + + + + + + + + + + + + + + + Glossary - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Glossary

+

Unfortunately, there is no way to talk about bitcoin privacy and the intricacies +of JoinMarket without a little bit of jargon.

+

This glossary explains some of the concepts and terms used in Jam.

+
+

+[ +A · +B · +C · +D · +E · +F · +G · +H · +I · +J · +K · +L · +M · +N · +O · +P · +Q · +R · +S · +T · +U · +V · +W · +X · +Y · +Z +] +

+
+

A

+

Address

+

A bitcoin address—also called bitcoin invoice address1—is a string of +characters that you send to someone else to receive funds.

+

There are currently three invoice address formats in use:

+ +

For more details please refer to the Bitcoin Wiki. Jam defaults to +Bech32 addresses.

+

Address Reuse

+

Address reuse refers to the practice of reusing a single bitcoin invoice +address for multiple transactions. It is highly discouraged since it +harms the privacy of yourself and others. You should never reuse addresses.

+

Bitcoin Wiki: Address Reuse

+

Anonymity Set

+

The only way to hide in plain sight is by hiding in a crowd. The anonymity set +is simply the size of this crowd.

+

If you are putting on a hat and sunglasses to hide in a crowd of people that are +wearing the same hat and sunglasses, your anonymity set is the size of this +crowd. If said crowd is 50 people, an attacker could mistake you for anyone out +of these 50 people. Similarly, when doing a collaborative +transaction in bitcoin, you are creating an +onchain footprint that is equivalent to the onchain footprint of +others.

+

B

+

Base Layer

+

Bitcoin's base layer (or Layer 1) refers to any transaction +that touches the timechain, i.e. all onchain +transactions. The base layer is concerned with global consensus and settlement.

+

Higher layers build ontop the settlement assurrances of the base layer. One +example of a Layer 2 system is the Lightning Network. All money is layered, +including gold and fiat monies. Read Layered Money by Nik Bhatia to understand +this in more detail.

+

Layered Money

+

Batch Transaction

+

A batch transaction is a transaction that combines multiple real-world +transactions into one on-chain transaction. It has multiple inputs and multiple +outputs. Different parties may control one or multiple inputs and receive one or +multiple outputs.

+

Privacy Fundamentals

+

Bech32

+

Bech32 is an invoice address format. It was specified in BIP +173 and is used for both SegWit and Taproot addresses.

+

Blockchain

+

A mostly meaningless marketing term used to confuse newcomers. While "block +chain" is still the main term used to refer to Bitcoin's linked +data structure of blocks, it has increasingly become meaningless over the years +as it got co-opted by grifters, charlatans & marketers. A better, more +descriptive term of said data structure is timechain.

+

C

+

Chain Analysis

+

Chain analysis is is the practice of applying heuristics to a +timechain's public transaction graph. The goal of chain analysis +is to link the pseudonymous identities created by bitcoin software with "real" +identities corresponding to natural persons or entities.

+

Chain analysis is based on flawed assumptions, because ownership in bitcoin is +defined by secret knowledge, not possession. Identities can only be linked +probabilistically, not provably. One of the main assumptions used by chain +analysis companies is the common input ownership +heuristic. Collaborative transactions break +this heuristic.

+

CoinJoin

+

A CoinJoin is a collaborative transaction that combines inputs from multiple +parties. The purpose of a CoinJoin is to combine inputs and create outputs in +ways that improves the financial privacy of participants, without relying on a +trusted third party for custody. When done correctly, a CoinJoin breaks any +deterministic links between transactions, moving the process of chain +analysis from quasi-deterministic with high certainty to +probabilistic with low certainty.

+

CoinJoins break the common input ownership +heuristic that is used by chain analysis +companies to de-anonymize actors. The concept was 1st introduced in 2011 by Bitcointalk user hashcoin2, but later popularised in 2013 by Gregory Maxwell.34

+

All CoinJoin transactions are collaborative transactions. The two main types of +CoinJoin transactions are equal-output and +unequal-output CoinJoins. Other differences might be interactivity (or lack +thereof) and number of participants.

+

Collaborative Transaction

+

A collaborative transaction is a bitcoin transaction that is initiated and +signed by multiple participants. A collaborative transaction involves two or +more parties and is thus always a batch transaction. All +CoinJoins are collaborative transactions.

+

Change

+

When using physical cash, spending a $100 bill to pay for a $25 item, you will +get $75 back in change. The reason for this is that you can't spend just a part +of the bill, because ripping off a quarter of it for payment will invalidate the +bill. Consequently, when bills change hands, the whole bill has to be spent, and +an appropriate amount of change goes back to the spender.

+

Bitcoin works the same way. When sats change hands, the spender has to spend the +whole UTXO. Bitcoin creates the appropriate amount of change +automatically. Because all transactions are recorded transparently and publicly on the timechain,

+

As of this writing,5 a simple spend is +the most common transaction type, which describes the example given above: one +input ($100 bill) produces two outputs: $25 for the merchant, and $75 in change. +The act of an outside observer guessing whether you bought something for $25 or +$75 (or: who was the customer of the transaction, and who was the merchant) is +what is called change detection.

+

Change Detection

+

When it comes to chain analysis, change detection is the name +of the game. The goal of chain analysis companies is to link identities to +transactions, and to do that, one has to detect whether funds changed hands or not.

+

Technically speaking, change detection is trying to figure out which output of a +transaction is a change output. Change detection is based on various heuristics. +False positives will always exist, even if the transaction under scrutiny is a +simple spend. Consequently, it is more an art than a science.

+

To quote one special investigations team speaking on chain analysis:

+
+

Attributing ownership, however, is often nuanced because outside observers can +only infer it depending on factors such as availability and quality of the +evidence. Evidence means proof that indeed an address belongs to an individual +or entity. Unless you own an address yourself, it is very difficult to say +with absolute certainty who an address is owned by. This is why it’s more +fitting to consider blockchain analytics more of an art than science.

+

CSIT

+
+

Keep in mind that ownership can change without any on-chain transaction +happening, e.g. by passing on a private key directly. It is also possible that +amount to be paid lines up perfectly with a single UTXO, meaning that what looks +like a self-spend is actually a payment.

+

One can only conclude, as is also mentioned in the report linked above, that "an +external observer cannot possibly gain a full picture or claim 100% confidence +in ownership attribution."

+

Privacy Fundamentals: The Bitcoin Transaction

+

Bitcoin Wiki: Change Detection

+

CIOH

+

Short for Common Input Ownership Heuristic.

+

Common Input Ownership Heuristic

+

The common input ownership heuristic assumes that all inputs of a transaction +are controlled by a single entity. This assumption is clearly wrong, because +collaborative transactions exist. +CoinJoin transactions are designed to break this heuristic.

+

D

+

Doxxic Change

+

"Doxxic" change is any leftover change that is going back to you when +participating in an equal-output CoinJoin. Doxxic +change is problematic because it can potentially destroy any privacy benefits +gained from a CoinJoin.

+

The word is a combination of "toxic" and "doxxing." Doxxing is the act of finding +out the legal identity (or similar identifiying information) of a pseudonymous +entity. Bitcoin is a pseudonymous system and does not require the True +Names6 of participants.

+

You can use the sweep functionality to avoid doxxic +change in Jam.

+

E

+

Eclipse Attack

+

An eclipse attack is an attack in networked systems in which an attacker targets +a node to convince it of a false network state. The attacker surrounds the node +in order to conceal or block off accurate information, leaving the attacked +node(s) in the dark in terms of the global network state.

+

An eclipse attack is similar to a Sybil attack.

+

Bitcoin Stack Exchange: Eclipse Attack vs. Sybil Attack

+

Equal-Output CoinJoin

+

An equal-output CoinJoin is a collaborative transaction that produces outputs of +equal denomination, i.e. outputs of equal value when measured in sats. For this +reason, these types of transactions are also referred to as equal-amount or +equal-value CoinJoin transactions.

+

Equal-output CoinJoins are batch transaction that are +easily identifiable on-chain due to their uniform output structure.

+

Like any collaborative transaction, an equal-output CoinJoin breaks the Common +Input Ownership Heuristic. Participating in +such a transaction allows you to gain privacy by "hiding in the crowd."

+

Jam defaults to collaborative transactions when sending and +sweeping, creating equal-output CoinJoins.

+

F

+

Fidelity Bond

+

A fidelity bond is an insurance policies which protects the policyholder from +wrongful acts committed by others. The term comes from the world of business and +finance, thus the policyholders are usually companies, and the other parties are +usually employees.

+

In JoinMarket, a fidelity bond is a mechanism which ensures that market actors +act honestly. It is a protection mechanism against Sybil +attacks, because a fidelity bond makes the creation of +cryptographic identities costly.

+
+

Warning

+

It is impossible to move or spend funds that are locked in a fidelity bond +before the bond expires. They cannot be used in collaborative transactions +(neither as taker nor as maker) +as fidelity bonds are time-locked by the Bitcoin protocol.

+
+

Fidelity bonds improve the privacy guarantees of the whole system and increase +your chance of being chosen as a market maker drastically.

+

What Are Fidelity Bonds and How Do They Work in JoinMarket?

+

JoinMarket: Fidelity Bonds

+

JoinMarket: Financial Mathematics of Fidelity Bonds

+

Creating a Fidelity Bond in Jam

+

J

+

Jam

+

Jam is both the name of the project and the verb we use when a +collaborative transaction is in progress.

+
+

Sir! The radar, sir! It appears to be... [Jam starts flowing through the +computer screen] jammed!

+

Spaceballs

+
+

About

+

jamapp.org

+

Jar

+

In Jam, a "jar" is a container that holds some sats of yours.7 Jars +exist to segregate your sats into multiple buckets that are disconnected from +each other, which aids privacy. To not risk any privacy degradation, you can +only spend from one jar at a time.

+

There are 5 jars by default. The default jar to receive funds is Jar A.

+

M

+

Maker

+

A market maker is someone who offers bitcoin liquidity to the market, to be used by +others for collaborative transactions. You can create an offer via the "Earn" +tab and become a market maker.

+

Earn Screen

+

The Maker Role

+

Mempool

+

Short for 'memory pool.' A pool of valid bitcoin transactions +held by each node, that are not yet confirmed in the timechain.

+

Mempool

+

O

+

Offchain

+

An offchain (or off-chain) transaction is any transaction that does not happen +onchain. Examples include transactions on the Lightning network, the +handing over of physical private keys, as well as transactions on centralized +ledgers such as exchanges and other trusted third parties.

+

Some offchain transactions, such as handing over private keys on USB sticks or +similar, are outside of the scope of chain analysis. +Consequently, chain analysis can never be completely accurate.

+

Onchain

+

An onchain (or on-chain) transaction is a bitcoin transaction that is settled on +the bitcoin timechain. The analysis of these transactions is +called chain analysis, which is the spying on and +de-anonymizing of bitcoin's users by trying to find patterns in the onchain +data.

+

P

+

P2PKH

+

Short for pay-to-public-key-hash.

+

Learn Me A Bitcoin: P2PKH

+

P2SH

+

Short for pay-to-script-hash.

+

Learn Me A Bitcoin: P2SH

+

PayJoin

+

A PayJoin is a collaborative transaction between two parties that facilitates an +actual payment for a good or service. The merchant agrees to provide one or +multiple inputs to the transaction, increasing the privacy of both parties.

+

A PayJoin has different onchain characteristics than an +equal-output CoinJoin and is not detectable via chain +analysis alone. A PayJoin transaction has multiple +interpretations, all of which are equally valid. In addition to breaking the +common input ownership heuristic it poisons +the basis of all chain analysis, because of its +undetectability.

+

Bitcoin Wiki: PayJoin

+

Bitcoin Wiki: PayJoin Adoption

+

S

+

Sats

+

Short for satoshis, plural of sat (satoshi).

+

A sat the smallest fraction of a bitcoin that can be expressed +on-chain. There are 100,000,000 sats in a bitcoin. There are +multiple currency symbols for a sat emerging. In Jam, the sat +symbol8 is used: +

+

Scheduler

+

The 'scheduler' is a component of JoinMarket which schedules multiple +collaborative transactions in a row. It will use +random intervals and amounts to make timing analysis and de-anonymization via +chain analysis more difficult.

+

The 'Sweep' screen uses the scheduler to sweep funds to one or +multiple external wallets under your control.

+

Simple Spend

+

A transaction that splits one input into two outputs: payment and change.

+

The "simple spend" is the most common bitcoin transaction type to date, since +most wallet implementations do not optimize for privacy. For most simple spend +transactions it is possible to discern which output is the actual payment or +which one is the change. This change detection makes +the tracing of funds possible.

+

Privacy Fundamentals: The Bitcoin Transaction

+

SNICKER

+

Simple Non-Interactive Coinjoin with Keys for Encryption Reused.

+

SNICKER blog post

+

Sybil Attack

+

A Sybil attack is a special kind of attack in peer-to-peer networked computing. +The victim is surrounded by malicious entities, each of which act as if they are +a separate entity. The victim believes that everything is in order, that he is +getting an accurate state of the network from multiple independent peers. In +actuality, the Sybil attacker controls all entities surrounding the victim. +Consequently, the attacker is able to trick the victim into accepting a +malicious network state.

+

JoinMarket uses fidelity bonds to protect users from Sybil attacks.

+

Design for Improving JoinMarket's Resistance to Sybil Attacks Using Fidelity Bonds

+

Wikipedia: Sybil Attack

+

Sweep

+

A 'sweep' send will transfer all funds of a jar or all funds of your wallet. To +sweep all funds from your wallet multiple transactions are created using the +scheduler.

+

'Sweep' Screen

+

T

+

Taint

+

Taint is an external property defined by chain analysis +surveillance firms. It is an attempt to trace the origin and ownership of +UTXOs, classifying their owners and building lists of "good" and "bad" +money.

+

All taint in bitcoin always is and always will be arbitrarily defined and +probabilistically applied. Just like change detection, it +is more an art than a science. It can never be done exactly. False positives and +false negatives will always arise.

+

The bitcoin network is indifferent to taint. Miners will include any transaction +in a valid block that will reward them economically. Any application of taint on +the block production level is equivalent to imposing additional rules via a +soft-fork, which fully validating nodes can reject.

+

Taker

+

A market taker is someone who buys bitcoin liquidity from the market, taking up +market makers on their offers. You can see active offers in the order +book.

+

You will automatically take offers when running the scheduler via +the "Sweep" functionality.

+

Sweep

+

Earn Screen

+

The Taker Role

+

Timechain

+

The data structure of Bitcoin's base layer. It represents a timestamped and linked list of blocks. Anyone can create a new block, but each block must have +sufficient proof of work, making it costly to create new blocks.

+

Bitcoin is Time

+

Timelock

+

A UTXO can be locked up by a script which defines that said UTXO can only be spent in a block that +is higher than a certain value. This makes UTXOs unspendable before a specific time.

+

Transaction

+

A bitcoin transaction describes the movement of sats. It is structured +data that describes inputs and outputs, among other things. A valid bitcoin +transaction has at least one input and at least one output. Every transaction +input refers to the output of a previous transaction. We say that an input +"consumes" an output. If an output is not consumed yet, we speak of an unspent +transaction output, or UTXO, for short.

+

Privacy Fundamentals: The Bitcoin Transaction

+

Bitcoin Wiki: Transaction

+

Learn Me a Bitcoin: Transactions

+

TX

+

Short for transaction.

+

U

+

Unspent Transaction Output

+

The tip of the chain of signatures which originates in a coinbase output. It's a "coin" that +has not yet been spent and can still be spend.

+

UTXO

+

Short for Unspent Transaction Output.

+
+
+
    +
  1. +

    The term invoice is proposed in BIP-179 as an alternative. 

    +
  2. +
  3. +

    Blind Bitcoin Transfers hashcoin, July 2011 

    +
  4. +
  5. +

    I taint rich! Maxwell, Jan. 2013 

    +
  6. +
  7. +

    CoinJoin: Bitcoin privacy for the real world Maxwell, Aug. 2013 

    +
  8. +
  9. +

    Block 744,811 

    +
  10. +
  11. +

    Vernor Vinge, 1981, True Names 

    +
  12. +
  13. +

    What we call "jars" are usually called "mixdepths" in JoinMarket. They are also referred to as "pockets" and "accounts" in some of the older parts of the JoinMarket documentation. 

    +
  14. +
  15. +

    satsymbol.com 

    +
  16. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..f9878a3 --- /dev/null +++ b/index.html @@ -0,0 +1,1011 @@ + + + + + + + + + + + + + + + + + + + + Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Getting Started

+

Jam is an interface for JoinMarket1, a special kind of bitcoin software that +focuses on privacy and security. The goal of Jam is to make it easier to improve +the financial privacy of yourself and others.

+
+

Warning

+

Both Jam and its documentation are a work in progress. We are writing +these docs as we progress, out in the open. If you want to help, please +do!

+
+

Contributing

+

Before You Start

+

Before you get going with Jam you should understand the "why" behind it all.

+

Motivation

+

Privacy Fundamentals

+

As mentioned above, Jam uses JoinMarket under the hood. What sets JoinMarket +apart is that it has no single point of failure. It is completely peer-to-peer, +there is no central coordinator, no "doxxic change", no company behind it all, +no marketing department, and no central entity making any money off of it.

+

All development is done by volunteers. Consequently, please heed the following +warning:

+
+

Danger

+

Jam is considered beta software. While JoinMarket is tried and tested, Jam is new and things might break. Use with caution. Please report any issues directly on GitHub.

+
+

Installation

+

The easiest way to install Jam is via one of the full-node software solutions +that includes Jam as an app or plug-in. You can also install it manually +yourself.

+

Installation

+

First Use

+

Once installed, you will have to add some funds to Jam to get going. If you are +new to JoinMarket in general and Jam in particular, you might want to have a +look at the "Cheatsheet."

+

Cheatsheet

+

Getting Help

+

Since there is no company or fixed team behind Jam or JoinMarket, your best bet +to get help are public chat groups and public forums. Also make sure to have a +look at the FAQ to get answers to frequently asked questions.

+

FAQ

+

GitHub Issues

+

Matrix Room

+

Telegram Group

+
+
+
    +
  1. +

    Jam and JoinMarket are separate projects. For more information on JoinMarket, see the JoinMarket GitHub Page 

    +
  2. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/00-cheatsheet/index.html b/interface/00-cheatsheet/index.html new file mode 100644 index 0000000..35ab517 --- /dev/null +++ b/interface/00-cheatsheet/index.html @@ -0,0 +1,985 @@ + + + + + + + + + + + + + + + + + + + + + + Cheatsheet - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Cheatsheet

+

While everyone will use Jam differently, here is one way you can think about the +general application flow:

+

+

Some of your UTXOs might be chunky and identifiable, like whole or large +pieces of fruit. Once you make delicious jam out of them, they are less chunky +and less identifiable. You are free to offer your fruits to others so they can +make jam more easily.

+

Without the fruity metaphor: to increase the privacy and fungibility of your +funds—and thus your security overall—you should use Jam as both a market +maker ('Earn' tab) and a taker ('Send' and 'Sweep' tabs). Use +a Jar's sweep functionality or the Scheduler to transfer funds out of +Jam, e.g. to move all your funds to cold storage or to use them to open +lightning channels. If you want to pay others for goods and services, use +send.

+

First Use

+
    +
  1. Receive sats to fund your wallet
  2. +
  3. Send a collaborative transaction to one of your jars
  4. +
  5. Earn sats by offering liquidity1
  6. +
  7. Sweep your wallet using the scheduler
  8. +
  9. Rinse and repeat!
  10. +
+
+

Click "Cheatsheet" at the bottom of the screen to open up the cheatsheet in Jam.

+

+

+

Receive

+
+

Things to Note

+

Some processes in Jam might take a long time to complete. Further, Jam is +considered beta software. While JoinMarket is tried and tested, Jam is new and +things might break. Use with caution. Please report any issues directly on +GitHub.

+

Make sure to understand the privacy fundamentals, best practices, as well as the +motivation behind this software. Also, understand that you are participating in +a free market. How much you can earn and how many fees you have to pay depends +on market conditions.

+

Motivation

+

Privacy Fundamentals

+

Fees

+
+
+
    +
  1. +

    Make sure to create a fidelity bond to increase the chances of your offer being taken. 

    +
  2. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/01-receive/index.html b/interface/01-receive/index.html new file mode 100644 index 0000000..f52f2bc --- /dev/null +++ b/interface/01-receive/index.html @@ -0,0 +1,892 @@ + + + + + + + + + + + + + + + + + + + + + + Receive - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Receive

+

Use the 'Receive' tab to receive funds.

+

+

+

A new invoice address will be generated every time. You can scan the +QR code with a mobile wallet or copy/paste the invoice address to receive funds +from someone else, or send funds from another wallet yourself.

+
+

Info

+

Jam uses jars under the hood to separate funds into disconnected +containers. Think of jars as different pockets in your wallet, or different +identities. The default jar to receive funds is Jar A.

+
+

Once you have funded your wallet, you can use the 'Send' tab to do +a collaborative transaction.

+

Send

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/02-send/index.html b/interface/02-send/index.html new file mode 100644 index 0000000..65b634e --- /dev/null +++ b/interface/02-send/index.html @@ -0,0 +1,896 @@ + + + + + + + + + + + + + + + + + + + + + + Send - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Send

+

Use the 'Send' tab to send funds to someone or to one of jars. Jam defaults to +collaborative transactions when sending, which enhances your privacy and +security.

+
+

Info

+

Jam uses jars under the hood to separate funds into disconnected +containers. Think of jars as different pockets in your wallet, or different +identities.

+
+

You can choose the number of collaborators in the send options. The higher the +number of collaborators, the larger your anonymity set.

+

+

+

Use the 'Sweep' button in the amount field to empty a single jar, or use the +Sweep tab to sweep all non-frozen funds of your wallet to external +addresses.

+

After you made your first collaborative transaction with one of your jars as the +recipient, you are ready to earn.

+

Earn

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/03-earn/index.html b/interface/03-earn/index.html new file mode 100644 index 0000000..f768ce1 --- /dev/null +++ b/interface/03-earn/index.html @@ -0,0 +1,969 @@ + + + + + + + + + + + + + + + + + + + + + + Earn - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Earn

+

Use the 'Earn' tab to earn sats by offering liquidity to other market +participants. You will be acting as a market maker. Creating a +fidelity bond is recommended. +In Jam, takers pay 100% of the mining fees: as a market maker, you will not pay anything. Just profit!

+

+

+

Fidelity Bonds

+

Make sure to create a fidelity bond to increase the chances of your offer +being taken.

+

A fidelity bond is a mechanism which ensures that market actors act honestly. It +is a protection mechanism against Sybil attacks. A fidelity bond makes +the creation of cryptographic identities costly.

+

Fidelity bonds improve the privacy guarantees of the whole system and increase +your chance of being chosen as a market maker drastically.

+

Be aware that funds locked in a Fidelity Bond will not be included in your offer amount, +so remember to keep additional funds in order to participate as a market maker.

+
+

Warning

+

It is impossible to move or spend funds that are locked in a fidelity bond +before the bond expires. They cannot be used in collaborative transactions +(neither as taker nor as maker) +as fidelity bonds are time-locked by the Bitcoin protocol.

+
+

Fidelity Bonds

+

Offer Options

+

There are two types of offers:

+
    +
  1. Absolute offer: the fee you are charging is set in absolute terms, e.g. as 250 sats.
  2. +
  3. Relative offer: the fee you are charging is set in percentage terms, e.g. as 0.03%.
  4. +
+

Once you are done earning, you can sweep all funds to an external wallet.

+

Sweep

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/04-sweep/index.html b/interface/04-sweep/index.html new file mode 100644 index 0000000..03ff515 --- /dev/null +++ b/interface/04-sweep/index.html @@ -0,0 +1,889 @@ + + + + + + + + + + + + + + + + + + + + + + Sweep - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Sweep

+

Use the 'Sweep' tab to empty your wallet using the scheduler. The scheduler will +execute a series of collaborative transactions with randomized parameters, which +will send your funds to multiple destination addresses over time.

+

+

+

Once the scheduler is active you will see a green indicator light, which means +that the scheduler service is running. The service will take any +matching offer automatically.

+

+

+

You can stop the scheduler at any time.

+

Cheatsheet

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/fidelity-bonds/index.html b/interface/fidelity-bonds/index.html new file mode 100644 index 0000000..6faf472 --- /dev/null +++ b/interface/fidelity-bonds/index.html @@ -0,0 +1,911 @@ + + + + + + + + + + + + + + + + + + + + + + Fidelity Bonds - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Fidelity Bonds

+

A fidelity bond is a mechanism which ensures that market actors act honestly. It +is a protection mechanism against various kinds of attacks that involve the +creation of fraudulent identities.

+

Glossary: Fidelity Bond

+
+

Warning

+

It is impossible to move or spend funds that are locked in a fidelity bond +before the bond expires. They cannot be used in collaborative transactions +(neither as taker nor as maker) +as fidelity bonds are time-locked by the Bitcoin protocol.

+
+

You can create a fidelity bond via the Earn screen. It involves the following steps:

+
    +
  1. Set expiration date (which defines the bond's duration)
  2. +
  3. Select a jar as funding source
  4. +
  5. Select a UTXO, preferably one labeled cj-out
  6. +
+

After that, you will be asked to review the bond configuration. If everything +looks right, you can create the fidelity bond which will time-lock your +funds for the set duration.

+
+

Refer to the screenshots below to understand the steps in more detail:

+

+

+

+

+

+

+

+

+

+

+

Orderbook

+

Earn

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/settings/index.html b/interface/settings/index.html new file mode 100644 index 0000000..bbba3e6 --- /dev/null +++ b/interface/settings/index.html @@ -0,0 +1,984 @@ + + + + + + + + + + + + + + + + + + + + + + Settings - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Settings

+

Access the settings by clicking on the gear icon () in the top-right corner.

+

+

+

General Settings

+
    +
  • Hide/show balance
  • +
  • Display amounts in bitcoin or sats
  • +
  • Switch between light & dark theme
  • +
  • Set interface language (Your language is missing? Contribute!)
  • +
+

Wallet Settings

+

Jam supports the creation and handling of multiple wallets. However, only one +wallet can be actively used at a time. Wallets are locked when not used. Your +"active" wallet is the one that is currently unlocked.

+
    +
  • Show seed phrase: show the seed phrase of the active wallet
  • +
  • Lock wallet: lock the wallet that is currently active
  • +
  • Switch wallet: open another wallet and lock the current one
  • +
  • Create new wallet: initialize a new, empty wallet
  • +
+
+

Question

+

Want to import a wallet? Look at the FAQ!

+
+ + + + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/interface/wallet/index.html b/interface/wallet/index.html new file mode 100644 index 0000000..b67abe9 --- /dev/null +++ b/interface/wallet/index.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + + + + + + + + + + + Wallet Overview - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Wallet Overview

+

Clicking on the active wallet in the top-left corner will open the +wallet view.

+

+

+

You can see your jars and whats in them by clicking on the arrow. Clicking on a +jar will open its detail view, which allows you to inspect individual UTXOs, as +well as freeze/unfreeze them.

+

+

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/js/external-links.js b/js/external-links.js new file mode 100644 index 0000000..89dc3e9 --- /dev/null +++ b/js/external-links.js @@ -0,0 +1,23 @@ +function addListenerMulti(element, eventNames, listener) { + const events = eventNames.split(" ") + for (let i = 0, iLen = events.length; i < iLen; i++) { + element.addEventListener(events[i], listener, false) + } +} + +addListenerMulti(document, "DOMContentLoaded DOMContentSwitch", (event) => { + // Add an icon to all external links + const links = document.querySelectorAll(".md-content a") + for (let i = 0, length = links.length; i < length; i++) { + if ( + links[i].hostname !== window.location.hostname && + links[i].hostname !== "" && + links[i].classList.contains("md-icon") !== true && + links[i].classList.contains("download-button") !== true + ) { + links[i].target = "_blank" + links[i].classList.add("external") + links[i].rel = "noopener" + } + } +}) diff --git a/market/fees/index.html b/market/fees/index.html new file mode 100644 index 0000000..e77d9d2 --- /dev/null +++ b/market/fees/index.html @@ -0,0 +1,1008 @@ + + + + + + + + + + + + + + + + + + + + + + Fees - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Fees

+

Fees play a crucial role in the incentive structure of both Bitcoin and +JoinMarket. They form the basis for the economic incentives of both systems. In +Bitcoin, you pay fees to a miner in order for your transaction to be included in +a block. The higher the fee you are willing to pay, the higher the likelihood +that your transaction will be included quickly.

+

In JoinMarket, you pay fees to market makers in order to use their +liquidity to both of your advantage. However because the market maker gets the fee as he is waiting around and providing the liquidity.

+

Consequently, when you are sending a collaborative transaction in Jam—or when you are using the scheduler to do multiple transactions—you have to pay fees to miners and makers. How high these fees are depends on market and mempool conditions.

+

Of course, you can offer liquidity yourself via the Earn functionality, allowing you to be on the receiving end when it comes to maker fees.

+

Earn

+

Paying Maker Fees

+

When doing a collaborative transaction via the Send or Sweep tabs, +you are taking liquidity offers from others, effectively becoming a market +taker.

+

How much you will pay in maker fees depends on the fee market of the current offers. You can get an overview of fees by inspecting the order book.

+

FAQ: How high are the fees that I do have to pay?

+

Orderbook

+

Paying Mining Fees

+

Just like all users of onchain bitcoin, you will have to pay +transaction fees to miners.

+

Note that collaborative transactions are larger, in terms of bytes, than +"regular" bitcoin transactions. Since the cost of an onchain transaction is +determined by its size in bytes—not by value transferred—a collaborative +transaction is more expensive than a simple spend.

+

FAQ: How high are the fees that I do have to pay?

+

Mempool

+

Earning Maker Fees

+

As mentioned above, you can use the Earn tab to earn maker fees +yourself. Simply choose an offer type, select how many fees you would like to earn, and press "Start Earning!".

+

Make sure to check the orderbook to compare your offer with current +market rates. If your offer isn't competitive, it's likely nobody will take it and thus +you will earn zero sats.

+

FAQ: How much can I earn?

+

Orderbook

+

Fee Conversion

+

All fees are denominated in sats. Use one of the tools below to convert them to fiat:

+ +
+

See also "a note on fees" from the JoinMarket documentation.

+

A Note on Fees

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/market/mempool/index.html b/market/mempool/index.html new file mode 100644 index 0000000..fc80e14 --- /dev/null +++ b/market/mempool/index.html @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + + + + + + + + + + Mempool - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Mempool

+

The mempool (memory pool) is a pool of transactions that are not included in the +timechain yet. It is a waiting room for transactions, if you will. Every full +node has its own mempool—there is no single mempool that is shared by nodes, +there is an individual mempool for every single node. Mempools might differ +depending on node configuration. Nodes can decide which transactions to keep, +which transactions to pass on to other nodes, and which transactions to drop.

+

Miners will consult their mempools to construct candidate blocks. Once a +transaction is included in a valid block—and your node confirms the blocks +validity—it is considered confirmed and removed from the node's mempool.

+

Learn me a bitcoin: Memory Pool

+

Miners are incentivised to include transactions that reward them the most, i.e. +transactions that pay the highest mining fees. Because mining fees are set by +the users, you can view mining fees as a kind of bribe that is paid by the users +to the miners. If the bribe is high, the chance of your transaction being +included is high. If it is low, the chance of inclusion is lower.

+

Paying Mining Fees

+

Mempool and Transaction Fees

+

Bitcoin block space is scarce. If onchain activity is high, the mempool will be +crowded. The more crowded the mempool, the higher the "bribe" you will have to +pay to miners.

+

Fee estimation is an attempt to guess how high the fee needs to be for your +transaction to be included in the future. It is more an art than a science, +since the future is always uncertain and mempool conditions might change +quickly.

+

Most mempool explorers have some sort of fee estimation. You can also use the +estimatesmartfee command to do a fee estimation based on your +mempool:

+
bitcoin-cli estimatesmartfee 21 economical
+
+

Mempool Instances

+

We recommend that you use your own node to inspect the mempool. For example, you +can use the getrawmempool command to inspect your mempool:

+
bitcoin-cli getrawmempool true
+
+

Of course, plenty of graphical user interfaces exist too. The software that is +powering mempool.space is free software and can be installed quite easily on +your node.

+

Mempool One-Click Installation

+

Mempool Visualisations

+

You can also refer to public mempool instaces in case you don't have access to +the mempool of your own node. Note, however, that using public mempool and block +explorers has certain privacy implications, as whoever is running these websites +will be able to correlate your IP with the blocks and transactions you look up. +Use Tor or a VPN to mitigate this.

+

mempool.space

+

There are also great visualisations that help you understand what's going on, +Bitfeed and Mempool Observer being two of them.

+

Visualisation: Mempool Observer

+

Visualisation: Bitfeed

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/market/orderbook/index.html b/market/orderbook/index.html new file mode 100644 index 0000000..cb86ee1 --- /dev/null +++ b/market/orderbook/index.html @@ -0,0 +1,887 @@ + + + + + + + + + + + + + + + + + + + + + + Orderbook - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Orderbook

+

The order book (or orderbook) shows what kind of offers are currently on the +market. It gives insights in regards to offer types, fees, offer sizes, and +fidelity bonds put up by market makers.

+

Jam will set up a service that allows you to watch the order book on your node. +This removes the trust in a third party. You can view the order book directly in +Jam via the "Show orderbook" button on the Earn screen.

+

+

There are also public order books that you can inspect, in case you do not have +access to your own node:

+

nixbitcoin.org/orderbook

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/market/volume/index.html b/market/volume/index.html new file mode 100644 index 0000000..bb3814c --- /dev/null +++ b/market/volume/index.html @@ -0,0 +1,885 @@ + + + + + + + + + + + + + + + + + + + + + + Volume - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Volume

+

In JoinMarket, liquidity is sold and bought on a free market. Consequently, +market volume and depth depends on market conditions. You can inspect the order +book to get an overview of the current offers.

+

Orderbook

+

Some sites show historical statistics in regards to market volume and liquidity. +Please note that the statistics shown on these sites sometimes use proprietary +data and algorithms.

+

JoinMarket KPIs

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/philosophy/00-motivation/index.html b/philosophy/00-motivation/index.html new file mode 100644 index 0000000..6dc04f7 --- /dev/null +++ b/philosophy/00-motivation/index.html @@ -0,0 +1,1045 @@ + + + + + + + + + + + + + + + + + + + + + + Motivation - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Motivation

+
+

There is a sacred realm of privacy for every man and woman where he makes his +choices and decisions — a realm of his own essen­tial rights and liber­ties into +which the law, gener­ally speaking, must not intrude.

+

Geoffrey Fisher, Archbishop of Canter­bury (1959)

+
+

Jam is a tool, just like bitcoin. Before using it, you should understand how you +could benefit from using it, how it works, and how to use it correctly. In order +to answer the "how" you should also understand the "why" --- why was it created, +and what is the problem in the first place?

+

To answer that properly, we will have to talk about privacy and financial +privacy in general, and bitcoin privacy in particular:

+
    +
  • Why care about privacy?
  • +
  • Why use Jam?
  • +
+

Why Care About Privacy?

+
+

"Privacy is neces­sary for an open society in the electronic age. +Privacy is not secrecy. A private matter is something one doesn't want +the whole world to know, but a secret matter is something one doesn't +want anybody to know. Privacy is the power to selec­tively reveal +oneself to the world."

+

Eric Hughes

+
+

With these powerful words Eric Hughes opened his Cypher­punk's +Manifesto +in 1993. The differ­ence between privacy and secrecy is subtle, but +impor­tant. Choosing to remain private does not imply that one has +secrets or has something to hide. To illus­trate this just realize that +what you do on the toilet or in the bedroom is neither illegal nor +a secret (in most cases), yet you close the door and pull the curtains.

+

Similarly, how much money you have and where you spend it is not +neces­sarily a secret matter. It should, however, be a private one. Most +would agree that your boss should not know how you choose to spend your +salary.

+

The impor­tance of privacy is recog­nized by many inter­na­tional +bodies. From the American Decla­ra­tion of the Rights and Duties of +Man to the United Nations, it is recog­nized that privacy is +a funda­mental human right worldwide.

+
+

No one shall be subjected to arbitrary inter­fer­ence with his +privacy, family, home or corre­spon­dence, nor to attacks upon his +honour and reputa­tion. Everyone has the right to the protec­tion of +the law against such inter­fer­ence or attacks.

+

Article 12, United Nations Decla­ra­tion of Human Rights

+
+

Although Bitcoin was often described as an anony­mous method of payment +by early propo­nents and by the media, it is anything but. Bitcoin is +pseudo­ny­mous at best and as of today making sure that your +pseudo­ny­mous bitcoin identi­ties cannot be linked to your real-world +identity proves diffi­cult for most people. 

+

Bitcoin is an open system. Its public ledger can be inspected and +studied by everyone. Thus every trans­ac­tion that is embedded in its +proof-of-work chain will be exposed for as long as Bitcoin exists: +eternity. Failing to follow privacy best practices now can poten­tially +have negative reper­cus­sions in the future.

+

Privacy, like security, is a process and it is diffi­cult, but not +impos­sible. Tools continue to be devel­oped to help preserve privacy +while using Bitcoin and fortu­nately most of these tools become easier +to use over time. Unfor­tu­nately no panacea exists. One has to remain +aware of the trade­offs and follow best practices as they evolve.1

+

Free Software

+

Why Jam?

+

Jam is a front-end for JoinMarket, a privacy-focused bitcoin software +that uses a peer-to-peer marketplace to facilitate collaborative transactions, +also called "CoinJoins."2

+

A collaborative transaction, as the name implies, is a bitcoin transaction that +is done collaboratively by multiple parties. The tricky part of getting a +collaborative transactions done is not technical, but social. It is a problem of +matchmaking, timing, and trust.

+

Usually, this problem is solved with a central coordinator.

+

JoinMarket takes a different approach. It allows participants to propose +collaborative transactions to others, creating an open market of buyers and +sellers, which removes the central coordinator from the equation.

+

JoinMarket

+

Tech Fundamentals

+

With the motivation and purpose of Jam covered, understanding the +fundamentals of bitcoin in general and bitcoin privacy in particular might be +useful.

+

Privacy Fundamentals

+
+
+
    +
  1. +

    Some parts of the above are based on "Bitcoin Privacy: Best +Practices, +written by Gigi and released under CC BY-SA 4.0 license." 

    +
  2. +
  3. +

    We prefer to refer to them as collaborative transactions, which is more concise and explanatory. 

    +
  4. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/philosophy/01-free-software/index.html b/philosophy/01-free-software/index.html new file mode 100644 index 0000000..d3de4b4 --- /dev/null +++ b/philosophy/01-free-software/index.html @@ -0,0 +1,906 @@ + + + + + + + + + + + + + + + + + + + + + + Free Software - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Free Software

+

Jam is free as in freedom. We believe that free software is an imperative for +a free society, which is why Jam is released under a free software license.

+

Bitcoin is financial software. Consequently, any financial liberation that is +enabled by Bitcoin rests on the four essential freedoms granted by free +software.

+

What is Free Software?

+
+

“Free software” means software that respects users' freedom and community. + Roughly, it means that the users have the freedom to run, copy, distribute, + study, change and improve the software. Thus, “free software” is a matter of + liberty, not price. To understand the concept, you should think of “free” as + in “free speech,” not as in “free beer.”

+
+

Free software puts the users in control, both collectively and individually. +Free software is not only about being "open" and "more secure." While these are +nice side-effects, the main issue is about control and respecting user's +freedoms.

+

Why Free Software Is Even More Important Now

+
+

Freedom means having control over your own life. If you use a program to carry +out activities in your life, your freedom depends on your having control over +the program. You deserve to have control over the programs you use, and all +the more so when you use them for something important in your life.

+
+

Most software and software products force the user into a master-slave +relationship, as do most monetary systems and financial products. Bitcoin is +freedom money because the software that makes Bitcoin possible is free +software—free as in freedom. There are no masters, only peers.

+

Bitcoin

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/philosophy/02-bitcoin/index.html b/philosophy/02-bitcoin/index.html new file mode 100644 index 0000000..cb1dd2c --- /dev/null +++ b/philosophy/02-bitcoin/index.html @@ -0,0 +1,943 @@ + + + + + + + + + + + + + + + + + + + + + + Bitcoin - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Bitcoin

+

There is much to be said about Bitcoin and why it was created. Many books have +been written, much speculation was and is still being had in terms of Satoshi's +"true" vision and motivation.3

+

Undoubtedly, there are certain values embodied in the Bitcoin system—certain +opinions that are embedded in the code, expressing how things should be done and +what should be avoided. Nothing makes this more clear than the +announcement post of Bitcoin, written by Satoshi himself.

+

Below are some highlights that are particularly relevant:

+
+

I've developed a new open source P2P e-cash system called Bitcoin. It's +completely decentralized, with no central server or trusted parties, +because everything is based on crypto proof instead of trust.

+
+

No central server. No trusted third party. Peer-to-peer (P2P), instead of +client-server or master-slave.

+

Thanks to strong cryptography, trust in third parties can be eliminated. When +possible, rely on cryptographic proof instead of trust. Trusted third parties +should be eliminated because (a) they introduce friction and (b) they are +security holes.1

+
+

We have to trust [banks] with our privacy, trust them not to let +identity thieves drain our accounts. [...] Before strong encryption, users had +to rely on password protection to secure their files, placing trust in the +system administrator to keep their information private. Privacy could always +be overridden by the admin based on his judgment call weighing the principle +of privacy against other concerns, or at the behest of his superiors.

+
+

Privacy. Admins that spy on you. Systems that are designed to spy on you. +Unfortunately, it's almost non-existent in today's world of surveillance +capitalism and dragnet surveillance.

+

While credit requires identity, money does not. When you can trust the money you +don't have to trust the person. In Bitcoin, there are no persons; only +pseudonymous identities. Identities that are generated cryptographically at +virtually no cost.

+
+

With e-currency based on cryptographic proof, without the need to trust a +third party middleman, money can be secure and transactions effortless.

+
+

No middlemen. Secure and effortless. The reason why your browser will show you a +green lock or a shield when a connection is encrypted is that privacy and +security are two sides of the same coin. Without privacy, your physical security +might be at risk.2 Without privacy, free thought and free speech are +impeded.

+
+

The result is a distributed system with no single point of failure.

+
+

No single point of failure. No admins.That is one of the main value propositions +of Bitcoin, and what makes it so resilient. This resiliency, and the fact that +the users are in charge—and nobody else—is what sets Bitcoin apart. JoinMarket +continues this philosophical approach: economic actors in a peer-to-peer system, +no single point of failure.

+

JoinMarket

+
+
+
    +
  1. +

    Szabo, 2001. Trusted Third Parties Are Security Holes 

    +
  2. +
  3. +

    Jameson Lopp, List of Known Physical Bitcoin Attacks 

    +
  4. +
  5. +

    A selection of books is available in the Bitcoin and Cypherpunk History section of bitcoin-resources.com/books 

    +
  6. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/philosophy/03-joinmarket/index.html b/philosophy/03-joinmarket/index.html new file mode 100644 index 0000000..1c45a5b --- /dev/null +++ b/philosophy/03-joinmarket/index.html @@ -0,0 +1,931 @@ + + + + + + + + + + + + + + + + + + + + + + JoinMarket - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

JoinMarket

+

JoinMarket, just like Bitcoin, doesn't have a single point of failure. It can be +understood as a protocol that facilitates certain kinds of collaborative +transactions—CoinJoins—via an open market.

+

Creating collaborative transactions is not a technical problem, but a problem of +coordination. Someone has to bring the participants together, coordinate time +and place, as well as amounts and fees.

+

Usually, this problem is solved by a central coordinator. In the +best case, the central coordinator is non-custodial and blinded, meaning that +user funds are never at risk, and the amount of information the central +coordinator can obtain is minimal. However, even in this optimal case, the +central coordinator is still a single point of failure.

+

In addition to being a central point of failure, any central coordinator usually +charges a fee for the coordination service, which means that it is an entity +that is making money. In most cases, this entity is a company that can be +pressured and subverted, as has happened in the past. Even without any outside +pressure, an economic entity might make certain decisions against the best +interest of its users, just out of self-preservation alone.1

+

JoinMarket provides a decentralised alternative to these central coordination +services. It is not a central entity, it is software that is coordinating the +actions of multiple peers, just like Bitcoin. JoinMarket is neutral, meaning +that the system itself is not charging its users to use the software for +coordination. Fees are earned by market makers, i.e. those who are +willing to provide liquidity to the open market. Consequently, JoinMarket is not +a financial entity. Only the users are making money. JoinMarket is not.

+

Glossary

+

JoinMarket is a tried and tested CoinJoin implementation, having been actively +used on Bitcoin's mainnet since 2015.2 Because of its lack of a +centralised coordinator, it works a bit differently than other CoinJoin +implementations.3 You can read about the details of JoinMarket's +design in the high-level +design +document of the JoinMarket docs.

+

JoinMarket is free and open-source software, which means that anyone is free to +use, inspect, and modify the software.

+

Free Software

+

Because of its decentralised nature, and thus the lack of funds and focused +effort that a central company structure allows, the JoinMarket software was, +historically, a bit difficult to set up and use. We hope that the efforts around +Jam will make it a bit easier.

+

Installation

+
+
+
    +
  1. +

    See, for example: https://archive.ph/C53tk, https://archive.ph/hIYJO 

    +
  2. +
  3. +

    See the Bitcoin Wiki for https://en.bitcoin.it/wiki/JoinMarket 

    +
  4. +
  5. +

    Shinobi, 2021 JoinMarket Vs. ZeroLink 

    +
  6. +
+
+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/privacy/01-fundamentals/index.html b/privacy/01-fundamentals/index.html new file mode 100644 index 0000000..9fe8dd9 --- /dev/null +++ b/privacy/01-fundamentals/index.html @@ -0,0 +1,1103 @@ + + + + + + + + + + + + + + + + + + + + + + Fundamentals - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Fundamentals

+

When it comes to Bitcoin, misconceptions abound. This is not surprising. Bitcoin +is a new thing, and, consequently, all metaphors and comparisons +fall short, in one way or another.

+

One misconception is that Bitcoin is private and untraceable. In actuality, +regular Bitcoin use often has weaker privacy guarantees than using the +traditional banking system, as Gregory Maxwell pointed out many years +ago:

+
+

“Your inlaws can see that you're buying birth control that deprives them of +grandchildren, your employer learns about the non-profits you support with money +from your paycheck, and thieves see your latest purchases and how wealthy you +are which helps them target and scam you. Poor privacy in Bitcoin can be a major +practical disadvantage for both individuals and businesses.”

+
+

To understand why this is, we have to understand how Bitcoin operates. This, +however, turns out to be very difficult. To understand one part, one needs to +have a solid understanding of computer science and cryptography. To understand +another part, one needs to have a solid understanding of economics and game +theory—not to mention money, networks, governance, energy and energy markets, +monetary history, and so on. The list of relevant disciplines is almost endless.

+

However, it is possible to look at some parts of Bitcoin in isolation +and—hopefully—gain a better understanding by zooming in. One such part is the +Bitcoin transaction.

+

The Bitcoin Transaction

+

In the simplest sense, a Bitcoin transaction is just a bunch of data that +describes the movement of bitcoins.

+

A bitcoin transaction consists of inputs and outputs. Every transaction input +refers to the output of a previous transaction (except the coinbase transaction). We say that an input "consumes" +an output. If an output is not consumed yet, we speak of an unspent transaction +output, or UTXO, for short.

+

Once properly understood, it is easy to see what the Bitcoin network generates: +a linked data structure that, starting from a common root—the genesis +block—splits and combines bundles of sats as time goes on. Properly visualized, +it would look a bit like an upside-down tree.

+

+

+

Every transaction has at least one input and at least one output. The simplest +and traditionally most common transaction type has one input and two outputs: +one describing the actual payment and one describing the change that goes back +to the one who initiated the payment.

+

+

The concept of change is required because Bitcoin doesn't allow an update of the +past. It is an append-only log, so instead of going back and modifying past +entries, new entries have to be created to reflect any updates. Transactions are +what create these updates. For a simple transaction, one new "entry" is created +to update the balance of the receiver, and one new entry is created to update +your own balance. You can think of it as paying for something that costs $5 with +a $20 bill. The merchant receives five dollars, and you get $15—the change—back. +However, we don't have physical coins and bills, we only have an append-only +log. So instead of bills of smaller denominations, new entries—new UTXOs—are +created.

+

+

While this design is ingenious when it comes to validation—you can easily make +sure that everything adds up at all times—there are certain nuances to consider +when it comes to privacy.

+

For example, if it is trivial to determine which output is a change output and +which one isn't, it is trivial to cluster outputs and thus identify not only the +flow of funds, but also who transacted with whom, at what times, and—of +course—the amounts that were transacted. Imagine a data leak that exposes all +transactions of every company, every individual, every politician, every bank, +every merchant, every online shop, and every vending machine. When used naively, +this data leak is Bitcoin.

+

Luckily, the situation is not as grim as it sounds. Developments and techniques +exist to remedy this situation. To understand them, we have to understand the +various transaction types that Bitcoin allows.

+

Bitcoin Transaction Types

+

We already discussed the most common transaction type: the "simple spend." There +are also transactions that have only one input and one output, transactions that +have multiple inputs and one output, and transactions that have multiple inputs +and multiple outputs. Let's call them "No Change," "Consolidation," and "Batch," +respectively.

+

+

While Bitcoin's transaction graph is public, it is important to point out that +any analysis that is applied to this data is heuristic. For example, a user +might create a transaction that splits a UTXO in half, resulting in two outputs +that belong to the same entity. Or, to pick another example, a regular spend +might produce two outputs that are exactly equal, making change detection +virtually impossible.

+

+

Because identification can only happen heuristically, one part of the solution +to Bitcoin's privacy conundrum lies in collaboration.

+

Collaborative Transactions

+

When it comes to privacy, collaboration is the norm. Take encryption, for +example. If you want to have a secure communications channel with another party, +you start a collaborative process. You meet, you exchange secret information, +and you use this secret information to encrypt your messages. We call this +exchange of secret information a "handshake," and over the last decades, we +implemented all kinds of handshakes into our communication and networking +protocols to make sure that bad actors can't eavesdrop on our communications.

+

Similarly, cryptographers and security researchers are currently working on +protocols and techniques that make sure that bad actors can't eavesdrop on your +every financial move. As with end-to-end encryption, these protections are +important for all and a matter of life-and-death for some. Dissidents, +journalists, whistleblowers, political activists—these are only a few groups of +people that depend on secure communications, which includes financial +communication. That privacy is important for these groups is an understatement. +It is absolutely essential. This is also why the Human Rights Foundation +launched a fund to support software developers who are making the Bitcoin +network more private, decentralized, and resilient.

+

So, how can we think about a "handshake" in the world of bitcoin transactions? +It's quite simple, really. As mentioned above, a bitcoin transaction can have +multiple inputs and multiple outputs. The privacy techniques that are currently +being developed are making use of this feature. The interesting part is that not +all inputs have to be controlled by the same party. Thus, the "handshake" is +about bringing multiple parties together to collaborate on a bitcoin +transaction.

+

Once the collaborating parties agree on the parameters of the transaction, the +transaction is signed by all parties and broadcast to the network. Because of +the heuristical nature of transaction analysis, an onlooker won't be able to +figure out the flow of funds.

+

+

One especially promising technique to increase the privacy of all is to combine +the above with an actual payment. In this scenario, the "handshake" is about +bringing a merchant and a customer together to craft a special transaction that +can only be deciphered by said merchant or customer. An eavesdropper is left +with multiple interpretations of the transaction, each equally likely. Such a +transaction is called a “PayJoin.”

+

Even if only a small percentage of transactions are PayJoin transactions, the +privacy of all participants in the network is increased substantially.

+

As more wallets and merchants adopt and support these privacy features, we will +see a substantial increase in privacy on Bitcoin's base layer. However, as we +have seen with the adoption of Transport Layer Security on the Internet, it +takes some time for an upgrade of this sort to be implemented and embraced.

+

Transport Layer Security

+

When the internet was a new thing, we didn't think that it would envelop all our +communications and all our lives. Encryption was an afterthought. After a while, +however, we figured out that having all our communications available in plain +text, readable by everyone who had the interest and technical proficiency to do +so, wasn't a terribly good idea. Consequently, we made a concerted effort to +change things. We upgraded from HTTP to HTTPS and from plain text +messages to end-to-end encryption. While this switch isn’t 100% +complete yet, encrypted communication became the default over time. This upgrade +took a long time, since, similar to Bitcoin, nobody is in charge of the +internet.

+ + +
+

Best Practices

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/privacy/02-best-practices/index.html b/privacy/02-best-practices/index.html new file mode 100644 index 0000000..21450fc --- /dev/null +++ b/privacy/02-best-practices/index.html @@ -0,0 +1,1120 @@ + + + + + + + + + + + + + + + + + + + + + + Best Practices - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

Best Practices

+

As with every­thing in Bitcoin, taking control of your privacy is +a gradual, step-by-step process. Learning about and imple­menting these +best practices takes patience and respon­si­bility, so do not be +discour­aged if it seems overwhelming at first. Every step, no matter +how small, is a step in the right direction.

+

Take Action

+

The following are action­able steps you can take to increase +your privacy:

+ +

Self-custody your coins

+

Not your keys, not your bitcoin. If someone +else is holding your bitcoin for you, they know every­thing there is to +know about these coins: amounts, trans­ac­tion histo­ries, future +trans­ac­tions, etc. Taking self-custody of your coins is the first and +most essen­tial step.

+

Bitcoin Wallet Guide

+

Do not reuse addresses

+

Reusing addresses destroys the privacy of +both the sender and the receiver. It should be avoided at all costs.

+

Address Reuse

+

Minimize exposure to KYC

+

Linking your real-world identity to your +bitcoin addresses is a neces­sary evil in most juris­dic­tions. While +the effec­tive­ness of these regula­tions is question­able, the +impli­ca­tions for regular users are mostly negative as a multi­tude of +data leaks have shown. If you choose to use KYC on- or off-ramps, make +sure that you under­stand the relation­ship between yourself and the +service in question. You are trusting this service with your personal +data, including the future safety of this data. +If you want to skip KYC entirely, have +a look at no-KYC only.

+

No KYC Only

+

Minimize exposure to third parties

+

Trusted third parties are security holes. If you can rely on yourself instead of +trusted third parties, you should.

+

Trusted Third Parties Are Security Holes

+

Run your own node

+

Not your node, not your rules. Running your own node is essen­tial to use +Bitcoin in a private manner. Every inter­ac­tion with the Bitcoin network is +facil­i­tated by a node. If you are not in control of this node, whatever you +are doing is seen by the node you are inter­acting with. This means whoever is +in control of the node is able to see what you are doing. The bitcoiner node +guide is a great resource to get you started.

+

Bitcoiner Node Guide

+

Use the Light­ning Network for small trans­ac­tions

+

The off-chain nature of the light­ning network increases the trans­ac­tional +privacy of its users without having to jump through too many hoops. While it is +still early, the absolutely reckless days of the light­ning network are likely +behind us. Using it for small- and medium-sized trans­ac­tions can help improve +both your privacy as well as your fee footprint.

+

Bitcoiner Lightning Guide

+

Do not use public block explorers

+

Looking up addresses in public block explorers will link those addresses with +your IP, which, in turn, can be linked to your real identity. Software packages +like Umbrel, Citadel, RaspiBlitz, and BTCPay Server make it easy to run your own +block explorer. If you have to use a public block explorer, make sure to mask +your IP by connecting to them via Tor, +or at least use a VPN.

+

Mempool Instances

+

CoinJoin early and often

+

Because Bitcoin is forever, using trans­ac­tional best practices such as +collab­o­ra­tive CoinJoin trans­ac­tions will ensure that your privacy is +protected going forward. While CoinJoin trans­ac­tions are nuanced, +user-friendly software exists to help you create and automate these kinds of +trans­ac­tions. Samourai's Whirlpool is a good  solution for Android users, for +example. There is also JoinMarket, which, thanks to projects like +JoininBox and Jam, can be set up +quite easily on your own node.

+

Getting Started with Jam

+

Installation

+
+

+The above is a slightly modified version of Bitcoin Privacy: Best +Practices" by Gigi, released originally under a +CC BY-SA 4.0 license and modified for Jam by the author.

+

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..a2e87c2 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Getting Started","text":"

Jam is an interface for JoinMarket1, a special kind of bitcoin software that focuses on privacy and security. The goal of Jam is to make it easier to improve the financial privacy of yourself and others.

Warning

Both Jam and its documentation are a work in progress. We are writing these docs as we progress, out in the open. If you want to help, please do!

Contributing

"},{"location":"#before-you-start","title":"Before You Start","text":"

Before you get going with Jam you should understand the \"why\" behind it all.

Motivation

Privacy Fundamentals

As mentioned above, Jam uses JoinMarket under the hood. What sets JoinMarket apart is that it has no single point of failure. It is completely peer-to-peer, there is no central coordinator, no \"doxxic change\", no company behind it all, no marketing department, and no central entity making any money off of it.

All development is done by volunteers. Consequently, please heed the following warning:

Danger

Jam is considered beta software. While JoinMarket is tried and tested, Jam is new and things might break. Use with caution. Please report any issues directly on GitHub.

"},{"location":"#installation","title":"Installation","text":"

The easiest way to install Jam is via one of the full-node software solutions that includes Jam as an app or plug-in. You can also install it manually yourself.

Installation

"},{"location":"#first-use","title":"First Use","text":"

Once installed, you will have to add some funds to Jam to get going. If you are new to JoinMarket in general and Jam in particular, you might want to have a look at the \"Cheatsheet.\"

Cheatsheet

"},{"location":"#getting-help","title":"Getting Help","text":"

Since there is no company or fixed team behind Jam or JoinMarket, your best bet to get help are public chat groups and public forums. Also make sure to have a look at the FAQ to get answers to frequently asked questions.

FAQ

GitHub Issues

Matrix Room

Telegram Group

  1. Jam and JoinMarket are separate projects. For more information on JoinMarket, see the JoinMarket GitHub Page \u21a9

"},{"location":"FAQ/","title":"FAQ","text":"

Have a question that is not listed here? Let us know!

Contributing

"},{"location":"FAQ/#frequently-asked-questions","title":"Frequently Asked Questions","text":"

This FAQ compiles questions that relate to Jam in particular. For things related to JoinMarket in general, please refer to the JoinMarket documentation.

"},{"location":"FAQ/#how-much-can-i-earn","title":"How much can I earn?","text":"

Earning sats entails providing liquidity to other market participants. Consequently, how much you can earn depends on multiple factors, market conditions and liquidity size being two of them. In general, the more liquidity you provide, the more you can earn. That being said, you are competing in an open market, and because competition is global and only constraint by market forces, the margin is usually thin.

If your offers are not taken by market participants, your offer might be too expensive. Check the order book and compare your offer to the market price. If your offer is competitive and is still ignored, make sure to create a Fidelity Bond, which signals that you are a serious market participant and not a malicious entity.

See also \"a few words about incentives\" from the JoinMarket documentation.

"},{"location":"FAQ/#how-high-are-the-fees-that-i-do-have-to-pay","title":"How high are the fees that I do have to pay?","text":"

The amount of fees you have to pay depends on market and blockspace conditions. They are dictated by supply and demand, both for collaborative transactions and single user transactions.

Market makers provide liquidity and set the fee they want to earn, either in absolute or percentage terms. Market takers have to agree to take these offers voluntarily. Check the orderbook to get an up-to-date overview of the current fee market.

In addition to these fees, you will have to pay mining fees for you and the makers. Mining fees depend on how many transactions are currently in the mempool. Inspect your mempool or use a public site like mempool.space to do a fee estimation.

Hint

We recommended that you run your own mempool.space instance on your full node.

See also \"a note on fees\" from the JoinMarket documentation.

"},{"location":"FAQ/#im-getting-an-error-when-trying-to-open-the-wallet","title":"I'm getting an error when trying to open the wallet","text":"

The following error can pop up in case JoinMarket didnt't shut down cleanly:

wallet.jmdat cannot be created/opened, it is locked.\n

Warning

Make sure that you have written down your wallet seed before executing any command

You can resolve this by manually deleting the wallet .lock file as explained in issue #173.

"},{"location":"FAQ/#why-is-my-collaborative-transaction-taking-so-long","title":"Why is my collaborative transaction taking so long?","text":"

This can have multiple reasons. Tor or general network connection issues, participants not responding in a timely manner, missing requirements to source commitments (see the docs), period of slow block production, unexpected increase of transaction fees, etc.

For a better assessment, the following can be taken as a guideline:

  • single collaborative transactions generally take only a few minutes (<15min)
  • a scheduled sweep can take hours, even days (<3days)

If an operation takes longer than that, then there might be a different issue. See \"Something else is/seems stuck\" for more info.

"},{"location":"FAQ/#something-else-isseems-stuck-what-can-i-do","title":"Something else is/seems stuck; what can I do?","text":"

If a single collaborative transaction takes hours, or if your scheduled sweep already takes over three days, there might be a different underlying problem.

A general rule of thumb is: Any operation either succeeds or fails. If an operation is aborted prematurely, there is no danger of loss of funds.

All operations can be aborted by locking your wallet.

Since Jam does not yet have a way to provide fine grained error information to users, it is always a good idea to inspect the log files for warning and error messages.

"},{"location":"FAQ/#how-do-i-view-the-log-file","title":"How do I view the log file?","text":"

If you are running Jam with one of the supported integrations (RaspiBlitz, Citadel, Umbrel, etc.) chances are you can view the logs inside the app (See Settings > Show logs).

If the option is not displayed, or if you run the standalone docker image yourself, you can find all log files inside the container in directory /var/log/jam/. See jmwalletd_stdout.log or jmwalletd_stderr.log for problems with Jam.

e.g. tail -n 200 -f /var/log/jam/jmwalletd_stdout.log

If you run JoinMarket natively, you can find the logs files inside the logs folder of JoinMarket's working directory (e.g. /home/<user>/.joinmarket/logs)

e.g. tail -n 200 -f /home/user/.joinmarket/logs/jmwalletd_logs.log

"},{"location":"FAQ/#how-to-resolve-no-connection-to-gateway","title":"How to resolve \"No connection to gateway\"?","text":"

This can have several reasons and basically means that the UI cannot reach the backend service. Depending on your installation (native setup, docker images, local/remote hosts, etc.), there are a number of things you should verify.

Please make sure that:

  • Your Bitcoin Core instance is up and running, fully synced and is accepting RPC requests.
bitcoin-cli getblockchaininfo\n
  • The backend service is running and is reachable on the specified ports. Verify that you get a response from the server, by executing a request on the host that is running your JoinMarket instance (if you run an Umbrel node, this requests needs to be executed inside the Jam docker container):
curl --insecure https://127.0.0.1:28183/api/v1/session\n
  • Check the logs for any errors or warnings.

  • If all the above fails, try restarting every service or do a complete node reboot.

  • As a last resort, seek help in the support channel.

"},{"location":"FAQ/#can-i-import-an-existing-wallet","title":"Can I import an existing wallet?","text":"

Yes, it is possible to import an existing wallet. However, not yet via the web interface, but with a few manual steps via the command line.

  • Log into the host machine, e.g. with ssh (see an example for Umbrel below)
  • Navigate to JoinMarket's root directory
  • Invoke the recover mechansim of the wallet-tool.py script
. jmvenv/bin/activate # if virtual environment is enabled\npython3 scripts/wallet-tool.py recover --gap-limit=200 --recoversync\n
  • Answer questions (provide seed phrase, etc.). Make sure that you put \".jmdat\" at the end of the name for the wallet, otherwise it won't be displayed in Jam. Answer the question for support of fidelity bonds with \"y\" (yes).
root@821939a90a7c:/src# python3 scripts/wallet-tool.py recover --gap-limit=200 --recoversync\nUser data location: /root/.joinmarket/\nInput mnemonic recovery phrase: zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong\nInput mnemonic extension, leave blank if there isnt one: \nEnter new passphrase to encrypt wallet: \nReenter new passphrase to encrypt wallet: \nInput wallet file name (default: wallet.jmdat): recover.jmdat\nWould you like this wallet to support fidelity bonds? write 'n' if you don't know what this is (y/n): y\nWrite down this wallet recovery mnemonic\n\nzoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong\n\nRecovered wallet OK\n
  • All done.

Here is an example of how you'd get into the Jam container on Umbrel:

  • Log into your umbrel with ssh umbrel@umbrel.local
  • Move into the jam container with docker exec -it jam_web_1 bash
  • Navigate to JoinMarket's root directory with cd /src
  • Now follow the import procedure as explained above
  • Leave the command line with exit (multiple times)
"},{"location":"about/","title":"About","text":"

Jam is a graphical user interface for JoinMarket, and while obviously related, is a separate project developed by a separate set of people.

"},{"location":"about/#about-jam","title":"About Jam","text":"

Jam is a free and open-source project that aims to improve the financial privacy of yourself and others, without relying on a trusted third party. It was started in 2021 by various volunteers and is still developed and maintained on a volunteer basis. As mentioned above, Jam is a front-end for JoinMarket, a privacy-focused bitcoin software that uses a peer-to-peer marketplace to facilitate collaborative transactions.

The goal of Jam is to provide an interface that makes JoinMarket easier to use, and thus more easily accessible for more people.

"},{"location":"about/#about-joinmarket","title":"About JoinMarket","text":"

JoinMarket is a special kind of software that is aimed at improving the privacy and fungibility of bitcoin transactions. The main way to improve privacy and fungibility on-chain is via collaborative transactions.

A collaborative transaction requires the coordination of multiple parties. The right resources (UTXOs) have to be available in the right quantity at the right time.

Consequently, the problem that needs to be solved is not a technological problem, but an economic problem. JoinMarket solves this problem not by central coordination, but by creating a market that allows participants to allocate these resources in the best way, according to their individual needs.

"},{"location":"about/#about-the-name","title":"About the Name","text":"

The name \"Jam\" is a backronym, stands for JoinMarket's Awesome, Man, and shouldn't be taken too seriously. However, it works on multiple levels (Let's jam the signal!) and \"cooking jam\" is also a fun metaphor for mixing something in a tasty way (and putting it in jars).

"},{"location":"about/#about-the-philosophy","title":"About the Philosophy","text":"

We believe that, in the long run, open protocols will survive. Platforms, on the other hand, are run by companies and all companies eventually go bankrupt.

The motivation behind Jam (and JoinMarket\u2014and Bitcoin, for that matter) is to build something that doesn't go away.

Motivation

"},{"location":"contribute/","title":"Contributing","text":"

There are many ways you can contribute: testing, sharing ideas, writing documentation, creating tutorials, and\u2014of course\u2014writing code.

"},{"location":"contribute/#say-hello","title":"Say Hello","text":"

It doesn't hurt to say hi and connect with the people that are already working on Jam, or have worked on it in the past.

Matrix Room

Telegram Chat

"},{"location":"contribute/#study-the-basics","title":"Study the Basics","text":"

Identity and privacy are complex topics in general, and Bitcoin privacy is particularly tricky. Make sure to familiarise yourself with the basics before you get involved.

Privacy Fundamentals

Bitcoin Wiki: Privacy

"},{"location":"contribute/#understand-the-philosophy","title":"Understand the Philosophy","text":"

Before you really get going you should understand the philosophy behind Jam and the foundations it is built upon.

Motivation

A Cypherpunk's Manifesto

"},{"location":"contribute/#what-to-work-on","title":"What to Work On","text":"

While a very rough roadmap and some milestones exist, it's usually best to \"scratch your own itch.\" Found a bug? Fix it! Have a proposal to make something better? Create an issue! Found a typo? Fix it! Is Jam not available in your language? Translate it!

It can be daunting to get started, but Jam, like every software project, is just code & design & text.

"},{"location":"contribute/#code","title":"Code","text":"

Review a pull request or work on some open issues. Small tasks that are relatively easy to do will have the \"good first issue\" label.

"},{"location":"contribute/#design","title":"Design","text":"

Have a look at the Figma files, comment on them, or propose a change.

"},{"location":"contribute/#text","title":"Text","text":"

If you're good with words and copy editing, or if you want to help to translate Jam into multiple languages, join the translation team.

"},{"location":"contribute/#just-get-started","title":"Just Get Started!","text":"

Since all development happens out in the open and there are no gatekeepers, getting involved is as easy as showing up.

This is a free and open-source software project and we love receiving pull-requests, bug reports, ideas, and feedback from everyone. See the CONTRIBUTING.md file on GitHub for more details on how to get started participating in this project.

"},{"location":"glossary/","title":"Glossary","text":"

Unfortunately, there is no way to talk about bitcoin privacy and the intricacies of JoinMarket without a little bit of jargon.

This glossary explains some of the concepts and terms used in Jam.

[ A \u00b7 B \u00b7 C \u00b7 D \u00b7 E \u00b7 F \u00b7 G \u00b7 H \u00b7 I \u00b7 J \u00b7 K \u00b7 L \u00b7 M \u00b7 N \u00b7 O \u00b7 P \u00b7 Q \u00b7 R \u00b7 S \u00b7 T \u00b7 U \u00b7 V \u00b7 W \u00b7 X \u00b7 Y \u00b7 Z ]

"},{"location":"glossary/#a","title":"A","text":""},{"location":"glossary/#address","title":"Address","text":"

A bitcoin address\u2014also called bitcoin invoice address1\u2014is a string of characters that you send to someone else to receive funds.

There are currently three invoice address formats in use:

  • P2PKH starting with 1
  • P2SH starting with 3
  • Bech32 starting with bc1

For more details please refer to the Bitcoin Wiki. Jam defaults to Bech32 addresses.

"},{"location":"glossary/#address-reuse","title":"Address Reuse","text":"

Address reuse refers to the practice of reusing a single bitcoin invoice address for multiple transactions. It is highly discouraged since it harms the privacy of yourself and others. You should never reuse addresses.

Bitcoin Wiki: Address Reuse

"},{"location":"glossary/#anonymity-set","title":"Anonymity Set","text":"

The only way to hide in plain sight is by hiding in a crowd. The anonymity set is simply the size of this crowd.

If you are putting on a hat and sunglasses to hide in a crowd of people that are wearing the same hat and sunglasses, your anonymity set is the size of this crowd. If said crowd is 50 people, an attacker could mistake you for anyone out of these 50 people. Similarly, when doing a collaborative transaction in bitcoin, you are creating an onchain footprint that is equivalent to the onchain footprint of others.

"},{"location":"glossary/#b","title":"B","text":""},{"location":"glossary/#base-layer","title":"Base Layer","text":"

Bitcoin's base layer (or Layer 1) refers to any transaction that touches the timechain, i.e. all onchain transactions. The base layer is concerned with global consensus and settlement.

Higher layers build ontop the settlement assurrances of the base layer. One example of a Layer 2 system is the Lightning Network. All money is layered, including gold and fiat monies. Read Layered Money by Nik Bhatia to understand this in more detail.

Layered Money

"},{"location":"glossary/#batch-transaction","title":"Batch Transaction","text":"

A batch transaction is a transaction that combines multiple real-world transactions into one on-chain transaction. It has multiple inputs and multiple outputs. Different parties may control one or multiple inputs and receive one or multiple outputs.

Privacy Fundamentals

"},{"location":"glossary/#bech32","title":"Bech32","text":"

Bech32 is an invoice address format. It was specified in BIP 173 and is used for both SegWit and Taproot addresses.

"},{"location":"glossary/#blockchain","title":"Blockchain","text":"

A mostly meaningless marketing term used to confuse newcomers. While \"block chain\" is still the main term used to refer to Bitcoin's linked data structure of blocks, it has increasingly become meaningless over the years as it got co-opted by grifters, charlatans & marketers. A better, more descriptive term of said data structure is timechain.

"},{"location":"glossary/#c","title":"C","text":""},{"location":"glossary/#chain-analysis","title":"Chain Analysis","text":"

Chain analysis is is the practice of applying heuristics to a timechain's public transaction graph. The goal of chain analysis is to link the pseudonymous identities created by bitcoin software with \"real\" identities corresponding to natural persons or entities.

Chain analysis is based on flawed assumptions, because ownership in bitcoin is defined by secret knowledge, not possession. Identities can only be linked probabilistically, not provably. One of the main assumptions used by chain analysis companies is the common input ownership heuristic. Collaborative transactions break this heuristic.

"},{"location":"glossary/#coinjoin","title":"CoinJoin","text":"

A CoinJoin is a collaborative transaction that combines inputs from multiple parties. The purpose of a CoinJoin is to combine inputs and create outputs in ways that improves the financial privacy of participants, without relying on a trusted third party for custody. When done correctly, a CoinJoin breaks any deterministic links between transactions, moving the process of chain analysis from quasi-deterministic with high certainty to probabilistic with low certainty.

CoinJoins break the common input ownership heuristic that is used by chain analysis companies to de-anonymize actors. The concept was 1st introduced in 2011 by Bitcointalk user hashcoin2, but later popularised in 2013 by Gregory Maxwell.34

All CoinJoin transactions are collaborative transactions. The two main types of CoinJoin transactions are equal-output and unequal-output CoinJoins. Other differences might be interactivity (or lack thereof) and number of participants.

"},{"location":"glossary/#collaborative-transaction","title":"Collaborative Transaction","text":"

A collaborative transaction is a bitcoin transaction that is initiated and signed by multiple participants. A collaborative transaction involves two or more parties and is thus always a batch transaction. All CoinJoins are collaborative transactions.

"},{"location":"glossary/#change","title":"Change","text":"

When using physical cash, spending a $100 bill to pay for a $25 item, you will get $75 back in change. The reason for this is that you can't spend just a part of the bill, because ripping off a quarter of it for payment will invalidate the bill. Consequently, when bills change hands, the whole bill has to be spent, and an appropriate amount of change goes back to the spender.

Bitcoin works the same way. When sats change hands, the spender has to spend the whole UTXO. Bitcoin creates the appropriate amount of change automatically. Because all transactions are recorded transparently and publicly on the timechain,

As of this writing,5 a simple spend is the most common transaction type, which describes the example given above: one input ($100 bill) produces two outputs: $25 for the merchant, and $75 in change. The act of an outside observer guessing whether you bought something for $25 or $75 (or: who was the customer of the transaction, and who was the merchant) is what is called change detection.

"},{"location":"glossary/#change-detection","title":"Change Detection","text":"

When it comes to chain analysis, change detection is the name of the game. The goal of chain analysis companies is to link identities to transactions, and to do that, one has to detect whether funds changed hands or not.

Technically speaking, change detection is trying to figure out which output of a transaction is a change output. Change detection is based on various heuristics. False positives will always exist, even if the transaction under scrutiny is a simple spend. Consequently, it is more an art than a science.

To quote one special investigations team speaking on chain analysis:

Attributing ownership, however, is often nuanced because outside observers can only infer it depending on factors such as availability and quality of the evidence. Evidence means proof that indeed an address belongs to an individual or entity. Unless you own an address yourself, it is very difficult to say with absolute certainty who an address is owned by. This is why it\u2019s more fitting to consider blockchain analytics more of an art than science.

CSIT

Keep in mind that ownership can change without any on-chain transaction happening, e.g. by passing on a private key directly. It is also possible that amount to be paid lines up perfectly with a single UTXO, meaning that what looks like a self-spend is actually a payment.

One can only conclude, as is also mentioned in the report linked above, that \"an external observer cannot possibly gain a full picture or claim 100% confidence in ownership attribution.\"

Privacy Fundamentals: The Bitcoin Transaction

Bitcoin Wiki: Change Detection

"},{"location":"glossary/#cioh","title":"CIOH","text":"

Short for Common Input Ownership Heuristic.

"},{"location":"glossary/#common-input-ownership-heuristic","title":"Common Input Ownership Heuristic","text":"

The common input ownership heuristic assumes that all inputs of a transaction are controlled by a single entity. This assumption is clearly wrong, because collaborative transactions exist. CoinJoin transactions are designed to break this heuristic.

"},{"location":"glossary/#d","title":"D","text":""},{"location":"glossary/#doxxic-change","title":"Doxxic Change","text":"

\"Doxxic\" change is any leftover change that is going back to you when participating in an equal-output CoinJoin. Doxxic change is problematic because it can potentially destroy any privacy benefits gained from a CoinJoin.

The word is a combination of \"toxic\" and \"doxxing.\" Doxxing is the act of finding out the legal identity (or similar identifiying information) of a pseudonymous entity. Bitcoin is a pseudonymous system and does not require the True Names6 of participants.

You can use the sweep functionality to avoid doxxic change in Jam.

"},{"location":"glossary/#e","title":"E","text":""},{"location":"glossary/#eclipse-attack","title":"Eclipse Attack","text":"

An eclipse attack is an attack in networked systems in which an attacker targets a node to convince it of a false network state. The attacker surrounds the node in order to conceal or block off accurate information, leaving the attacked node(s) in the dark in terms of the global network state.

An eclipse attack is similar to a Sybil attack.

Bitcoin Stack Exchange: Eclipse Attack vs. Sybil Attack

"},{"location":"glossary/#equal-output-coinjoin","title":"Equal-Output CoinJoin","text":"

An equal-output CoinJoin is a collaborative transaction that produces outputs of equal denomination, i.e. outputs of equal value when measured in sats. For this reason, these types of transactions are also referred to as equal-amount or equal-value CoinJoin transactions.

Equal-output CoinJoins are batch transaction that are easily identifiable on-chain due to their uniform output structure.

Like any collaborative transaction, an equal-output CoinJoin breaks the Common Input Ownership Heuristic. Participating in such a transaction allows you to gain privacy by \"hiding in the crowd.\"

Jam defaults to collaborative transactions when sending and sweeping, creating equal-output CoinJoins.

"},{"location":"glossary/#f","title":"F","text":""},{"location":"glossary/#fidelity-bond","title":"Fidelity Bond","text":"

A fidelity bond is an insurance policies which protects the policyholder from wrongful acts committed by others. The term comes from the world of business and finance, thus the policyholders are usually companies, and the other parties are usually employees.

In JoinMarket, a fidelity bond is a mechanism which ensures that market actors act honestly. It is a protection mechanism against Sybil attacks, because a fidelity bond makes the creation of cryptographic identities costly.

Warning

It is impossible to move or spend funds that are locked in a fidelity bond before the bond expires. They cannot be used in collaborative transactions (neither as taker nor as maker) as fidelity bonds are time-locked by the Bitcoin protocol.

Fidelity bonds improve the privacy guarantees of the whole system and increase your chance of being chosen as a market maker drastically.

What Are Fidelity Bonds and How Do They Work in JoinMarket?

JoinMarket: Fidelity Bonds

JoinMarket: Financial Mathematics of Fidelity Bonds

Creating a Fidelity Bond in Jam

"},{"location":"glossary/#j","title":"J","text":""},{"location":"glossary/#jam","title":"Jam","text":"

Jam is both the name of the project and the verb we use when a collaborative transaction is in progress.

Sir! The radar, sir! It appears to be... [Jam starts flowing through the computer screen] jammed!

Spaceballs

About

jamapp.org

"},{"location":"glossary/#jar","title":"Jar","text":"

In Jam, a \"jar\" is a container that holds some sats of yours.7 Jars exist to segregate your sats into multiple buckets that are disconnected from each other, which aids privacy. To not risk any privacy degradation, you can only spend from one jar at a time.

There are 5 jars by default. The default jar to receive funds is Jar A.

"},{"location":"glossary/#m","title":"M","text":""},{"location":"glossary/#maker","title":"Maker","text":"

A market maker is someone who offers bitcoin liquidity to the market, to be used by others for collaborative transactions. You can create an offer via the \"Earn\" tab and become a market maker.

Earn Screen

The Maker Role

"},{"location":"glossary/#mempool","title":"Mempool","text":"

Short for 'memory pool.' A pool of valid bitcoin transactions held by each node, that are not yet confirmed in the timechain.

Mempool

"},{"location":"glossary/#o","title":"O","text":""},{"location":"glossary/#offchain","title":"Offchain","text":"

An offchain (or off-chain) transaction is any transaction that does not happen onchain. Examples include transactions on the Lightning network, the handing over of physical private keys, as well as transactions on centralized ledgers such as exchanges and other trusted third parties.

Some offchain transactions, such as handing over private keys on USB sticks or similar, are outside of the scope of chain analysis. Consequently, chain analysis can never be completely accurate.

"},{"location":"glossary/#onchain","title":"Onchain","text":"

An onchain (or on-chain) transaction is a bitcoin transaction that is settled on the bitcoin timechain. The analysis of these transactions is called chain analysis, which is the spying on and de-anonymizing of bitcoin's users by trying to find patterns in the onchain data.

"},{"location":"glossary/#p","title":"P","text":""},{"location":"glossary/#p2pkh","title":"P2PKH","text":"

Short for pay-to-public-key-hash.

Learn Me A Bitcoin: P2PKH

"},{"location":"glossary/#p2sh","title":"P2SH","text":"

Short for pay-to-script-hash.

Learn Me A Bitcoin: P2SH

"},{"location":"glossary/#payjoin","title":"PayJoin","text":"

A PayJoin is a collaborative transaction between two parties that facilitates an actual payment for a good or service. The merchant agrees to provide one or multiple inputs to the transaction, increasing the privacy of both parties.

A PayJoin has different onchain characteristics than an equal-output CoinJoin and is not detectable via chain analysis alone. A PayJoin transaction has multiple interpretations, all of which are equally valid. In addition to breaking the common input ownership heuristic it poisons the basis of all chain analysis, because of its undetectability.

Bitcoin Wiki: PayJoin

Bitcoin Wiki: PayJoin Adoption

"},{"location":"glossary/#s","title":"S","text":""},{"location":"glossary/#sats","title":"Sats","text":"

Short for satoshis, plural of sat (satoshi).

A sat the smallest fraction of a bitcoin that can be expressed on-chain. There are 100,000,000 sats in a bitcoin. There are multiple currency symbols for a sat emerging. In Jam, the sat symbol8 is used:

"},{"location":"glossary/#scheduler","title":"Scheduler","text":"

The 'scheduler' is a component of JoinMarket which schedules multiple collaborative transactions in a row. It will use random intervals and amounts to make timing analysis and de-anonymization via chain analysis more difficult.

The 'Sweep' screen uses the scheduler to sweep funds to one or multiple external wallets under your control.

"},{"location":"glossary/#simple-spend","title":"Simple Spend","text":"

A transaction that splits one input into two outputs: payment and change.

The \"simple spend\" is the most common bitcoin transaction type to date, since most wallet implementations do not optimize for privacy. For most simple spend transactions it is possible to discern which output is the actual payment or which one is the change. This change detection makes the tracing of funds possible.

Privacy Fundamentals: The Bitcoin Transaction

"},{"location":"glossary/#snicker","title":"SNICKER","text":"

Simple Non-Interactive Coinjoin with Keys for Encryption Reused.

SNICKER blog post

"},{"location":"glossary/#sybil-attack","title":"Sybil Attack","text":"

A Sybil attack is a special kind of attack in peer-to-peer networked computing. The victim is surrounded by malicious entities, each of which act as if they are a separate entity. The victim believes that everything is in order, that he is getting an accurate state of the network from multiple independent peers. In actuality, the Sybil attacker controls all entities surrounding the victim. Consequently, the attacker is able to trick the victim into accepting a malicious network state.

JoinMarket uses fidelity bonds to protect users from Sybil attacks.

Design for Improving JoinMarket's Resistance to Sybil Attacks Using Fidelity Bonds

Wikipedia: Sybil Attack

"},{"location":"glossary/#sweep","title":"Sweep","text":"

A 'sweep' send will transfer all funds of a jar or all funds of your wallet. To sweep all funds from your wallet multiple transactions are created using the scheduler.

'Sweep' Screen

"},{"location":"glossary/#t","title":"T","text":""},{"location":"glossary/#taint","title":"Taint","text":"

Taint is an external property defined by chain analysis surveillance firms. It is an attempt to trace the origin and ownership of UTXOs, classifying their owners and building lists of \"good\" and \"bad\" money.

All taint in bitcoin always is and always will be arbitrarily defined and probabilistically applied. Just like change detection, it is more an art than a science. It can never be done exactly. False positives and false negatives will always arise.

The bitcoin network is indifferent to taint. Miners will include any transaction in a valid block that will reward them economically. Any application of taint on the block production level is equivalent to imposing additional rules via a soft-fork, which fully validating nodes can reject.

"},{"location":"glossary/#taker","title":"Taker","text":"

A market taker is someone who buys bitcoin liquidity from the market, taking up market makers on their offers. You can see active offers in the order book.

You will automatically take offers when running the scheduler via the \"Sweep\" functionality.

Sweep

Earn Screen

The Taker Role

"},{"location":"glossary/#timechain","title":"Timechain","text":"

The data structure of Bitcoin's base layer. It represents a timestamped and linked list of blocks. Anyone can create a new block, but each block must have sufficient proof of work, making it costly to create new blocks.

Bitcoin is Time

"},{"location":"glossary/#timelock","title":"Timelock","text":"

A UTXO can be locked up by a script which defines that said UTXO can only be spent in a block that is higher than a certain value. This makes UTXOs unspendable before a specific time.

"},{"location":"glossary/#transaction","title":"Transaction","text":"

A bitcoin transaction describes the movement of sats. It is structured data that describes inputs and outputs, among other things. A valid bitcoin transaction has at least one input and at least one output. Every transaction input refers to the output of a previous transaction. We say that an input \"consumes\" an output. If an output is not consumed yet, we speak of an unspent transaction output, or UTXO, for short.

Privacy Fundamentals: The Bitcoin Transaction

Bitcoin Wiki: Transaction

Learn Me a Bitcoin: Transactions

"},{"location":"glossary/#tx","title":"TX","text":"

Short for transaction.

"},{"location":"glossary/#u","title":"U","text":""},{"location":"glossary/#unspent-transaction-output","title":"Unspent Transaction Output","text":"

The tip of the chain of signatures which originates in a coinbase output. It's a \"coin\" that has not yet been spent and can still be spend.

"},{"location":"glossary/#utxo","title":"UTXO","text":"

Short for Unspent Transaction Output.

  1. The term invoice is proposed in BIP-179 as an alternative.\u00a0\u21a9

  2. Blind Bitcoin Transfers hashcoin, July 2011\u00a0\u21a9

  3. I taint rich! Maxwell, Jan. 2013\u00a0\u21a9

  4. CoinJoin: Bitcoin privacy for the real world Maxwell, Aug. 2013\u00a0\u21a9

  5. Block 744,811\u00a0\u21a9

  6. Vernor Vinge, 1981, True Names \u21a9

  7. What we call \"jars\" are usually called \"mixdepths\" in JoinMarket. They are also referred to as \"pockets\" and \"accounts\" in some of the older parts of the JoinMarket documentation.\u00a0\u21a9

  8. satsymbol.com \u21a9

"},{"location":"interface/00-cheatsheet/","title":"Cheatsheet","text":"

While everyone will use Jam differently, here is one way you can think about the general application flow:

Some of your UTXOs might be chunky and identifiable, like whole or large pieces of fruit. Once you make delicious jam out of them, they are less chunky and less identifiable. You are free to offer your fruits to others so they can make jam more easily.

Without the fruity metaphor: to increase the privacy and fungibility of your funds\u2014and thus your security overall\u2014you should use Jam as both a market maker ('Earn' tab) and a taker ('Send' and 'Sweep' tabs). Use a Jar's sweep functionality or the Scheduler to transfer funds out of Jam, e.g. to move all your funds to cold storage or to use them to open lightning channels. If you want to pay others for goods and services, use send.

"},{"location":"interface/00-cheatsheet/#first-use","title":"First Use","text":"
  1. Receive sats to fund your wallet
  2. Send a collaborative transaction to one of your jars
  3. Earn sats by offering liquidity1
  4. Sweep your wallet using the scheduler
  5. Rinse and repeat!

Click \"Cheatsheet\" at the bottom of the screen to open up the cheatsheet in Jam.

Receive

"},{"location":"interface/00-cheatsheet/#things-to-note","title":"Things to Note","text":"

Some processes in Jam might take a long time to complete. Further, Jam is considered beta software. While JoinMarket is tried and tested, Jam is new and things might break. Use with caution. Please report any issues directly on GitHub.

Make sure to understand the privacy fundamentals, best practices, as well as the motivation behind this software. Also, understand that you are participating in a free market. How much you can earn and how many fees you have to pay depends on market conditions.

Motivation

Privacy Fundamentals

Fees

  1. Make sure to create a fidelity bond to increase the chances of your offer being taken.\u00a0\u21a9

"},{"location":"interface/01-receive/","title":"Receive","text":"

Use the 'Receive' tab to receive funds.

A new invoice address will be generated every time. You can scan the QR code with a mobile wallet or copy/paste the invoice address to receive funds from someone else, or send funds from another wallet yourself.

Info

Jam uses jars under the hood to separate funds into disconnected containers. Think of jars as different pockets in your wallet, or different identities. The default jar to receive funds is Jar A.

Once you have funded your wallet, you can use the 'Send' tab to do a collaborative transaction.

Send

"},{"location":"interface/02-send/","title":"Send","text":"

Use the 'Send' tab to send funds to someone or to one of jars. Jam defaults to collaborative transactions when sending, which enhances your privacy and security.

Info

Jam uses jars under the hood to separate funds into disconnected containers. Think of jars as different pockets in your wallet, or different identities.

You can choose the number of collaborators in the send options. The higher the number of collaborators, the larger your anonymity set.

Use the 'Sweep' button in the amount field to empty a single jar, or use the Sweep tab to sweep all non-frozen funds of your wallet to external addresses.

After you made your first collaborative transaction with one of your jars as the recipient, you are ready to earn.

Earn

"},{"location":"interface/03-earn/","title":"Earn","text":"

Use the 'Earn' tab to earn sats by offering liquidity to other market participants. You will be acting as a market maker. Creating a fidelity bond is recommended. In Jam, takers pay 100% of the mining fees: as a market maker, you will not pay anything. Just profit!

"},{"location":"interface/03-earn/#fidelity-bonds","title":"Fidelity Bonds","text":"

Make sure to create a fidelity bond to increase the chances of your offer being taken.

A fidelity bond is a mechanism which ensures that market actors act honestly. It is a protection mechanism against Sybil attacks. A fidelity bond makes the creation of cryptographic identities costly.

Fidelity bonds improve the privacy guarantees of the whole system and increase your chance of being chosen as a market maker drastically.

Be aware that funds locked in a Fidelity Bond will not be included in your offer amount, so remember to keep additional funds in order to participate as a market maker.

Warning

It is impossible to move or spend funds that are locked in a fidelity bond before the bond expires. They cannot be used in collaborative transactions (neither as taker nor as maker) as fidelity bonds are time-locked by the Bitcoin protocol.

Fidelity Bonds

"},{"location":"interface/03-earn/#offer-options","title":"Offer Options","text":"

There are two types of offers:

  1. Absolute offer: the fee you are charging is set in absolute terms, e.g. as 250 sats.
  2. Relative offer: the fee you are charging is set in percentage terms, e.g. as 0.03%.

Once you are done earning, you can sweep all funds to an external wallet.

Sweep

"},{"location":"interface/04-sweep/","title":"Sweep","text":"

Use the 'Sweep' tab to empty your wallet using the scheduler. The scheduler will execute a series of collaborative transactions with randomized parameters, which will send your funds to multiple destination addresses over time.

Once the scheduler is active you will see a green indicator light, which means that the scheduler service is running. The service will take any matching offer automatically.

You can stop the scheduler at any time.

Cheatsheet

"},{"location":"interface/fidelity-bonds/","title":"Fidelity Bonds","text":"

A fidelity bond is a mechanism which ensures that market actors act honestly. It is a protection mechanism against various kinds of attacks that involve the creation of fraudulent identities.

Glossary: Fidelity Bond

Warning

It is impossible to move or spend funds that are locked in a fidelity bond before the bond expires. They cannot be used in collaborative transactions (neither as taker nor as maker) as fidelity bonds are time-locked by the Bitcoin protocol.

You can create a fidelity bond via the Earn screen. It involves the following steps:

  1. Set expiration date (which defines the bond's duration)
  2. Select a jar as funding source
  3. Select a UTXO, preferably one labeled cj-out

After that, you will be asked to review the bond configuration. If everything looks right, you can create the fidelity bond which will time-lock your funds for the set duration.

Refer to the screenshots below to understand the steps in more detail:

Orderbook

Earn

"},{"location":"interface/settings/","title":"Settings","text":"

Access the settings by clicking on the gear icon () in the top-right corner.

"},{"location":"interface/settings/#general-settings","title":"General Settings","text":"
  • Hide/show balance
  • Display amounts in bitcoin or sats
  • Switch between light & dark theme
  • Set interface language (Your language is missing? Contribute!)
"},{"location":"interface/settings/#wallet-settings","title":"Wallet Settings","text":"

Jam supports the creation and handling of multiple wallets. However, only one wallet can be actively used at a time. Wallets are locked when not used. Your \"active\" wallet is the one that is currently unlocked.

  • Show seed phrase: show the seed phrase of the active wallet
  • Lock wallet: lock the wallet that is currently active
  • Switch wallet: open another wallet and lock the current one
  • Create new wallet: initialize a new, empty wallet

Question

Want to import a wallet? Look at the FAQ!

"},{"location":"interface/settings/#community-links","title":"Community Links","text":"
  • Documentation: you are here!
  • GitHub: track issues & participate in development
  • Matrix: technical discussion & help
  • Telegram: general discussion (old room)
  • Jam Twitter
  • JoinMarket Twitter
"},{"location":"interface/wallet/","title":"Wallet Overview","text":"

Clicking on the active wallet in the top-left corner will open the wallet view.

You can see your jars and whats in them by clicking on the arrow. Clicking on a jar will open its detail view, which allows you to inspect individual UTXOs, as well as freeze/unfreeze them.

"},{"location":"market/fees/","title":"Fees","text":"

Fees play a crucial role in the incentive structure of both Bitcoin and JoinMarket. They form the basis for the economic incentives of both systems. In Bitcoin, you pay fees to a miner in order for your transaction to be included in a block. The higher the fee you are willing to pay, the higher the likelihood that your transaction will be included quickly.

In JoinMarket, you pay fees to market makers in order to use their liquidity to both of your advantage. However because the market maker gets the fee as he is waiting around and providing the liquidity.

Consequently, when you are sending a collaborative transaction in Jam\u2014or when you are using the scheduler to do multiple transactions\u2014you have to pay fees to miners and makers. How high these fees are depends on market and mempool conditions.

Of course, you can offer liquidity yourself via the Earn functionality, allowing you to be on the receiving end when it comes to maker fees.

Earn

"},{"location":"market/fees/#paying-maker-fees","title":"Paying Maker Fees","text":"

When doing a collaborative transaction via the Send or Sweep tabs, you are taking liquidity offers from others, effectively becoming a market taker.

How much you will pay in maker fees depends on the fee market of the current offers. You can get an overview of fees by inspecting the order book.

FAQ: How high are the fees that I do have to pay?

Orderbook

"},{"location":"market/fees/#paying-mining-fees","title":"Paying Mining Fees","text":"

Just like all users of onchain bitcoin, you will have to pay transaction fees to miners.

Note that collaborative transactions are larger, in terms of bytes, than \"regular\" bitcoin transactions. Since the cost of an onchain transaction is determined by its size in bytes\u2014not by value transferred\u2014a collaborative transaction is more expensive than a simple spend.

FAQ: How high are the fees that I do have to pay?

Mempool

"},{"location":"market/fees/#earning-maker-fees","title":"Earning Maker Fees","text":"

As mentioned above, you can use the Earn tab to earn maker fees yourself. Simply choose an offer type, select how many fees you would like to earn, and press \"Start Earning!\".

Make sure to check the orderbook to compare your offer with current market rates. If your offer isn't competitive, it's likely nobody will take it and thus you will earn zero sats.

FAQ: How much can I earn?

Orderbook

"},{"location":"market/fees/#fee-conversion","title":"Fee Conversion","text":"

All fees are denominated in sats. Use one of the tools below to convert them to fiat:

  • Sats converter
  • Bitkoin.io

See also \"a note on fees\" from the JoinMarket documentation.

A Note on Fees

"},{"location":"market/mempool/","title":"Mempool","text":"

The mempool (memory pool) is a pool of transactions that are not included in the timechain yet. It is a waiting room for transactions, if you will. Every full node has its own mempool\u2014there is no single mempool that is shared by nodes, there is an individual mempool for every single node. Mempools might differ depending on node configuration. Nodes can decide which transactions to keep, which transactions to pass on to other nodes, and which transactions to drop.

Miners will consult their mempools to construct candidate blocks. Once a transaction is included in a valid block\u2014and your node confirms the blocks validity\u2014it is considered confirmed and removed from the node's mempool.

Learn me a bitcoin: Memory Pool

Miners are incentivised to include transactions that reward them the most, i.e. transactions that pay the highest mining fees. Because mining fees are set by the users, you can view mining fees as a kind of bribe that is paid by the users to the miners. If the bribe is high, the chance of your transaction being included is high. If it is low, the chance of inclusion is lower.

Paying Mining Fees

"},{"location":"market/mempool/#mempool-and-transaction-fees","title":"Mempool and Transaction Fees","text":"

Bitcoin block space is scarce. If onchain activity is high, the mempool will be crowded. The more crowded the mempool, the higher the \"bribe\" you will have to pay to miners.

Fee estimation is an attempt to guess how high the fee needs to be for your transaction to be included in the future. It is more an art than a science, since the future is always uncertain and mempool conditions might change quickly.

Most mempool explorers have some sort of fee estimation. You can also use the estimatesmartfee command to do a fee estimation based on your mempool:

bitcoin-cli estimatesmartfee 21 economical\n
"},{"location":"market/mempool/#mempool-instances","title":"Mempool Instances","text":"

We recommend that you use your own node to inspect the mempool. For example, you can use the getrawmempool command to inspect your mempool:

bitcoin-cli getrawmempool true\n

Of course, plenty of graphical user interfaces exist too. The software that is powering mempool.space is free software and can be installed quite easily on your node.

Mempool One-Click Installation

"},{"location":"market/mempool/#mempool-visualisations","title":"Mempool Visualisations","text":"

You can also refer to public mempool instaces in case you don't have access to the mempool of your own node. Note, however, that using public mempool and block explorers has certain privacy implications, as whoever is running these websites will be able to correlate your IP with the blocks and transactions you look up. Use Tor or a VPN to mitigate this.

mempool.space

There are also great visualisations that help you understand what's going on, Bitfeed and Mempool Observer being two of them.

Visualisation: Mempool Observer

Visualisation: Bitfeed

"},{"location":"market/orderbook/","title":"Orderbook","text":"

The order book (or orderbook) shows what kind of offers are currently on the market. It gives insights in regards to offer types, fees, offer sizes, and fidelity bonds put up by market makers.

Jam will set up a service that allows you to watch the order book on your node. This removes the trust in a third party. You can view the order book directly in Jam via the \"Show orderbook\" button on the Earn screen.

There are also public order books that you can inspect, in case you do not have access to your own node:

nixbitcoin.org/orderbook

"},{"location":"market/volume/","title":"Volume","text":"

In JoinMarket, liquidity is sold and bought on a free market. Consequently, market volume and depth depends on market conditions. You can inspect the order book to get an overview of the current offers.

Orderbook

Some sites show historical statistics in regards to market volume and liquidity. Please note that the statistics shown on these sites sometimes use proprietary data and algorithms.

JoinMarket KPIs

"},{"location":"philosophy/00-motivation/","title":"Motivation","text":"

There is a sacred realm of privacy for every man and woman where he makes his choices and decisions\u2009\u2014\u2009a realm of his own essen\u00adtial rights and liber\u00adties into which the law, gener\u00adally speaking, must not intrude.

Geoffrey Fisher, Archbishop of Canter\u00adbury (1959)

Jam is a tool, just like bitcoin. Before using it, you should understand how you could benefit from using it, how it works, and how to use it correctly. In order to answer the \"how\" you should also understand the \"why\" --- why was it created, and what is the problem in the first place?

To answer that properly, we will have to talk about privacy and financial privacy in general, and bitcoin privacy in particular:

  • Why care about privacy?
  • Why use Jam?
"},{"location":"philosophy/00-motivation/#why-care-about-privacy","title":"Why Care About Privacy?","text":"

\"Privacy is neces\u00adsary for an open society in the electronic age. Privacy is not secrecy. A\u00a0private matter is something one doesn't want the whole world to know, but a\u00a0secret matter is something one doesn't want anybody to know. Privacy is the power to selec\u00adtively reveal oneself to the\u00a0world.\"

Eric Hughes

With these powerful words Eric Hughes opened his Cypher\u00adpunk's Manifesto in 1993. The differ\u00adence between privacy and secrecy is subtle, but impor\u00adtant. Choosing to remain private does not imply that one has secrets or has something to hide. To illus\u00adtrate this just realize that what you do on the toilet or in the bedroom is neither illegal nor a\u00a0secret (in most cases), yet you close the door and pull the curtains.

Similarly, how much money you have and where you spend it is not neces\u00adsarily a\u00a0secret matter. It should, however, be a\u00a0private one. Most would agree that your boss should not know how you choose to spend your salary.

The impor\u00adtance of privacy is recog\u00adnized by many inter\u00adna\u00adtional bodies. From the American Decla\u00adra\u00adtion of the Rights and Duties of Man to the United Nations, it is recog\u00adnized that privacy is a\u00a0funda\u00admental human right worldwide.

No one shall be subjected to arbitrary inter\u00adfer\u00adence with his privacy, family, home or corre\u00adspon\u00addence, nor to attacks upon his honour and reputa\u00adtion. Everyone has the right to the protec\u00adtion of the law against such inter\u00adfer\u00adence or\u00a0attacks.

Article 12, United Nations Decla\u00adra\u00adtion of Human\u00a0Rights

Although Bitcoin was often described as an anony\u00admous method of payment by early propo\u00adnents and by the media, it is anything but. Bitcoin is pseudo\u00adny\u00admous at best and as of today making sure that your pseudo\u00adny\u00admous bitcoin identi\u00adties cannot be linked to your real-world identity proves diffi\u00adcult for most\u00a0people.\u00a0

Bitcoin is an open system. Its public ledger can be inspected and studied by everyone. Thus every trans\u00adac\u00adtion that is embedded in its proof-of-work chain will be exposed for as long as Bitcoin exists: eternity. Failing to follow privacy best practices now can poten\u00adtially have negative reper\u00adcus\u00adsions in the\u00a0future.

Privacy, like security, is a\u00a0process and it is diffi\u00adcult, but not impos\u00adsible. Tools continue to be devel\u00adoped to help preserve privacy while using Bitcoin and fortu\u00adnately most of these tools become easier to use over time. Unfor\u00adtu\u00adnately no panacea exists. One has to remain aware of the trade\u00adoffs and follow best practices as they\u00a0evolve.1

Free Software

"},{"location":"philosophy/00-motivation/#why-jam","title":"Why Jam?","text":"

Jam is a front-end for JoinMarket, a privacy-focused bitcoin software that uses a peer-to-peer marketplace to facilitate collaborative transactions, also called \"CoinJoins.\"2

A collaborative transaction, as the name implies, is a bitcoin transaction that is done collaboratively by multiple parties. The tricky part of getting a collaborative transactions done is not technical, but social. It is a problem of matchmaking, timing, and trust.

Usually, this problem is solved with a central coordinator.

JoinMarket takes a different approach. It allows participants to propose collaborative transactions to others, creating an open market of buyers and sellers, which removes the central coordinator from the equation.

JoinMarket

"},{"location":"philosophy/00-motivation/#tech-fundamentals","title":"Tech Fundamentals","text":"

With the motivation and purpose of Jam covered, understanding the fundamentals of bitcoin in general and bitcoin privacy in particular might be useful.

Privacy Fundamentals

  1. Some parts of the above are based on \"Bitcoin Privacy: Best Practices, written by Gigi and released under CC BY-SA 4.0 license.\"\u00a0\u21a9

  2. We prefer to refer to them as collaborative transactions, which is more concise and explanatory.\u00a0\u21a9

"},{"location":"philosophy/01-free-software/","title":"Free Software","text":"

Jam is free as in freedom. We believe that free software is an imperative for a free society, which is why Jam is released under a free software license.

Bitcoin is financial software. Consequently, any financial liberation that is enabled by Bitcoin rests on the four essential freedoms granted by free software.

What is Free Software?

\u201cFree software\u201d means software that respects users' freedom and community. Roughly, it means that the users have the freedom to run, copy, distribute, study, change and improve the software. Thus, \u201cfree software\u201d is a matter of liberty, not price. To understand the concept, you should think of \u201cfree\u201d as in \u201cfree speech,\u201d not as in \u201cfree beer.\u201d

Free software puts the users in control, both collectively and individually. Free software is not only about being \"open\" and \"more secure.\" While these are nice side-effects, the main issue is about control and respecting user's freedoms.

Why Free Software Is Even More Important Now

Freedom means having control over your own life. If you use a program to carry out activities in your life, your freedom depends on your having control over the program. You deserve to have control over the programs you use, and all the more so when you use them for something important in your life.

Most software and software products force the user into a master-slave relationship, as do most monetary systems and financial products. Bitcoin is freedom money because the software that makes Bitcoin possible is free software\u2014free as in freedom. There are no masters, only peers.

Bitcoin

"},{"location":"philosophy/02-bitcoin/","title":"Bitcoin","text":"

There is much to be said about Bitcoin and why it was created. Many books have been written, much speculation was and is still being had in terms of Satoshi's \"true\" vision and motivation.3

Undoubtedly, there are certain values embodied in the Bitcoin system\u2014certain opinions that are embedded in the code, expressing how things should be done and what should be avoided. Nothing makes this more clear than the announcement post of Bitcoin, written by Satoshi himself.

Below are some highlights that are particularly relevant:

I've developed a new open source P2P e-cash system called Bitcoin. It's completely decentralized, with no central server or trusted parties, because everything is based on crypto proof instead of trust.

No central server. No trusted third party. Peer-to-peer (P2P), instead of client-server or master-slave.

Thanks to strong cryptography, trust in third parties can be eliminated. When possible, rely on cryptographic proof instead of trust. Trusted third parties should be eliminated because (a) they introduce friction and (b) they are security holes.1

We have to trust [banks] with our privacy, trust them not to let identity thieves drain our accounts. [...] Before strong encryption, users had to rely on password protection to secure their files, placing trust in the system administrator to keep their information private. Privacy could always be overridden by the admin based on his judgment call weighing the principle of privacy against other concerns, or at the behest of his superiors.

Privacy. Admins that spy on you. Systems that are designed to spy on you. Unfortunately, it's almost non-existent in today's world of surveillance capitalism and dragnet surveillance.

While credit requires identity, money does not. When you can trust the money you don't have to trust the person. In Bitcoin, there are no persons; only pseudonymous identities. Identities that are generated cryptographically at virtually no cost.

With e-currency based on cryptographic proof, without the need to trust a third party middleman, money can be secure and transactions effortless.

No middlemen. Secure and effortless. The reason why your browser will show you a green lock or a shield when a connection is encrypted is that privacy and security are two sides of the same coin. Without privacy, your physical security might be at risk.2 Without privacy, free thought and free speech are impeded.

The result is a distributed system with no single point of failure.

No single point of failure. No admins.That is one of the main value propositions of Bitcoin, and what makes it so resilient. This resiliency, and the fact that the users are in charge\u2014and nobody else\u2014is what sets Bitcoin apart. JoinMarket continues this philosophical approach: economic actors in a peer-to-peer system, no single point of failure.

JoinMarket

  1. Szabo, 2001. Trusted Third Parties Are Security Holes \u21a9

  2. Jameson Lopp, List of Known Physical Bitcoin Attacks \u21a9

  3. A selection of books is available in the Bitcoin and Cypherpunk History section of bitcoin-resources.com/books \u21a9

"},{"location":"philosophy/03-joinmarket/","title":"JoinMarket","text":"

JoinMarket, just like Bitcoin, doesn't have a single point of failure. It can be understood as a protocol that facilitates certain kinds of collaborative transactions\u2014CoinJoins\u2014via an open market.

Creating collaborative transactions is not a technical problem, but a problem of coordination. Someone has to bring the participants together, coordinate time and place, as well as amounts and fees.

Usually, this problem is solved by a central coordinator. In the best case, the central coordinator is non-custodial and blinded, meaning that user funds are never at risk, and the amount of information the central coordinator can obtain is minimal. However, even in this optimal case, the central coordinator is still a single point of failure.

In addition to being a central point of failure, any central coordinator usually charges a fee for the coordination service, which means that it is an entity that is making money. In most cases, this entity is a company that can be pressured and subverted, as has happened in the past. Even without any outside pressure, an economic entity might make certain decisions against the best interest of its users, just out of self-preservation alone.1

JoinMarket provides a decentralised alternative to these central coordination services. It is not a central entity, it is software that is coordinating the actions of multiple peers, just like Bitcoin. JoinMarket is neutral, meaning that the system itself is not charging its users to use the software for coordination. Fees are earned by market makers, i.e. those who are willing to provide liquidity to the open market. Consequently, JoinMarket is not a financial entity. Only the users are making money. JoinMarket is not.

Glossary

JoinMarket is a tried and tested CoinJoin implementation, having been actively used on Bitcoin's mainnet since 2015.2 Because of its lack of a centralised coordinator, it works a bit differently than other CoinJoin implementations.3 You can read about the details of JoinMarket's design in the high-level design document of the JoinMarket docs.

JoinMarket is free and open-source software, which means that anyone is free to use, inspect, and modify the software.

Free Software

Because of its decentralised nature, and thus the lack of funds and focused effort that a central company structure allows, the JoinMarket software was, historically, a bit difficult to set up and use. We hope that the efforts around Jam will make it a bit easier.

Installation

  1. See, for example: https://archive.ph/C53tk, https://archive.ph/hIYJO \u21a9

  2. See the Bitcoin Wiki for https://en.bitcoin.it/wiki/JoinMarket \u21a9

  3. Shinobi, 2021 JoinMarket Vs. ZeroLink \u21a9

"},{"location":"privacy/01-fundamentals/","title":"Fundamentals","text":"

When it comes to Bitcoin, misconceptions abound. This is not surprising. Bitcoin is a new thing, and, consequently, all metaphors and comparisons fall short, in one way or another.

One misconception is that Bitcoin is private and untraceable. In actuality, regular Bitcoin use often has weaker privacy guarantees than using the traditional banking system, as Gregory Maxwell pointed out many years ago:

\u201cYour inlaws can see that you're buying birth control that deprives them of grandchildren, your employer learns about the non-profits you support with money from your paycheck, and thieves see your latest purchases and how wealthy you are which helps them target and scam you. Poor privacy in Bitcoin can be a major practical disadvantage for both individuals and businesses.\u201d

To understand why this is, we have to understand how Bitcoin operates. This, however, turns out to be very difficult. To understand one part, one needs to have a solid understanding of computer science and cryptography. To understand another part, one needs to have a solid understanding of economics and game theory\u2014not to mention money, networks, governance, energy and energy markets, monetary history, and so on. The list of relevant disciplines is almost endless.

However, it is possible to look at some parts of Bitcoin in isolation and\u2014hopefully\u2014gain a better understanding by zooming in. One such part is the Bitcoin transaction.

"},{"location":"privacy/01-fundamentals/#the-bitcoin-transaction","title":"The Bitcoin Transaction","text":"

In the simplest sense, a Bitcoin transaction is just a bunch of data that describes the movement of bitcoins.

A bitcoin transaction consists of inputs and outputs. Every transaction input refers to the output of a previous transaction (except the coinbase transaction). We say that an input \"consumes\" an output. If an output is not consumed yet, we speak of an unspent transaction output, or UTXO, for short.

Once properly understood, it is easy to see what the Bitcoin network generates: a linked data structure that, starting from a common root\u2014the genesis block\u2014splits and combines bundles of sats as time goes on. Properly visualized, it would look a bit like an upside-down tree.

Every transaction has at least one input and at least one output. The simplest and traditionally most common transaction type has one input and two outputs: one describing the actual payment and one describing the change that goes back to the one who initiated the payment.

The concept of change is required because Bitcoin doesn't allow an update of the past. It is an append-only log, so instead of going back and modifying past entries, new entries have to be created to reflect any updates. Transactions are what create these updates. For a simple transaction, one new \"entry\" is created to update the balance of the receiver, and one new entry is created to update your own balance. You can think of it as paying for something that costs $5 with a $20 bill. The merchant receives five dollars, and you get $15\u2014the change\u2014back. However, we don't have physical coins and bills, we only have an append-only log. So instead of bills of smaller denominations, new entries\u2014new UTXOs\u2014are created.

While this design is ingenious when it comes to validation\u2014you can easily make sure that everything adds up at all times\u2014there are certain nuances to consider when it comes to privacy.

For example, if it is trivial to determine which output is a change output and which one isn't, it is trivial to cluster outputs and thus identify not only the flow of funds, but also who transacted with whom, at what times, and\u2014of course\u2014the amounts that were transacted. Imagine a data leak that exposes all transactions of every company, every individual, every politician, every bank, every merchant, every online shop, and every vending machine. When used naively, this data leak is Bitcoin.

Luckily, the situation is not as grim as it sounds. Developments and techniques exist to remedy this situation. To understand them, we have to understand the various transaction types that Bitcoin allows.

"},{"location":"privacy/01-fundamentals/#bitcoin-transaction-types","title":"Bitcoin Transaction Types","text":"

We already discussed the most common transaction type: the \"simple spend.\" There are also transactions that have only one input and one output, transactions that have multiple inputs and one output, and transactions that have multiple inputs and multiple outputs. Let's call them \"No Change,\" \"Consolidation,\" and \"Batch,\" respectively.

While Bitcoin's transaction graph is public, it is important to point out that any analysis that is applied to this data is heuristic. For example, a user might create a transaction that splits a UTXO in half, resulting in two outputs that belong to the same entity. Or, to pick another example, a regular spend might produce two outputs that are exactly equal, making change detection virtually impossible.

Because identification can only happen heuristically, one part of the solution to Bitcoin's privacy conundrum lies in collaboration.

"},{"location":"privacy/01-fundamentals/#collaborative-transactions","title":"Collaborative Transactions","text":"

When it comes to privacy, collaboration is the norm. Take encryption, for example. If you want to have a secure communications channel with another party, you start a collaborative process. You meet, you exchange secret information, and you use this secret information to encrypt your messages. We call this exchange of secret information a \"handshake,\" and over the last decades, we implemented all kinds of handshakes into our communication and networking protocols to make sure that bad actors can't eavesdrop on our communications.

Similarly, cryptographers and security researchers are currently working on protocols and techniques that make sure that bad actors can't eavesdrop on your every financial move. As with end-to-end encryption, these protections are important for all and a matter of life-and-death for some. Dissidents, journalists, whistleblowers, political activists\u2014these are only a few groups of people that depend on secure communications, which includes financial communication. That privacy is important for these groups is an understatement. It is absolutely essential. This is also why the Human Rights Foundation launched a fund to support software developers who are making the Bitcoin network more private, decentralized, and resilient.

So, how can we think about a \"handshake\" in the world of bitcoin transactions? It's quite simple, really. As mentioned above, a bitcoin transaction can have multiple inputs and multiple outputs. The privacy techniques that are currently being developed are making use of this feature. The interesting part is that not all inputs have to be controlled by the same party. Thus, the \"handshake\" is about bringing multiple parties together to collaborate on a bitcoin transaction.

Once the collaborating parties agree on the parameters of the transaction, the transaction is signed by all parties and broadcast to the network. Because of the heuristical nature of transaction analysis, an onlooker won't be able to figure out the flow of funds.

One especially promising technique to increase the privacy of all is to combine the above with an actual payment. In this scenario, the \"handshake\" is about bringing a merchant and a customer together to craft a special transaction that can only be deciphered by said merchant or customer. An eavesdropper is left with multiple interpretations of the transaction, each equally likely. Such a transaction is called a \u201cPayJoin.\u201d

Even if only a small percentage of transactions are PayJoin transactions, the privacy of all participants in the network is increased substantially.

As more wallets and merchants adopt and support these privacy features, we will see a substantial increase in privacy on Bitcoin's base layer. However, as we have seen with the adoption of Transport Layer Security on the Internet, it takes some time for an upgrade of this sort to be implemented and embraced.

"},{"location":"privacy/01-fundamentals/#transport-layer-security","title":"Transport Layer Security","text":"

When the internet was a new thing, we didn't think that it would envelop all our communications and all our lives. Encryption was an afterthought. After a while, however, we figured out that having all our communications available in plain text, readable by everyone who had the interest and technical proficiency to do so, wasn't a terribly good idea. Consequently, we made a concerted effort to change things. We upgraded from HTTP to HTTPS and from plain text messages to end-to-end encryption. While this switch isn\u2019t 100% complete yet, encrypted communication became the default over time. This upgrade took a long time, since, similar to Bitcoin, nobody is in charge of the internet.

Best Practices

"},{"location":"privacy/02-best-practices/","title":"Best Practices","text":"

As with every\u00adthing in Bitcoin, taking control of your privacy is a\u00a0gradual, step-by-step process. Learning about and imple\u00admenting these best practices takes patience and respon\u00adsi\u00adbility, so do not be discour\u00adaged if it seems overwhelming at first. Every step, no matter how small, is a\u00a0step in the right direction.

"},{"location":"privacy/02-best-practices/#take-action","title":"Take Action","text":"

The following are action\u00adable steps you can take to increase your\u00a0privacy:

  • Self-custody your\u00a0coins
  • Do not reuse addresses
  • Minimize exposure to KYC (Know Your Customer)
  • Minimize exposure to third\u00a0parties
  • Run your own\u00a0node
  • Use the Light\u00adning Network for small transactions
  • Do not use public block explorers
  • CoinJoin early and\u00a0often
"},{"location":"privacy/02-best-practices/#self-custody-your-coins","title":"Self-custody your coins","text":"

Not your keys, not your bitcoin. If someone else is holding your bitcoin for you, they know every\u00adthing there is to know about these coins: amounts, trans\u00adac\u00adtion histo\u00adries, future trans\u00adac\u00adtions, etc. Taking self-custody of your coins is the first and most essen\u00adtial\u00a0step.

Bitcoin Wallet Guide

"},{"location":"privacy/02-best-practices/#do-not-reuse-addresses","title":"Do not reuse addresses","text":"

Reusing addresses destroys the privacy of both the sender and the receiver. It should be avoided at all\u00a0costs.

Address Reuse

"},{"location":"privacy/02-best-practices/#minimize-exposure-to-kyc","title":"Minimize exposure to KYC","text":"

Linking your real-world identity to your bitcoin addresses is a\u00a0neces\u00adsary evil in most juris\u00addic\u00adtions. While the effec\u00adtive\u00adness of these regula\u00adtions is question\u00adable, the impli\u00adca\u00adtions for regular users are mostly negative as a\u00a0multi\u00adtude of data leaks have shown. If you choose to use KYC on- or off-ramps, make sure that you under\u00adstand the relation\u00adship between yourself and the service in question. You are trusting this service with your personal data, including the future safety of this data. If you want to skip KYC entirely, have a\u00a0look at no-KYC only.

No KYC Only

"},{"location":"privacy/02-best-practices/#minimize-exposure-to-third-parties","title":"Minimize exposure to third parties","text":"

Trusted third parties are security holes. If you can rely on yourself instead of trusted third parties, you\u00a0should.

Trusted Third Parties Are Security Holes

"},{"location":"privacy/02-best-practices/#run-your-own-node","title":"Run your own node","text":"

Not your node, not your rules. Running your own node is essen\u00adtial to use Bitcoin in a\u00a0private manner. Every inter\u00adac\u00adtion with the Bitcoin network is facil\u00adi\u00adtated by a\u00a0node. If you are not in control of this node, whatever you are doing is seen by the node you are inter\u00adacting with. This means whoever is in control of the node is able to see what you are doing. The bitcoiner node guide is a\u00a0great resource to get you\u00a0started.

Bitcoiner Node Guide

"},{"location":"privacy/02-best-practices/#use-the-lightning-network-for-small-transactions","title":"Use the Light\u00adning Network for small trans\u00adac\u00adtions","text":"

The off-chain nature of the light\u00adning network increases the trans\u00adac\u00adtional privacy of its users without having to jump through too many hoops. While it is still early, the absolutely reckless days of the light\u00adning network are likely behind us. Using it for small- and medium-sized trans\u00adac\u00adtions can help improve both your privacy as well as your fee footprint.

Bitcoiner Lightning Guide

"},{"location":"privacy/02-best-practices/#do-not-use-public-block-explorers","title":"Do not use public block explorers","text":"

Looking up addresses in public block explorers will link those addresses with your IP, which, in turn, can be linked to your real identity. Software packages like Umbrel, Citadel, RaspiBlitz, and BTCPay Server make it easy to run your own block explorer. If you have to use a\u00a0public block explorer, make sure to mask your IP by connecting to them via Tor, or at least use a\u00a0VPN.

Mempool Instances

"},{"location":"privacy/02-best-practices/#coinjoin-early-and-often","title":"CoinJoin early and often","text":"

Because Bitcoin is forever, using trans\u00adac\u00adtional best practices such as collab\u00ado\u00adra\u00adtive CoinJoin trans\u00adac\u00adtions will ensure that your privacy is protected going forward. While CoinJoin trans\u00adac\u00adtions are nuanced, user-friendly software exists to help you create and automate these kinds of trans\u00adac\u00adtions. Samourai's Whirlpool is a good\u00a0 solution for Android users, for example. There is also JoinMarket, which, thanks to projects like JoininBox and Jam, can be set up quite easily on your own node.

Getting Started with Jam

Installation

The above is a slightly modified version of Bitcoin Privacy: Best Practices\" by Gigi, released originally under a CC BY-SA 4.0 license and modified for Jam by the author.

"},{"location":"software/installation/","title":"Installation","text":"

Jam comes packaged with the following full-node solutions:

  • Umbrel
  • Citadel
  • RaspiBlitz
  • MyNode
  • Start9
  • RaspiBolt

You should be able to install Jam with one click if you are running any of the above. Except for RaspiBolt, where you'll need to use the command line.

You can also do a manual installation.

"},{"location":"software/installation/#install-as-a-package","title":"Install as a Package","text":"

The easiest way to install Jam is to install it as a package.

Info

Please understand the trade-offs you are making when installing Jam as a package. Make sure to verify the integrity and authenticity of the node software you are running. And, if possible, verify the Jam installation yourself.

"},{"location":"software/installation/#with-umbrel","title":"...with Umbrel","text":"

Jam can be installed directly from the Umbrel app store:

  • Open the interface of your Umbrel node (type umbrel.local in your browser)
  • Find \"Jam\" in the Umbrel app store
  • Click install
  • Done!
"},{"location":"software/installation/#with-citadel","title":"...with Citadel","text":"

Jam can be installed directly from the Citadel app store:

  • Open the interface of your Citadel node (type citadel.local in your browser)
  • Find \"Jam\" in the Citadel app store
  • Click install
  • Done!

Info

If you are asked to enter a username and password after installation, enter \"citadel\" as the username and the password that Citadel provides for you.

"},{"location":"software/installation/#with-raspiblitz","title":"...with RaspiBlitz","text":"

Jam can be installed directly from the Raspiblitz WebUI since RaspiBlitz v1.9.0.

Alternatively you can install Jam via the command line, since RaspiBlitz v1.7.2 and up. To install it, exit the RaspiBlitz menu and run:

patch\nconfig.scripts/bonus.joinmarket-webui.sh on\n

To get information on how to connect to Jam run:

config.scripts/bonus.joinmarket-webui.sh menu\n
"},{"location":"software/installation/#with-mynode","title":"...with MyNode","text":"

Jam can be installed directly from the MyNode Marketplace:

  • Open the interface of your MyNode device (type mynode.local in your browser)
  • Find \"Jam\" in the Markplace (Note: the JoinMarket app must also be installed)
  • Click install
  • Done!
"},{"location":"software/installation/#with-start9","title":"...with Start9","text":"

Jam can be installed directly from the Start9 Marketplace:

  • Open the interface on EmbassyOS (type your personalized embassy address similar to embassy-example-example.local in your browser)
  • Find \"Jam\" in the Start9 Marketplace
  • Click install
  • Done!
"},{"location":"software/installation/#with-raspibolt","title":"...with RaspiBolt","text":"

See the RaspiBolt guide for detailed instructions.

"},{"location":"software/installation/#manual-installation","title":"Manual Installation","text":"

There are three ways to set up Jam manually:

  1. Run the standalone docker image (easiest)
  2. Connect Jam to a local JoinMarket instance
  3. Connect Jam to a remote JoinMarket instance

All these methods have benefits and drawbacks. One method is easy, but you have less control. Others give you more flexibility, but require several manual steps. Choose the method that works best for you. The rule of thumb is: Always prefer to build and verify the applications locally yourself if you have the necessary technical skills to do so.

"},{"location":"software/installation/#with-docker-image","title":"...with docker image","text":"

Using docker is the easiest way to run JoinMarket with Jam. However, a disadvantage is that you have to trust the developers and it is rather difficult to verify the authenticity.

Prerequisites:

  • Bitcoin Core
  • docker

The official Jam standalone docker image is already bundled with JoinMarket and Tor. It takes care of starting all subservices (API, Orderbook, etc.) and everything works out-of-the-box.

If you are connecting to a remote Bitcoin Core node, run:

docker run --rm  -it \\\n        --env JM_RPC_HOST=\"IP_OF_HOST_RUNNING_BITCOIN_CORE\" \\\n        --env JM_RPC_PORT=\"API_PORT_OF_BITCOIN_CORE\" \\\n        --env JM_RPC_USER=\"BTC_RPC_USERNAME\" \\\n        --env JM_RPC_PASSWORD=\"****************\" \\\n        --env APP_USER=\"JAM_USERNAME\" \\\n        --env APP_PASSWORD=\"****************\" \\\n        --env ENSURE_WALLET=\"true\" \\\n        --env REMOVE_LOCK_FILES=\"true\" \\\n        --env RESTORE_DEFAULT_CONFIG=\"true\" \\\n        --volume jmdatadir:/root/.joinmarket \\\n        --publish \"8080:80\" \\\n        ghcr.io/joinmarket-webui/jam-standalone:${jam_version}\n

If you are connecting to a local Bitcoin Core node, use the above command but add param --add-host=host.docker.internal:host-gateway and set the environment variable JM_RPC_HOST to host.docker.internal.

After starting the container, Jam can be accessed by visiting http://localhost:8080 in your browser.

Make sure to replace the above dummy values for IP, port, RPC username, and RPC password with values appropriate to your setup. For example:

docker run --rm  -it \\\n        --env JM_RPC_HOST=\"192.168.1.1\" \\\n        --env JM_RPC_PORT=\"8332\" \\\n        --env JM_RPC_USER=\"bitcoin\" \\\n        --env JM_RPC_PASSWORD=\"n5a___YOUR_RPC_PASSWORD___yNA\" \\\n        --env APP_USER=\"jam\" \\\n        --env APP_PASSWORD=\"AvQ___YOUR_APP_PASSWORD___iCw\" \\\n        --env ENSURE_WALLET=\"true\" \\\n        --env REMOVE_LOCK_FILES=\"true\" \\\n        --env RESTORE_DEFAULT_CONFIG=\"true\" \\\n        --volume jmdatadir:/root/.joinmarket \\\n        --publish \"8080:80\" \\\n        ghcr.io/joinmarket-webui/jam-standalone:${jam_version}\n

Please use your password manager or something like openssl rand -base64 32 to generate strong passwords.

"},{"location":"software/installation/#connecting-to-a-local-joinmarket-instance","title":"...connecting to a local JoinMarket instance","text":"

Prerequisites:

  • Bitcoin Core
  • Tor
  • JoinMarket
  • docker or node & npm

If you have successfully installed JoinMarket, generate a self-signed SSL certificate in JoinMarket's working directory, then navigate to JoinMarket's root directory and start jmwalletd and ob-watcher.

In JoinMarket's working directory (e.g. ~/.joinmarket/):

mkdir ssl/ && cd \"$_\"\nopenssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes \\\n  -out cert.pem -keyout key.pem \\\n  -subj \"/C=US/ST=Utah/L=Lehi/O=Your Company, Inc./OU=IT/CN=example.com\"\n

In JoinMarket's root directory:

. jmvenv/bin/activate\npython3 scripts/jmwalletd.py\n
. jmvenv/bin/activate\npython3 scripts/obwatch/ob-watcher.py --host=127.0.0.1\n

Info

Bind both services to 127.0.0.1 instead of 0.0.0.0 to not expose them to your local network.

It is recommended to install both services as system services, e.g. via systemd. Also, see your joinmarket.cfg config file and adapt the values to your needs. It is generally advised to leave all settings at their default values. The above commands all use the standard values (e.g. for ports).

Info

Please make sure to provide values for config variables max_cj_fee_abs and max_cj_fee_rel in joinmarket.cfg. Set them to values you feel comfortable with.

Once jmwalletd and ob-watcher are running, the last thing to do is to launch Jam. You can either run the docker image, or download the source code and run it via npm. If you run Jam via the docker image, you will have to make sure that the \"internal\" host is used:

# Option 1: run Jam via docker\n\ndocker run --rm  -it \\\n        --add-host=host.docker.internal:host-gateway \\\n        --env JAM_JMWALLETD_HOST=\"host.docker.internal\" \\\n        --env JAM_JMWALLETD_API_PORT=\"28183\" \\\n        --env JAM_JMWALLETD_WEBSOCKET_PORT=\"28283\" \\\n        --env JAM_JMOBWATCH_PORT=\"62601\" \\\n        --publish \"3000:80\" \\\n        ghcr.io/joinmarket-webui/jam-ui-only:${jam_version}\n
# Option 2: run Jam via npm\n\ngit clone https://github.com/joinmarket-webui/jam.git --branch ${jam_version} --depth=1\ncd jam/\nnpm install\nnpm start\n

Success

Always make sure to verify the code that you run.

When successful, Jam can be accessed by visiting http://localhost:3000 in your browser.

"},{"location":"software/installation/#connecting-to-a-remote-joinmarket-instance","title":"...connecting to a remote JoinMarket instance","text":"

Do all the same steps as in Connecting to a local JoinMarket instance but before starting Jam (either directly or with docker), create a ssh tunnel to the remote host.

ssh yourhost.local -v -o GatewayPorts=true -N \\\n  -L 28183:127.0.0.1:28183 -L 28283:127.0.0.1:28283 -L 62601:127.0.0.1:62601\n

Once you managed to install Jam, make sure to understand how to use it.

First Use

"},{"location":"software/license/","title":"License","text":"

Both Jam and JoinMarket are released under free and open-source software licenses.

Philosophy: Free Software

"},{"location":"software/license/#jam","title":"Jam","text":"

Jam and is licensed under the MIT License. The Jam documentation is licensed under the GNU FDL.

  • Jam LICENSE
  • JamDocs LICENSE
"},{"location":"software/license/#joinmarket","title":"JoinMarket","text":"

JoinMarket is released under the GPLv3.

  • JoinMarket LICENSE
"},{"location":"software/verification/","title":"Verification","text":"

All releases are signed by one of the Jam contributors. As of this writing (742,834), releases are signed with dergigi's PGP key which has the following fingerprint:

8198 A185 30A5 22A0 9561 2439 89C4 A25E 69A5 DE7F\n

To verify a specific release, import the key

curl https://dergigi.com/PGP.txt | gpg --import\n

and verify the git tag of your local copy:

git verify-tag v0.0.10\n

This should produce an output that contains \"good signature\" as well as the key fingerprint mentioned above:

gpg: Signature made Fr  5 Aug 14:17:58 2022 CEST\ngpg:                using RSA key 8198A18530A522A09561243989C4A25E69A5DE7F\ngpg: Good signature from \"Gigi <dergigi@pm.me>\" [unknown]\n...\nPrimary key fingerprint: 8198 A185 30A5 22A0 9561  2439 89C4 A25E 69A5 DE7F\n

You can also see if a release was signed properly by clicking on the verification tag next to the version number on the releases page on GitHub.

It should say that \"This tag was signed with the committer\u2019s verified signature\" and show you the last 16 characters of the GPG key ID listed above (89C4 A25E 69A5 DE7F).

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..739d473 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,133 @@ + + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + + None + 2023-10-25 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..8258cd0 Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/software/installation/index.html b/software/installation/index.html new file mode 100644 index 0000000..16cc15b --- /dev/null +++ b/software/installation/index.html @@ -0,0 +1,1298 @@ + + + + + + + + + + + + + + + + + + + + + + Installation - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + +

Installation

+

Jam comes packaged with the following full-node solutions:

+ +

You should be able to install Jam with one click if you are running any of the +above. +Except for RaspiBolt, where you'll need to use the command line.

+

You can also do a manual installation.

+
+

Install as a Package

+

The easiest way to install Jam is to install it as a package.

+
+

Info

+

Please understand the trade-offs you are making when installing Jam as a +package. Make sure to verify the integrity and authenticity of the node +software you are running. And, if possible, verify the Jam +installation yourself.

+
+

...with Umbrel

+

Jam can be installed directly from the Umbrel app store:

+
    +
  • Open the interface of your Umbrel node
    (type umbrel.local in your browser)
  • +
  • Find "Jam" in the Umbrel app store
  • +
  • Click install
  • +
  • Done!
  • +
+

...with Citadel

+

Jam can be installed directly from the Citadel app store:

+
    +
  • Open the interface of your Citadel node
    (type citadel.local in your browser)
  • +
  • Find "Jam" in the Citadel app store
  • +
  • Click install
  • +
  • Done!
  • +
+
+

Info

+

If you are asked to enter a username and password after installation, enter +"citadel" as the username and the password that Citadel provides for you.

+
+

...with RaspiBlitz

+

Jam can be installed directly from the Raspiblitz WebUI since RaspiBlitz v1.9.0.

+

Alternatively you can install Jam via the command line, since RaspiBlitz v1.7.2 and up. To install it, exit the RaspiBlitz menu and run:

+
patch
+config.scripts/bonus.joinmarket-webui.sh on
+
+

To get information on how to connect to Jam run:

+
config.scripts/bonus.joinmarket-webui.sh menu
+
+

...with MyNode

+

Jam can be installed directly from the MyNode Marketplace:

+
    +
  • Open the interface of your MyNode device
    (type mynode.local in your browser)
  • +
  • Find "Jam" in the Markplace
    (Note: the JoinMarket app must also be installed)
  • +
  • Click install
  • +
  • Done!
  • +
+

...with Start9

+

Jam can be installed directly from the Start9 Marketplace:

+
    +
  • Open the interface on EmbassyOS
    (type your personalized embassy address similar to embassy-example-example.local in your browser)
  • +
  • Find "Jam" in the Start9 Marketplace
  • +
  • Click install
  • +
  • Done!
  • +
+

...with RaspiBolt

+

See the RaspiBolt guide for detailed instructions.

+
+

Manual Installation

+

There are three ways to set up Jam manually:

+
    +
  1. Run the standalone docker image (easiest)
  2. +
  3. Connect Jam to a local JoinMarket instance
  4. +
  5. Connect Jam to a remote JoinMarket instance
  6. +
+

All these methods have benefits and drawbacks. One method is easy, but you +have less control. Others give you more flexibility, but require several +manual steps. Choose the method that works best for you. +The rule of thumb is: Always prefer to build and verify the applications +locally yourself if you have the necessary technical skills to do so.

+

...with docker image

+

Using docker is the easiest way to run JoinMarket with Jam. +However, a disadvantage is that you have to trust the developers and it is +rather difficult to verify the authenticity.

+

Prerequisites:

+
    +
  • Bitcoin Core
  • +
  • docker
  • +
+

The official Jam standalone docker image +is already bundled with JoinMarket and Tor. It takes care of starting all +subservices (API, Orderbook, etc.) and everything works out-of-the-box.

+

If you are connecting to a remote Bitcoin Core node, run:

+
docker run --rm  -it \
+        --env JM_RPC_HOST="IP_OF_HOST_RUNNING_BITCOIN_CORE" \
+        --env JM_RPC_PORT="API_PORT_OF_BITCOIN_CORE" \
+        --env JM_RPC_USER="BTC_RPC_USERNAME" \
+        --env JM_RPC_PASSWORD="****************" \
+        --env APP_USER="JAM_USERNAME" \
+        --env APP_PASSWORD="****************" \
+        --env ENSURE_WALLET="true" \
+        --env REMOVE_LOCK_FILES="true" \
+        --env RESTORE_DEFAULT_CONFIG="true" \
+        --volume jmdatadir:/root/.joinmarket \
+        --publish "8080:80" \
+        ghcr.io/joinmarket-webui/jam-standalone:${jam_version}
+
+

If you are connecting to a local Bitcoin Core node, use the above command but +add param --add-host=host.docker.internal:host-gateway and set the environment +variable JM_RPC_HOST to host.docker.internal.

+

After starting the container, Jam can be accessed by visiting +http://localhost:8080 in your browser.

+

Make sure to replace the above dummy values for IP, port, RPC username, and RPC +password with values appropriate to your setup. For example:

+
docker run --rm  -it \
+        --env JM_RPC_HOST="192.168.1.1" \
+        --env JM_RPC_PORT="8332" \
+        --env JM_RPC_USER="bitcoin" \
+        --env JM_RPC_PASSWORD="n5a___YOUR_RPC_PASSWORD___yNA" \
+        --env APP_USER="jam" \
+        --env APP_PASSWORD="AvQ___YOUR_APP_PASSWORD___iCw" \
+        --env ENSURE_WALLET="true" \
+        --env REMOVE_LOCK_FILES="true" \
+        --env RESTORE_DEFAULT_CONFIG="true" \
+        --volume jmdatadir:/root/.joinmarket \
+        --publish "8080:80" \
+        ghcr.io/joinmarket-webui/jam-standalone:${jam_version}
+
+

Please use your password manager or something like openssl rand -base64 32 to +generate strong passwords.

+

...connecting to a local JoinMarket instance

+

Prerequisites:

+ +

If you have successfully installed JoinMarket, generate a +self-signed SSL certificate in JoinMarket's working directory, then navigate +to JoinMarket's root directory and start jmwalletd and ob-watcher.

+

In JoinMarket's working directory (e.g. ~/.joinmarket/):

+
mkdir ssl/ && cd "$_"
+openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes \
+  -out cert.pem -keyout key.pem \
+  -subj "/C=US/ST=Utah/L=Lehi/O=Your Company, Inc./OU=IT/CN=example.com"
+
+

In JoinMarket's root directory:

+
. jmvenv/bin/activate
+python3 scripts/jmwalletd.py
+
+
. jmvenv/bin/activate
+python3 scripts/obwatch/ob-watcher.py --host=127.0.0.1
+
+
+

Info

+

Bind both services to 127.0.0.1 instead of 0.0.0.0 to not expose them to +your local network.

+
+

It is recommended to install both services as system services, e.g. via +systemd. Also, see your joinmarket.cfg config file and adapt the values to +your needs. It is generally advised to leave all settings at their default +values. The above commands all use the standard values (e.g. for ports).

+
+

Info

+

Please make sure to provide values for config variables max_cj_fee_abs +and max_cj_fee_rel in joinmarket.cfg. Set them to values you feel +comfortable with.

+
+

Once jmwalletd and ob-watcher are running, the last thing to do is to launch +Jam. You can either run the docker image, or download the source code and run it +via npm. If you run Jam via the docker image, you will have to make sure that +the "internal" host is used:

+
# Option 1: run Jam via docker
+
+docker run --rm  -it \
+        --add-host=host.docker.internal:host-gateway \
+        --env JAM_JMWALLETD_HOST="host.docker.internal" \
+        --env JAM_JMWALLETD_API_PORT="28183" \
+        --env JAM_JMWALLETD_WEBSOCKET_PORT="28283" \
+        --env JAM_JMOBWATCH_PORT="62601" \
+        --publish "3000:80" \
+        ghcr.io/joinmarket-webui/jam-ui-only:${jam_version}
+
+
# Option 2: run Jam via npm
+
+git clone https://github.com/joinmarket-webui/jam.git --branch ${jam_version} --depth=1
+cd jam/
+npm install
+npm start
+
+
+

Success

+

Always make sure to verify the code that you run.

+
+

When successful, Jam can be accessed by visiting +http://localhost:3000 in your browser.

+

...connecting to a remote JoinMarket instance

+

Do all the same steps as in Connecting to a local JoinMarket instance +but before starting Jam (either directly or with docker), create a ssh tunnel +to the remote host.

+
ssh yourhost.local -v -o GatewayPorts=true -N \
+  -L 28183:127.0.0.1:28183 -L 28283:127.0.0.1:28283 -L 62601:127.0.0.1:62601
+
+
+

Once you managed to install Jam, make sure to understand how to use it.

+

First Use

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/software/license/index.html b/software/license/index.html new file mode 100644 index 0000000..00b5d48 --- /dev/null +++ b/software/license/index.html @@ -0,0 +1,952 @@ + + + + + + + + + + + + + + + + + + + + + + License - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

License

+

Both Jam and JoinMarket are released under free and open-source software licenses.

+

Philosophy: Free Software

+

Jam

+

Jam and is licensed under the MIT License. +The Jam documentation is licensed under the GNU FDL.

+ +
+

JoinMarket

+

JoinMarket is released under the GPLv3.

+ + + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/software/verification/index.html b/software/verification/index.html new file mode 100644 index 0000000..610b4e8 --- /dev/null +++ b/software/verification/index.html @@ -0,0 +1,898 @@ + + + + + + + + + + + + + + + + + + + + Verification - Jam Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Verification

+

All releases are signed by one of the Jam contributors. As of this writing (742,834), releases are signed with dergigi's PGP key which has the following fingerprint:

+
8198 A185 30A5 22A0 9561 2439 89C4 A25E 69A5 DE7F
+
+

To verify a specific release, import the key

+
curl https://dergigi.com/PGP.txt | gpg --import
+
+

and verify the git tag of your local copy:

+
git verify-tag v0.0.10
+
+

This should produce an output that contains "good signature" as well as the key fingerprint mentioned above:

+
gpg: Signature made Fr  5 Aug 14:17:58 2022 CEST
+gpg:                using RSA key 8198A18530A522A09561243989C4A25E69A5DE7F
+gpg: Good signature from "Gigi <dergigi@pm.me>" [unknown]
+...
+Primary key fingerprint: 8198 A185 30A5 22A0 9561  2439 89C4 A25E 69A5 DE7F
+
+
+

You can also see if a release was signed properly by clicking on the +verification tag Verification badge next to +the version number on the releases page on GitHub.

+

It should say that "This tag was signed with the committer’s verified +signature" and show you the last 16 characters of the GPG key ID listed above +(89C4 A25E 69A5 DE7F).

+ + + + + + +
+
+ + +
+ +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file