Contractless-Faucet/README.md

194 lines
6.6 KiB
Markdown

# Contractless Faucet
This faucet uses PHP and JSON storage. It connects directly to a Contractless
node through the authenticated RPC protocol, creates and signs transfers
locally, and submits them without invoking Contractless CLI programs.
## Requirements
- 64-bit PHP 8.1 or newer
- Composer
- The Contractless PHP Skein and Falcon modules
- `contractless/contractless-php-rpc`
- Access to a compatible Contractless RPC node
- A dedicated, registered faucet wallet
- Read access to that wallet file
- A writable private directory for the JSON claim ledger
Install the native modules first:
```text
https://contractless.dev/contractless/Contractless-PHP-Modules
```
Install the RPC package in the Composer project containing the faucet:
```bash
composer require contractless/contractless-php-rpc:^0.2.0 -W
```
The web-server account needs permission to read Composer's `vendor` directory
and faucet wallet, and write the configured claim-ledger directory. It does
not need access to a node runtime, balance sheet, or Contractless CLI binary.
The faucet configuration, wallet file, wallet decryption key, and claim ledger
must never be downloadable through the web server.
## Configuration
For an installation at:
```text
/var/www/project/public/faucet
```
copy the included template to the private project root:
```bash
cp /var/www/project/public/faucet/.env.example /var/www/project/faucet.env
sudo chown root:www-data /var/www/project/faucet.env
sudo chmod 640 /var/www/project/faucet.env
```
Then edit `/var/www/project/faucet.env` and replace every example value with
the correct faucet settings.
The faucet automatically loads `faucet.env` from the project root two
directories above the faucet:
```text
/var/www/project/faucet.env
```
No Apache configuration, PHP-FPM pool changes, shell exports, or service
restarts are required. Reloading the faucet page uses the saved values.
The optional `FAUCET_ENV_FILE` process variable can point to a different file,
but normal installations do not need it.
`FAUCET_ADDRESS` determines the active network:
- An address ending in `.cltc` configures testnet and displays `CLTC`.
- An address ending in `.clc` configures mainnet and displays `CLC`.
The faucet address itself must be the registered canonical 40-character short
address. Faucet recipients may enter either a canonical short address or a
registered vanity address. Vanity inputs are resolved through RPC, and the
canonical owner address is used for the transfer and 24-hour claim ledger.
Point the faucet at its dedicated wallet and provide that wallet's decryption
key:
```text
CONTRACTLESS_WALLET_PATH=/var/www/project/faucet.wallet
CONTRACTLESS_WALLET_KEY=wallet-decryption-key
```
The RPC library reads the public key from the wallet, extracts the encrypted
private key from its image, verifies the image payload HMAC, decrypts the
private key, proves that the Falcon keypair matches, and verifies that the
wallet's short address is derived from that public key.
`FAUCET_ADDRESS` must match the canonical `short_address` saved in this wallet.
Keep the wallet file and decryption key outside the public document root, but
inside a path PHP is permitted to read. For the example layout, the public
document root is `/var/www/project/public`, so `/var/www/project/faucet.wallet`
is private from HTTP while remaining available to PHP. Never expose the wallet
or key through HTML, JavaScript, logs, error responses, or source control.
Before enabling the faucet, verify the wallet through the installed RPC
package:
```bash
cd /path/to/Contractless-PHP-RPC
php examples/load_wallet.php /private/path/to/faucet.wallet 'wallet decryption key'
```
Configure the node used for RPC:
```text
CONTRACTLESS_RPC_HOST=127.0.0.1
CONTRACTLESS_RPC_PORT=50050
CONTRACTLESS_RPC_TIMEOUT=10
```
Use port `50050` for the default testnet RPC or `50055` for the default mainnet
RPC unless the selected node uses a different configured port.
The faucet searches for Composer's autoloader in its own directory, its parent
directory, and the web-project root two directories above it. Set
`FAUCET_COMPOSER_AUTOLOAD` to the absolute `vendor/autoload.php` path only when
Composer is installed elsewhere.
For production, set `FAUCET_CLAIMS_FILE` and `FAUCET_LOCK_FILE` to paths
outside the public web root. The included `storage` directory is suitable for
local setup and includes an Apache access-denial rule, but server-level private
storage is preferable.
## Claim Rules
Each successful request sends 25 base testnet or mainnet coins and pays a
0.25-coin transfer fee from the faucet wallet.
Before reserving or broadcasting a claim, the faucet:
- Retrieves its confirmed base-coin balance through RPC
- Refuses the request when the faucet cannot cover the claim and fee
- Confirms that the receiving canonical wallet address is registered
- Creates and signs the transfer locally
- Submits the exact signed transaction through RPC
The faucet records a successful claim only after the node returns
`successful_broadcast: true`.
A claim is rejected when either the canonical wallet address or normalized
client IP has claimed during the preceding 24 hours. IPv4-mapped IPv6 addresses
are treated as IPv4. Native IPv6 clients are grouped by `/64`.
Claims are reserved under an exclusive file lock before broadcasting. This
prevents simultaneous requests from passing the same address or IP check.
Failed broadcasts release their reservation so the user may try again.
The faucet trusts `REMOTE_ADDR` and intentionally ignores forwarded-IP headers.
When deploying behind a reverse proxy, configure the proxy or web server to
replace `REMOTE_ADDR` only from explicitly trusted proxy addresses.
## JSON Ledger
The claim ledger is keyed directly by canonical wallet address and normalized
IP:
```json
{
"version": 1,
"last_request_timestamp_ms": 0,
"total_claimed_atomic": 2500000000,
"total_claims": 1,
"addresses": {
"abcd000000000000000000000000000000001234.cltc": {
"claimed_timestamp": 1785000000,
"status": "completed",
"address": "abcd000000000000000000000000000000001234.cltc",
"ip": "203.0.113.10",
"txid": "transaction hash"
}
},
"ips": {
"203.0.113.10": {
"claimed_timestamp": 1785000000,
"status": "completed",
"address": "abcd000000000000000000000000000000001234.cltc",
"ip": "203.0.113.10",
"txid": "transaction hash"
}
}
}
```
## Security
Run the faucet under a dedicated operating-system account with access only to
its private configuration and claim ledger. Do not run PHP or the faucet as
root. Serve the site over HTTPS, keep directory listing disabled, and keep
`faucet.env` outside the public web root.