From bcc94d1268fe1b8caf8dd14609e2a26bd7944ee1 Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Thu, 27 Feb 2025 16:45:48 -0500 Subject: [PATCH 1/7] chore: publish --- packages/fast-usdc/src/exos/status-manager.js | 30 ++++++++----------- packages/fast-usdc/src/fast-usdc.contract.js | 9 +++--- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/packages/fast-usdc/src/exos/status-manager.js b/packages/fast-usdc/src/exos/status-manager.js index f854337bc8c..2403f045c59 100644 --- a/packages/fast-usdc/src/exos/status-manager.js +++ b/packages/fast-usdc/src/exos/status-manager.js @@ -117,9 +117,8 @@ export const prepareStatusManager = ( /** * @param {EvmHash} txId * @param {TransactionRecord} record - * @returns {Promise} */ - const publishTxnRecord = async (txId, record) => { + const publishTxnRecord = (txId, record) => { const txNode = E(txnsNode).makeChildNode(txId, { sequence: true, // avoid overwriting other output in the block }); @@ -133,9 +132,10 @@ export const prepareStatusManager = ( storedCompletedTxs.add(txId); } - const capData = await E(marshaller).toCapData(record); - - await E(txNode).setValue(JSON.stringify(capData)); + // Don't await, just writing to vstorage. + void E.when(E(marshaller).toCapData(record), capData => + E(txNode).setValue(JSON.stringify(capData)), + ); }; /** @@ -144,10 +144,7 @@ export const prepareStatusManager = ( */ const publishEvidence = (hash, evidence) => { // Don't await, just writing to vstorage. - void publishTxnRecord( - hash, - harden({ evidence, status: TxStatus.Observed }), - ); + publishTxnRecord(hash, harden({ evidence, status: TxStatus.Observed })); }; /** @@ -174,10 +171,10 @@ export const prepareStatusManager = ( ); publishEvidence(txHash, evidence); if (status === PendingTxStatus.AdvanceSkipped) { - void publishTxnRecord(txHash, harden({ status, risksIdentified })); + publishTxnRecord(txHash, harden({ status, risksIdentified })); } else if (status !== PendingTxStatus.Observed) { // publishEvidence publishes Observed - void publishTxnRecord(txHash, harden({ status })); + publishTxnRecord(txHash, harden({ status })); } }; @@ -200,7 +197,7 @@ export const prepareStatusManager = ( ]; const txpost = { ...tx, status }; pendingSettleTxs.set(key, harden([...prefix, txpost, ...suffix])); - void publishTxnRecord(tx.txHash, harden({ status })); + publishTxnRecord(tx.txHash, harden({ status })); } return zone.exo( @@ -288,7 +285,7 @@ export const prepareStatusManager = ( * @param {boolean} success whether the Transfer succeeded */ advanceOutcomeForMintedEarly(txHash, success) { - void publishTxnRecord( + publishTxnRecord( txHash, harden({ status: success @@ -381,10 +378,7 @@ export const prepareStatusManager = ( * @param {import('./liquidity-pool.js').RepayAmountKWR} split */ disbursed(txHash, split) { - void publishTxnRecord( - txHash, - harden({ split, status: TxStatus.Disbursed }), - ); + publishTxnRecord(txHash, harden({ split, status: TxStatus.Disbursed })); }, /** @@ -394,7 +388,7 @@ export const prepareStatusManager = ( * @param {boolean} success */ forwarded(txHash, success) { - void publishTxnRecord( + publishTxnRecord( txHash, harden({ status: success ? TxStatus.Forwarded : TxStatus.ForwardFailed, diff --git a/packages/fast-usdc/src/fast-usdc.contract.js b/packages/fast-usdc/src/fast-usdc.contract.js index 8f114f99f3f..5703719591f 100644 --- a/packages/fast-usdc/src/fast-usdc.contract.js +++ b/packages/fast-usdc/src/fast-usdc.contract.js @@ -67,10 +67,11 @@ harden(meta); * @param {ERef} marshaller * @param {FeeConfig} feeConfig */ -const publishFeeConfig = async (node, marshaller, feeConfig) => { +const publishFeeConfig = (node, marshaller, feeConfig) => { const feeNode = E(node).makeChildNode(FEE_NODE); - const value = await E(marshaller).toCapData(feeConfig); - return E(feeNode).setValue(JSON.stringify(value)); + void E.when(E(marshaller).toCapData(feeConfig), value => + E(feeNode).setValue(JSON.stringify(value)), + ); }; /** @@ -247,7 +248,7 @@ export const contract = async (zcf, privateArgs, zone, tools) => { // So we use zone.exoClassKit above to define the liquidity pool kind // and pass the shareMint into the maker / init function. - void publishFeeConfig(storageNode, marshaller, feeConfig); + publishFeeConfig(storageNode, marshaller, feeConfig); const shareMint = await provideSingleton( zone.mapStore('mint'), From e3f6fc4a99f3a14ba9c300b59a980687894defbc Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Thu, 27 Feb 2025 18:13:14 -0500 Subject: [PATCH 2/7] chore: `Advancer` void annotations --- packages/fast-usdc/src/exos/advancer.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/fast-usdc/src/exos/advancer.js b/packages/fast-usdc/src/exos/advancer.js index 0878598ad1a..9ba161b0d62 100644 --- a/packages/fast-usdc/src/exos/advancer.js +++ b/packages/fast-usdc/src/exos/advancer.js @@ -211,6 +211,8 @@ export const prepareAdvancerKit = ( poolAccount, harden({ USDC: advanceAmount }), ); + // WARNING: this must never reject, see handler @throws {never} below + // void not enforced by linter until #10627 no-floating-vows void watch(depositV, this.facets.depositHandler, { advanceAmount, destination, @@ -233,6 +235,7 @@ export const prepareAdvancerKit = ( /** * @param {undefined} result * @param {AdvancerVowCtx & { tmpSeat: ZCFSeat }} ctx + * @throws {never} WARNING: this function must not throw, because user funds are at risk */ onFulfilled(result, ctx) { const { poolAccount, intermediateRecipient, settlementAddress } = @@ -265,6 +268,7 @@ export const prepareAdvancerKit = ( * * @param {Error} error * @param {AdvancerVowCtx & { tmpSeat: ZCFSeat }} ctx + * @throws {never} WARNING: this function must not throw, because user funds are at risk */ onRejected(error, { tmpSeat, advanceAmount, ...restCtx }) { log( @@ -285,17 +289,12 @@ export const prepareAdvancerKit = ( /** * @param {undefined} result * @param {AdvancerVowCtx} ctx + * @throws {never} WARNING: this function must not throw, because user funds are at risk */ onFulfilled(result, ctx) { const { notifier } = this.state; const { advanceAmount, destination, ...detail } = ctx; log('Advance succeeded', { advanceAmount, destination }); - // During development, due to a bug, this call threw. - // The failure was silent (no diagnostics) due to: - // - #10576 Vows do not report unhandled rejections - // For now, the advancer kit relies on consistency between - // notify, statusManager, and callers of handleTransactionEvent(). - // TODO: revisit #10576 during #10510 notifier.notifyAdvancingResult({ destination, ...detail }, true); }, /** @@ -314,6 +313,8 @@ export const prepareAdvancerKit = ( tmpReturnSeat, harden({ USDC: advanceAmount }), ); + // WARNING: this must never reject, see handler @throws {never} below + // void not enforced by linter until #10627 no-floating-vows void watch(withdrawV, this.facets.withdrawHandler, { advanceAmount, tmpReturnSeat, @@ -325,6 +326,7 @@ export const prepareAdvancerKit = ( * * @param {undefined} result * @param {{ advanceAmount: Amount<'nat'>; tmpReturnSeat: ZCFSeat; }} ctx + * @throws {never} WARNING: this function must not throw, because user funds are at risk */ onFulfilled(result, { advanceAmount, tmpReturnSeat }) { const { borrower } = this.state; @@ -342,6 +344,7 @@ export const prepareAdvancerKit = ( /** * @param {Error} error * @param {{ advanceAmount: Amount<'nat'>; tmpReturnSeat: ZCFSeat; }} ctx + * @throws {never} WARNING: this function must not throw, because user funds are at risk */ onRejected(error, { advanceAmount, tmpReturnSeat }) { log( From d3db6ef2284f2b7a4cebc3261bc9ee784d8d1c97 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 28 Feb 2025 15:35:40 -0800 Subject: [PATCH 3/7] feat: check conflicting evidence before quorum --- .../fast-usdc/src/exos/transaction-feed.js | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/packages/fast-usdc/src/exos/transaction-feed.js b/packages/fast-usdc/src/exos/transaction-feed.js index 98e668357bf..8fe181abcee 100644 --- a/packages/fast-usdc/src/exos/transaction-feed.js +++ b/packages/fast-usdc/src/exos/transaction-feed.js @@ -192,38 +192,43 @@ export const prepareTransactionFeedKit = (zone, zcf) => { const found = [...pending.values()].filter(store => store.has(txHash), ); - const minAttestations = Math.ceil(operators.getSize() / 2); - trace( - 'transaction', - txHash, - 'has', - found.length, - 'of', - minAttestations, - 'necessary attestations', - ); - if (found.length < minAttestations) { - return; + + { + let lastEvidence; + for (const store of found) { + const next = store.get(txHash); + if (lastEvidence && !keyEQ(lastEvidence, next)) { + // Ignore conflicting evidence, but treat it as an error + // because it should never happen and needs to be prevented + // from happening again. + trace( + '🚨 conflicting evidence for', + txHash, + ':', + lastEvidence, + '!=', + next, + ); + Fail`conflicting evidence for ${quote(txHash)}`; + } + lastEvidence = next; + } } - let lastEvidence; - for (const store of found) { - const next = store.get(txHash); - if (lastEvidence && !keyEQ(lastEvidence, next)) { - // Ignore conflicting evidence, but treat it as an error - // because it should never happen and needs to be prevented - // from happening again. - trace( - '🚨 conflicting evidence for', - txHash, - ':', - lastEvidence, - '!=', - next, - ); - Fail`conflicting evidence for ${quote(txHash)}`; + { + const minAttestations = Math.ceil(operators.getSize() / 2); + trace( + 'transaction', + txHash, + 'has', + found.length, + 'of', + minAttestations, + 'necessary attestations', + ); + if (found.length < minAttestations) { + return; } - lastEvidence = next; } const riskStores = [...risks.values()].filter(store => From e06360deb74d04379f8b3d9581ac13dcfa6517ec Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 28 Feb 2025 15:54:02 -0800 Subject: [PATCH 4/7] chore: replace debug() with trace() --- .../orchestration/src/exos/packet-tools.js | 19 +++++++++++-------- packages/orchestration/src/utils/zoe-tools.js | 7 +++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/orchestration/src/exos/packet-tools.js b/packages/orchestration/src/exos/packet-tools.js index 2b873ebc2eb..46f0ef7c0f9 100644 --- a/packages/orchestration/src/exos/packet-tools.js +++ b/packages/orchestration/src/exos/packet-tools.js @@ -3,6 +3,9 @@ import { Shape as NetworkShape } from '@agoric/network'; import { M, matches } from '@endo/patterns'; import { E } from '@endo/far'; import { pickFacet } from '@agoric/vat-data'; +import { makeTracer } from '@agoric/internal'; + +const trace = makeTracer('PacketTools'); const { toCapData } = makeMarshal(undefined, undefined, { marshalName: 'JustEncoder', @@ -207,7 +210,7 @@ export const preparePacketTools = (zone, vowTools) => { async receiveUpcall(obj) { const { monitor, resolverToPattern, upcallQueue, pending } = this.state; - console.debug( + trace( `Trying ${resolverToPattern.getSize()} current patterns and ${pending} pending patterns against`, just(obj), ); @@ -219,7 +222,7 @@ export const preparePacketTools = (zone, vowTools) => { // Check all our fulfilled patterns for matches. for (const [resolver, pattern] of resolverToPattern.entries()) { if (matches(obj, pattern)) { - console.debug('Matched pattern:', just(pattern)); + trace('Matched pattern:', just(pattern)); resolver.resolve(obj); resolverToPattern.delete(resolver); return; @@ -228,10 +231,10 @@ export const preparePacketTools = (zone, vowTools) => { if (upcallQueue) { // We have some pending patterns (ones that have been requested but // haven't yet settled) that may match this object. - console.debug('Stashing object in upcallQueue'); + trace('Stashing object in upcallQueue'); this.state.upcallQueue = harden(upcallQueue.concat(obj)); } - console.debug('No match yet.'); + trace('No match yet.'); }, }, sendPacketWatcher: { @@ -276,10 +279,10 @@ export const preparePacketTools = (zone, vowTools) => { onFulfilled(pattern, { resolver }) { const { resolverToPattern, upcallQueue } = this.state; - console.debug('watchPacketPattern onFulfilled', just(pattern)); + trace('watchPacketPattern onFulfilled', just(pattern)); if (!upcallQueue) { // Save the pattern for later. - console.debug('No upcall queue yet. Save the pattern for later.'); + trace('No upcall queue yet. Save the pattern for later.'); resolverToPattern.init(resolver, pattern); return; } @@ -288,13 +291,13 @@ export const preparePacketTools = (zone, vowTools) => { const i = upcallQueue.findIndex(obj => matches(obj, pattern)); if (i < 0) { // No match yet. Save the pattern for later. - console.debug('No match yet. Save the pattern for later.'); + trace('No match yet. Save the pattern for later.'); resolverToPattern.init(resolver, pattern); return; } // Success! Remove the matched object from the queue. - console.debug( + trace( 'Success! Remove the matched object from the queue.', just(upcallQueue[i]), ); diff --git a/packages/orchestration/src/utils/zoe-tools.js b/packages/orchestration/src/utils/zoe-tools.js index a5cbbe389f8..803982c8fe1 100644 --- a/packages/orchestration/src/utils/zoe-tools.js +++ b/packages/orchestration/src/utils/zoe-tools.js @@ -18,6 +18,9 @@ import { makeError, q, Fail } from '@endo/errors'; import { depositToSeat } from '@agoric/zoe/src/contractSupport/index.js'; import { E } from '@endo/far'; +import { makeTracer } from '@agoric/internal'; + +const trace = makeTracer('ZoeTools'); const { assign, keys, values } = Object; @@ -121,7 +124,7 @@ export const makeZoeTools = (zcf, { when, allVows, allSettled, asVow }) => { amounts, paymentKwr, ); - console.debug(depositResponse); + trace('localTransfer depositResponse', depositResponse); throw makeError(`One or more deposits failed ${q(errors)}`); } // TODO #9541 remove userSeat from baggage @@ -174,7 +177,7 @@ export const makeZoeTools = (zcf, { when, allVows, allSettled, asVow }) => { amounts, paymentKwr, ); - console.debug(depositResponse); + trace('withdrawToSeat depositResponse', depositResponse); }); return harden({ From e6070aabf7520035b4ee9f3a815274991805e208 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 28 Feb 2025 16:00:15 -0800 Subject: [PATCH 5/7] docs: TxFeed does not inspect evidence --- packages/fast-usdc/src/exos/transaction-feed.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/fast-usdc/src/exos/transaction-feed.js b/packages/fast-usdc/src/exos/transaction-feed.js index 8fe181abcee..632e7cf2f16 100644 --- a/packages/fast-usdc/src/exos/transaction-feed.js +++ b/packages/fast-usdc/src/exos/transaction-feed.js @@ -1,3 +1,4 @@ +/** @file Exo for @see {prepareTransactionFeedKit} */ import { makeTracer } from '@agoric/internal'; import { prepareDurablePublishKit } from '@agoric/notifier'; import { keyEQ, M } from '@endo/patterns'; @@ -66,6 +67,11 @@ export const stateShape = { }; /** + * A TransactionFeed is responsible for finding quorum among oracles. + * + * It receives attestations, records their evidence, and when enough oracles + * agree, publishes the results for the advancer to act on. + * * @param {Zone} zone * @param {ZCF} zcf */ @@ -159,7 +165,7 @@ export const prepareTransactionFeedKit = (zone, zcf) => { /** * Add evidence from an operator. * - * NB: the operatorKit is responsible for + * NB: the operatorKit is responsible for revoking access. * * @param {CctpTxEvidence} evidence * @param {RiskAssessment} riskAssessment @@ -169,10 +175,6 @@ export const prepareTransactionFeedKit = (zone, zcf) => { const { operators, pending, risks } = this.state; trace('attest', operatorId, evidence); - // TODO https://github.com/Agoric/agoric-sdk/pull/10720 - // TODO validate that it's a valid for Fast USDC before accepting - // E.g. that the `recipientAddress` is the FU settlement account and that - // the EUD is a chain supported by FU. const { txHash } = evidence; // accept the evidence From 65d5c9aba04f8f010ef9565bbdf474fec29b5db2 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 28 Feb 2025 16:49:05 -0800 Subject: [PATCH 6/7] test: self disagreement --- packages/fast-usdc/test/exos/transaction-feed.test.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/fast-usdc/test/exos/transaction-feed.test.ts b/packages/fast-usdc/test/exos/transaction-feed.test.ts index 77c32a76e49..57b2ac1a4d9 100644 --- a/packages/fast-usdc/test/exos/transaction-feed.test.ts +++ b/packages/fast-usdc/test/exos/transaction-feed.test.ts @@ -160,9 +160,14 @@ test('disagreement', async t => { assert(e1.txHash === e1bad.txHash); op1.operator.submitEvidence(e1); + // conflicting between operators t.throws(() => op2.operator.submitEvidence(e1bad), { - message: - 'conflicting evidence for "0xc81bc6105b60a234c7c50ac17816ebcd5561d366df8bf3be59ff387552761702"', + message: /conflicting evidence/, + }); + + // self conflicting + t.throws(() => op1.operator.submitEvidence(e1bad), { + message: /conflicting evidence/, }); }); From 741be7943546b17d1a7bdebf2b7028b2ca366e05 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 28 Feb 2025 17:00:56 -0800 Subject: [PATCH 7/7] feat: clean up upon last attest Before this each third attest was treated as a new transaction --- .../fast-usdc/src/exos/transaction-feed.js | 66 +++++---- .../test/exos/transaction-feed.test.ts | 36 +++-- .../snapshots/fast-usdc.contract.test.ts.md | 140 +++--------------- .../snapshots/fast-usdc.contract.test.ts.snap | Bin 24460 -> 23623 bytes 4 files changed, 82 insertions(+), 160 deletions(-) diff --git a/packages/fast-usdc/src/exos/transaction-feed.js b/packages/fast-usdc/src/exos/transaction-feed.js index 632e7cf2f16..2c9f9643cfb 100644 --- a/packages/fast-usdc/src/exos/transaction-feed.js +++ b/packages/fast-usdc/src/exos/transaction-feed.js @@ -1,8 +1,8 @@ /** @file Exo for @see {prepareTransactionFeedKit} */ import { makeTracer } from '@agoric/internal'; import { prepareDurablePublishKit } from '@agoric/notifier'; -import { keyEQ, M } from '@endo/patterns'; import { Fail, quote } from '@endo/errors'; +import { keyEQ, M } from '@endo/patterns'; import { CctpTxEvidenceShape, RiskAssessmentShape } from '../type-guards.js'; import { defineInertInvitation } from '../utils/zoe.js'; import { prepareOperatorKit } from './operator-kit.js'; @@ -65,6 +65,7 @@ export const stateShape = { pending: M.remotable(), risks: M.remotable(), }; +harden(stateShape); /** * A TransactionFeed is responsible for finding quorum among oracles. @@ -154,11 +155,13 @@ export const prepareTransactionFeedKit = (zone, zcf) => { /** @param {string} operatorId */ removeOperator(operatorId) { - const { operators } = this.state; + const { operators, pending, risks } = this.state; trace('removeOperator', operatorId); const operatorKit = operators.get(operatorId); operatorKit.admin.disable(); operators.delete(operatorId); + pending.delete(operatorId); + risks.delete(operatorId); }, }, operatorPowers: { @@ -217,40 +220,47 @@ export const prepareTransactionFeedKit = (zone, zcf) => { } } - { - const minAttestations = Math.ceil(operators.getSize() / 2); - trace( - 'transaction', - txHash, - 'has', - found.length, - 'of', - minAttestations, - 'necessary attestations', - ); - if (found.length < minAttestations) { - return; - } + const minAttestations = Math.ceil(operators.getSize() / 2); + trace( + 'transaction', + txHash, + 'has', + found.length, + 'of', + minAttestations, + 'necessary attestations', + ); + + if (found.length < minAttestations) { + // wait for more + return; } const riskStores = [...risks.values()].filter(store => store.has(txHash), ); - // take the union of risks identified from all operators - const risksIdentified = allRisksIdentified(riskStores, txHash); - // sufficient agreement, so remove from pending risks, then publish - for (const store of found) { - store.delete(txHash); + // Publish at the threshold of agreement + if (found.length === minAttestations) { + // take the union of risks identified from all operators + const risksIdentified = allRisksIdentified(riskStores, txHash); + trace('publishing evidence', evidence, risksIdentified); + publisher.publish({ + evidence, + risk: { risksIdentified }, + }); + return; } - for (const store of riskStores) { - store.delete(txHash); + + if (found.length === pending.getSize()) { + // all have reported so clean up + for (const store of found) { + store.delete(txHash); + } + for (const store of riskStores) { + store.delete(txHash); + } } - trace('publishing evidence', evidence, risksIdentified); - publisher.publish({ - evidence, - risk: { risksIdentified }, - }); }, }, public: { diff --git a/packages/fast-usdc/test/exos/transaction-feed.test.ts b/packages/fast-usdc/test/exos/transaction-feed.test.ts index 57b2ac1a4d9..ccfeb7e2e50 100644 --- a/packages/fast-usdc/test/exos/transaction-feed.test.ts +++ b/packages/fast-usdc/test/exos/transaction-feed.test.ts @@ -3,6 +3,7 @@ import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; import { deeplyFulfilledObject } from '@agoric/internal'; import { makeHeapZone } from '@agoric/zone'; +import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js'; import { prepareTransactionFeedKit, stateShape, @@ -185,31 +186,48 @@ test('disagreement after publishing', async t => { updateCount: 1n, }); - // it's simply ignored - t.notThrows(() => op3.operator.submitEvidence(e1bad)); + t.throws(() => op3.operator.submitEvidence(e1bad), { + message: /conflicting evidence/, + }); t.like(await evidenceSubscriber.getUpdateSince(0), { updateCount: 1n, }); - // now another op repeats the bad evidence, so it's published to the stream. - // It's the responsibility of the Advancer to fail because it has already processed that tx hash. - op1.operator.submitEvidence(e1bad); + // Disagreement is still detected after publishing + t.throws(() => op1.operator.submitEvidence(e1bad), { + message: /conflicting evidence/, + }); t.like(await evidenceSubscriber.getUpdateSince(0), { - updateCount: 2n, + updateCount: 1n, }); }); test('remove operator', async t => { const feedKit = makeFeedKit(); - const { op1 } = await makeOperators(feedKit); + const evidenceSubscriber = feedKit.public.getEvidenceSubscriber(); + const { op1, op2 } = await makeOperators(feedKit); const evidence = MockCctpTxEvidences.AGORIC_PLUS_OSMO(); + let published; + void evidenceSubscriber + .getUpdateSince(0) + .then(accepted => (published = accepted.value.evidence)); + // works before disabling op1.operator.submitEvidence(evidence); + await eventLoopIteration(); + t.falsy(published); - await feedKit.creator.removeOperator('op1'); - + // remove op1 and their in-flight evidence + feedKit.creator.removeOperator('op1'); t.throws(() => op1.operator.submitEvidence(evidence), { message: 'submitEvidence for disabled operator', }); + + // one attestation is now sufficient (half of two) but the only evidence was just removed + await eventLoopIteration(); + t.falsy(published); + op2.operator.submitEvidence(evidence); + await eventLoopIteration(); + t.deepEqual(published, evidence); }); diff --git a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md index 3d4a77bb395..06fdfc8ca41 100644 --- a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md +++ b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md @@ -3103,15 +3103,14 @@ Generated by [AVA](https://avajs.dev). }, }, pending: { - 'operator-0': {}, - 'operator-1': { - '0x000008': { + 'operator-0': { + '0x0000010': { aux: { forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzvr5wscqq9qe499xw', + recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzetpwfkrxqq5g04wk9', }, blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037671n, + blockNumber: 21037673n, blockTimestamp: 1632340000n, chainId: 1, tx: { @@ -3119,142 +3118,37 @@ Generated by [AVA](https://avajs.dev). forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', sender: '0xDefaultFakeEthereumAddress', }, - txHash: '0x000008', + txHash: '0x0000010', }, }, - 'operator-2': { - '0x000001': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nqq2qhf2ep2', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037664n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 1000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000001', - }, - '0x000002': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nx3skganpde3k2jrpwpc8jqq5jzq8ex', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037665n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 108000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000002', - }, - '0x000003': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nx3ssq9qfqjyle', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037666n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 110000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000003', - }, - '0x000004': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nx33qq9q874uwh', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037667n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 120000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000004', - }, - '0x000005': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nx33sq9qdp5z6c', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037668n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 125000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000005', - }, - '0x000006': { - aux: { - forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nvfhkydgqzs8gv9xu', - }, - blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037669n, - blockTimestamp: 1632340000n, - chainId: 1, - tx: { - amount: 6000000n, - forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', - sender: '0xDefaultFakeEthereumAddress', - }, - txHash: '0x000006', - }, - '0x000007': { + 'operator-1': { + '0x0000010': { aux: { forwardingChannel: 'channel-21', - recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzv3nqq2qhf2ep2', + recipientAddress: 'agoric10rchqqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq06924zr6mmnd4hnzetpwfkrxqq5g04wk9', }, blockHash: '0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665', - blockNumber: 21037670n, + blockNumber: 21037673n, blockTimestamp: 1632340000n, chainId: 1, tx: { - amount: 150000000n, + amount: 5000000n, forwardingAddress: 'noble1x0ydg69dh6fqvr27xjvp6maqmrldam6yfelqkd', sender: '0xDefaultFakeEthereumAddress', }, - txHash: '0x000007', + txHash: '0x0000010', }, }, + 'operator-2': {}, }, risks: { - 'operator-0': {}, - 'operator-1': { - '0x000008': {}, + 'operator-0': { + '0x0000010': {}, }, - 'operator-2': { - '0x000001': { - risksIdentified: [ - 'RISK1', - ], - }, - '0x000002': {}, - '0x000003': {}, - '0x000004': {}, - '0x000005': {}, - '0x000006': {}, - '0x000007': {}, + 'operator-1': { + '0x0000010': {}, }, + 'operator-2': {}, }, settlerKit: { creator: Object @Alleged: Fast USDC Settler creator {}, diff --git a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.snap b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.snap index 3bcf939dafea5146c8307fbdcfc5ef04b4ee27a0..eb51e85e3f44942b12eb565318653cc16ceee61c 100644 GIT binary patch literal 23623 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μ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 IO@B-R0G%c%RsaA1