Skip to content

Commit

Permalink
Merge branch 'main' into multinut
Browse files Browse the repository at this point in the history
  • Loading branch information
callebtc committed Mar 23, 2024
2 parents 7cc948d + 3feb023 commit 81ba4f7
Show file tree
Hide file tree
Showing 47 changed files with 1,090 additions and 447 deletions.
27 changes: 19 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ MINT_DERIVATION_PATH="m/0'/0'/0'"

MINT_DATABASE=data/mint

# Lightning
# Supported: FakeWallet, LndRestWallet, CoreLightningRestWallet, BlinkWallet, LNbitsWallet, StrikeWallet
MINT_LIGHTNING_BACKEND=FakeWallet
# Funding source backends
# Supported: FakeWallet, LndRestWallet, CoreLightningRestWallet, BlinkWallet, LNbitsWallet, StrikeUSDWallet
MINT_BACKEND_BOLT11_SAT=FakeWallet
# Only works if a usd derivation path is set
# MINT_BACKEND_BOLT11_SAT=FakeWallet

# for use with LNbitsWallet
MINT_LNBITS_ENDPOINT=https://legend.lnbits.com
Expand All @@ -76,18 +78,27 @@ MINT_CORELIGHTNING_REST_CERT="./clightning-2-rest/certificate.pem"
# Use with BlinkWallet
MINT_BLINK_KEY=blink_abcdefgh

# Use with StrikeWallet
# Use with StrikeUSDWallet (usd only, does not currently support sats/msats)
MINT_STRIKE_KEY=ABC123

# fee to reserve in percent of the amount
LIGHTNING_FEE_PERCENT=1.0
# minimum fee to reserve
LIGHTNING_RESERVE_FEE_MIN=2000

# Management
# max peg-in amount in satoshis
# Limits

# Max peg-in amount in satoshis
# MINT_MAX_PEG_IN=100000
# max peg-out amount in satoshis
# Max peg-out amount in satoshis
# MINT_MAX_PEG_OUT=100000
# use to allow only peg-out to LN
# Use to allow only peg-out to LN
# MINT_PEG_OUT_ONLY=FALSE

# Rate limit requests to mint. Make sure that you can see request IPs in the logs.
# You may need to adjust your reverse proxy if you only see requests originating from 127.0.0.1
# MINT_RATE_LIMIT=TRUE
# Determines the number of all requests allowed per minute per IP
# MINT_GLOBAL_RATE_LIMIT_PER_MINUTE=60
# Determines the number of transactions (mint, melt, swap) allowed per minute per IP
# MINT_TRANSACTION_RATE_LIMIT_PER_MINUTE=20
13 changes: 12 additions & 1 deletion .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: Docker Build

on:
push:
release:
types: [published]

Expand All @@ -21,6 +20,15 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Cache Docker layers
uses: actions/cache@v4
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Determine Tag
id: get_tag
run: |
Expand All @@ -36,3 +44,6 @@ jobs:
context: .
push: ${{ github.event_name == 'release' }}
tags: ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ steps.get_tag.outputs.tag }}
platforms: linux/amd64,linux/arm64
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
35 changes: 35 additions & 0 deletions .github/workflows/pypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Pip package

on:
push:
release:
types: [published]

jobs:
build-and-push:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
poetry-version: ["1.7.1"]
steps:
- name: Checkout
uses: actions/checkout@v4

- uses: ./.github/actions/prepare
with:
python-version: ${{ matrix.python-version }}
poetry-version: ${{ matrix.poetry-version }}

- name: Build package
run: |
poetry build
- name: Install package
run: |
pip install --upgrade dist/*.whl
- name: Upload to PyPI on release
if: github.event_name == 'release'
run: |
poetry publish -u __token__ -p ${{ secrets.PYPI_API_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/regtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
MINT_PORT: 3337
MINT_TEST_DATABASE: ${{ inputs.mint-database }}
TOR: false
MINT_LIGHTNING_BACKEND: ${{ inputs.backend-wallet-class }}
MINT_BACKEND_BOLT11_SAT: ${{ inputs.backend-wallet-class }}
MINT_LNBITS_ENDPOINT: http://localhost:5001
MINT_LNBITS_KEY: d08a3313322a4514af75d488bcc27eee
MINT_LND_REST_ENDPOINT: https://localhost:8081/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
poetry-version: ${{ inputs.poetry-version }}
- name: Run tests
env:
MINT_LIGHTNING_BACKEND: FakeWallet
MINT_BACKEND_BOLT11_SAT: FakeWallet
WALLET_NAME: test_wallet
MINT_HOST: localhost
MINT_PORT: 3337
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test:
test-lndrest:
PYTHONUNBUFFERED=1 \
DEBUG=true \
MINT_LIGHTNING_BACKEND=LndRestWallet \
MINT_BACKEND_BOLT11_SAT=LndRestWallet \
MINT_LND_REST_ENDPOINT=https://localhost:8081/ \
MINT_LND_REST_CERT=../cashu-regtest-enviroment/data/lnd-3/tls.cert \
MINT_LND_REST_MACAROON=../cashu-regtest-enviroment/data/lnd-3/data/chain/bitcoin/regtest/admin.macaroon \
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

*Disclaimer: The author is NOT a cryptographer and this work has not been reviewed. This means that there is very likely a fatal flaw somewhere. Cashu is still experimental and not production-ready.*

Cashu is an Ecash implementation based on David Wagner's variant of Chaumian blinding ([protocol specs](https://github.com/cashubtc/nuts)). Token logic based on [minicash](https://github.com/phyro/minicash) ([description](https://gist.github.com/phyro/935badc682057f418842c72961cf096c)) which implements a [Blind Diffie-Hellman Key Exchange](https://cypherpunks.venona.com/date/1996/03/msg01848.html) scheme written down [here](https://gist.github.com/RubenSomsen/be7a4760dd4596d06963d67baf140406). The database mechanics in Cashu Nutshell and the Lightning backend uses parts from [LNbits](https://github.com/lnbits/lnbits-legend).
Cashu is an Ecash implementation based on David Wagner's variant of Chaumian blinding ([protocol specs](https://github.com/cashubtc/nuts)). Token logic based on [minicash](https://github.com/phyro/minicash) ([description](https://gist.github.com/phyro/935badc682057f418842c72961cf096c)) which implements a [Blind Diffie-Hellman Key Exchange](https://cypherpunks.venona.com/date/1996/03/msg01848.html) scheme written down [here](https://gist.github.com/RubenSomsen/be7a4760dd4596d06963d67baf140406).

<p align="center">
<a href="#the-cashu-protocol">Cashu protocol</a> ·
Expand Down Expand Up @@ -169,12 +169,19 @@ You can find the API docs at [http://localhost:4448/docs](http://localhost:4448/
# Running a mint
This command runs the mint on your local computer. Skip this step if you want to use the [public test mint](#test-instance) instead.

Before you can run your own mint, make sure to enable a Lightning backend in `MINT_LIGHTNING_BACKEND` and set `MINT_PRIVATE_KEY` in your `.env` file.
## Docker

```
docker run -d -p 3338:3338 --name nutshell -e MINT_BACKEND_BOLT11_SAT=FakeWallet -e MINT_LISTEN_HOST=0.0.0.0 -e MINT_LISTEN_PORT=3338 -e MINT_PRIVATE_KEY=TEST_PRIVATE_KEY cashubtc/nutshell:0.15.2 poetry run mint
```

## From this repository
Before you can run your own mint, make sure to enable a Lightning backend in `MINT_BACKEND_BOLT11_SAT` and set `MINT_PRIVATE_KEY` in your `.env` file.
```bash
poetry run mint
```

For testing, you can use Nutshell without a Lightning backend by setting `MINT_LIGHTNING_BACKEND=FakeWallet` in the `.env` file.
For testing, you can use Nutshell without a Lightning backend by setting `MINT_BACKEND_BOLT11_SAT=FakeWallet` in the `.env` file.


# Running tests
Expand All @@ -185,7 +192,7 @@ poetry install --with dev

Then, make sure to set up your mint's `.env` file to use a fake Lightning backend and disable Tor:
```bash
MINT_LIGHTNING_BACKEND=FakeWallet
MINT_BACKEND_BOLT11_SAT=FakeWallet
TOR=FALSE
```
You can run the tests with
Expand Down
25 changes: 22 additions & 3 deletions cashu/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ def from_row(cls, row: Row):
# ------- API: INFO -------


class MintMeltMethodSetting(BaseModel):
method: str
unit: str
min_amount: Optional[int] = None
max_amount: Optional[int] = None


class GetInfoResponse(BaseModel):
name: Optional[str] = None
pubkey: Optional[str] = None
Expand Down Expand Up @@ -487,7 +494,7 @@ class PostSplitResponse_Very_Deprecated(BaseModel):


class PostCheckStateRequest(BaseModel):
secrets: List[str] = Field(..., max_items=settings.mint_max_request_length)
Ys: List[str] = Field(..., max_items=settings.mint_max_request_length)


class SpentState(Enum):
Expand All @@ -500,7 +507,7 @@ def __str__(self):


class ProofState(BaseModel):
secret: str
Y: str
state: SpentState
witness: Optional[str] = None

Expand Down Expand Up @@ -529,9 +536,21 @@ class CheckFeesResponse_deprecated(BaseModel):
# ------- API: RESTORE -------


class PostRestoreRequest(BaseModel):
outputs: List[BlindedMessage] = Field(
..., max_items=settings.mint_max_request_length
)


class PostRestoreResponse(BaseModel):
outputs: List[BlindedMessage] = []
promises: List[BlindedSignature] = []
signatures: List[BlindedSignature] = []
promises: Optional[List[BlindedSignature]] = [] # deprecated since 0.15.1

# duplicate value of "signatures" for backwards compatibility with old clients < 0.15.1
def __init__(self, **data):
super().__init__(**data)
self.promises = self.signatures


# ------- KEYSETS -------
Expand Down
18 changes: 8 additions & 10 deletions cashu/core/crypto/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,33 @@ def derive_keys(mnemonic: str, derivation_path: str):
bip32 = BIP32.from_seed(mnemonic.encode())
orders_str = [f"/{i}'" for i in range(settings.max_order)]
return {
2
** i: PrivateKey(
2**i: PrivateKey(
bip32.get_privkey_from_path(derivation_path + orders_str[i]),
raw=True,
)
for i in range(settings.max_order)
}


def derive_keys_sha256(master_key: str, derivation_path: str = ""):
def derive_keys_sha256(seed: str, derivation_path: str = ""):
"""
Deterministic derivation of keys for 2^n values.
TODO: Implement BIP32.
"""
return {
2
** i: PrivateKey(
hashlib.sha256(
(master_key + derivation_path + str(i)).encode("utf-8")
).digest()[:32],
2**i: PrivateKey(
hashlib.sha256((seed + derivation_path + str(i)).encode("utf-8")).digest()[
:32
],
raw=True,
)
for i in range(settings.max_order)
}


def derive_pubkey(master_key: str):
def derive_pubkey(seed: str):
return PrivateKey(
hashlib.sha256((master_key).encode("utf-8")).digest()[:32],
hashlib.sha256((seed).encode("utf-8")).digest()[:32],
raw=True,
).pubkey

Expand Down
7 changes: 3 additions & 4 deletions cashu/core/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@


def derive_keys_backwards_compatible_insecure_pre_0_12(
master_key: str, derivation_path: str = ""
seed: str, derivation_path: str = ""
):
"""
WARNING: Broken key derivation for backwards compatibility with 0.11.
"""
return {
2
** i: PrivateKey(
hashlib.sha256((master_key + derivation_path + str(i)).encode("utf-8"))
2**i: PrivateKey(
hashlib.sha256((seed + derivation_path + str(i)).encode("utf-8"))
.hexdigest()
.encode("utf-8")[:32],
raw=True,
Expand Down
Loading

0 comments on commit 81ba4f7

Please sign in to comment.