diff --git a/contracts/collectible.yaml.template b/contracts/collectible.yaml.template
index 3ac661b..6c9a120 100644
--- a/contracts/collectible.yaml.template
+++ b/contracts/collectible.yaml.template
@@ -3,7 +3,7 @@ testnet: true
issuer:
codexId: qg8TdlRF-~RGz7bI-pceS960-evWjLKg-NcWTNWy-D9pIYBA
version: 0
- api: r~mUOw
+ checksum: r~mUOw
name: OtherToken
method: issue
timestamp: "2024-12-18T10:32:00-02:00"
diff --git a/contracts/usdt.yaml.template b/contracts/usdt.yaml.template
index 596f93a..cbf6269 100644
--- a/contracts/usdt.yaml.template
+++ b/contracts/usdt.yaml.template
@@ -1,9 +1,9 @@
consensus: bitcoin
testnet: true
issuer:
- codexId: y6L7YTlM-5_v4LWy-oQsj5hV-I2imvxD-zRu0JBo-yaguhrY
+ codexId: 7C15w3W1-L0T~zXw-Aeh5~kV-Zquz729-HXQFKQW-_5lX9O8
version: 0
- api: rLosfg
+ checksum: AYkSrg
name: USDT
method: issue
timestamp: "2024-12-18T10:32:00-02:00"
diff --git a/demo-analysis-en.md b/demo-analysis-en.md
new file mode 100644
index 0000000..a91f56e
--- /dev/null
+++ b/demo-analysis-en.md
@@ -0,0 +1,637 @@
+# RGB Demo.sh Execution Analysis Report
+
+## π Table of Contents
+1. [Script Overview](#script-overview)
+2. [Core Components](#core-components)
+3. [Execution Flow Details](#execution-flow-details)
+4. [Sequence Diagrams](#sequence-diagrams)
+5. [Scenario Descriptions](#scenario-descriptions)
+6. [Key Function Analysis](#key-function-analysis)
+
+---
+
+## Script Overview
+
+`demo.sh` is a complete RGB protocol testing sandbox script that demonstrates the issuance and transfer flow of RGB smart contracts on the Bitcoin network.
+
+### Main Features
+- π¦ Issue two types of RGB assets: USDT (RGB20) and Collectible (RGB25)
+- πΈ Perform multiple asset transfers between three wallets
+- β
Verify the correctness of all transfers
+- π Support two wallet types: wpkh and tapret-key-only
+
+### Technology Stack
+- **Language**: Bash 4.0+
+- **Blockchain**: Bitcoin Regtest
+- **Wallets**: bp-wallet, rgb-wallet
+- **Indexer**: Electrum (default) / Esplora
+- **Containers**: Docker Compose
+
+---
+
+## Core Components
+
+### 1. Variable Configuration
+```
+CONTRACT_DIR="contracts" # Contract files directory
+NETWORK="regtest" # Bitcoin test network
+WALLET_PATH="wallets" # Wallet path
+SATS=800 # Satoshis per transfer
+FEE=260 # Transaction fee
+```
+
+### 2. RGB Wallet Types
+- **wpkh**: Traditional SegWit wallet (BIP84)
+- **tapret-key-only**: Taproot wallet (BIP86)
+
+### 3. Indexer Configuration
+- **Electrum**: Port 50001
+- **Esplora**: HTTP API on port 8094
+
+### 4. Contract Mapping
+```
+CONTRACT_NAME_MAP["usdt"] = USDT
+CONTRACT_NAME_MAP["collectible"] = OtherToken
+```
+
+---
+
+## Execution Flow Details
+
+### Phase 1: Initial Setup
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant D as Docker Services
+
+ S->>S: Check Bash version (needs 4.0+)
+ S->>S: Check required tools (cargo, docker, jq, etc.)
+ S->>S: Install Rust crates
+ Note over S: bp-wallet v0.12.0-rc.1
+ Note over S: rgb-wallet v0.12.0-rc.3
+ S->>D: Start Docker services
+ activate D
+ D->>D: Start bitcoind
+ D->>D: Start electrum/esplora
+ D->>D: Create miner wallet
+ D->>D: Mine 103 blocks (get available balance)
+ deactivate D
+```
+
+**Key Steps**:
+1. β
`check_tools()`: Verify all dependency tools
+2. π§ `install_rust_crate()`: Install bp-wallet and rgb-wallet
+3. π³ `start_services()`: Start Docker containers
+4. βοΈ `prepare_btc_wallet()`: Mine to get initial funds
+
+---
+
+### Phase 2: Wallet Preparation
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant W0 as Wallet_0
+ participant W1 as Wallet_1
+ participant W2 as Wallet_2
+
+ S->>W0: prepare_rgb_wallet(wallet_0, wpkh)
+ activate W0
+ W0->>W0: Generate seed
+ W0->>W0: Derive keys
+ W0->>W0: Initialize RGB wallet
+ W0->>W0: Create descriptor
+ deactivate W0
+
+ S->>W1: prepare_rgb_wallet(wallet_1, wpkh)
+ activate W1
+ W1->>W1: Same initialization flow
+ deactivate W1
+
+ S->>W2: prepare_rgb_wallet(wallet_2, wpkh)
+ activate W2
+ W2->>W2: Same initialization flow
+ deactivate W2
+```
+
+**Each wallet initialization includes**:
+1. π Create seed file (`bp-hot seed`)
+2. π Derive key pairs (`bp-hot derive`)
+3. π¨ Initialize RGB storage (`rgb init`)
+4. πΌ Create wallet instance (`rgb create`)
+
+---
+
+### Phase 3: Contract Issuance
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant W0 as Wallet_0
+ participant D as Docker/Bitcoin
+ participant BC as Blockchain
+
+ S->>W0: get_issue_utxo()
+ W0->>D: Request funding address
+ D->>W0: Return address
+ D->>BC: sendtoaddress (1 BTC)
+ BC->>BC: Mine 1 block for confirmation
+ W0->>W0: Sync wallet
+
+ S->>W0: issue_contract(usdt)
+ activate W0
+ W0->>W0: Read contract template (usdt.yaml.template)
+ W0->>W0: Replace parameters (supply: 2000)
+ W0->>W0: Import issuer file
+ W0->>W0: Execute issuance (rgb issue)
+ W0->>W0: Record contract_id
+ Note over W0: USDT contract ID generated
+ deactivate W0
+
+ S->>W0: issue_contract(collectible)
+ activate W0
+ W0->>W0: Same flow to issue Collectible
+ Note over W0: Collectible contract ID generated
+ deactivate W0
+```
+
+**Contract Parameters**:
+- **Supply**: 2000 units
+- **Binding**: Specific UTXO (txid:vout)
+- **Types**: NIA (RGB20) and CFA (RGB25)
+
+---
+
+### Phase 4: Contract Distribution
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant W0 as Wallet_0
+ participant W1 as Wallet_1
+ participant W2 as Wallet_2
+ participant FS as File System
+
+ S->>W0: export_contract(usdt)
+ W0->>FS: Copy contract file to contracts/
+
+ S->>FS: import_contract(usdt, wallet_1)
+ FS->>W1: Copy contract file to data1/
+
+ S->>FS: import_contract(usdt, wallet_2)
+ FS->>W2: Copy contract file to data2/
+
+ Note over W0,W2: Repeat same flow for Collectible
+```
+
+**Notes**:
+- RGB contracts are shared via file system
+- Each wallet needs to import the contract definition to receive that asset
+
+---
+
+### Phase 5: Asset Transfers
+
+This is the most complex part. Let me show a complete transfer flow in detail:
+
+```mermaid
+sequenceDiagram
+ participant Sender as Wallet_0 (Sender)
+ participant Recipient as Wallet_1 (Recipient)
+ participant Bitcoin as Bitcoin Network
+ participant Indexer as Indexer (Electrum)
+
+ Note over Sender,Recipient: Transfer 100 USDT: Wallet_0 -> Wallet_1
+
+ rect rgb(230, 240, 255)
+ Note over Sender,Recipient: 1. Preparation Phase
+ Sender->>Sender: check_balance(2000 USDT)
+ Recipient->>Recipient: check_balance(0 USDT)
+ end
+
+ rect rgb(255, 240, 230)
+ Note over Sender,Recipient: 2. Invoice Generation
+ Recipient->>Bitcoin: Request new address/UTXO
+ Bitcoin-->>Recipient: Return UTXO
+ Recipient->>Recipient: rgb invoice (100 USDT)
+ Recipient-->>Sender: Invoice string
+ end
+
+ rect rgb(240, 255, 240)
+ Note over Sender,Recipient: 3. Create Transfer
+ Sender->>Sender: rgb pay (process invoice)
+ Sender->>Sender: Generate PSBT (Partially Signed Bitcoin Transaction)
+ Sender->>Sender: Generate Consignment (RGB proof)
+ Sender-->>Recipient: Copy consignment file
+ end
+
+ rect rgb(255, 255, 230)
+ Note over Sender,Recipient: 4. Validate and Accept
+ Recipient->>Recipient: rgb accept (validate consignment)
+ Recipient->>Recipient: Verify state transition validity
+ Recipient->>Recipient: Update local state
+ end
+
+ rect rgb(255, 230, 255)
+ Note over Sender,Recipient: 5. Sign and Broadcast
+ Sender->>Sender: bp-hot sign (sign PSBT)
+ Sender->>Sender: rgb finalize (finalize transaction)
+ Sender->>Bitcoin: broadcast (broadcast transaction)
+ Bitcoin->>Bitcoin: Mine 1 block for confirmation
+ end
+
+ rect rgb(230, 255, 255)
+ Note over Sender,Recipient: 6. Sync and Verify
+ Sender->>Indexer: sync wallet
+ Recipient->>Indexer: sync wallet
+ Sender->>Sender: check_balance(1900 USDT)
+ Recipient->>Recipient: check_balance(100 USDT)
+ end
+```
+
+#### Transfer Type Descriptions
+
+**Transfers included in Scenario 0 (default)**:
+
+| # | Asset | Sender | Recipient | Amount | Type | Description |
+|---|-------|--------|-----------|--------|------|-------------|
+| 0 | USDT | wallet_0 | wallet_1 | 100 | Aborted | Aborted transfer |
+| 1 | USDT | wallet_0 | wallet_1 | 100 | Normal | Retry success |
+| 2 | Collectible | wallet_0 | wallet_1 | 200 | Normal | CFA asset |
+| 3 | USDT | wallet_0 | wallet_1 | 200 | Witness | Using witness output |
+| 4 | USDT | wallet_1 | wallet_2 | 250 | Normal | Spend multiple allocations |
+| 5 | Collectible | wallet_1 | wallet_2 | 100 | Normal | CFA asset |
+| 6 | USDT | wallet_2 | wallet_0 | 100 | Witness | Close loop, return to issuer |
+| 7 | Collectible | wallet_2 | wallet_0 | 50 | Witness | CFA close loop |
+| 8 | USDT | wallet_0 | wallet_1 | 50 | Normal | Spend returned assets |
+| 9 | Collectible | wallet_0 | wallet_1 | 25 | Normal | CFA re-transfer |
+| 10 | USDT | wallet_1 | wallet_2 | 100 | Normal | Spend all (no change) |
+| 11 | USDT | wallet_2 | wallet_0 | 250 | Witness | Return all |
+
+---
+
+### Phase 6: Final Verification
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant W0 as Wallet_0
+ participant W1 as Wallet_1
+ participant W2 as Wallet_2
+
+ S->>W0: check_balance(usdt)
+ W0-->>S: 2000 β
+ S->>W1: check_balance(usdt)
+ W1-->>S: 0 β
+ S->>W2: check_balance(usdt)
+ W2-->>S: 0 β
+
+ S->>W0: check_balance(collectible)
+ W0-->>S: 1825 β
+ S->>W1: check_balance(collectible)
+ W1-->>S: 125 β
+ S->>W2: check_balance(collectible)
+ W2-->>S: 50 β
+
+ Note over S: All balance verifications passed!
+```
+
+---
+
+### Phase 7: Cleanup
+
+```mermaid
+sequenceDiagram
+ participant S as Script
+ participant D as Docker Services
+ participant FS as File System
+
+ S->>D: Stop all services
+ D->>D: Gracefully stop electrs/socat
+ D->>D: docker compose down
+ S->>FS: Delete data directories
+ Note over FS: data0, data1, data2
datacore, dataindex
+```
+
+---
+
+## Scenario Descriptions
+
+The script supports 4 predefined scenarios:
+
+### scenario_0 (default)
+- **Wallet Type**: wpkh (SegWit)
+- **Includes**: Aborted transfer test
+- **Number of Transfers**: 12
+- **Test Points**:
+ - β
Normal transfers
+ - β
Aborted/retry transfers
+ - β
Witness output transfers
+ - β
Spend multiple allocations
+ - β
No-change transfers
+
+### scenario_1
+- **Wallet Type**: tapret-key-only (Taproot)
+- **Other**: Same as scenario_0
+
+### scenario_10
+- **Wallet Type**: wpkh
+- **Excludes**: Aborted transfer test
+- **Number of Transfers**: 11
+
+### scenario_11
+- **Wallet Type**: tapret-key-only
+- **Excludes**: Aborted transfer test
+- **Number of Transfers**: 11
+
+---
+
+## Key Function Analysis
+
+### 1. transfer_assets()
+The most important function that handles the complete asset transfer flow.
+
+**Parameters**:
+```bash
+transfer_assets wallet_0/wallet_1 2000/0 100 1900/100 0 0 usdt
+ β β β β β β β
+ sender/recipient initial amt final wit reuse contract
+```
+
+**Internal Flow**:
+1. `transfer_create()`: Create transfer (generate PSBT and consignment)
+2. `transfer_complete()`: Complete transfer (validate, sign, broadcast)
+
+### 2. prepare_rgb_wallet()
+Initialize RGB wallet.
+
+**Steps**:
+1. Generate BIP39 seed
+2. Derive HD keys (BIP84 or BIP86)
+3. Create RGB wallet
+4. Set descriptor mapping
+
+### 3. issue_contract()
+Issue RGB contract.
+
+**Steps**:
+1. Read YAML template
+2. Replace parameters (supply, UTXO)
+3. Import issuer file
+4. Execute issue command
+5. Record contract_id
+
+### 4. check_balance()
+Verify wallet balance.
+
+**Verification Logic**:
+1. List all unspent outputs (UTXOs)
+2. Get RGB allocations for each UTXO
+3. Sum up total balance
+4. Compare with expected value
+
+---
+
+## Execution Time Estimation
+
+| Phase | Time | Notes |
+|-------|------|-------|
+| Initial Setup | ~30-60s | First run requires Rust compilation |
+| Wallet Preparation | ~10s Γ 3 | Per wallet |
+| Contract Issuance | ~5s Γ 2 | Per contract |
+| Single Transfer | ~10-15s | Including mining and sync |
+| **Total** | **~5-10 minutes** | Full run of scenario_0 |
+
+---
+
+## Data Flow Diagram
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+β demo.sh Execution Flow β
+ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 1. Environment Check and Init β
+ β - Bash version β₯ 4.0 β
+ β - Tool dependencies (cargo, docker...)β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 2. Install Rust Crates β
+ β - bp-wallet v0.12.0-rc.1 β
+ β - rgb-wallet v0.12.0-rc.3 β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 3. Start Docker Services β
+ β βββββββββββββββββββββββββββββββββββ β
+ β β bitcoind (regtest) β β
+ β β electrum / esplora β β
+ β βββββββββββββββββββββββββββββββββββ β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 4. Prepare Bitcoin Wallet β
+ β - Create miner wallet β
+ β - Mine 103 blocks (get funds) β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 5. Prepare RGB Wallets (0/1/2) β
+ β βββββββββββββββββββββββββββββββββββ β
+ β β Generate seed β β
+ β β Derive keys (BIP84/BIP86) β β
+ β β Initialize RGB storage β β
+ β β Create wallet instance β β
+ β βββββββββββββββββββββββββββββββββββ β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 6. Issue RGB Contracts β
+ β βββββββββββββββββββββββββββββββββββ β
+ β β USDT (RGB20): 2000 units β β
+ β β Collectible (RGB25): 2000 units β β
+ β βββββββββββββββββββββββββββββββββββ β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 7. Export/Import Contracts β
+ β wallet_0 ββexportββ> contracts/ β
+ β contracts/ ββimportββ> wallet_1/2 β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 8. Asset Transfer Loop (multiple) β
+ β βββββββββββββββββββββββββββββββββββ β
+ β β Recipient generates invoice β β
+ β β Sender creates transfer (PSBT) β β
+ β β Recipient validates consignment β β
+ β β Sender signs and broadcasts β β
+ β β Mine for confirmation β β
+ β β Both parties sync wallets β β
+ β β Verify balances β β
+ β βββββββββββββββββββββββββββββββββββ β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 9. Final Balance Verification β
+ β β
wallet_0: 2000 USDT, 1825 CFA β
+ β β
wallet_1: 0 USDT, 125 CFA β
+ β β
wallet_2: 0 USDT, 50 CFA β
+ βββββββββββββββββββββββββββββββββββββββββ
+ β
+ βΌ
+ βββββββββββββββββββββββββββββββββββββββββ
+ β 10. Cleanup β
+ β - Stop Docker services β
+ β - Delete data directories β
+ βββββββββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## Technical Highlights
+
+### RGB Protocol Key Concepts
+
+1. **Client-side Validation**: RGB state is validated off-chain
+2. **Consignment**: Data package containing state transition proofs
+3. **PSBT**: Partially Signed Bitcoin Transaction
+4. **Seal**: Mechanism to bind RGB state to UTXO
+
+### Two Commitment Methods
+
+1. **OP_RETURN (opret)**: Uses OP_RETURN output
+2. **Tapret**: Uses Taproot output (more private)
+
+### Transfer Modes
+
+1. **Blinded UTXO**: Recipient provides specific UTXO
+2. **Witness Output (wout)**: Sender creates new witness output
+
+---
+
+## Troubleshooting
+
+### 1. Bash Version Error
+```bash
+ERROR: This script requires Bash 4.0 or higher
+```
+**Solution**: Install newer bash on macOS
+```bash
+brew install bash
+/opt/homebrew/bin/bash demo.sh
+```
+
+### 2. Docker Port Conflict
+```bash
+ERROR: port 50001 is already bound
+```
+**Solution**: Stop services occupying the port
+```bash
+./demo.sh --stop
+```
+
+### 3. Missing Tools
+```bash
+ERROR: could not find required tool "jq"
+```
+**Solution**: Install missing tools
+```bash
+brew install jq
+```
+
+---
+
+## Command Line Arguments
+
+```bash
+./demo.sh [options]
+
+Options:
+ -h, --help Display help information
+ -l, --list List available scenarios
+ -s, --scenario Run specified scenario (default: 0)
+ -v, --verbose Enable verbose output
+ -r, --recompile Force recompile
+ --esplora Use esplora indexer (default: electrum)
+ -u, --skip-stop Don't stop Docker containers after completion
+ --stop Stop Docker containers
+```
+
+### Usage Examples
+
+```bash
+# Run default scenario (wpkh, includes abort test)
+./demo.sh
+
+# Run Taproot scenario
+./demo.sh -s 1
+
+# Use Esplora indexer
+./demo.sh --esplora
+
+# Verbose mode + don't stop services
+./demo.sh -v -u
+
+# List all scenarios
+./demo.sh -l
+```
+
+---
+
+## Summary
+
+`demo.sh` is a comprehensive RGB protocol testing script that demonstrates:
+
+β
**Complete Lifecycle**: From wallet creation to asset issuance, to multiple transfers
+β
**Multiple Scenarios**: Support different wallet types and transfer modes
+β
**Strict Validation**: Balance and state checks at every step
+β
**Automation**: One-click run for the entire test flow
+β
**Cleanup Mechanism**: Automatically clean up environment and data
+
+This is an excellent starting point for learning and testing the RGB protocol!
+
+---
+
+## Appendix: Key File Structure
+
+```
+rgb-sandbox/
+βββ demo.sh # Main script
+βββ contracts/ # Contract files directory
+β βββ usdt.yaml.template # USDT contract template
+β βββ collectible.yaml.template # Collectible contract template
+βββ issuers/ # Issuer definitions
+β βββ RGB20-Simplest-v0-*.issuer
+β βββ RGB25-UniquelyFungible-v0-*.issuer
+βββ wallets/ # Wallet files
+β βββ wallet_*.seed # Seed files
+β βββ wallet_*.derive # Derived keys
+βββ data0/ # wallet_0's RGB data
+βββ data1/ # wallet_1's RGB data
+βββ data2/ # wallet_2's RGB data
+βββ bp-wallet/ # bp-wallet binaries
+β βββ bin/
+β βββ bp
+β βββ bp-hot
+βββ rgb-wallet/ # rgb-wallet binaries
+ βββ bin/
+ βββ rgb
+```
+
+---
+
+**Generated**: 2026-02-03
+**Script Version**: demo.sh (RGB v0.12)
diff --git a/demo.sh b/demo.sh
index 5fc070c..b0360b0 100755
--- a/demo.sh
+++ b/demo.sh
@@ -1,5 +1,18 @@
#!/usr/bin/env bash
+# Check bash version (need 4.0+ for associative arrays)
+if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
+ echo "ERROR: This script requires Bash 4.0 or higher (you have ${BASH_VERSION})"
+ echo ""
+ echo "On macOS, install a newer bash with:"
+ echo " brew install bash"
+ echo ""
+ echo "Then run the script explicitly with the newer bash:"
+ echo " /opt/homebrew/bin/bash demo.sh # for Apple Silicon"
+ echo " /usr/local/bin/bash demo.sh # for Intel Mac"
+ exit 1
+fi
+
# variables
CONTRACT_DIR="contracts"
DEBUG=0
@@ -19,7 +32,7 @@ export SEED_PASSWORD="seed test password"
BP_WALLET_FEATURES="--features=cli,hot"
BP_WALLET_VER="0.12.0-rc.1"
RGB_WALLET_FEATURES=""
-RGB_WALLET_VER="0.12.0-rc.1.1"
+RGB_WALLET_VER="0.12.0-rc.3"
# RGB wallet types
WALLET_TYPES=("wpkh" "tapret-key-only")
@@ -117,7 +130,7 @@ _wait_indexers_sync() {
electrum_json="{\"jsonrpc\": \"2.0\", \"wallet_type\": \"blockchain.block.header\", \"params\": [$block_count], \"id\": 0}"
while :; do
electrum_res="$(echo "$electrum_json" \
- | netcat -w1 localhost $ELECTRUM_PORT \
+ | nc -w1 localhost $ELECTRUM_PORT \
| jq '.result')"
[ -n "$electrum_res" ] && break
echo -n "."
@@ -198,12 +211,16 @@ _show_state() {
# helper functions
check_tools() {
_subtit "checking required tools"
- local required_tools="awk base64 cargo cut docker grep head jq netcat sha256sum tr"
+ local required_tools="awk base64 cargo cut docker grep head jq sha256sum tr"
for tool in $required_tools; do
if ! which "$tool" >/dev/null; then
- _die "could not find reruired tool \"$tool\", please install it and try again"
+ _die "could not find required tool \"$tool\", please install it and try again"
fi
done
+ # Check for netcat (can be 'nc' or 'netcat' depending on system)
+ if ! which nc >/dev/null && ! which netcat >/dev/null; then
+ _die "could not find required tool \"netcat\" (or \"nc\"), please install it and try again"
+ fi
if ! docker compose >/dev/null; then
_die "could not call docker compose (hint: install docker compose plugin)"
fi
@@ -225,6 +242,16 @@ install_rust_crate() {
local features opts
local debug=""
local force=""
+
+ # Check if binary already exists and skip if not forcing recompile
+ if [ -d "./$crate/bin" ] && [ $RECOMPILE != 1 ]; then
+ local bin_count=$(ls "./$crate/bin" 2>/dev/null | wc -l)
+ if [ "$bin_count" -gt 0 ]; then
+ _subtit "skipping $crate installation (binary already exists)"
+ return 0
+ fi
+ fi
+
if [ -n "$3" ]; then
read -r -a features <<< "$3"
fi
@@ -263,9 +290,9 @@ set_aliases() {
stop_services() {
_subtit "stopping services"
# cleanly stop esplora
- if $COMPOSE ps |grep -q esplora; then
+ if docker compose ps |grep -q esplora; then
for SRV in socat electrs; do
- $COMPOSE exec esplora bash -c "sv -w 60 force-stop /etc/service/$SRV"
+ docker compose exec esplora bash -c "sv -w 60 force-stop /etc/service/$SRV"
done
fi
@@ -277,7 +304,8 @@ start_services() {
_subtit "checking data directories"
for data_dir in data0 data1 data2; do
if [ -d "$data_dir" ]; then
- if [ "$(stat -c %u $data_dir)" = "0" ]; then
+ # macOS uses 'stat -f %u' instead of 'stat -c %u'
+ if [ "$(stat -f %u $data_dir 2>/dev/null || stat -c %u $data_dir 2>/dev/null)" = "0" ]; then
echo "existing data directory \"$data_dir\" found, owned by root"
echo "please remove it and try again (e.g. 'sudo rm -r $data_dir')"
_die "cannot continue"
@@ -293,7 +321,7 @@ start_services() {
[ "$PROFILE" = "electrum" ] && EXPOSED_PORTS=(50001)
[ "$PROFILE" = "esplora" ] && EXPOSED_PORTS=(8094)
for port in "${EXPOSED_PORTS[@]}"; do
- if netcat -z localhost "$port"; then
+ if nc -z localhost "$port"; then
_die "port $port is already bound, services can't be started"
fi
done
@@ -421,8 +449,9 @@ issue_contract() {
-e "s/txid/$TXID_ISSUE/" \
-e "s/vout/$VOUT_ISSUE/" \
"$contract_tmpl" > "$contract_yaml"
- _subtit "issuing"
- _trace "${RGB[@]}" -d "data${wallet_id}" import issuers/*
+ _subtit "importing issuer files (contract type definitions)"
+ _trace "${RGB[@]}" -d "data${wallet_id}" import issuers/*.issuer
+ _subtit "issuing contract from YAML"
_trace "${RGB[@]}" -d "data${wallet_id}" issue -w "$wallet" "$contract_yaml" \
>$TRACE_OUT 2>&1
issuance="$(cat $TRACE_OUT)"
@@ -459,7 +488,7 @@ prepare_rgb_wallet() {
_trace "${BPHOT[@]}" seed "$WALLET_PATH/$wallet.seed"
_trace "${BPHOT[@]}" derive -N -s $der_scheme \
"$WALLET_PATH/$wallet.seed" "$WALLET_PATH/$wallet.derive" >$TRACE_OUT
- account="$(cat $TRACE_OUT | awk '/Account/ {print $NF}')"
+ account="$(cat $TRACE_OUT | awk '/Account:/ {print $2}')"
DESC_MAP[$wallet]="$account/<0;1>/*"
[ $DEBUG = 1 ] && echo "descriptor: ${DESC_MAP[$wallet]}"
WALLETS+=("$wallet")
@@ -468,8 +497,13 @@ prepare_rgb_wallet() {
# RGB setup
_subtit "creating RGB wallet $wallet"
wallet_id=${WLT_ID_MAP[$wallet]}
- _trace "${RGB[@]}" -d "data${wallet_id}" init -q
+ _trace "${RGB[@]}" -d "data${wallet_id}" init
_trace "${RGB[@]}" -d "data${wallet_id}" create --"$wallet_type" "$wallet" "${DESC_MAP[$wallet]}"
+ # RGB v0.12 stores wallets as NAME.wallet directories, but accepts NAME in commands
+ # Rename the directory if needed for compatibility
+ if [ -d "data${wallet_id}/bitcoin.testnet/$wallet" ] && [ ! -d "data${wallet_id}/bitcoin.testnet/$wallet.wallet" ]; then
+ mv "data${wallet_id}/bitcoin.testnet/$wallet" "data${wallet_id}/bitcoin.testnet/$wallet.wallet"
+ fi
}
sign_and_broadcast() {
@@ -573,7 +607,7 @@ transfer_create() {
local fee=()
[ -n "$SATS" ] && sats=(--sats "$SATS")
[ -n "$FEE" ] && fee=(--fee "$FEE")
- _trace "${RGB[@]}" -d "$send_data" pay -w "$SEND_WLT" \
+ _trace "${RGB[@]}" -d "$send_data" pay "$INDEXER_CLI" -w "$SEND_WLT" \
"${sats[@]}" "${fee[@]}" --force \
"$INVOICE" "$send_data/$CONSIGNMENT" "$send_data/$PSBT"
if ! ls "$send_data/$CONSIGNMENT" >/dev/null 2>&1; then
@@ -728,8 +762,8 @@ set_aliases
trap cleanup EXIT
# install crates
-install_rust_crate "bp-wallet" "$BP_WALLET_VER" "$BP_WALLET_FEATURES" "--git https://github.com/BP-WG/bp-wallet --branch v0.12" # commit 0d439062
-install_rust_crate "rgb-wallet" "$RGB_WALLET_VER" "$RGB_WALLET_FEATURES" "--git https://github.com/RGB-WG/rgb --branch v0.12" # commit 9ffff7fb
+install_rust_crate "bp-wallet" "$BP_WALLET_VER" "$BP_WALLET_FEATURES" "--git https://github.com/BP-WG/bp-wallet --branch v0.12"
+install_rust_crate "rgb-wallet" "$RGB_WALLET_VER" "$RGB_WALLET_FEATURES" "--git https://github.com/RGB-WG/rgb --rev b8c85817c8f1e3336c25dff7e328dff0121722fe"
mkdir "$CONTRACT_DIR"
diff --git a/docker-compose.yml b/docker-compose.yml
index 9eb6bda..45455a2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,22 +1,30 @@
services:
bitcoind:
profiles: [electrum]
- image: registry.gitlab.com/hashbeam/docker/bitcoind:27.1
+ image: registry.gitlab.com/hashbeam/docker/bitcoind:28.1
command: "-fallbackfee=0.0002"
volumes:
- ./datacore:/srv/app/.bitcoin
+ healthcheck:
+ test: ["CMD-SHELL", "su -c 'bitcoin-cli -regtest getblockchaininfo' blits"]
+ interval: 5s
+ timeout: 5s
+ retries: 30
+ start_period: 10s
electrs:
profiles: [electrum]
- image: registry.gitlab.com/hashbeam/docker/electrs:0.10.0
+ image: registry.gitlab.com/hashbeam/docker/electrs:0.10.9
depends_on:
- - bitcoind
+ bitcoind:
+ condition: service_healthy
ports:
- 50001:50001
volumes:
- ./dataelectrs:/srv/app/db
+ restart: unless-stopped
esplora:
profiles: [esplora]
- image: blockstream/esplora:956c74f42eb6ad803d8aedc272ba83d3aa6dcf5c
+ image: blockstream/esplora:latest
command: /srv/explorer/run.sh bitcoin-regtest explorer
environment:
DEBUG: verbose
diff --git a/issuers/RGB20-Simplest-v0-rLosfg.issuer b/issuers/RGB20-Simplest-v0-rLosfg.issuer
index 408e7ff..222f34c 100644
Binary files a/issuers/RGB20-Simplest-v0-rLosfg.issuer and b/issuers/RGB20-Simplest-v0-rLosfg.issuer differ
diff --git a/rgb-schemata b/rgb-schemata
new file mode 160000
index 0000000..7a66a9b
--- /dev/null
+++ b/rgb-schemata
@@ -0,0 +1 @@
+Subproject commit 7a66a9b02a3a36d3f121cbc5833fe876caf9f1f2