Repository navigation
Conversation
…and read a Config that grew A registry revision (spec rev 5.6, [CFG-10]) is one governance Update that moves Config #9 to the new registry and appends #13, the registry pools are crossing from. update-config now does exactly that. `--migrate-registry-to` writes #9 and takes #13 from the value #9 held, so it cannot be mistyped, and it insists on `--spo-bans-policy` in the same Update, because the ban list moves with the registry. `--end-registry-migration` empties #13 without removing it. A Config longer than the rev-5.5 layout used to be refused by update-config, because re-encoding it would drop the appended field. DeployedConfig now carries appended fields verbatim, and update-config plus the three off-chain readers decode through it. ConfigDatum stays the thirteen-field mirror, because TreasuryMovementValidator decodes it on chain and a fourteenth field would move its pin. New tests evaluate the deployed TM blueprint program, confirm and mint alike, against a Config with #13 appended, both mid-migration and ended: the live validator accepts it, so the migration's Update does not stop treasury movements.
… operator guide A bridge's contracts release is fixed at its genesis, and binocular now carries two: rev 5.5 (ft main, the preprod bridge) and rev 5.6 (ft 096f76c, the release heimdall embeds). `bridge.contracts` says which one a bridge was deployed with, and it defaults to rev5.5. The vendored blueprint for that release travels with its bytes, and it decides the two version-dependent parameterizations: the registry's added Config policy, and the ban list's Config policy in place of the registry hash. It also decides the Config arity genesis writes (13, or 14 with #13 empty). The rev 5.6 policy ids are pinned against heimdall's independent Rust derivation. A registry revision does not change the release. deploy-script-refs and register-bridge-creds now recognise a Config whose treasury still matches but whose registry has moved, and leave that half to heimdall instead of refusing. `bridge.plutus-json` defaults to empty and is refused when it cannot be read. It used to default to a sibling ft checkout and fall back silently, which made the contracts a command built with depend on that checkout's branch. docs/operator-guide.md is binocular's first guide for the people who run a bridge. It covers what binocular does for one, the `bridge` section, genesis in order across heimdall and binocular, the watchtower, and changing the Config (including the registry migration). It ends with what the common refusals mean. The README's command table, which listed commands that no longer exist, now points to it.
The guide's revision section now gives the order: operators upgrade heimdall at their own pace, the new version runs the unrevised bridge unchanged, and the governance Update comes once every node runs it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spec rev 5.6 (ft-bifrost-bridge #56, [CFG-10]) revises the SPO registry without redeploying the bridge. One governance Update moves Config #9 to the new registry, moves #8 to its ban list, and appends #13
previous_spos_registry_policy_id, the registry pools are crossing from. heimdall carries registrations across by itself (lantr-io/heimdall#114). This PR is binocular's part of that Update, and it makes sure binocular keeps working once the Config has fourteen fields.update-config--migrate-registry-to <policy>sets ci: migrate workflow from mill to sbt #9 to the new registry and feat(peg-out): complete peg-out flow + witness/reorg fixes + optional peg-out config #13 to whatever ci: migrate workflow from mill to sbt #9 held, in one edit. feat(peg-out): complete peg-out flow + witness/reorg fixes + optional peg-out config #13 is read from the datum, not typed: a feat(peg-out): complete peg-out flow + witness/reorg fixes + optional peg-out config #13 that isn't the old ci: migrate workflow from mill to sbt #9 would point every node at a list with nothing to migrate.--spo-bans-policyin the same Update. The three fault verifiers are compiled from the registry hash, and the ban policy from theirs, so the ban list has to move with the registry.--end-registry-migrationempties feat(peg-out): complete peg-out flow + witness/reorg fixes + optional peg-out config #13 once every pool has crossed. It never removes the field ([CFG-5] only appends).The rollout's step c3 is therefore:
Reading a Config that grew
update-configused to refuse any Config longer than the rev 5.5 layout, because re-encoding it would drop the appended field. Refusing was safe, but it made #13 impossible to write, and impossible to write any other field once #13 exists.DeployedConfignow carries appended fields verbatim, andupdate-config, the proof service, the sweep setup and the PoR sweeper all decode through it.ConfigDatumis deliberately unchanged, still the thirteen-field mirror.TreasuryMovementValidatordecodes it on chain, so a fourteenth field would move that validator's pinned hash. That would mean a new TM script for a change that has nothing to do with it.The deployed TM validator and #13
This was the real risk: the TM validator is already deployed, and it reads the Config. New tests evaluate the pinned blueprint program, the exact UPLC on chain, on both the confirm and mint paths, against a Config with #13 appended, once mid-migration and once ended. It accepts all four. So the migration's Update does not stop treasury movements on a live bridge.
Which contracts a bridge runs:
bridge.contractsbinocular now carries two contracts releases: rev 5.5 (ft
main, what the preprod bridge runs) and rev 5.6 (ft096f76c, what heimdall embeds).bridge.contractsin the config file says which one the bridge was deployed with. It defaults torev5.5, so existing config files keep working, and the preprod config now states it explicitly.It's a property of the bridge, fixed at genesis, and a registry revision does not change it. The revision replaces the registry and the ban list, which heimdall deploys. The Config, peg and TM scripts that binocular spends stay the ones the bridge was deployed with.
The vendored blueprint carries its release, and the release decides:
spos_registry: rev 5.6 adds the Config NFT policy as a fourth parameter.spo_bans: the first parameter is the registry policy in rev 5.5, and the Config NFT policy in rev 5.6.config.akgenesis mint casts all 14.The rev 5.6 policy ids are pinned against heimdall's independent Rust derivation from the same bytes, the same cross-check that already locks rev 5.5.
After a revision:
deploy-script-refsandregister-bridge-credsBoth rebuilt the registry and ban list from #12 and refused unless they matched #9 and #8, so after a revision both would have failed on the live bridge. They now classify the Config:
bridge.plutus-jsonIt used to default to
../../FluidTokens/ft-bifrost-bridge/onchain/plutus.jsonand fall back to the packaged blueprint silently when that file was absent. The contracts a command built with therefore depended on whether, and on which branch, an ft checkout sat next to the working directory. On a machine whose checkout is on the rev 5.6 branch, a genesis would have deployed rev 5.6 without a word. It now defaults to empty, meaning the packaged blueprint ofcontracts, and a path that can't be read is refused.docs/operator-guide.mdbinocular's first guide for the people who run a bridge. It covers:
bridgesection (contractsabove all);The README's command table, which listed commands that no longer exist, now points to it.
Not covered here
config.akaccepts an Update that appends a field. The spec saysconfig.akaccepts any datum shape, but that has to be seen on chain. The preprod rehearsal (a separate test bridge migrated end to end before release) is where it will be.Tests
All 724 pass under
sbt testFullafter the full cache reset. Plainsbt testin sbt 2 is incremental: it reported 125 and 621 on earlier runs of this branch, which is exactly the partial-run trap binocular's CLAUDE.md warns about. The freshness check now passes whichever of the two vendored releases the neighbouring ft checkout is on.