Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions experiments/cross-chain-bridge/localnet/app-rewards-harness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,25 @@ const EVIDENCE_FILE = process.env.OZ_EVIDENCE_FILE ?? null
const REWARD_TIMEOUT_MS = Number(process.env.OZ_REWARD_TIMEOUT_S ?? 900) * 1000
const TRAFFIC_TIMEOUT_MS = Number(process.env.OZ_TRAFFIC_TIMEOUT_S ?? 300) * 1000
const POLL_INTERVAL_MS = 5000
// Scan ingests a transaction from the SV participant after the submitting
// participant has committed it. This bounds the wait for that ingestion.
const SCAN_TIMEOUT_MS = 120 * 1000

const LEDGER_TOKEN = process.env.OZ_LEDGER_TOKEN_FILE
? readFileSync(process.env.OZ_LEDGER_TOKEN_FILE, 'utf8').trim()
: null

// Templates of Splice's `splice-amulet` Daml package, addressed by package
// name (`#<package-name>:<module>:<template>`) so that the Ledger API resolves
// them across every version of the package instead of one pinned package id.
// Each link shows the definition at Splice 0.8.3, the LocalNet release that
// `scripts/ledger.sh` defaults to.
// https://github.com/canton-network/splice/blob/8460154135f39019b8bb370c9c1321ff13c9bb10/daml/splice-amulet/daml/Splice/AmuletRules.daml#L172
const AMULET_RULES = '#splice-amulet:Splice.AmuletRules:AmuletRules'
// https://github.com/canton-network/splice/blob/8460154135f39019b8bb370c9c1321ff13c9bb10/daml/splice-amulet/daml/Splice/Amulet.daml#L447
const REWARD_COUPON_V2 = '#splice-amulet:Splice.Amulet:RewardCouponV2'
// https://github.com/canton-network/splice/blob/8460154135f39019b8bb370c9c1321ff13c9bb10/daml/splice-amulet/daml/Splice/Amulet.daml#L303
const FEATURED_APP_RIGHT = '#splice-amulet:Splice.Amulet:FeaturedAppRight'

// The parties of the Daml Script record `BridgeParties`, in its field names.
const ROLES = ['ba', 'br', 'pa', 'wtokAdmin', 'recipient', 'holder', 'attester1', 'attester2', 'attester3']
Expand Down Expand Up @@ -207,7 +219,10 @@ const latestRound = async () => Number((await scanApi('GET', '/v0/dso')).latest_

// Feature `party` with the DevNet choice. A fresh validator buys its first
// synchronizer traffic on its own interval, so the first submission that costs
// traffic may be refused until then; the loop retries.
// traffic may be refused until then; the loop retries. The submit returns once
// the participant holds the right, so its ACS confirms the right at once. Scan
// ingests the right from the SV participant later, so the check on Scan polls
// for the contract.
async function featureParty(role, party) {
const dso = await scanApi('GET', '/v0/dso')
const rules = dso.amulet_rules.contract
Expand All @@ -228,9 +243,13 @@ async function featureParty(role, party) {
throw err
}
}, TRAFFIC_TIMEOUT_MS)
const featured = await scanApi('GET', '/v0/featured-apps')
const mine = (featured.featured_apps ?? []).filter((a) => a.payload?.provider === party)
if (mine.length !== 1) fail(`Scan reports ${mine.length} featured app rights for ${role}, expected 1`)
const rights = await acs(party, FEATURED_APP_RIGHT)
if (rights.length !== 1) fail(`the participant holds ${rights.length} featured app rights for ${role}, expected 1`)
const { contractId } = rights[0]
await waitFor(`Scan to list the featured app right of ${role}`, async () => {
const featured = await scanApi('GET', '/v0/featured-apps')
return (featured.featured_apps ?? []).some((a) => a.contract_id === contractId) ? contractId : null
}, SCAN_TIMEOUT_MS)
log(`featured ${role} (${party.slice(0, 24)}...)`)
}

Expand Down
30 changes: 25 additions & 5 deletions experiments/interoperability/traffic-rewards/harness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ const REWARD_TIMEOUT_MS = Number(process.env.OZ_REWARD_TIMEOUT_S ?? 900) * 1000
// A fresh app-provider validator holds no synchronizer traffic. It buys traffic
// from the SV on its own interval, so the first call that costs traffic waits.
const TRAFFIC_TIMEOUT_MS = Number(process.env.OZ_TRAFFIC_TIMEOUT_S ?? 300) * 1000
// Scan ingests a transaction from the SV participant after the submitting
// participant has committed it. This bounds the wait for that ingestion.
const SCAN_TIMEOUT_MS = 120 * 1000
const POLL_INTERVAL_MS = 5000

// The token of the participant admin user. The gate mints it, because the same
Expand All @@ -83,9 +86,12 @@ const T = {
// Splice packages, which LocalNet vets on the app-provider participant. The
// `#package-name` form resolves to the highest vetted version, so the pin is
// `OZ_SPLICE_VERSION` of `scripts/ledger.sh`. This client reads the payloads of
// Splice 0.7.1, and a release that changes either one fails an assertion below
// rather than reporting a version mismatch here.
// Splice 0.8.3, and a release that changes either one fails an assertion below
// rather than reporting a version mismatch here. Each link shows the
// definition at Splice 0.8.3.
// https://github.com/canton-network/splice/blob/8460154135f39019b8bb370c9c1321ff13c9bb10/daml/splice-amulet/daml/Splice/Amulet.daml#L447
rewardCouponV2: '#splice-amulet:Splice.Amulet:RewardCouponV2',
// https://github.com/canton-network/splice/blob/8460154135f39019b8bb370c9c1321ff13c9bb10/daml/splice-api-reward-assignment-v1/daml/Splice/Api/RewardAssignmentV1.daml#L40
rewardCoupon: '#splice-api-reward-assignment-v1:Splice.Api.RewardAssignmentV1:RewardCoupon',
}

Expand Down Expand Up @@ -447,6 +453,7 @@ async function selfFeature() {
},
TRAFFIC_TIMEOUT_MS,
)
let contractId = null
if (!status.has_featured_app_right) {
// A fresh validator holds no synchronizer traffic and buys it from the SV on
// its own interval, and it answers 429 until then.
Expand All @@ -462,12 +469,25 @@ async function selfFeature() {
},
TRAFFIC_TIMEOUT_MS,
)
log(`self-granted the featured app right (${granted.contract_id.slice(0, 16)}...)`)
contractId = granted.contract_id
log(`self-granted the featured app right (${contractId.slice(0, 16)}...)`)
} else {
log('the app-provider already holds a featured app right')
}
const featured = await scanApi('GET', '/v0/featured-apps')
const mine = (featured.featured_apps ?? []).filter((a) => a.payload?.provider === status.party_id)
// The wallet answers once the validator has committed the right, and Scan
// ingests it from the SV participant later, so the check on Scan polls. A
// right granted here matches on its contract id; a right from an earlier run
// matches on the provider.
const matches = (a) => (contractId ? a.contract_id === contractId : a.payload?.provider === status.party_id)
const mine = await waitFor(
'Scan to list the featured app right of the app-provider',
async () => {
const featured = await scanApi('GET', '/v0/featured-apps')
const hits = (featured.featured_apps ?? []).filter(matches)
return hits.length > 0 ? hits : null
},
SCAN_TIMEOUT_MS,
)
assertEq('Scan reports one featured app right for the app-provider', mine.length, 1)
return status.party_id
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/ledger.sh
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ ledger_init() {
LEDGER_JSON_API_URL="${OZ_JSON_API_URL:-http://127.0.0.1:$LEDGER_JSON_API_PORT}"

LOCALNET_KEEP="${OZ_KEEP_LOCALNET:-0}"
LOCALNET_SPLICE_VERSION="${OZ_SPLICE_VERSION:-0.7.1}"
LOCALNET_SPLICE_VERSION="${OZ_SPLICE_VERSION:-0.8.3}"
LOCALNET_SPLICE_REPO="${OZ_SPLICE_REPO:-https://github.com/canton-network/splice.git}"
LOCALNET_PROJECT="${OZ_LOCALNET_PROJECT:-oz-localnet-gate}"
LOCALNET_PARTY_HINT="${OZ_LOCALNET_PARTY_HINT:-ozspecs-interop-1}"
Expand Down
Loading