Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/mesh' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
iamyulong committed Dec 13, 2024
2 parents 2057ecf + 6cb8f0a commit 36685db
Show file tree
Hide file tree
Showing 33 changed files with 1,087 additions and 274 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,17 +255,19 @@ jobs:
env:
# This is to skip keygen step
RADIXDLT_NODE_KEY: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY=
run: ./gradlew :core:run --info &
run: |
echo "db.historical_substate_values.enable=true" >> core/default.config
./gradlew :core:run --info &
- name: Wait for 2 minutes
run: sleep 2m
- name: Install mesh-cli
run: curl -sSfL https://raw.githubusercontent.com/coinbase/mesh-cli/master/scripts/install.sh | sh -s
- name: Run Data API tests
run: ./bin/rosetta-cli check:data --configuration-file core-rust/mesh-api-server/mesh-cli-configs/default.json
run: ./bin/rosetta-cli --configuration-file core-rust/mesh-api-server/mesh-cli-configs/localnet.json check:data
- name: Run Construction API tests
run: ./bin/rosetta-cli check:construction --configuration-file core-rust/mesh-api-server/mesh-cli-configs/default.json
run: ./bin/rosetta-cli --configuration-file core-rust/mesh-api-server/mesh-cli-configs/localnet.json check:construction
- name: Run Coinbase-spec tests
run: ./bin/rosetta-cli check:spec --configuration-file core-rust/mesh-api-server/mesh-cli-configs/default.json
run: ./bin/rosetta-cli --configuration-file core-rust/mesh-api-server/mesh-cli-configs/localnet.json check:spec
cross-xwin:
name: Cross compile to Windows
runs-on: ubuntu-latest
Expand Down
278 changes: 278 additions & 0 deletions core-rust/mesh-api-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
# Mesh API Implementation for Radix

## Mesh API information

- [Mesh API Homepage](https://docs.cdp.coinbase.com/mesh/docs/welcome)
- [Mesh API Specification](https://github.com/coinbase/mesh-specifications)
- [Mesh API CLI Test Tool](https://github.com/coinbase/mesh-cli)

## Supported Features

| Feature | Status |
| ---------------------------- | ----------------------------------------------------------------------|
| Data API | Feature-complete, with some quirks |
| - `/network/list` | Complete |
| - `/network/status` | Complete |
| - `/network/options` | Complete |
| - `/block` | Feature-complete (exposes only balance-changing operations) |
| - `/block/transaction` | Feature-complete (exposes only balance-changing operations) |
| - `/account/balance` | Complete (historical balances available if explicitly enabled) |
| - `/mempool` | Complete (transactions are not held for a meaningful duration) |
| - `/mempool/transaction` | Complete (basic operations supported) |
| Construction API | Complete |
| - `/construction/derive` | Complete |
| - `/construction/preprocess` | Complete |
| - `/construction/metadata` | Complete |
| - `/construction/payloads` | Complete (supports Withdraw and Deposit operations only) |
| - `/construction/combine` | Complete |
| - `/construction/parse` | Complete (basic operations supported) |
| - `/construction/hash` | Complete |
| - `/construction/submit` | Complete |

## Additional Considerations

### Accounts

The current implementation has the following constraints:
- **Supports only account components**: Returns block operations or balances exclusively for accounts. Other components (e.g., smart contracts, lockers) are ignored.
- **Supports only Withdraw, Deposit, and FeePayment operations**: Minting and burning are skipped.

These constraints simplify the implementation without causing Mesh CLI tests to fail. If non-account components must be supported, the following may be required:
- Adding support for Minting and Burning operations.
- Providing explicit support for non-account components in balance fetching (or using `dump_component_state()`, which is resource-intensive).
- Exempting some addresses.

### Operations

Currently, a very specific parser is used to extract operations from given instructions (endpoints: `/mempool/transaction` and `/construction/parse`).
It works only with the instructions constructed by Mesh.
`Withdraw` and `Deposit` are the direct result of the instructions being used, while a `FeePayment` is added at commit time.

Technically, it would be possible to use transaction previews, receipts, and balance change summaries to extract operations.
But we don't do it for following reasons:
- both endpoint methods should work offline
- both endpoint methods should be static (not affected by current state of the network)
- this approach is deemed too resource-heavy

## Configuration

### Server settings
There are 3 configuration settings for a node's Mesh API server, which can:
- enable/disable Mesh API server launch (disabled by default),
- override the default port (3337),
- override the default bind address (127.0.0.1).

#### Node running bare-metal
```plaintext
api.mesh.enabled=<true/false>
api.mesh.port=<port number>
api.mesh.bind_address=<ip address>
```
#### Node running in Docker
Set below environmental variables

```plaintext
RADIXDLT_MESH_API_ENABLED=<true/false>
RADIXDLT_MESH_API_PORT=<port number>
RADIXDLT_MESH_API_BIND_ADDRESS=<ip address>
```

### Enable historical balances for reconciliation tests
In order to proceed with reconciliation tests historical balances shall be enabled.
There are 2 useful settings:
- enable/disable historical substate values (disabled by default),
- adjust the state version history length to keep (60000 by default).

#### Node running bare-metal
```plaintext
db.historical_substate_values.enable=<true/false>
state_hash_tree.state_version_history_length=<history_length_to_keep>
```

#### Node running in Docker
```
RADIXDLT_DB_HISTORICAL_SUBSTATE_VALUES_ENABLE=<true/false>
RADIXDLT_STATE_HASH_TREE_STATE_VERSION_HISTORY_LENGTH=<history_length_to_keep>
```

### Base URL

```plaintext
http://<bind_address>:<port>/mesh
```

**Example**: Fetching account balance
```plaintext
http://localhost:3337/mesh/account/balance
```

## Testing

### Mesh CLI

#### Steps:
1. [Terminal 1] Download the `rosetta-cli` prebuilt binary:
```bash
curl -sSfL https://raw.githubusercontent.com/coinbase/mesh-cli/master/scripts/install.sh | sh -s

alias mesh-cli='./bin/rosetta-cli --configuration-file <root-of-babylon-node-repo>/core-rust/mesh-api-server/mesh-cli-configs/localnet.json'
```
**Note:** As of November 2024, there are issues with the prebuilt MacOS binary. Use the workaround below:
```bash
git clone [email protected]:coinbase/mesh-cli
cd mesh-cli
git checkout bbbd759
alias mesh-cli='go run main.go --configuration-file <root-of-babylon-node-repo>/core-rust/mesh-api-server/mesh-cli-configs/localnet.json'
```

2. [Terminal 2] Launch the node:

- Node running bare-metal
- Change working directory to the root of the `babylon-node` repository
- Enable Mesh API server in `core/default.config`
```plaintext
api.mesh.enabled=true
```
- Optionally setup Mesh port and bind address
```
api.mesh.port=3337
api.mesh.bind_address=
```
- For reconciliation tests enable historical balances and optionally set state history length
```
db.historical_substate_values.enable=true
state_hash_tree.state_version_history_length=60000
```

- Start the node
```bash
RADIXDLT_NODE_KEY=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY= ./gradlew :core:run --info
```

- Node running in Docker

- Manual setup for production or testnet

Follow these steps to setup a node - [Manual Setup with Docker](https://docs.radixdlt.com/v1/docs/node-setup-docker).

Before launching a node set Mesh environment variables (mentioned in previous section) in `radix-fullnode-compose.yml` in `core` section:
- Enable Mesh API server:
```yaml
RADIXDLT_MESH_API_ENABLED: 'true'
```
- Optionally setup Mesh port and bind address
```yaml
RADIXDLT_MESH_API_PORT: 3337
RADIXDLT_MESH_API_BIND_ADDRESS: '0.0.0.0'
```
- For reconciliation tests enable historical balances and optionally set state history length
```yaml
RADIXDLT_DB_HISTORICAL_SUBSTATE_VALUES_ENABLE: 'true'
RADIXDLT_STATE_HASH_TREE_STATE_VERSION_HISTORY_LENGTH: 60000
```

- Simple setup for testnet

Follow these steps to setup a node - [Simple testnet setup](https://github.com/radixdlt/babylon-node/tree/develop/testnet-node).

Before launching a node set Mesh environment variables (mentioned in previous section) in `radix-node.env`:
- Enable Mesh API server:
```plaintext
RADIXDLT_MESH_API_ENABLED=true
```
- Optionally setup Mesh port and bind address
```plaintext
RADIXDLT_MESH_API_PORT=3337
RADIXDLT_MESH_API_BIND_ADDRESS=0.0.0.0
```
- For reconciliation tests enable historical balances and optionally set state history length
```plaintext
RADIXDLT_DB_HISTORICAL_SUBSTATE_VALUES_ENABLE=true
RADIXDLT_STATE_HASH_TREE_STATE_VERSION_HISTORY_LENGTH=60000
```

3. [Terminal 1] Run Mesh API tests:
```bash
mesh-cli check:data
mesh-cli check:construction
mesh-cli check:spec
```

#### Reconciliation Tests

If whole ledger shall be reconciled for eg. `mainnet` or `stokenet`, then make sure to:
- Set a future `state_version` in the `data.end_conditions.index` field of the `mesh-cli` config file.
- Launch the node with an empty database.
- Start `mesh-cli` as soon as possible to avoid pruning historical balances.

### Unit Tests

- **Java:**
```bash
./gradlew :core:test --tests '*MeshApiMempoolEndpointsTest*'
```
- **Rust:** (To Be Determined)

## Abstractions

### NetworkIdentifier

Fields:
- `blockchain`: "radix"
- `network`: Network variant (e.g., `mainnet`, `stokenet`, `localnet`).
- `sub_network_identifier`: Not set.

### Block

Represents a single transaction.

### BlockIdentifier

Fields:
- `index`: State version.
- `hash`: Hex-encoded string of 32 bytes composed of:
- `transaction_tree_hash` (bytes[0..12]).
- `receipt_tree_hash` (bytes[0..12]).
- `state_version` (bytes[0..8]).

### TransactionIdentifier

- **User transaction:** Bech32-encoded `transaction_intent_hash` (e.g., `txid_tdx_2_1nvm90npmkjcltvpy38nr373pt38ctptgg9y0g3wemhtjxyjmau7s32hd0n`).
- **Non-user transaction:** Bech32-encoded `ledger_transaction_hash` (e.g., `ledgertransaction_tdx_2_1s45u3f6xrh4tf4040aqt9fql3wqlhvwwwfpaz4rsru3pr88f3anstnds7s`).

### AccountIdentifier

Fields:
- `address`: Bech32-encoded Global Entity Address.
- `sub_account`: Not set.
- `metadata`: Not set.

### Currency

Fields:
- `symbol`: Bech32-encoded Resource Address.
- `decimals`: Resource divisibility.
- `metadata`: Not set.

### Amount

Fields:
- `value`: Currency amount.
- `currency`: Resource information.
- `metadata`: Not set.

### Operation

Fields:
- `operation_identifier`: Index of the operation within a transaction.
- `related_operations`: Not set.
- `type`:
- `Withdraw`: Withdraw assets from an account (always success, failed operations are filtered out).
- `Deposit`: Deposit assets to an account (always success, failed operations are filtered out).
- `FeePayment`: Withdraw assets to cover transaction fees (always success, even if the transaction fails).
- `status`: Operation status.
- `account`: Account transferring the resources.
- `amount`: Amount of currency transferred.
- `coin_change`: Not set.
- `metadata`: Not set.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"network": "localnet"
},
"online_url": "http://127.0.0.1:3337/mesh",
"data_directory": "test-data",
"data_directory": "test-data/localnet",
"http_timeout": 10,
"max_retries": 5,
"retry_elapsed_time": 0,
Expand Down Expand Up @@ -40,14 +40,15 @@
"pruning_block_disabled": false,
"pruning_balance_disabled": false,
"initial_balance_fetch_disabled": false,
"historical_balance_disabled": false,
"end_conditions": {
"tip": true,
"index": 10000
}
},
"construction": {
"offline_url": "http://localhost:3337/mesh",
"constructor_dsl_file": "workflows.ros",
"constructor_dsl_file": "localnet.ros",
"prefunded_accounts": [
{
"account_identifier": {
Expand Down
59 changes: 59 additions & 0 deletions core-rust/mesh-api-server/mesh-cli-configs/mainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"network": {
"blockchain": "radix",
"network": "mainnet"
},
"online_url": "http://127.0.0.1:3337/mesh",
"data_directory": "test-data/mainnet",
"http_timeout": 10,
"max_retries": 5,
"retry_elapsed_time": 0,
"max_online_connections": 120,
"max_sync_concurrency": 64,
"tip_delay": 300,
"max_reorg_depth": 100,
"log_configuration": false,
"compression_disabled": false,
"l0_in_memory_enabled": false,
"all_in_memory_enabled": false,
"error_stack_trace_disabled": false,
"coin_supported": false,
"data": {
"active_reconciliation_concurrency": 16,
"inactive_reconciliation_concurrency": 4,
"inactive_reconciliation_frequency": 250,
"log_blocks": false,
"log_transactions": false,
"log_balance_changes": false,
"log_reconciliations": false,
"ignore_reconciliation_error": false,
"exempt_accounts": "",
"bootstrap_balances": "",
"interesting_accounts": "",
"reconciliation_disabled": false,
"reconciliation_drain_disabled": false,
"inactive_discrepancy_search_disabled": false,
"balance_tracking_disabled": false,
"coin_tracking_disabled": false,
"status_port": 9090,
"results_output_file": "",
"pruning_block_disabled": false,
"pruning_balance_disabled": false,
"initial_balance_fetch_disabled": false,
"historical_balance_disabled": false,
"end_conditions": {
"index": 104281038
}
},
"construction": {
"offline_url": "http://localhost:3337/mesh",
"constructor_dsl_file": "mainnet.ros",
"stale_depth": 1000,
"broadcast_limit": 1000,
"end_conditions": {
"radix_workflow": 1
}
},
"perf": null,
"sign": null
}
Loading

0 comments on commit 36685db

Please sign in to comment.