Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transaction vstorage #10633

Merged
merged 22 commits into from
Dec 17, 2024
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
2 changes: 2 additions & 0 deletions multichain-testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Install the relevant dependencies:
yarn install
```

(Note that the '@agoric/*' deps will come from the parent directory due to `yarn link --relative .. --all`)

Ensure you have Kubernetes available. See https://docs.cosmology.zone/starship/get-started/step-2.

The following will install `kubectl`, `kind`, `helm`, and `yq` as needed:
Expand Down
50 changes: 49 additions & 1 deletion multichain-testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"packageManager": "[email protected]",
"devDependencies": {
"@agoric/cosmic-proto": "dev",
"@agoric/fast-usdc": "dev",
"@cosmjs/crypto": "^0.32.4",
"@cosmjs/proto-signing": "^0.32.4",
"@cosmjs/stargate": "^0.32.4",
Expand All @@ -41,7 +42,54 @@
"typescript": "~5.7.2"
},
"resolutions": {
"axios": "1.6.7"
"axios": "1.6.7",
"@agoric/cosmos": "portal:../golang/cosmos",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you use tooling to add all these resolutions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note that the '@agoric/*' deps will come from the parent directory due to `yarn link --relative ../../.. --all`)

"@agoric/ertp": "portal:../packages/ERTP",
"@agoric/swingset-vat": "portal:../packages/SwingSet",
"@agoric/access-token": "portal:../packages/access-token",
"agoric": "portal:../packages/agoric-cli",
"@agoric/async-flow": "portal:../packages/async-flow",
"@agoric/base-zone": "portal:../packages/base-zone",
"@agoric/builders": "portal:../packages/builders",
"@agoric/cache": "portal:../packages/cache",
"@agoric/casting": "portal:../packages/casting",
"@agoric/client-utils": "portal:../packages/client-utils",
"@agoric/cosmic-proto": "portal:../packages/cosmic-proto",
"@agoric/cosmic-swingset": "portal:../packages/cosmic-swingset",
"@agoric/create-dapp": "portal:../packages/create-dapp",
"@agoric/deploy-script-support": "portal:../packages/deploy-script-support",
"@agoric/eslint-config": "portal:../packages/eslint-config",
"@agoric/fast-usdc": "portal:../packages/fast-usdc",
"@agoric/governance": "portal:../packages/governance",
"@agoric/import-manager": "portal:../packages/import-manager",
"@agoric/inter-protocol": "portal:../packages/inter-protocol",
"@agoric/internal": "portal:../packages/internal",
"@agoric/kmarshal": "portal:../packages/kmarshal",
"@agoric/network": "portal:../packages/network",
"@agoric/notifier": "portal:../packages/notifier",
"@agoric/orchestration": "portal:../packages/orchestration",
"@agoric/pegasus": "portal:../packages/pegasus",
"@agoric/smart-wallet": "portal:../packages/smart-wallet",
"@agoric/solo": "portal:../packages/solo",
"@agoric/sparse-ints": "portal:../packages/sparse-ints",
"@agoric/spawner": "portal:../packages/spawner",
"@agoric/stat-logger": "portal:../packages/stat-logger",
"@agoric/store": "portal:../packages/store",
"@agoric/swing-store": "portal:../packages/swing-store",
"@agoric/swingset-liveslots": "portal:../packages/swingset-liveslots",
"@agoric/swingset-xsnap-supervisor": "portal:../packages/swingset-xsnap-supervisor",
"@agoric/telemetry": "portal:../packages/telemetry",
"@agoric/time": "portal:../packages/time",
"@agoric/vat-data": "portal:../packages/vat-data",
"@agoric/vats": "portal:../packages/vats",
"@agoric/vm-config": "portal:../packages/vm-config",
"@agoric/vow": "portal:../packages/vow",
"@agoric/wallet": "portal:../packages/wallet",
"@agoric/wallet-backend": "portal:../packages/wallet/api",
"@agoric/xsnap": "portal:../packages/xsnap",
"@agoric/xsnap-lockdown": "portal:../packages/xsnap-lockdown",
"@agoric/zoe": "portal:../packages/zoe",
"@agoric/zone": "portal:../packages/zone"
},
"eslintConfig": {
"root": true,
Expand Down
40 changes: 32 additions & 8 deletions multichain-testing/test/fast-usdc/fast-usdc.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import anyTest from '@endo/ses-ava/prepare-endo.js';

import type { TestFn } from 'ava';
import { encodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
import { AmountMath } from '@agoric/ertp';
Expand All @@ -13,6 +14,13 @@ import { commonSetup, type SetupContextWithWallets } from '../support.js';
import { makeFeedPolicy, oracleMnemonics } from './config.js';
import { makeRandomDigits } from '../../tools/random.js';
import { balancesFromPurses } from '../../tools/purse.js';
import { makeTracer } from '@agoric/internal';
import type {
CctpTxEvidence,
EvmAddress,
} from '@agoric/fast-usdc/src/types.js';

const log = makeTracer('MCFU');

const { keys, values, fromEntries } = Object;
const { isGTE, isEmpty, make } = AmountMath;
Expand Down Expand Up @@ -153,6 +161,7 @@ test.serial('oracles accept', async t => {
return offerToUsedInvitation[0][0] === `${name}-accept`;
},
`${name} invitation used`,
{ log },
),
);
}
Expand Down Expand Up @@ -191,6 +200,7 @@ test.serial('lp deposits', async t => {
({ shareWorth }) =>
!isGTE(currShareWorth.numerator, shareWorth.numerator),
'share worth numerator increases from deposit',
{ log },
),
);

Expand All @@ -203,6 +213,7 @@ test.serial('lp deposits', async t => {
return currentPoolShares && isGTE(currentPoolShares, poolSharesWanted);
},
'lp has pool shares',
{ log },
),
);
});
Expand All @@ -216,6 +227,7 @@ const advanceAndSettleScenario = test.macro({
nobleAgoricChannelId,
oracleWds,
retryUntilCondition,
smartWalletKit,
useChain,
usdcOnOsmosis,
vstorageClient,
Expand Down Expand Up @@ -250,15 +262,15 @@ const advanceAndSettleScenario = test.macro({
);
t.log('got forwardingAddress', userForwardingAddr);

// TODO export CctpTxEvidence type
const evidence = harden({
const evidence: CctpTxEvidence = harden({
blockHash:
'0x90d7343e04f8160892e94f02d6a9b9f255663ed0ac34caca98544c8143fee665',
blockNumber: 21037663n,
txHash: `0xc81bc6105b60a234c7c50ac17816ebcd5561d366df8bf3be59ff3875527617${makeRandomDigits(makeRandomNumber(), 2n)}`,
tx: {
amount: mintAmt,
forwardingAddress: userForwardingAddr,
sender: '0x9a9eE9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9' as EvmAddress,
},
aux: {
forwardingChannel: nobleAgoricChannelId,
Expand All @@ -267,7 +279,7 @@ const advanceAndSettleScenario = test.macro({
chainId: 42161,
});

console.log('User initiates evm mint:', evidence.txHash);
log('User initiates evm mint:', evidence.txHash);

// submit evidences
await Promise.all(
Expand Down Expand Up @@ -299,25 +311,35 @@ const advanceAndSettleScenario = test.macro({
),
);

const queryTxStatus = async () =>
vstorageClient.queryData(
`published.${contractName}.status.${evidence.txHash}`,
const queryTxStatus = async () => {
const record = await smartWalletKit.readPublished(
`fastUsdc.txns.${evidence.txHash}`,
);
if (!record) {
throw new Error(`no record for ${evidence.txHash}`);
}
// @ts-expect-error unknown may not have 'status'
if (!record.status) {
throw new Error(`no status for ${evidence.txHash}`);
}
// @ts-expect-error still unknown?
return record.status;
};

const assertTxStatus = async (status: string) =>
t.notThrowsAsync(() =>
retryUntilCondition(
() => queryTxStatus(),
txStatus => {
console.log('tx status', txStatus);
log('tx status', txStatus);
return txStatus === status;
},
`${evidence.txHash} is ${status}`,
),
);

await assertTxStatus('ADVANCED');
console.log('Advance completed, waiting for mint...');
log('Advance completed, waiting for mint...');

nobleTools.mockCctpMint(mintAmt, userForwardingAddr);
await t.notThrowsAsync(() =>
Expand Down Expand Up @@ -393,6 +415,7 @@ test.serial('lp withdraws', async t => {
return !currentPoolShares || isEmpty(currentPoolShares);
},
'lp no longer has pool shares',
{ log },
),
);

Expand All @@ -404,6 +427,7 @@ test.serial('lp withdraws', async t => {
BigInt(balance.amount) - BigInt(currentUSDCBalance!.amount!) >
LP_DEPOSIT_AMOUNT,
"lp's USDC balance increases",
{ log },
),
);
});
Expand Down
33 changes: 27 additions & 6 deletions multichain-testing/tools/e2e-tools.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check
/** global harden */
import { makeSmartWalletKit, LOCAL_CONFIG } from '@agoric/client-utils';
import { assert } from '@endo/errors';
import { E, Far } from '@endo/far';
import { Nat } from '@endo/nat';
Expand All @@ -9,12 +10,16 @@ import { makeHttpClient, makeAPI } from './makeHttpClient.js';
import { dedup, makeQueryKit, poll } from './queryKit.js';
import { makeVStorage } from './batchQuery.js';
import { makeRetryUntilCondition } from './sleep.js';
import { makeTracer } from '@agoric/internal';

/**
* @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
* @import { EnglishMnemonic } from '@cosmjs/crypto';
* @import { RetryUntilCondition } from './sleep.js';
*/

const trace = makeTracer('E2ET');

const BLD = '000000ubld';

export const txAbbr = tx => {
Expand Down Expand Up @@ -223,7 +228,7 @@ export const provisionSmartWallet = async (
const txInfo = await sendAction({ method: 'executeOffer', offer });
console.debug('spendAction', txInfo);
for await (const update of updates) {
// console.log('update', address, update);
trace('update', address, update);
if (update.updated !== 'offerStatus' || update.status.id !== offer.id) {
continue;
}
Expand Down Expand Up @@ -355,7 +360,7 @@ const voteLatestProposalAndWait = async ({
await blockTool.waitForBlock(1, { step: `voting`, on: lastProposalId })
) {
info = await agd.query(['gov', 'proposal', lastProposalId]);
console.log(
trace(
`Waiting for proposal ${lastProposalId} to pass (status=${info.status})`,
);
}
Expand Down Expand Up @@ -398,7 +403,7 @@ const runCoreEval = async (

const evalPaths = evals.map(e => [e.permit, e.code]).flat();
log(evalPaths);
console.log('await tx', evalPaths);
trace('await tx', evalPaths);
const result = await agd.tx(
[
'gov',
Expand All @@ -413,7 +418,7 @@ const runCoreEval = async (
// FIXME TypeError#1: unrecognized details 0
// assert(result.code, 0);

console.log('await voteLatestProposalAndWait', evalPaths);
trace('await voteLatestProposalAndWait', evalPaths);
const detail = await voteLatestProposalAndWait({ agd, blockTool });
log(detail.proposal_id, detail.voting_end_time, detail.status);

Expand All @@ -428,6 +433,8 @@ const runCoreEval = async (
};

/**
* @deprecated use `@agoric/client-utils` instead
*
* @param {typeof console.log} log
* @param {import('@agoric/swingset-vat/tools/bundleTool.js').BundleCache} bundleCache
* @param {object} io
Expand Down Expand Up @@ -462,7 +469,7 @@ export const makeE2ETools = async (
if (typeof info === 'object' && Object.keys(info).length > 0) {
// XXX normally we have the caller pass in the log function
// later, but the way blockTool is factored, we have to supply it early.
console.log({ ...info, delay: ms / 1000 }, '...');
trace({ ...info, delay: ms / 1000 }, '...');
}
return delay(ms);
};
Expand Down Expand Up @@ -531,10 +538,23 @@ export const makeE2ETools = async (

const copyFiles = makeCopyFiles({ execFileSync, log });

/**
* @deprecated use `@agoric/client-utils` instead
*/
const vstorageClient = makeQueryKit(vstorage).query;

/** @type {import('@agoric/client-utils').SmartWalletKit} */
const smartWalletKit = await makeSmartWalletKit(
{
fetch,
delay,
},
LOCAL_CONFIG,
);

return {
vstorageClient,
smartWalletKit,
installBundles,
runCoreEval: buildAndRunCoreEval,
/**
Expand Down Expand Up @@ -605,8 +625,9 @@ export const seatLike = updates => {
});
};

/** @param {Awaited<ReturnType<provisionSmartWallet>>} wallet */
/** @param {Awaited<ReturnType<typeof provisionSmartWallet>>} wallet */
export const makeDoOffer = wallet => {
/** @type {(offer: OfferSpec) => Promise<void>} */
const doOffer = async offer => {
const updates = wallet.offers.executeOffer(offer);
// const seat = seatLike(updates);
Expand Down
3 changes: 2 additions & 1 deletion multichain-testing/tools/noble-tools.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IBCChannelID } from '@agoric/vats';
import type { ExecSync } from './agd-lib.js';
import type { ChainAddress } from '@agoric/orchestration';
import type { NobleAddress } from '@agoric/fast-usdc/src/types.js';

const kubectlBinary = 'kubectl';
const noblePod = 'noblelocal-genesis-0';
Expand Down Expand Up @@ -82,7 +83,7 @@ export const makeNobleTools = (
const queryForwardingAddress = (
channelId: IBCChannelID,
address: ChainAddress['value'],
): { address: string; exists: boolean } => {
): { address: NobleAddress; exists: boolean } => {
checkEnv();
log('querying forwarding address', address, channelId);
return JSON.parse(
Expand Down
11 changes: 4 additions & 7 deletions multichain-testing/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
{
"extends": "../tsconfig.json",
"include": [
"src",
"tools",
"test"
],
"compilerOptions": {
"checkJs": false
}
"src",
"tools",
"test"
]
}
Loading
Loading