From 7e62d8f811e212f8160c36a3b954aee8c0e1fb90 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 16 Dec 2024 14:16:17 -0800 Subject: [PATCH] feat: publish OBSERVED with first evidence --- .../boot/test/fast-usdc/fast-usdc.test.ts | 10 +++ packages/fast-usdc/src/exos/status-manager.js | 14 ++-- packages/fast-usdc/test/exos/advancer.test.ts | 66 ++++++++++--------- packages/fast-usdc/test/exos/settler.test.ts | 5 +- .../test/exos/status-manager.test.ts | 9 ++- 5 files changed, 61 insertions(+), 43 deletions(-) diff --git a/packages/boot/test/fast-usdc/fast-usdc.test.ts b/packages/boot/test/fast-usdc/fast-usdc.test.ts index afbd8d532f1..14f04876108 100644 --- a/packages/boot/test/fast-usdc/fast-usdc.test.ts +++ b/packages/boot/test/fast-usdc/fast-usdc.test.ts @@ -258,6 +258,16 @@ test.serial('makes usdc advance', async t => { ); harness?.resetRunPolicy(); + t.deepEqual( + storage + .getValues(`published.fastUsdc.txns.${evidence.txHash}`) + .map(defaultSerializer.parse), + [ + { evidence, status: 'OBSERVED' }, // observation includes evidence observed + { status: 'ADVANCING' }, + ], + ); + const doc = { node: `fastUsdc.txns`, owner: `the Ethereum transactions upon which Fast USDC is acting`, diff --git a/packages/fast-usdc/src/exos/status-manager.js b/packages/fast-usdc/src/exos/status-manager.js index 937a7285c34..0fb63eed628 100644 --- a/packages/fast-usdc/src/exos/status-manager.js +++ b/packages/fast-usdc/src/exos/status-manager.js @@ -109,7 +109,7 @@ export const prepareStatusManager = ( sequence: true, // avoid overwriting other output in the block }); void E(txNode).setValue( - JSON.stringify(pureDataMarshaller.toCapData(harden(record))), + JSON.stringify(pureDataMarshaller.toCapData(record)), ); }; @@ -119,7 +119,10 @@ export const prepareStatusManager = ( */ const publishEvidence = (hash, evidence) => { // Don't await, just writing to vstorage. - void publishTxnRecord(hash, evidence); + void publishTxnRecord( + hash, + harden({ evidence, status: TxStatus.Observed }), + ); }; /** @@ -128,7 +131,7 @@ export const prepareStatusManager = ( */ const publishStatus = (hash, status) => { // Don't await, just writing to vstorage. - void publishTxnRecord(hash, { status }); + void publishTxnRecord(hash, harden({ status })); if (TerminalTxStatus[status]) { // UNTIL https://github.com/Agoric/agoric-sdk/issues/7405 // Queue it for deletion later because if we deleted it now the earlier @@ -160,7 +163,10 @@ export const prepareStatusManager = ( harden({ ...evidence, status }), ); publishEvidence(txHash, evidence); - publishStatus(txHash, status); + if (status !== PendingTxStatus.Observed) { + // publishEvidence publishes Observed + publishStatus(txHash, status); + } }; /** diff --git a/packages/fast-usdc/test/exos/advancer.test.ts b/packages/fast-usdc/test/exos/advancer.test.ts index 2b01dcb689d..7f118598f88 100644 --- a/packages/fast-usdc/test/exos/advancer.test.ts +++ b/packages/fast-usdc/test/exos/advancer.test.ts @@ -175,8 +175,8 @@ test('updates status to ADVANCING in happy path', async t => { bootstrap: { storage }, } = t.context; - const mockEvidence = MockCctpTxEvidences.AGORIC_PLUS_OSMO(); - void advancer.handleTransactionEvent(mockEvidence); + const evidence = MockCctpTxEvidences.AGORIC_PLUS_OSMO(); + void advancer.handleTransactionEvent(evidence); // pretend borrow succeeded and funds were depositing to the LCA resolveLocalTransferV(); @@ -186,8 +186,11 @@ test('updates status to ADVANCING in happy path', async t => { await eventLoopIteration(); t.deepEqual( - storage.getDeserialized(`fun.txns.${mockEvidence.txHash}`), - [mockEvidence, { status: PendingTxStatus.Advancing }], + storage.getDeserialized(`fun.txns.${evidence.txHash}`), + [ + { evidence, status: PendingTxStatus.Observed }, + { status: PendingTxStatus.Advancing }, + ], 'ADVANCED status in happy path', ); @@ -215,11 +218,11 @@ test('updates status to ADVANCING in happy path', async t => { t.like(inspectNotifyCalls(), [ [ { - txHash: mockEvidence.txHash, - forwardingAddress: mockEvidence.tx.forwardingAddress, - fullAmount: usdc.make(mockEvidence.tx.amount), + txHash: evidence.txHash, + forwardingAddress: evidence.tx.forwardingAddress, + fullAmount: usdc.make(evidence.tx.amount), destination: { - value: decodeAddressHook(mockEvidence.aux.recipientAddress).query.EUD, + value: decodeAddressHook(evidence.aux.recipientAddress).query.EUD, }, }, true, // indicates transfer succeeded @@ -255,13 +258,13 @@ test('updates status to OBSERVED on insufficient pool funds', async t => { intermediateRecipient, }); - const mockEvidence = MockCctpTxEvidences.AGORIC_PLUS_DYDX(); - void advancer.handleTransactionEvent(mockEvidence); + const evidence = MockCctpTxEvidences.AGORIC_PLUS_DYDX(); + void advancer.handleTransactionEvent(evidence); await eventLoopIteration(); t.deepEqual( - storage.getDeserialized(`fun.txns.${mockEvidence.txHash}`), - [mockEvidence, { status: PendingTxStatus.Observed }], + storage.getDeserialized(`fun.txns.${evidence.txHash}`), + [{ evidence, status: PendingTxStatus.Observed }], 'OBSERVED status on insufficient pool funds', ); @@ -285,12 +288,12 @@ test('updates status to OBSERVED if makeChainAddress fails', async t => { }, } = t.context; - const mockEvidence = MockCctpTxEvidences.AGORIC_UNKNOWN_EUD(); - await advancer.handleTransactionEvent(mockEvidence); + const evidence = MockCctpTxEvidences.AGORIC_UNKNOWN_EUD(); + await advancer.handleTransactionEvent(evidence); t.deepEqual( - storage.getDeserialized(`fun.txns.${mockEvidence.txHash}`), - [mockEvidence, { status: PendingTxStatus.Observed }], + storage.getDeserialized(`fun.txns.${evidence.txHash}`), + [{ evidence, status: PendingTxStatus.Observed }], 'OBSERVED status on makeChainAddress failure', ); @@ -314,16 +317,19 @@ test('calls notifyAdvancingResult (AdvancedFailed) on failed transfer', async t brands: { usdc }, } = t.context; - const mockEvidence = MockCctpTxEvidences.AGORIC_PLUS_DYDX(); - void advancer.handleTransactionEvent(mockEvidence); + const evidence = MockCctpTxEvidences.AGORIC_PLUS_DYDX(); + void advancer.handleTransactionEvent(evidence); // pretend borrow and deposit to LCA succeed resolveLocalTransferV(); await eventLoopIteration(); t.deepEqual( - storage.getDeserialized(`fun.txns.${mockEvidence.txHash}`), - [mockEvidence, { status: PendingTxStatus.Advancing }], + storage.getDeserialized(`fun.txns.${evidence.txHash}`), + [ + { evidence, status: PendingTxStatus.Observed }, + { status: PendingTxStatus.Advancing }, + ], 'tx is Advancing', ); @@ -340,14 +346,12 @@ test('calls notifyAdvancingResult (AdvancedFailed) on failed transfer', async t t.like(inspectNotifyCalls(), [ [ { - txHash: mockEvidence.txHash, - forwardingAddress: mockEvidence.tx.forwardingAddress, - fullAmount: usdc.make(mockEvidence.tx.amount), - advanceAmount: feeTools.calculateAdvance( - usdc.make(mockEvidence.tx.amount), - ), + txHash: evidence.txHash, + forwardingAddress: evidence.tx.forwardingAddress, + fullAmount: usdc.make(evidence.tx.amount), + advanceAmount: feeTools.calculateAdvance(usdc.make(evidence.tx.amount)), destination: { - value: decodeAddressHook(mockEvidence.aux.recipientAddress).query.EUD, + value: decodeAddressHook(evidence.aux.recipientAddress).query.EUD, }, }, false, // this indicates transfer failed @@ -364,13 +368,13 @@ test('updates status to OBSERVED if pre-condition checks fail', async t => { }, } = t.context; - const mockEvidence = MockCctpTxEvidences.AGORIC_NO_PARAMS(); + const evidence = MockCctpTxEvidences.AGORIC_NO_PARAMS(); - await advancer.handleTransactionEvent(mockEvidence); + await advancer.handleTransactionEvent(evidence); t.deepEqual( - storage.getDeserialized(`fun.txns.${mockEvidence.txHash}`), - [mockEvidence, { status: PendingTxStatus.Observed }], + storage.getDeserialized(`fun.txns.${evidence.txHash}`), + [{ evidence, status: PendingTxStatus.Observed }], 'tx is recorded as OBSERVED', ); diff --git a/packages/fast-usdc/test/exos/settler.test.ts b/packages/fast-usdc/test/exos/settler.test.ts index 11a5ffe9fd2..f23f90702d4 100644 --- a/packages/fast-usdc/test/exos/settler.test.ts +++ b/packages/fast-usdc/test/exos/settler.test.ts @@ -236,7 +236,7 @@ test('happy path: disburse to LPs; StatusManager removes tx', async t => { await eventLoopIteration(); const { storage } = t.context; t.deepEqual(storage.getDeserialized(`fun.txns.${cctpTxEvidence.txHash}`), [ - cctpTxEvidence, + { evidence: cctpTxEvidence, status: 'OBSERVED' }, { status: 'ADVANCING' }, { status: 'ADVANCED' }, { status: 'DISBURSED' }, @@ -314,8 +314,7 @@ test('slow path: forward to EUD; remove pending tx', async t => { ); const { storage } = t.context; t.deepEqual(storage.getDeserialized(`fun.txns.${cctpTxEvidence.txHash}`), [ - cctpTxEvidence, - { status: 'OBSERVED' }, + { evidence: cctpTxEvidence, status: 'OBSERVED' }, { status: 'FORWARDED' }, ]); diff --git a/packages/fast-usdc/test/exos/status-manager.test.ts b/packages/fast-usdc/test/exos/status-manager.test.ts index c93441c40a6..14c45185fa8 100644 --- a/packages/fast-usdc/test/exos/status-manager.test.ts +++ b/packages/fast-usdc/test/exos/status-manager.test.ts @@ -55,7 +55,7 @@ test('ADVANCED transactions are published to vstorage', async t => { const { storage } = t.context; t.deepEqual(storage.getDeserialized(`fun.txns.${evidence.txHash}`), [ - evidence, + { evidence, status: 'OBSERVED' }, { status: 'ADVANCING' }, ]); }); @@ -90,8 +90,7 @@ test('OBSERVED transactions are published to vstorage', async t => { const { storage } = t.context; t.deepEqual(storage.getDeserialized(`fun.txns.${evidence.txHash}`), [ - evidence, - { status: 'OBSERVED' }, + { evidence, status: 'OBSERVED' }, ]); }); @@ -235,7 +234,7 @@ test('advanceOutcome transitions to ADVANCED and ADVANCE_FAILED', async t => { ]); await eventLoopIteration(); t.deepEqual(storage.getDeserialized(`fun.txns.${e1.txHash}`), [ - e1, + { evidence: e1, status: 'OBSERVED' }, { status: 'ADVANCING' }, { status: 'ADVANCED' }, ]); @@ -249,7 +248,7 @@ test('advanceOutcome transitions to ADVANCED and ADVANCE_FAILED', async t => { ]); await eventLoopIteration(); t.deepEqual(storage.getDeserialized(`fun.txns.${e2.txHash}`), [ - e2, + { evidence: e2, status: 'OBSERVED' }, { status: 'ADVANCING' }, { status: 'ADVANCE_FAILED' }, ]);