Skip to content

Commit

Permalink
feat: deleteCompletedTxs
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Dec 14, 2024
1 parent e09e2c5 commit e81fdcd
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
7 changes: 6 additions & 1 deletion packages/fast-usdc/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ export const TxStatus = /** @type {const} */ ({
});
harden(TxStatus);

// TODO: define valid state transitions
// According to the state diagram
export const TerminalTxStatus = {
[TxStatus.Forwarded]: true,
[TxStatus.ForwardFailed]: true,
[TxStatus.Disbursed]: true,
};

/**
* Status values for the StatusManager.
Expand Down
40 changes: 38 additions & 2 deletions packages/fast-usdc/src/exos/status-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
EvmHashShape,
PendingTxShape,
} from '../type-guards.js';
import { PendingTxStatus, TxStatus } from '../constants.js';
import { PendingTxStatus, TerminalTxStatus, TxStatus } from '../constants.js';

/**
* @import {MapStore, SetStore} from '@agoric/store';
Expand Down Expand Up @@ -78,11 +78,26 @@ export const prepareStatusManager = (
valueShape: M.arrayOf(PendingTxShape),
});

/** @type {SetStore<EvmHash>} */
/**
* Transactions seen *ever* by the contract.
*
* Note that these are stored in IAVL and grow monotonically. At some point in the future we may want to prune them.
*
* @type {SetStore<EvmHash>}
*/
const seenTxs = zone.setStore('SeenTxs', {
keyShape: M.string(),
});

/**
* Transactions that have completed, but are still in vstorage.
*
* @type {SetStore<EvmHash>}
*/
const storedCompletedTxs = zone.setStore('StoredCompletedTxs', {
keyShape: M.string(),
});

/**
* @param {CctpTxEvidence['txHash']} hash
* @param {CctpTxEvidence} evidence
Expand All @@ -101,6 +116,13 @@ export const prepareStatusManager = (
const txnNodeP = E(transactionsNode).makeChildNode(hash);
// Don't await, just writing to vstorage.
void E(txnNodeP).setValue(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
// writes in this block would be wiped. For now we keep track of what to
// delete when we know it'll be another block.
storedCompletedTxs.add(hash);
}
};

/**
Expand Down Expand Up @@ -158,6 +180,7 @@ export const prepareStatusManager = (
advanceOutcome: M.call(M.string(), M.nat(), M.boolean()).returns(),
observe: M.call(CctpTxEvidenceShape).returns(M.undefined()),
hasBeenObserved: M.call(CctpTxEvidenceShape).returns(M.boolean()),
deleteCompletedTxs: M.call().returns(M.undefined()),
dequeueStatus: M.call(M.string(), M.bigint()).returns(
M.or(
{
Expand Down Expand Up @@ -223,6 +246,19 @@ export const prepareStatusManager = (
return seenTxs.has(evidence.txHash);
},

// UNTIL https://github.com/Agoric/agoric-sdk/issues/7405
deleteCompletedTxs() {
for (const txHash of storedCompletedTxs.values()) {
// As of now, setValue('') on a non-sequence node will delete it
const txNode = E(transactionsNode).makeChildNode(txHash, {
sequence: false,
});
void E(txNode)
.setValue('')
.then(() => storedCompletedTxs.delete(txHash));
}
},

/**
* Remove and return an `ADVANCED` or `OBSERVED` tx waiting to be `SETTLED`.
*
Expand Down
10 changes: 10 additions & 0 deletions packages/fast-usdc/test/exos/settler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ test('happy path: disburse to LPs; StatusManager removes tx', async t => {
'ADVANCED',
'DISBURSED',
]);

// Check deletion of DISBURSED transactions
statusManager.deleteCompletedTxs();
await eventLoopIteration();
t.is(storage.data.get(`fun.txns.${cctpTxEvidence.txHash}`), undefined);
});

test('slow path: forward to EUD; remove pending tx', async t => {
Expand Down Expand Up @@ -314,6 +319,11 @@ test('slow path: forward to EUD; remove pending tx', async t => {
'OBSERVED',
'FORWARDED',
]);

// Check deletion of FORWARDED transactions
statusManager.deleteCompletedTxs();
await eventLoopIteration();
t.is(storage.data.get(`fun.txns.${cctpTxEvidence.txHash}`), undefined);
});

test('Settlement for unknown transaction', async t => {
Expand Down

0 comments on commit e81fdcd

Please sign in to comment.