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 theengine
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 addeduse-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.