Skip to main content

Migrating to Treasury v24.x.y

The upgrade from Treasury 0.3.x (formally known as "silo") to v24.x.y is a large change. However, everything in 0.3.x should continue to work up to v24.4.y with minor exceptions.

This document outlines the changes that are occuring and what you need to do to migrate.

Migration Path

You must upgrade to v24.2.x first. Afterwards, you can then update to anything else. Notably, v24.4.x will continue to maintain backwards compatibility with most legacy APIs. v24.5.x and newer no longer support any legacy APIs.

New API

As documented on this website, Treasury has a new API. If you are using any of the old gRPC API's, you must migrate to using the new API at somepoint after upgrading to v24.x.y as the gRPC endpoints will be removed in next major release.

New port

Ensure the user-facing Treasury container(s) (or supervisor running the container) is forwarding port 8777 in order to access the API. All of the older ports used for legacy UI and API access (9090, 9091, 1317) are no longer needed except to maintain legacy API's.

Internal "P2P" ports (default 26656, 7867) which link Treasury nodes together remain the same.

New Configuration file

Treasury is configured using a new, simplified toml configuration file.

You can migrate your existing settings to this new file by running the following.

cord migrate legacy-config --home path/to/treasury-home

CORS

CORS is now enforced on the new API, whereas the old API permits any domain to make requests to it. To properly access Treasury from a browser, you must allowlist the domains that are accessing.

# default
api start --origin "https://treasury.cordial.systems" --listen 0.0.0.0 --verbose

# can specific multiple
api start --origin "http://localhost" --origin "https://treasury.cordial.systems" --listen 0.0.0.0 --verbose

# any domain
api start --any-origin --listen 0.0.0.0 --verbose

You can specific this also via the API section in the treasury configuration file.

[api]
origins = ["http://localhost", "https://example.com"]

CORS can be turned off by configuring:

[api]
any-origin = true

Features

Features are a resource that you can update to turn on or off functionalities on Treasury. Their main use is to guard new functionaly and preserve legacy functions to help the migration process. By default, features are disabled (unless if you're starting a new install).

The main features are listed here:

new_transfer_rules: This opts into using the new policy engine for evaluating Transfer Rules (previously called "policies").

migrate_legacy_transfer_rules: Treasury will migrate all legacy transfer policies into Transfer rules. This is independent of new_transfer_rules and may be enabled/ran multiple times.

new_iam_rules: This opts into using the new Access Rule policy engine for permitting requests to treasury. This policy engine evaluates all requests to treasury. Previously the legacy "access rules" in treasury were all hardcoded, and will be converted to Access Rule resources when this feature is enabled.

legacy_disabled: This will disable all legacy endpoints.

legacy_signer: This feature opts into forcing the signer processes into using the legacy API. Otherwise signer by default will use the new API. You should not need to enable this. If you enable this, the signer processes (or treasury nodes overall) should be restarted for it to take effect.

auto_generate_rule_doc: Enabling this will opt into treasury continuing to automatically generate + sign a new rule document after API changes. This rule document is served under a legacy endpoint (":1317/cordialsys/wallet/policy/signedPaths"), but this may be released under a supported API later. If you do not use this, ignore.

delete_root: This deletes any user (and associated credentials) and access-rule with ID "root". Used for bootstrapping access-rule policies. You can name a temporary privileged account "root", and use this feature to delete them.

new_connector: This opts into the new connector process that is faster and more reliable (also supports new gas fee multiplier in Chain and Transfer resources). Requires new_iam_rules. Default enabled on new instances. If you enable or disable this, you will need to restart the connector to take effect.

legacy_rules_more_approvers: This increases the approval requirements for some of the legacy endpoints.

To update a feature or other resource, you can use the UI, or update via the command line tool treasury, or cord.

To completely migrate, you should aim to eventually enable all new_transfer_rules, new_iam_rules, new_connector, and legacy_disabled. If you created a root account, you should use delete_root to delete it.

Prevent feature changes

To prevent a feature from regressing, you can create a simple deny rule. For example, this rule would prevent the legacy_disabled feature from being disabled.

treasury access-rules create deny keep-legacy-disabled-rule --action custom/disable --resource features --name legacy_disabled --sign-with root-key --any-initiator

Similarly, to prevent a feature from being activated.

treasury access-rules create deny keep-signer-on-new-api --action custom/activate --resource features --name legacy_signer --sign-with root-key --any-initiator

Signer process migrated to new API

The signer process is migrated to use the new API. The signer will automatically safely rename keys upon updating to use the new API.

This migration can also be applied safely offline, before updating. It is idempotent and is okay to run multiple times.

signer migrate rename-legacy-key-shares --db path/to/treasury/signer.db

It copies key shares to a new / migrated name.

If for some reason this fails, you can update signer processes to continue using the old data / old names by enabling this configuration.

[signer.engine]
# signer will continue using new API, but will prioritize using legacy names to reference keys when used.
force-legacy-names = true

Connector process migrated to new API

The connector was rewritten to use the new API. The state machine managing transactions is also greatly cleaned up and more reliable.

Previously transactions were queued in a slow and simple now. Now Treasury + the new connector understands how to dequeue transactions in an event driven way. This means chains like Solana or Tron don't need to use any queuing, and can be retried much more easily if they timeout. Additionally, UTXO chains like bitcoin or Sui should be more reliable.

The connector is able to apply gas multipliers to enable the user to have more control over gas fees, either globally per chain or per individual transfer.

More protection against accidental double-sends when retrying was added. Now before retrying a transaction, Treasury will assert that any new transaction will be able to replace the old one. How it does this depends on the chain - on EVM and cosmos chains it will require the same nonce be used. On Solana it will ensure the 'recent-block-hash' has timed out. On Sui or Bitcoin, it will ensure at least some of the inputs being spent are re-used.

Signer backup functionality

Signer backups have been improved. In addition to immediately making a encrypted backup of new keys, signer also takes periodic encrypted snapshots. More functionalty to more easily manage backups has been added.

See more in backup subcmd.

signer backup

The backup file format has change. While the old format will continue to work, it's recommended to export everything again.

signer backup export --db path/to/signer.db --all

Everything will also get exported periodically into a snapshot too.

New Policy engines

Treasury will use new policy engines for evaulating requests (AccessRules), and transfers (TransferRules).

Previous legacy resources will be converted to the new resources.

You must opt into using the new policy engines after upgrading by enabling the features for each. Disabling the features will revert to using the legacy functionality.

Transfer Rules

The new Transfers will only be able to be managed via the new UI, API, or Command line. The legacy UI will not affect any transfer policies while the new policy engine is enabled.

Account defaults

You can still allowlist by account (as was done before). Before there was an implicit behavior where each account would assign itself a "default address" per chain. When exporting a rule/path document, this "default address" would be used as the deposit address for a chain on a given account.

Now accounts have a distinction default address mapping. When migrating, this implicit defaults will be exporting into an explicit mapping. Before, people could separately managing which addresses are defaults, and they can continue to do so with this account default mapping.

See more information on transfer rules in the API doc.

New UI

See new and improved UI at https://treasury.cordial.systems/transfers

API endpoints

The following API endpoints are highlighted to guide how to migrate to new endpoints.

Create Transfer

Follow the guide on signing requests for new treasury API.

To query data, you do not need to sign. You can curl the endpoints normally.

Get Address Balances or Transaction Histories

Follow the guide on using the Oracle API. The connector process will no longer poll and instead only be resposible for subscribing addresses to the Oracle API.

Container Init System

Previously, runit was used to run multiple services in Treasury container. Now s6 is used (https://github.com/just-containers/s6-overlay).

This isn't expected to cause any impact. Logs should be more reliable, runit had an issue with log truncation.

Most logs can now be JSON formated by providing env variable CORDIAL_LOG_FORMAT=json.

CLI

silo_log_level and engine-log-level are no longer options to cord start. Please set CORDIAL_LOG_LEVEL env instead.

Asset / Symbol resolution

This historically has been a tricky issue. Treasury aims to solve by using the Symbol resource.

Previously, assets (and user-defined asset names) were created in pairs:

# this was a 'silo' name for an asset
{
"asset": "USDC",
"native_asset": "SOL",
"external_assets_used": false
}

# this was a 'silo' name for a user defined asset mapping to USDC.SOL
{
"asset": "user-USDCe",
"native_asset": "SOL",
"external_assets_used": true
}

In the legacy codebase, you would set external_name on a token asset, which would allow you to refer to it using a user provided name.

In Treasury, assets are resources with resource names that look like:

  • chains/SOL/assets/SOL
  • chains/SOL/assets/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  • chains/SOL/assets/6DNSN2BJsaPFdFFc1zP37kkeNe4Usc1Sqkzr9C9vPWcU

Either an asset has a contract address (and becomes the ID element in a name), or there is no contract address (like native asset "SOL"). This is an in disputeable & immuteable reference to a token asset.

You may create Symbols to refer to assets. Symbols are named like:

Example:

{
"name": "chains/SOL/assets/user-USDCe",
"asset": "chains/SOL/assets/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
}

Currently, only one symbol can be assigned to an asset.

Now in any request in Treasury where you might reference an asset (chains/SOL/assets/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v), you can also instead reference a symbol name (chains/SOL/assets/user-USDCe). Treasury will deference symbol names and use the asset name internally.

{
"asset": "chains/SOL/assets/user-USDCe"
}
# or
{
"asset": "chains/SOL/assets/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
}

Migrating assets

Upon updating, treasury will automatically create Symbols based on if an asset has an .external_name set.

You will not be able to update this via the legacy API or legacy UI.

Supervisor / Cord

Supervisor + Cord have some minor organizational changes.

The cord binary has been split into two programs.

  • cord binary designed to be distributed and live outside of treasury container.
  • engine binary designed to start the engine process inside of container and not much else.

The supervisor binary has been merged into cord, and you can access it's functionality via cord supervise ....

cord supervise ... has the following minor changes from previous supervisor.

  • remove 'admin' server/CLI commands (should have been unused).
  • change stop/kill signal to be SIGTERM instead of SIGHUP as treasury v24.x.y uses s6 init system now.
  • add command to initialize/overwrite the container version to run with.
  • remove WAL storage of current used image in favor of simple config file
  • removed options --initial-image, --use-image-log, and added use-image command.
  • removed reset command
  • replace --silent flag with --debug-level <int>
  • merge supervisor into new cord binary

It may be helpful to see cord used in the deployment guides.