From 78f9bf16c7668cad0402b2e2363ee51706e530b5 Mon Sep 17 00:00:00 2001 From: Shreevatsa N Date: Wed, 6 Mar 2024 19:02:05 +0530 Subject: [PATCH] [Draft][WIP]: Asset benchmark script updates Signed-off-by: Shreevatsa N --- demo/src/asset-tx.ts | 3 + demo/src/asset-working-benchmark.ts | 260 ++++++++++++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 demo/src/asset-working-benchmark.ts diff --git a/demo/src/asset-tx.ts b/demo/src/asset-tx.ts index 9ce6801a..417af7ad 100644 --- a/demo/src/asset-tx.ts +++ b/demo/src/asset-tx.ts @@ -151,10 +151,13 @@ async function main() { space.uri, ); + console.log("AssetIssuance Local:", assetIssuance) + console.dir(assetIssuance, { depth: null, colors: true, }); + const issueExtrinsic = await Cord.Asset.dispatchIssueToChain( assetIssuance, networkAuthorityIdentity, diff --git a/demo/src/asset-working-benchmark.ts b/demo/src/asset-working-benchmark.ts new file mode 100644 index 00000000..b0919851 --- /dev/null +++ b/demo/src/asset-working-benchmark.ts @@ -0,0 +1,260 @@ +import * as Cord from "@cord.network/sdk"; +import { addNetworkMember } from "./utils/createAuthorities.js"; +import { createAccount } from "./utils/createAccount.js"; +import { createDid } from "./utils/generateDid"; + +// import { +// buildFromAssetProperties, +// failproofSubmit, +// buildFromAssetIssueProperties, +// } from "./utils/assets.js"; + +// import "dotenv/config"; + +// import { AssetTypeOf, IAssetProperties } from "./utils/asset-types.js"; + +import moment from "moment"; + +const { NETWORK_ADDRESS, ANCHOR_URI } = process.env; + +export const sleep = (ms: number): Promise => { + return new Promise((resolve) => { + setTimeout(() => resolve(), ms); + }); +}; + +async function main() { + const networkAddress = "ws://127.0.0.1:9944"; + const anchorUri = "//Alice"; + if (!anchorUri || !networkAddress) { + console.log("Missing variables"); + return -1; + } + console.log("Env Variables: ", networkAddress, anchorUri); + // Temporarily suppress console.log + let originalConsoleLog = console.log; + console.log = () => {}; + Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_IN_BLOCK }); + + await Cord.connect(networkAddress); + const api = Cord.ConfigService.get("api"); + // Restore console.log + console.log = originalConsoleLog; + const txCount = 10000; + const perBlock = 1000; + // Step 1: Setup Identities + console.log(`\nā„ļø Identities`); + const networkAuthorityIdentity = Cord.Utils.Crypto.makeKeypairFromUri( + anchorUri, + "sr25519", + ); + const { account: issuerIdentity } = createAccount(); + console.log(`šŸ¦ Issuer (${issuerIdentity.type}): ${issuerIdentity.address}`); + await addNetworkMember(networkAuthorityIdentity, issuerIdentity.address); + console.log("āœ… Issuer Identity created!"); + + const { mnemonic: issuerMnemonic, document: issuerDid } = await createDid( + networkAuthorityIdentity + ) + const issuerKeys = Cord.Utils.Keys.generateKeypairs(issuerMnemonic) + console.log( + `šŸ› Issuer (${issuerDid?.assertionMethod![0].type}): ${issuerDid.uri}` + ) + +// const { mnemonic: holderMnemonic, document: holderDid } = await createDid( +// networkAuthorityIdentity +// ) +// const holderKeys = Cord.Utils.Keys.generateKeypairs(holderMnemonic) +// console.log( +// `šŸ› Holder (${holderDid?.assertionMethod![0].type}): ${holderDid.uri}` +// ) + + + // Step 2: Create a new Chain Space + console.log(`\nā„ļø Chain Space Creation `) + const spaceProperties = await Cord.ChainSpace.buildFromProperties( + issuerDid.uri + ) + console.dir(spaceProperties, { + depth: null, + colors: true, + }) + + console.log(`\nā„ļø Chain Space Properties `) + const space = await Cord.ChainSpace.dispatchToChain( + spaceProperties, + issuerDid.uri, + networkAuthorityIdentity, + async ({ data }) => ({ + signature: issuerKeys.authentication.sign(data), + keyType: issuerKeys.authentication.type, + }) + ) + console.dir(space, { + depth: null, + colors: true, + }) + console.log('āœ… Chain Space created!') + + console.log(`\nā„ļø Chain Space Approval `) + await Cord.ChainSpace.sudoApproveChainSpace( + networkAuthorityIdentity, + space.uri, + 100 + ) + console.log(`āœ… Chain Space Approved`) + + + // Step 3: Create assets on-chain + console.log = () => {}; + /* Check which options one needs: note below only agree */ + Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_READY }); + //Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_IN_BLOCK}); + //Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_FINALIZED }); + console.log = originalConsoleLog; + + console.log(`\nā„ļø Create On-Chain Assets `); + let assetProperties: Cord.IAssetProperties = { + assetType: Cord.AssetTypeOf.art, + assetDesc: "Asset - " + Cord.Utils.UUID.generate(), + assetQty: 1000000, + assetValue: 10, + assetTag: "Tag - " + Cord.Utils.UUID.generate(), + assetMeta: "Meta - " + Cord.Utils.UUID.generate(), + }; + + const assetEntry = await Cord.Asset.buildFromAssetProperties( + assetProperties, + issuerDid.uri, + space.uri + ); + + console.dir(assetEntry, { + depth: null, + colors: true, + }); + + const extrinsic = await Cord.Asset.dispatchCreateToChain( + assetEntry, + networkAuthorityIdentity, + space.authorization, + async ({ data }) => ({ + signature: issuerKeys.authentication.sign(data), + keyType: issuerKeys.authentication.type, + }), + ) + + console.log("Asset Entry Local:", assetEntry) + + console.log("āœ… Asset created!"); + + console.log(`\nā„ļø Transaction Benchmarking `); + + let tx_batch: any = []; + let startTxPrep = moment(); + + try { + for (let j = 0; j < (txCount / perBlock); j++) { + let tx_batch1: any = []; + for (let k = 0; k < perBlock; k++) { + const { account: holderIdentity } = createAccount(); + + // const { mnemonic: holderMnemonic, document: holderDid } = await createDid( + // networkAuthorityIdentity + // ) + // const holderKeys = Cord.Utils.Keys.generateKeypairs(holderMnemonic) + // console.log( + // `šŸ› Holder (${holderDid?.assertionMethod![0].type}): ${holderDid.uri}` + // ) + + // console.log(`holderDid.uri: ${holderDid.uri}`) + + console.log(`\nā„ļø Issue Asset to Holder - Issuer Action `); + const assetIssuance = await Cord.Asset.buildFromIssueProperties( + assetEntry.uri, + `did:cord:${holderIdentity.address}`, + 1, + issuerDid.uri, + space.uri, + ); + + console.log("AssetIssuance Local:", assetIssuance) + + const issueExtrinsic = await Cord.Asset.prepareExtrinsic( + assetIssuance, + networkAuthorityIdentity, + space.authorization, + async ({ data }) => ({ + signature: issuerKeys.authentication.sign(data), + keyType: issuerKeys.authentication.type, + }), + ) + + tx_batch1.push(issueExtrinsic); + + process.stdout.write( + " šŸ”– Preparing " + + (j * perBlock + 1 + k) + + " transactions took " + + moment.duration(moment().diff(startTxPrep)).as("seconds").toFixed(3) + + "s\r", + ); + } + tx_batch[j] = tx_batch1; + } + } catch (e: any) { + console.log(e.errorCode, "-", e.message); + } + console.log("\n"); + + // console.log = () => {}; + // Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_FINALIZED }); + console.log = originalConsoleLog; + let batchAncStartTime = moment(); + let promises = []; + for (let j = 0; j < tx_batch.length; j++) { + try { + const tx = await api.tx.utility + .batchAll(tx_batch[j]); + + await tx.signAsync(issuerIdentity, { nonce: j + 1 }) + const send = new Promise((resolve) => tx.send((result) => { + if (result.status.isReady) + //if (result.isInBlock) + //if (result.isFinalized) + return resolve(true); + })); + promises.push(send); + } catch (e: any) { + console.log(e.errorCode, "-", e.message); + } + } + await Promise.all(promises); + + var batchAncDuration = moment + .duration(moment().diff(batchAncStartTime)) + .as("seconds"); + + console.log( + `\n šŸŽ Anchoring a batch of ${ + txCount + } transactions took ${batchAncDuration.toFixed(3)}s`, + ); + console.log( + ` šŸ™Œ Block TPS (batch transactions) - ${+( + txCount / batchAncDuration + ).toFixed(0)} `, + ); + + await sleep(1000); + await api.disconnect(); +} +main() + .then(() => console.log("\nBye! šŸ‘‹ šŸ‘‹ šŸ‘‹ ")) + .finally(Cord.disconnect); + +process.on("SIGINT", async () => { + console.log("\nBye! šŸ‘‹ šŸ‘‹ šŸ‘‹ \n"); + Cord.disconnect(); + process.exit(0); +});